Python wrappers for pdfcpu to extract and fill PDF forms
Project description
privacyforms-pdf
Python wrappers for pdfcpu to extract and fill PDF forms.
Features
- Extract form data from PDF files using pdfcpu
- Programmatic API via
PDFFormExtractorclass - Command-line interface with multiple commands
- Full type hints and comprehensive test coverage
- Support for all form field types (text, date, checkbox, radio button groups, etc.)
Requirements
- Python 3.14+
- pdfcpu must be installed on your system
Installation
# Clone the repository
git clone <repo-url>
cd privacyforms-pdf
# Install with uv
uv sync
Quick Start
Check if pdfcpu is installed
pdf-forms check
Command Line Usage
# Check if a PDF contains a form
pdf-forms info form.pdf
# List all form fields
pdf-forms list-fields form.pdf
# Get a specific field value
pdf-forms get-value form.pdf "Field Name"
# Extract form data to JSON
pdf-forms extract form.pdf -o output.json
# Extract form data to stdout
pdf-forms extract form.pdf
# Fill a form from JSON (validates before filling)
pdf-forms fill-form form.pdf data.json -o filled.pdf
# Fill a form without validation
pdf-forms fill-form form.pdf data.json -o filled.pdf --no-validate
# Fill a form in-place (modifies original)
pdf-forms fill-form form.pdf data.json
# Fill with strict mode (requires all form fields)
pdf-forms fill-form form.pdf data.json -o filled.pdf --strict
JSON Format
The fill-form command accepts a simple key:value JSON format where keys are field names and values are the values to fill:
{
"Candidate Name": "John Smith",
"Position": "Software Engineer",
"Start date": "2025-06-01",
"Full time": true,
"Diploma or GED": "Yes"
}
Python API
from privacyforms_pdf import PDFFormExtractor
# Initialize the extractor
extractor = PDFFormExtractor()
# Extract form data
form_data = extractor.extract("form.pdf")
# Access form information
print(f"PDF Version: {form_data.pdf_version}")
print(f"Has Form: {form_data.has_form}")
print(f"Total Fields: {len(form_data.fields)}")
# Iterate over fields
for field in form_data.fields:
print(f"{field.name}: {field.value}")
# Get specific field value
value = extractor.get_field_value("form.pdf", "Field Name")
# Check if PDF has a form
has_form = extractor.has_form("form.pdf")
# Export to JSON file
extractor.extract_to_json("form.pdf", "output.json")
# Fill a form using simple key:value format
form_data = {
"Candidate Name": "John Smith",
"Position": "Software Engineer",
"Full time": True,
"Start date": "2025-06-01"
}
extractor.fill_form("form.pdf", form_data, "filled.pdf")
# Or fill from a JSON file
extractor.fill_form_from_json("form.pdf", "data.json", "filled.pdf")
# Validate data before filling (returns list of errors)
errors = extractor.validate_form_data("form.pdf", form_data)
if errors:
print("Validation errors:", errors)
API Reference
PDFFormExtractor
The main class for extracting PDF form data.
Constructor
extractor = PDFFormExtractor(pdfcpu_path: str | None = None)
pdfcpu_path: Optional path to the pdfcpu executable. If not provided, searches in system PATH.
Methods
check_pdfcpu() -> bool: Check if pdfcpu is available and working.get_pdfcpu_version() -> str: Get the installed pdfcpu version.has_form(pdf_path: str | Path) -> bool: Check if a PDF contains a form.extract(pdf_path: str | Path) -> PDFFormData: Extract form data from a PDF.extract_to_json(pdf_path: str | Path, output_path: str | Path) -> None: Export form data to a JSON file.list_fields(pdf_path: str | Path) -> list[FormField]: List all form fields in a PDF.get_field_value(pdf_path: str | Path, field_name: str) -> str | bool | None: Get the value of a specific form field.get_field_by_id(pdf_path: str | Path, field_id: str) -> FormField | None: Get a form field by its ID.get_field_by_name(pdf_path: str | Path, field_name: str) -> FormField | None: Get a form field by its name.validate_form_data(pdf_path: str | Path, form_data: dict, *, strict: bool = False, allow_extra_fields: bool = False) -> list[str]: Validate form data (simple key:value format).fill_form(pdf_path: str | Path, form_data: dict, output_path: str | Path | None = None, *, validate: bool = True) -> Path: Fill a PDF form with data.fill_form_from_json(pdf_path: str | Path, json_path: str | Path, output_path: str | Path | None = None, *, validate: bool = True) -> Path: Fill a PDF form with data from a JSON file.
Data Classes
PDFFormData
Represents extracted PDF form data.
source: Path: Path to the source PDF file.pdf_version: str: Version of the PDF.has_form: bool: Whether the PDF contains a form.fields: list[FormField]: List of form fields.raw_data: dict[str, Any]: The raw JSON data from pdfcpu.
FormField
Represents a single form field.
field_type: str: The type of the form field (e.g., 'textfield', 'checkbox').pages: list[int]: List of pages where this field appears.id: str: The unique identifier of the field.name: str: The name of the field.value: str | bool: The current value of the field.locked: bool: Whether the field is locked.
Exceptions
PDFCPUError: Base exception for pdfcpu related errors.PDFCPUNotFoundError: Raised when pdfcpu is not found on the system.PDFCPUExecutionError: Raised when pdfcpu execution fails.PDFFormNotFoundError: Raised when the PDF does not contain any forms.FormValidationError: Raised when form data validation fails.
Development
Running Tests
# Run all tests
uv run pytest
# Run with coverage
uv run pytest --cov
# Run linting
uv run ruff check .
# Run type checking
uv run pyright
Project Structure
privacyforms-pdf/
├── privacyforms_pdf/ # Main package
│ ├── __init__.py # Package exports
│ ├── extractor.py # PDFFormExtractor implementation
│ └── cli.py # Command-line interface
├── tests/ # Test suite
│ ├── test_extractor.py # Tests for extractor
│ └── test_cli.py # Tests for CLI
├── pyproject.toml # Project configuration
└── README.md # This file
License
Copyright 2025 Andreas Jung (info@zopyx.com)
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file privacyforms_pdf-0.1.0.tar.gz.
File metadata
- Download URL: privacyforms_pdf-0.1.0.tar.gz
- Upload date:
- Size: 2.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b49e963e11923912f60925c3d2822de0b473660b943f1f4aa73ec26bab53f6c
|
|
| MD5 |
3d88cf433d3992bf001a907b45ba3ca4
|
|
| BLAKE2b-256 |
91ee4c93e5e5fd76738f4b5c113f16392d48824f78a1341ab5d5b9fd5b4c04bd
|
File details
Details for the file privacyforms_pdf-0.1.0-py3-none-any.whl.
File metadata
- Download URL: privacyforms_pdf-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f3c804cac5bd203308dd0c31c12a1a52bfc7933725d23f56562b4bdab241a17b
|
|
| MD5 |
be43e218742a02e7b75865932a563c14
|
|
| BLAKE2b-256 |
1adfad7c99ea7ca3cd64d9e4d44e02b3d7c1589ee5022af9cc652e8c5dc3aa00
|