Skip to main content

Python wrappers for pdfcpu to extract and fill PDF forms

Project description

privacyforms-pdf

CI Python 3.14+ Code style: ruff uv

Python wrappers for pdfcpu to extract and fill PDF forms.

Features

  • Extract form data from PDF files using pdfcpu
  • Programmatic API via PDFFormExtractor class
  • 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

privacyforms_pdf-0.1.2.tar.gz (2.7 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

privacyforms_pdf-0.1.2-py3-none-any.whl (11.5 kB view details)

Uploaded Python 3

File details

Details for the file privacyforms_pdf-0.1.2.tar.gz.

File metadata

  • Download URL: privacyforms_pdf-0.1.2.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

Hashes for privacyforms_pdf-0.1.2.tar.gz
Algorithm Hash digest
SHA256 80cb227ded5f42180851f224e54aca29775b4209a00fd7bcef83ce4b33f4a0f1
MD5 9af3511af2511cd684fb7d8e78f72c2a
BLAKE2b-256 65a9c2426d6d2bcd1d38ee1b4b9448740ad168fb92457dd5a6ae3650547e2c49

See more details on using hashes here.

File details

Details for the file privacyforms_pdf-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for privacyforms_pdf-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 7870b02c5ecb7d10b277a27ced439f3b5a7e47acbbd6e3d9741b59b0fa98491a
MD5 10527a7836a76147452c63564ffe0cf7
BLAKE2b-256 8f103b3f57b6467dbe132f3172469be27ce0395aa8c8605a4dd067c73fcbe222

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page