Docento.app Logo
Docento.app
Pen resting on a printed document
All Posts

How to Import Data Into a PDF Form (Pre-Fill Without Re-Authoring)

May 8, 2026·8 min read

If you have ever needed to send the same form to 50 customers with each customer's name, account number, and address pre-filled, you have met the case for data import. PDF forms support pre-population from external data, CSV, XML, JSON, FDF, XFDF, so each recipient receives a personalized form ready to review and complete. The mechanics are well-supported but oddly fragmented across tools. This guide walks through the practical paths.

Why import data into a form

  • Pre-fill customer information so recipients only need to fill the new sections
  • Auto-populate from a database, orders, contracts, applications generated from your records
  • Bulk-fill known fields like tax IDs, address blocks, account numbers
  • Re-issue corrected versions, fix one field, regenerate the populated form
  • Generate per-recipient versions of the same template

Done right, data import lets one form template serve hundreds or thousands of personalized copies.

The PDF form-data formats

A few formats are common:

  • FDF (Forms Data Format), Adobe's original binary-ish data format for PDF forms. Compact, supports most field types.
  • XFDF, XML version of FDF. Human-readable, supported widely.
  • XML, generic XML matching the form's field structure.
  • CSV, flat data, requires mapping to fields by name or column order.
  • JSON, modern, well-supported by libraries; needs explicit mapping to fields.
  • AcroForm with embedded XFA, XFA carries its own data model; less common.

For most workflows in 2026, XFDF (for native PDF tooling) or JSON (for programmatic pipelines) are the right choice.

Tools that import data into PDF forms

Adobe Acrobat Pro. Tools → Prepare Form → More → Import Data. Choose an FDF, XFDF, XML, or text file. Acrobat matches field names and pre-populates the form.

Foxit PDF Editor. Form → Import Data.

PDF-XChange Editor. Form → Import Form Data.

pdftk fill_form, open-source CLI. pdftk template.pdf fill_form data.fdf output filled.pdf. See pdftk introduction.

pdfcpu, modern Go-based PDF toolkit: pdfcpu form fill template.pdf data.json filled.pdf.

Programmatic libraries, pikepdf (Python), iText (Java), PDFKit (Node.js), PDFlib (multi-language) all support filling form fields from data structures.

Step-by-step: import an FDF in Acrobat Pro

  1. Open the PDF template
  2. Tools → Prepare Form
  3. More → Import Data (in the right-side panel)
  4. Choose the FDF / XFDF / XML / CSV file
  5. Acrobat matches field names and populates
  6. Verify each field looks right
  7. Save as a new file

Step-by-step: fill a form from CSV via CLI

For a single form fill:

pdftk template.pdf fill_form data.fdf output filled.pdf

For a batch of fills from a CSV:

import csv, subprocess
with open("customers.csv") as f:
    reader = csv.DictReader(f)
    for row in reader:
        # generate an FDF from the row
        fdf = generate_fdf(row)
        with open("temp.fdf", "w") as ff:
            ff.write(fdf)
        subprocess.run([
            "pdftk", "template.pdf",
            "fill_form", "temp.fdf",
            "output", f"filled_{row['customer_id']}.pdf"
        ])

This produces one filled PDF per customer.

Generating an FDF programmatically

An FDF file looks like:

%FDF-1.2
1 0 obj
<< /FDF
<< /Fields [
<< /T (customer_name) /V (Jane Doe) >>
<< /T (account_number) /V (ABC-12345) >>
<< /T (city) /V (Springfield) >>
] >> >>
endobj
trailer
<< /Root 1 0 R >>
%%EOF

For each field, /T is the field name and /V is the value. Strings are wrapped in parentheses. Boolean values use /Yes or /Off.

Python tools like fdfgen produce this automatically:

from fdfgen import forge_fdf

fields = [
    ("customer_name", "Jane Doe"),
    ("account_number", "ABC-12345"),
]
fdf = forge_fdf("", fields, [], [], [])
with open("data.fdf", "wb") as f:
    f.write(fdf)

XFDF, XML variant

XFDF is the same data in XML form:

<?xml version="1.0" encoding="UTF-8"?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
  <fields>
    <field name="customer_name"><value>Jane Doe</value></field>
    <field name="account_number"><value>ABC-12345</value></field>
  </fields>
</xfdf>

XFDF is easier to generate from XML pipelines, easier to inspect manually, and roughly as widely supported as FDF in modern tools.

Filling from JSON

For modern pipelines, pdfcpu accepts JSON directly:

{
  "forms": [
    {
      "fields": [
        { "name": "customer_name", "value": "Jane Doe" },
        { "name": "account_number", "value": "ABC-12345" }
      ]
    }
  ]
}

Then: pdfcpu form fill template.pdf data.json filled.pdf.

