Concept · Interactive documents

What are PDF forms (AcroForm)?
Create & fill PDFs in code

Last updated: 2026-06-29

An AcroForm is the interactive-form layer of the PDF specification. It adds fields a person can type into, tick, and select, and that your software can fill in seconds, no printing, no scanning, no retyping. This guide explains the field types, how appearance streams work, and how to author, fill, and flatten a form entirely in code.

The analogy: a paper form made smart

Think of a paper form: pre-printed labels, blank boxes to write in, tick boxes down the side. Anyone can fill it with a pen. But every time it lands in an office, someone has to read it and type the answers into a computer. That is slow, error-prone, and scales to zero.

A PDF form is that same form, made smart. The fields are real interactive objects your software can reach into and fill programmatically (from a database record, an API response, or a form submission) at any volume, instantly, without human transcription. When you are done, you flatten the form: bake the values into the page as static content so the recipient gets a clean, finished document, not a half-editable curiosity.

The four field types

The PDF AcroForm specification defines four kinds of interactive fields. rust-pdf supports all four and generates a correct /AP appearance stream for each at authoring time, so fields render in every viewer without the NeedAppearances flag.

Text field

Free-form text entry, single or multi-line. Used for names, addresses, descriptions, any open answer.

Checkbox

A binary on/off toggle. Checked state renders a tick or cross using the built-in ZapfDingbats font.

Radio group

Mutually exclusive options: selecting one deselects the rest. Defined as a group sharing a field name.

Dropdown

A choice field presenting a fixed list of options. Software sets the selected value by name, not by index.

Two jobs: author a blank form, then fill it

Working with PDF forms involves two distinct operations. They are often done at separate times: the blank template lives in version control; filling happens at runtime from live data.

1. Authoring

Place interactive fields on a page to create a blank form template.

  • Create a new Document and add a page
  • Call text_field, checkbox, radio_group, or dropdown with a name, page index, and bounding box
  • Field names are hierarchical: applicant.name creates a nested applicant parent field automatically
  • rust-pdf generates a /AP appearance stream for every field using built-in fonts, so no font loading is needed
  • Save the blank form; distribute it as a reusable template

2. Filling

Load the template and write values into its fields programmatically.

  • Load the form bytes into an EditableDoc
  • Call fill_text_field, set_checkbox, set_choice, or set_radio with the field name and value
  • Dotted field names navigate the hierarchy: applicant.name targets the right widget automatically
  • Optionally call flatten_forms() to bake values into static content (see below)
  • Save or stream the completed PDF

Flattening: making it final

A filled form is still interactive; a recipient could change the values. Flattening removes the form layer and burns the current values into the page as ordinary, non-editable content. The result looks identical in every viewer, but no field can be altered.

Flatten before archiving, emailing a signed copy, attaching to a record system, or converting to PDF/A for long-term storage. Once flattened the document behaves like any static PDF.

Where PDF forms are used

Any workflow where structured data needs to reach a human-readable PDF document, whether the human fills it or the software does.

Customer onboarding

Pre-fill application forms with data from your CRM, send a PDF ready to sign, flatten on receipt.

Government & tax forms

Agencies publish AcroForm templates; software fills them from taxpayer records and returns completed PDFs.

Contracts & agreements

Generate a contract pre-populated with party names, dates, and terms; send for e-signature or wet sign.

Database-driven generation

Pull thousands of records and render a unique filled, flattened PDF for each: invoices, statements, certificates.

Applications & surveys

Publish a blank AcroForm for users to fill in a viewer; collect the data back as field values, not images.

Interactive kiosks & portals

Serve a form in a web viewer; flatten and archive once submitted, keeping a human-readable audit trail.

How to author and fill a PDF form with rust-pdf

Place fields when authoring, then fill and flatten an existing form. The generated /AP means no NeedAppearances flag is required.

# pip install rustpdf
import rustpdf

# 1) Author a blank form
with rustpdf.Document() as doc:
    doc.add_page()
    doc.text_field("applicant.name", 0, [72, 690, 320, 712])
    doc.checkbox("agree", 0, [72, 650, 90, 668], checked=False)
    doc.dropdown("plan", 0, [72, 610, 260, 630], ["Basic", "Pro", "Enterprise"])
    doc.save("form.pdf")

# 2) Fill it, then flatten to a final read-only copy
with rustpdf.EditableDoc.load(open("form.pdf", "rb").read()) as ed:
    ed.fill_text_field("applicant.name", "Ada Lovelace")
    ed.set_checkbox("agree", True)
    ed.set_choice("plan", "Pro")
    ed.flatten_forms()                 # bake values; no longer editable
    ed.save("form_filled.pdf")
