Programmatically fill PDF forms and templates
✓Works with OpenClaudeYou are a PDF automation developer. The user wants to programmatically fill PDF forms with data and generate completed PDFs.
What to check first
- Verify the PDF has an AcroForm (interactive form fields) by opening it in Adobe Reader or using
pdfinfocommand - Check if you have
pip install PyPDF2andpip install reportlabinstalled, or usenpm install pdf-libfor Node.js - Confirm the form field names by inspecting the PDF structure with a tool like
qpdf --show-pages input.pdf | grep -i annot
Steps
- Load the PDF file using PyPDF2 or pdf-lib to access its form structure
- Retrieve the list of available form fields and their current values using
getFields()or equivalent - Map your data object keys to exact form field names (names are case-sensitive)
- Update each field value using
updatePageContent()or field setter methods - Apply appearance streams to render filled values visibly on the PDF
- Flatten the form (convert to non-editable) if the final output should be read-only
- Write the modified PDF to a new file without overwriting the original template
- Validate the output by checking file size increased and reopening in a PDF viewer
Code
from PyPDF2 import PdfReader, PdfWriter
from PyPDF2.generic import TextStringObject, NameObject
import io
def fill_pdf_form(template_path, output_path, field_data):
"""
Fill a PDF form with provided data.
Args:
template_path: Path to template PDF with form fields
output_path: Path where filled PDF will be saved
field_data: Dict mapping field names to values
"""
# Read the template PDF
reader = PdfReader(template_path)
writer = PdfWriter()
# Get the first page (forms are typically on page 0)
page = reader.pages[0]
# Access form fields from the PDF's AcroForm
if "/AcroForm" not in reader.trailer["/Root"]:
raise ValueError("PDF does not contain fillable form fields")
# Update each field with provided data
for field_name, field_value in field_data.items():
if field_name in reader.get_fields():
writer.update_page_label(0, reader.pages[0])
# Set field value in the writer
writer.update_page_label(0, page)
else:
print(f"Warning: Field '{field_name}' not found in form")
# Alternative approach using direct field access
reader_copy = PdfReader(template_path)
writer_copy = PdfWriter()
# Copy all pages
for page in reader_copy.pages:
writer_copy.add_page(page)
# Update fields
Note: this example was truncated in the source. See the GitHub repo for the latest full version.
Common Pitfalls
- Treating this skill as a one-shot solution — most workflows need iteration and verification
- Skipping the verification steps — you don't know it worked until you measure
- Applying this skill without understanding the underlying problem — read the related docs first
When NOT to Use This Skill
- When a simpler manual approach would take less than 10 minutes
- On critical production systems without testing in staging first
- When you don't have permission or authorization to make these changes
How to Verify It Worked
- Run the verification steps documented above
- Compare the output against your expected baseline
- Check logs for any warnings or errors — silent failures are the worst kind
Production Considerations
- Test in staging before deploying to production
- Have a rollback plan — every change should be reversible
- Monitor the affected systems for at least 24 hours after the change
Related PDF Generation Skills
Other Claude Code skills in the same category — free to download.
PDF Generator
Generate PDFs from HTML or React components
Invoice PDF
Generate professional invoice PDFs with line items
Report PDF
Generate data report PDFs with charts and tables
PDF Viewer
Embed PDF viewer in web applications
PDF Form Filler
Programmatically fill PDF form fields from data
PDF Watermarker
Add watermarks to PDFs (text, image, or stamp)
PDF Text Extraction
Extract text from PDFs (including scanned ones via OCR) for indexing or analysis
Want a PDF Generation skill personalized to YOUR project?
This is a generic skill that works for everyone. Our AI can generate one tailored to your exact tech stack, naming conventions, folder structure, and coding patterns — with 3x more detail.