PDFMove
How Do PDF Form Fields Work? AcroForm, Appearance Streams and Flattening
Guide

How Do PDF Form Fields Work? AcroForm, Appearance Streams and Flattening

7 min read

You filled in a PDF form and sent it, and the recipient says "the fields look blank." Or the form looks right in one program and shows a different font in another. All of these oddities come from how PDF forms are structured. This article explains what form fields correspond to inside the file and how flattening removes that structure.

Two separate worlds: page content and the interactive layer

A PDF page contains two different kinds of content.

The page content stream is the sequence of commands describing how the page is drawn. Text, lines, fills, images — everything static is here.

Annotations are separate objects that sit on top of the page. Sticky notes, highlights, hyperlinks and — our subject — form field widgets fall in this category.

That distinction is critical: a form field is not part of the page content. It's a separate object listed in the page object's /Annots array. The code that draws the page and the code that draws the form field run through different paths.

AcroForm: the document-level form dictionary

The document's catalog object contains an /AcroForm key pointing to a dictionary. That dictionary manages the entire form:

  • /Fields: the list of all form fields in the document. Fields can be hierarchical; a parent field can have multiple child fields.
  • /DA: the default appearance string. Information like font, size and color is defined here (something like /Helv 0 Tf 0 g).
  • /DR: the default resource dictionary. The actual definitions of the fonts named in /DA live here.
  • /NeedAppearances: a critical flag; we'll detail it shortly.
  • /XFA: XML-based dynamic form data, if present.

The form field object itself carries:

  • /FT: the field type — /Tx (text), /Btn (button/checkbox), /Ch (choice list), /Sig (signature).
  • /T: the field name ("full_name", "date").
  • /V: the field's value — the data the user entered.
  • /AP: the appearance dictionary — how that value is drawn.

The appearance stream: the source of inconsistency

Now we come to the most important point. A form field's value (/V) and the appearance of that value (/AP) are separate things.

/V is just data: (John Smith). It carries no information about which font, at what size, aligned where, that text is drawn on the page.

/AP is an appearance stream — a small XObject form containing drawing commands, just like the page content stream. A properly working form-filling program updates both the /V value and the /AP appearance stream when you type into a field.

The problem is that some programs skip the second step. They write the value and don't update the appearance. What happens then?

It depends on the viewer. An advanced viewer generates the appearance itself when /AP is missing or stale — using the font information from the /DA string. But not every viewer does it the same way: they behave differently on line spacing, vertical alignment, and clipping of overflowing text.

In simple viewers the field appears blank. Some lightweight PDF viewers and mobile apps don't have appearance generation capability. If /AP is missing, they draw nothing.

Printer drivers have the same problem. That's the most common technical reason behind the complaint "I filled in the form but it prints blank."

The NeedAppearances flag

As a solution to this situation, the /NeedAppearances flag was added to the standard. Set to true, it means: "don't trust the appearance streams in this form, regenerate them yourself."

Form-filling tools turn this flag on when they can't update the appearance.

But the flag doesn't fully solve the problem:

  • Viewers without appearance generation capability ignore the flag and the field stays blank.
  • Viewers that can generate appearances do so in their own style; the result varies from program to program.
  • Printer drivers generally pay no attention to the flag.

So /NeedAppearances solves the problem in certain viewers but provides no universal guarantee.

How flattening ends that uncertainty

The flattening operation does the following:

1. It takes each form field's appearance stream. If /AP exists it's used directly; if not, it's generated from the /V value and the /DA information.

2. It draws that appearance into the page content stream. Using the field's position (/Rect) and size, it's added either as an XObject form call or as direct drawing commands.

3. It removes the widget annotation from the /Annots array.

4. It deletes the /AcroForm dictionary and the /Fields list inside it.

5. It removes the form JavaScript — calculation and validation code is now non-functional.

The result: the value is now a permanent part of the page. No viewer needs to interpret anything, and it looks the same in every program and on every printer.