// dotnet add package RustPdf
using RustPdf;

using (var doc = new Document()) {
    doc.AddPage();
    doc.TextField("applicant.name", 0, (72, 690, 320, 712));
    doc.Checkbox("agree", 0, (72, 650, 90, 668), false);
    doc.Dropdown("plan", 0, (72, 610, 260, 630), new[]{ "Basic", "Pro", "Enterprise" });
    doc.Save("form.pdf");
}

using var ed = EditableDoc.Load(File.ReadAllBytes("form.pdf"));
ed.FillTextField("applicant.name", "Ada Lovelace");
ed.SetCheckbox("agree", true);
ed.SetChoice("plan", "Pro");
ed.FlattenForms();
ed.Save("form_filled.pdf");
// go get github.com/rustpdf/rustpdf-go@latest
doc, _ := rustpdf.New()
doc.AddPage()
doc.TextField("applicant.name", 0, [4]float64{72, 690, 320, 712}, "", 0)
doc.Checkbox("agree", 0, [4]float64{72, 650, 90, 668}, false)
doc.Dropdown("plan", 0, [4]float64{72, 610, 260, 630}, []string{"Basic", "Pro", "Enterprise"}, -1, 0)
doc.Save("form.pdf")
doc.Close()

ed, _ := rustpdf.Load(mustRead("form.pdf"))
defer ed.Close()
ed.FillTextField("applicant.name", "Ada Lovelace")
ed.SetCheckbox("agree", true)
ed.SetChoice("plan", "Pro")
ed.FlattenForms()
ed.Save("form_filled.pdf")
// npm install rustpdf
const { Document, EditableDoc } = require("rustpdf");
const fs = require("fs");

const doc = new Document();
doc.addPage();
doc.textField("applicant.name", 0, [72, 690, 320, 712]);
doc.checkbox("agree", 0, [72, 650, 90, 668], false);
doc.dropdown("plan", 0, [72, 610, 260, 630], ["Basic", "Pro", "Enterprise"]);
doc.save("form.pdf");

const ed = EditableDoc.load(fs.readFileSync("form.pdf"));
ed.fillTextField("applicant.name", "Ada Lovelace");
ed.setCheckbox("agree", true);
ed.setChoice("plan", "Pro");
ed.flattenForms();
ed.save("form_filled.pdf");
Output validated by: qpdfmutool

Form fields use the built-in Helvetica and ZapfDingbats fonts for their /AP streams, so no font file is needed. For eight-language coverage (Python, C#, Go, Node, PHP, Ruby, Delphi, Swift) see the documentation.

PDF forms FAQ

What is a PDF form / AcroForm?

An AcroForm is the interactive-form layer of the PDF specification. It adds fields (text boxes, checkboxes, radio buttons, and dropdowns) that a person can fill in a PDF viewer, or that software can fill programmatically. Each field is a widget annotation attached to a page, with an appearance stream that controls how it is drawn. AcroForm is part of the PDF standard and is supported by every major viewer.

What field types are supported in PDF forms?

The PDF AcroForm specification defines text fields (single or multi-line free text), checkboxes (on/off toggle), radio groups (one option from a mutually exclusive set), and choice fields such as dropdowns and list boxes. rust-pdf supports all four types: text_field, checkbox, radio_group, and dropdown.

How do I fill a PDF form in code?

Load the existing PDF into an editable document, then call fill_text_field, set_checkbox, set_choice, or set_radio with the field name and the desired value. In Python: ed.fill_text_field("applicant.name", "Ada Lovelace"). Hierarchical dotted names like applicant.name address a nested field inside a parent group. After filling, call flatten_forms() to produce a final, non-editable PDF.

What does flattening a form do?

Flattening bakes the current field values into the page as static, non-editable content and removes the interactive form layer. The result looks identical to the filled form in any viewer, but the fields can no longer be changed. Flattening is the right step before archiving a completed form, emailing a final copy, or attaching a document to a record system. Call flatten_forms() / FlattenForms() after filling to produce the final read-only PDF.

Do I need the NeedAppearances flag?

No. The NeedAppearances flag tells viewers to regenerate field appearances because the document's /AP streams are absent or stale. rust-pdf generates a correct /AP appearance stream for every field at authoring time, using the built-in Helvetica and ZapfDingbats fonts, so viewers render fields correctly without that flag. Avoiding NeedAppearances means the form looks right in every viewer, including those that ignore the flag.

Generate and fill PDF forms in your language

One Rust core, eight bindings: Python, C#/.NET, Go, Node.js, PHP, Ruby, Delphi, Swift. Prototype for free; license the corporate features when you ship.

Build PDF forms in your language: Go, PHP, Ruby, Node.js.