For pikepdf:

import pikepdf

data = {"customer_name": "Jane Doe", "account_number": "ABC-12345"}

with pikepdf.open("template.pdf") as pdf:
    fields = pdf.Root.AcroForm.Fields
    for f in fields:
        name = str(f.T)
        if name in data:
            f.V = pikepdf.String(data[name])
    pdf.save("filled.pdf")

This is the cleanest path for Python-based pipelines.

Matching fields by name

All these tools match input data to form fields by field name. The data file says "fill customer_name with 'Jane Doe'"; the form has a field named customer_name. Match made.

This makes naming critical:

  • Use consistent naming across templates so the same data file fills multiple forms
  • Avoid spaces and special characters
  • Use a documented data dictionary so everyone knows what acct_num means

If the data source uses different names than the form fields, transform the data in your script before filling.

Reset and clear

Before filling a template, sometimes you want to reset to a clean state:

  • Acrobat Pro: Tools → Prepare Form → More → Clear Form
  • CLI: Fill with empty values for all fields, or use pdftk's flatten carefully (which flattens fills but does not clear).

For a programmatic batch, start fresh from the original template each time rather than re-using a previously-filled copy.

Flattening after fill

After filling, you may want to flatten, convert form field values to page content so the result is no longer editable as a form. See how to flatten a PDF.

pdftk filled.pdf output final.pdf flatten

The form fields disappear; the values remain as page text. Useful for distributing read-only versions of filled forms.

Importing data into an XFA form

XFA forms use a different data model. To fill:

  • Adobe Acrobat / LiveCycle, the only fully-supported tools for XFA data import
  • Custom XML matching the XFA's binding schema

XFA is deprecated and most readers handle it poorly. For new forms, use AcroForm and avoid XFA. See PDF form field types explained for the broader context.

Common gotchas

Field names mismatch. The form has customer_name; the data says customerName. The fill silently skips. Make field naming consistent.

Unicode encoding issues. Names with accents (José, Müller) require UTF-8 encoding in FDF/XFDF. Test with realistic data including non-ASCII characters.

Date format mismatch. The form's date field is formatted as mm/dd/yyyy; the data file has 2026-05-08. Convert before filling or use a format-agnostic field.

Checkbox export value confusion. A checkbox has export value "Yes"; data file says "true" or "1". The fill does not match. Pass exactly the export value, not a different boolean representation.

Read-only fields. Read-only fields can be filled programmatically (since you have the source), but Acrobat's GUI import may skip them. Verify expected behavior in your tool of choice.

Required fields enforced after fill. A field filled programmatically may pass the required check even if your data is empty. The "required" attribute is for user fills, not data imports.

Calculated fields overwritten. A calculated field (e.g., line_total = quantity * price) recomputes after the form loads. If you import a value for line_total, the calculation overwrites it. Either import only the input fields, or disable the calculation before import.

Field appearance not refreshed. Some tools fill the data but do not update the visual appearance. The data is in the file; it just does not show until the user clicks the field. Use a tool that calls pdf.generate_appearance_streams() or equivalent. pikepdf handles this when pdf.save() is called.

Multi-line text fields. Importing a long string into a single-line field truncates visually but stores fully. Set the field to multiline if needed.

Signature fields cannot be data-imported. Signatures require user interaction (or a cryptographic signing process). You cannot pre-fill a signature.

Practical recipe: bulk pre-fill from CSV

For 100 personalized forms from a customer roster CSV:

  1. Define the template PDF with field names matching CSV column names
  2. Write a script that reads each CSV row and generates an FDF or JSON
  3. Loop: for each row, run pdftk or pikepdf to fill the template
  4. Save each output with a unique filename (filled_<customer_id>.pdf)
  5. Optionally flatten each output for read-only distribution
  6. Verify a random sample looks right

Estimated time: a few minutes to write, seconds per form to run.

Filling and serving on-demand

Some workflows fill forms server-side per request:

  1. User clicks "Generate my agreement"
  2. Server reads the template
  3. Server fills with user-specific data
  4. Server returns the filled PDF for download or email

This pattern works well with pikepdf, iText, or any of the major libraries. Combined with HTML-to-PDF, it covers most templated-document use cases.

Takeaway

Importing data into a PDF form turns one template into hundreds of personalized copies with little effort. Pick a data format that fits your pipeline (FDF/XFDF for native tools, JSON for modern automation). Match field names exactly between data and form. For one-offs, use Acrobat Pro's Import Data; for batch, use pdftk, pdfcpu, or pikepdf. Combine with flattening for read-only distribution and signing when the workflow requires it. For browser-based one-off fills, Docento.app handles form filling without installing tooling. For the reverse, extracting filled data, see how to export PDF form data.

Related Posts