| name | python-pdf-form-filling |
| description | Use this skill when you need to programmatically fill PDF form fields using Python. Covers inspecting field names and writing values to fillable PDFs. |
Filling PDF Forms with Python
Recommended Libraries
Option 1: PyPDF2 / PyPDF (pypdf)
from pypdf import PdfReader, PdfWriter
reader = PdfReader("input.pdf")
writer = PdfWriter()
writer.append(reader)
fields = reader.get_fields()
for field_name, field_obj in fields.items():
print(f"Field: {field_name}, Type: {field_obj.get('/FT')}, Value: {field_obj.get('/V')}")
Filling fields:
from pypdf import PdfReader, PdfWriter
reader = PdfReader("sc100-blank.pdf")
writer = PdfWriter()
writer.append(reader)
fill_data = {
"FieldName1": "Value1",
"FieldName2": "Value2",
}
writer.update_page_form_field_values(writer.pages[0], fill_data)
with open("sc100-filled.pdf", "wb") as f:
writer.write(f)
Option 2: pdfrw
import pdfrw
template = pdfrw.PdfReader("sc100-blank.pdf")
for page in template.pages:
annotations = page.get('/Annots')
if annotations:
for annot in annotations:
field_name = annot.get('/T')
field_type = annot.get('/FT')
print(f"Field: {field_name}, Type: {field_type}")
Filling with pdfrw:
import pdfrw
ANNOT_KEY = '/Annots'
ANNOT_FIELD_KEY = '/T'
ANNOT_VAL_KEY = '/V'
ANNOT_RECT_KEY = '/Rect'
SUBTYPE_KEY = '/Subtype'
WIDGET_SUBTYPE_KEY = '/Widget'
template = pdfrw.PdfReader("sc100-blank.pdf")
data = {
"(FieldName1)": "Value1",
"(FieldName2)": "Value2",
}
for page in template.pages:
annotations = page.get(ANNOT_KEY)
if annotations:
for annot in annotations:
field_name = annot.get(ANNOT_FIELD_KEY)
if field_name in data:
annot.update(pdfrw.PdfDict(V=data[field_name]))
annot.update(pdfrw.PdfDict(AP=''))
pdfrw.PdfWriter().write("sc100-filled.pdf", template)
Option 3: fillpdf / pdftk wrapper
from fillpdf import fillpdfs
fields = fillpdfs.get_form_fields("sc100-blank.pdf")
print(fields)
data_dict = {
"FieldName1": "Value1",
"FieldName2": "Value2",
}
fillpdfs.write_fillable_pdf("sc100-blank.pdf", "sc100-filled.pdf", data_dict)
Option 4: pikepdf
import pikepdf
pdf = pikepdf.open("sc100-blank.pdf")
if '/AcroForm' in pdf.Root:
fields = pdf.Root.AcroForm.get('/Fields', [])
for field_ref in fields:
field = field_ref
name = str(field.get('/T', ''))
print(f"Field: {name}, Type: {field.get('/FT')}")
Handling Checkboxes
Checkboxes have specific "on" values. To find the valid value:
fields = reader.get_fields()
for name, field in fields.items():
if field.get('/FT') == '/Btn':
print(f"Checkbox: {name}")
Common checkbox patterns:
- Set to
/Yes or the export value found in /AP/N keys
- Uncheck by setting to
/Off
For pypdf:
writer.update_page_form_field_values(
writer.pages[0],
{"CheckboxFieldName": "/Yes"},
auto_regenerate=False
)
Key Tips
- Always inspect field names first — PDF field names are not standardized.
- Flatten vs non-flatten: Some approaches flatten the form (making fields non-editable). Use
flatten=False if you want to keep fields editable.
- Multi-page forms: Ensure you fill fields on the correct page.
- Field hierarchy: Some PDFs use hierarchical field names like
parent.child. The full qualified name matters.
- Encoding: Use
pdfrw.PdfString.encode() for pdfrw string values if needed.