| Aspect | Before flattening | After flattening | |---|---|---| | Appearance consistency | Depends on the viewer | Certain | | Print reliability | Depends on the driver | Certain | | Editability | Yes | No | | JavaScript calculations | Work | Removed | | Screen reader form labels | Present | Lost | | File size | — | Shrinks slightly |

What if the appearance stream is broken

Here's one of flattening's traps. The tool fixes the existing /AP appearance stream in place. If that stream is stale or empty — that is, if the form-filling program wrote the value without updating the appearance — flattening can freeze a blank or wrong appearance.

The symptom: when you open the file in one program the values appear (that program generates the appearance itself), but after flattening it comes out blank.

The fix: open the form in a program that properly generates appearance streams and save it, then flatten. Or, if your flattening tool can generate the appearance from the /V value, use that.

The text overflow problem

Form fields are drawn inside their own rectangles (/Rect). If the text you entered doesn't fit that rectangle, in interactive mode the field can be scrolled — you click and scroll to read it.

In a flattened document there's no such thing as scrolling. Only the visible portion gets frozen; the rest is lost.

That's a real risk of data loss in long address fields, comment boxes and multi-line text areas. You need to check fields with long content before flattening.

XFA forms: a separate world

Some PDFs use XFA instead of (or alongside) AcroForm. That's Adobe's XML-based dynamic form technology: fields grow with the data, rows get added to tables, and the page count can change.

XFA forms aren't a natural part of the PDF standard; they're a separate technology embedded inside PDF. They work fully only in Adobe's own products. In other viewers you usually see a warning like "Adobe Reader is required to view this document."

XFA has been deprecated in newer PDF versions. Flattening an XFA form you run into is usually not possible; you first have to convert it into a plain AcroForm or a static PDF.

Its relationship to digital signatures

A digital signature stores a cryptographic hash of the byte range as it stood at the moment of signing. Because flattening rewrites the file, that hash no longer matches and signature validation fails.

Also, the signature field itself is a form field (/FT /Sig). If flattening turns it into fixed content, the signature's cryptographic structure is lost too — all that remains is the signature's visual representation, which carries no validation value.

The right order: fill → flatten → sign.

In summary

PDF form fields live in an interactive layer separate from the page content. A field's value (/V) and the drawing of that value (the /AP appearance stream) are separate structures, and when the appearance stream is missing or out of date each viewer makes its own interpretation — that's the source of inconsistent appearance and blank printing. The /NeedAppearances flag is a partial solution but not a universal one. Flattening ends the uncertainty by drawing the appearance permanently into the page content and removing the interactive layer entirely. Its cost is irreversibility and the loss of the accessibility structure; its risk is freezing a broken appearance stream or overflowing text.

Frequently Asked Questions

Why does the same form look different in different programs?

Because a form field's value and the appearance stream describing how that value is drawn are separate things. If the appearance stream is missing or out of date, each viewer draws the field with its own default font, size and alignment. A field that shows as 11-point Helvetica in one program can be drawn in 9-point system font in another. Flattening eliminates that uncertainty.

What does the NeedAppearances flag do?

It's a document-level flag meaning 'the appearance streams of the fields in this form are unreliable, the viewer should regenerate them.' A form-filling program that wrote a value without updating the appearance turns this flag on. The problem is that every viewer generates the appearance in its own style, creating inconsistency; and some simple viewers ignore the flag entirely and the fields show up blank.

Does form field data remain in the file after flattening?

A proper flattening removes the AcroForm dictionary and the widget annotations from the file, so the field data goes with them. But if the file carries an incremental update history, earlier versions can remain in the file. If sensitive information is involved, it's safer to run the file through an operation that fully rewrites it (compression, for example) after flattening, and to clean the metadata.

What is an XFA form, and how does it differ from AcroForm?

XFA is Adobe's XML-based dynamic form technology; fields can grow and shrink with the data and the page count can change. AcroForm is part of the PDF standard and is static. XFA forms work fully only in Adobe's own products; in other viewers you usually get a 'Adobe Reader is required to view this form' warning. XFA has been deprecated in newer PDF versions.

Try this out right away with Formu Düzleştir.

Try Formu Düzleştir