Skip to main content

Interactive Forms

paperjam can inspect, fill, create, and modify interactive AcroForm fields. Like all write operations, modifying forms returns a new Document.

Checking for forms

import paperjam

doc = paperjam.open("application.pdf")
print(doc.has_form) # True if an AcroForm dictionary is present

Inspecting form fields

for field in doc.form_fields:
print(f"{field.name!r} type={field.field_type} value={field.value!r}")
print(f" page={field.page} rect={field.rect}")
print(f" read_only={field.read_only} required={field.required}")
if field.max_length:
print(f" max_length={field.max_length}")
if field.options:
for opt in field.options:
print(f" option: {opt.display!r} ({opt.export_value!r})")

FormField attributes:

AttributeTypeDescription
namestrFully-qualified field name
field_typestr"text", "checkbox", "radio_button", "combo_box", "list_box", "push_button", "signature"
valuestr | NoneCurrent value
default_valuestr | NoneDefault value
pageint | None1-based page number
recttuple | NonePosition (x1, y1, x2, y2) in points
read_onlyboolWhether the field is read-only
requiredboolWhether the field is required
max_lengthintMaximum character length (0 = no limit)
optionstuple[ChoiceOption, ...]Options for combo/list boxes

Filling a form

fill_form() takes a mapping of field names to string values:

filled, result = doc.fill_form(
{
"first_name": "Alice",
"last_name": "Smith",
"email": "alice@example.com",
"agree_tos": "Yes", # checkboxes: "Yes" or "Off"
"country": "GB", # combo box: pass the export value
},
generate_appearances=True, # write explicit AP streams for max compatibility
)

print(f"Fields filled: {result.fields_filled}")
print(f"Fields not found: {result.fields_not_found}")
if result.not_found_names:
print(f"Missing: {', '.join(result.not_found_names)}")

filled.save("filled-application.pdf")

FillFormResult attributes:

AttributeTypeDescription
fields_filledintNumber of fields successfully filled
fields_not_foundintNumber of field names not found
not_found_namestuple[str, ...]Names of fields that were not found

Checkbox and radio button values

  • Checkboxes: pass "Yes" to check, "Off" to uncheck.
  • Radio buttons: pass the export value of the option to select.

Creating a new form field

add_form_field() appends a new field to the AcroForm:

from paperjam import ChoiceOption

# Text field
doc2, result = doc.add_form_field(
"full_name",
"text",
page=1,
rect=(72.0, 680.0, 300.0, 700.0),
font_size=12.0,
max_length=100,
required=True,
generate_appearance=True,
)

# Checkbox
doc2, result = doc.add_form_field(
"agree_tos",
"checkbox",
page=1,
rect=(72.0, 650.0, 90.0, 668.0),
value="Yes",
)

# Combo box with options
doc2, result = doc.add_form_field(
"country",
"combo_box",
page=1,
rect=(72.0, 620.0, 250.0, 640.0),
options=[
ChoiceOption(display="United Kingdom", export_value="GB"),
ChoiceOption(display="United States", export_value="US"),
ChoiceOption(display="Germany", export_value="DE"),
],
)

print(f"Created: {result.field_name} success={result.created}")
doc2.save("with-fields.pdf")

Supported field types for add_form_field:

Type stringDescription
"text"Single or multi-line text input
"checkbox"Boolean checkbox
"radio_button"One-of-N radio button group
"combo_box"Dropdown with optional free-text entry
"list_box"Scrollable selection list
"push_button"Button (triggers actions)
"signature"Digital signature field

Modifying an existing field

modify_form_field() changes properties of an existing field without replacing it:

doc2, result = doc.modify_form_field(
"full_name",
read_only=True, # lock the field
required=True,
max_length=50,
)
print(f"Modified: {result.field_name} success={result.modified}")

# Change the value of a text field
doc2, result = doc.modify_form_field("email", value="new@example.com")

# Replace options in a combo box
doc2, result = doc.modify_form_field(
"country",
options=[
ChoiceOption(display="France", export_value="FR"),
ChoiceOption(display="Spain", export_value="ES"),
],
)

ModifyFieldResult attributes:

AttributeTypeDescription
field_namestrName of the field that was targeted
modifiedboolWhether the field was found and modified

Form-aware merging

When merging documents that each contain forms, field names may collide. paperjam handles this automatically during paperjam.merge() — fields from each document are namespaced to avoid conflicts.