Introduction
What pdftract Does
pdftract is a PDF text extraction library that gets the hard parts right. Unlike naive PDF parsers that dump text in the order it appears in the PDF file (which is rarely the correct reading order), pdftract understands document layout and recovers the logical structure that humans perceive when reading a page.
Core Features
Correct reading order — Layout regions are segmented and sequenced before text is emitted, handling multi-column pages, sidebars, footnotes, and mixed-layout documents without relying on PDF operator order. pdftract groups text into semantic blocks (headings, paragraphs, lists, tables) and outputs them in the order a human would read.
Font encoding recovery — When ToUnicode CMaps are absent, wrong, or incomplete (a common problem in PDFs generated by legacy tools), pdftract works through a layered recovery pipeline: glyph name lookup via the Adobe Glyph List, font fingerprinting against known metrics and embedded checksums, and glyph outline shape matching. This means you get readable Unicode text even from broken PDFs.
Structure tree extraction — PDF/UA and PDF/A documents encode their logical structure (headings, paragraphs, lists, tables, reading order) in a StructTree. pdftract reads this directly when present, producing accurate semantic output at no extra cost. Tagged PDFs yield near-perfect extraction.
Per-page hybrid routing — Each page is independently classified and routed to the appropriate pipeline: vector text extraction (for pages with embedded fonts), full OCR (for scanned pages), or assisted OCR where vector hints improve raster accuracy. This hybrid approach optimizes for both accuracy and speed.
Structured output with provenance — The primary output is JSON carrying per-span bounding boxes, font name, size, and confidence score alongside the extracted text, not a flat string dump. You get rich metadata that enables downstream processing: layout analysis, font-aware styling, highlight extraction, and confidence-based filtering.
What You Can Extract
- Text — Plain text or structured JSON with per-character provenance
- Layout — Bounding boxes for blocks, lines, and spans
- Metadata — Title, author, creation date, page count, PDF version
- Structure — Headings, paragraphs, lists, tables (when present in the PDF)
- Annotations — Comments, highlights, form fields (Phase 7)
What pdftract Does Not Do
pdftract is deliberately scoped. The following features are not in scope for v1.0.0:
| Non-goal | Alternative |
|---|---|
| PDF authoring or writing | lopdf, pdfium-render, printpdf |
| Full PDF rendering / printing | PDFium, MuPDF, Poppler |
| Cryptographic signature validation | openssl smime, dedicated PKI libraries |
| Translation of extracted text | LibreTranslate, DeepL, Argos |
| Summarization | LLM tools via the MCP server integration |
| OCR engine training | Tesseract’s tesstrain tooling |
| Filling out PDF forms | Form-filling tools with authoring support |
| Watermark removal | Detected and excluded from output, not removed from PDF |
| Password cracking | pdfcrack, john |
For the full rationale and scope-lock doctrine, see the Non-Goals section in the project plan.
Supported PDF Features
pdftract supports PDF 1.4 through PDF 2.0, with varying levels of feature coverage:
- Text extraction — Full support for Type 1, TrueType, OpenType, and CID-keyed fonts
- Compression — All standard filters (FlateDecode, ASCIIHex, ASCII85, RunLength, CCITT, DCT)
- Encryption — RC4 40-bit, RC4 128-bit, AES-128, AES-256 (password required)
- Structure trees — PDF/UA logical structure reading
- Forms — AcroForm and XFA field extraction (read-only)
- Signatures — Signature metadata extraction (validation not performed)
- Attachments — File attachment extraction
- Articles — Thread extraction for logical reading flows
See the Advanced Topics section for deep dives into specific features.
Installation
pdftract is distributed as a native binary, a Python package, and a Docker image. Choose the installation method that matches your workflow.
Install via Cargo
cargo install pdftract
This installs the pdftract binary in ~/.cargo/bin/. Make sure ~/.cargo/bin is in your PATH.
Pre-built Binaries
Pre-built binaries are available from GitHub Releases. Download the archive for your platform, extract, and place the binary in your PATH.
Cargo Binstall
For faster installation without compiling from source:
cargo binstall pdftract
This downloads a pre-built binary from the GitHub Release instead of compiling locally.
Install via pip
pdftract is distributed on PyPI as a native Python extension with PyO3 bindings.
pip install pdftract
The Python package includes the same extraction engine as the CLI, accessible via a Python API. See Python SDK for usage.
Platform Wheels
Wheels are available for:
- Linux
x86_64(manylinux2014, musllinux) - macOS
x86_64andarm64 - Windows
x86_64
If no wheel is available for your platform, pip will fall back to building from source (requires Rust toolchain).
Install via Homebrew
Note: Homebrew formula is deferred to v1.1+. In the meantime, use cargo install pdftract or the Docker image.
See the Non-Goals section in the project plan for the rationale.
Install via Docker
Docker images are available on GitHub Container Registry:
docker pull ghcr.io/jedarden/pdftract:latest
docker run --rm -v $(pwd):/work ghcr.io/jedarden/pdftract:latest extract /work/document.pdf
Image Variants
| Tag | Description |
|---|---|
latest | Default features (vector extraction, basic OCR) |
ocr | Includes Tesseract for full OCR support |
full | All features including PDFium for rasterization |
Multi-arch manifests support amd64 and arm64 platforms.
Platform Support
Supported Platforms
| Platform | CI Status | Notes |
|---|---|---|
Linux x86_64 (glibc) | Fully CI-tested | Primary development platform |
Linux x86_64 (musl) | Fully CI-tested | Alpine-compatible |
Linux arm64 (glibc) | Fully CI-tested | ARM64 servers (e.g., Graviton) |
Linux arm64 (musl) | Fully CI-tested | Alpine ARM64 |
macOS x86_64 | Build-tested | See caveat below |
macOS arm64 | Build-tested | See caveat below |
Windows x86_64 | Build-tested | See caveat below |
Cross-Platform Test Limitation (KU-12)
Linux is fully CI-tested; macOS and Windows are build-tested and manually smoke-tested per release.
Per project architecture decision ADR-009, the CI pipeline runs on Linux-only infrastructure (iad-ci). macOS and Windows binaries are built via cross-compilation but are never executed in automated CI. This is acknowledged as Known Unknown KU-12 with the following mitigation:
- A manual smoke-test runbook is executed by the release lead before each milestone against at least one physical macOS machine and one Windows VM
- User bug reports for platform-specific issues are acknowledged within 48 hours and addressed in the next patch release
- No claim of “tested on macOS/Windows” appears in CI status badges
If you encounter a platform-specific issue on macOS or Windows, please file a bug report. The project is committed to fixing platform bugs promptly.
Minimum Rust Version
If building from source, pdftract requires Rust 1.78 or later. The MSRV is pinned in Cargo.toml and tested on every PR.
Verifying Installation
Run the following command to verify your installation:
pdftract --version
You should see output like:
pdftract 0.1.0
For the Python package:
python -c "import pdftract; print(pdftract.__version__)"
Environment Health Check
After installation, verify your environment is properly configured for pdftract:
pdftract doctor
This validates that all OS-level dependencies (Tesseract, leptonica, libtiff, etc.) are installed and correctly configured. See the Operations Runbook for detailed troubleshooting of each check.
Next Steps
Once installed, proceed to the Quickstart for a five-minute walkthrough of pdftract’s core features.
Quickstart
This five-minute walkthrough covers the core pdftract workflow: extract text from a PDF, inspect the structured JSON output, and try profile-based extraction.
Five-Minute Walkthrough
Prerequisites
- pdftract installed (see Installation)
- A PDF file to extract (any PDF will do)
If you don’t have a PDF handy, you can use the sample fixtures from the pdftract repository:
git clone https://github.com/jedarden/pdftract.git
cd pdftract
Verify Your Environment
Before extracting, verify your environment is properly configured:
pdftract doctor
Expected output:
Check Status Detail
─────────────────────────────────────────────
pdftract binary OK 0.1.0 (git: abc1234)
tesseract install OK v5.3.0
...
If any check shows FAIL, see the Operations Runbook for resolution steps.
Extract Your First PDF
The simplest extraction outputs plain text to stdout:
pdftract extract path/to/document.pdf
For structured JSON output (default):
pdftract extract path/to/document.pdf --output result.json
Or view JSON directly in your terminal (pipe to jq for pretty-printing):
pdftract extract path/to/document.pdf | jq .
Inspect the Output
The JSON output contains:
pages— Array of page objects, each withblocksandspansblocks— Semantic elements (headings, paragraphs, lists) with reading orderspans— Text fragments with bounding boxes, font metadata, and confidence scoresmetadata— Document title, author, page count, PDF version
Example:
{
"pages": [
{
"page": 1,
"width": 612,
"height": 792,
"blocks": [
{
"kind": "heading",
"text": "Introduction",
"bbox": [72, 680, 400, 700],
"level": 1
},
{
"kind": "paragraph",
"text": "This is the first paragraph...",
"bbox": [72, 640, 540, 670]
}
],
"spans": [
{
"text": "Introduction",
"bbox": [72, 680, 400, 700],
"font": "Times-Bold",
"size": 14.0,
"confidence": 0.99
}
]
}
],
"metadata": {
"title": "Sample Document",
"author": "John Doe",
"page_count": 1,
"pdf_version": "1.4"
}
}
Try Auto-Profile Mode
pdftract includes built-in profiles for common document types (invoices, receipts, contracts, etc.). Use --auto to automatically detect the profile:
pdftract extract invoice.pdf --auto
The auto-detected profile is logged to stderr:
[INFO] Detected profile: invoice
Profiles optimize extraction for specific document layouts:
- invoice — Extract line items, totals, vendor info
- receipt — Extract merchant, date, line items, tax, total
- contract — Extract parties, effective date, clauses
- bank_statement — Extract account info, statement period, transactions
See Profiles for the full list.
Batch Processing
To extract multiple PDFs in a folder:
pdftract extract *.pdf --output-dir results/
Each PDF produces a corresponding JSON file in results/:
results/
invoice1.pdf.json
invoice2.pdf.json
receipt.pdf.json
For recursive folder processing, use the grep command to search across all PDFs:
pdftract grep "search term" /path/to/folder
This outputs matching filenames and page numbers:
invoice.pdf:3: "search term" found on page 3
receipt.pdf:1: "search term" found on page 1
Common Options
| Option | Description |
|---|---|
--output FILE | Write output to file instead of stdout |
--text | Output plain text instead of JSON |
--output-dir DIR | Directory for batch output (with * glob) |
--auto | Auto-detect and apply document profile |
--profile NAME | Use specific profile (skip auto-detection) |
--password PASS | Password for encrypted PDFs |
--pages N-M | Extract specific page range |
--ocr | Force OCR mode for all pages |
See CLI Reference for complete command documentation.
What’s Next?
- Explore the CLI Reference for advanced options
- Read JSON Schema Reference for output format details
- Check Profiles for document-type-specific extraction
- Try the Python SDK for programmatic access
Troubleshooting
Extraction fails with “unsupported encryption”
The PDF is encrypted with a password. Use --password:
pdftract extract encrypted.pdf --password yourpassword
Output has wrong reading order
Some PDFs have malformed internal structure. Try --auto to enable profile-based layout recovery, or use --ocr to force OCR-based extraction.
Poor accuracy on scanned documents
Ensure the OCR features are enabled. The Docker :ocr and :full images include Tesseract. If building from source, enable the ocr feature:
cargo install pdftract --features ocr
For more help, see Troubleshooting.
CLI Reference
This page is auto-generated from the clap command tree. Run
cargo run --bin gen-cli-referenceto regenerate.
Command-Line Help for pdftract
This document contains the help content for the pdftract command-line program.
Command Overview:
pdftract↴pdftract list-diagnostics↴pdftract explain-diagnostic↴pdftract compare↴pdftract conformance↴pdftract sdk↴pdftract sdk codegen↴pdftract sdk validate↴pdftract extract↴pdftract classify↴pdftract inspect↴pdftract verify-receipt↴pdftract hash↴pdftract cache↴pdftract cache stats↴pdftract cache clear↴pdftract cache purge↴pdftract profiles↴pdftract profiles list↴pdftract profiles show↴pdftract profiles export↴pdftract profiles install↴pdftract profiles validate↴pdftract serve↴pdftract mcp↴pdftract validate↴pdftract migrate-schema↴pdftract doctor↴
pdftract
pdftract CLI - PDF extraction and conformance testing
Usage: pdftract <COMMAND>
Subcommands:
list-diagnostics— List all diagnostic codes with their metadataexplain-diagnostic— Explain a specific diagnostic code in detailcompare— Compare actual results against expected values with tolerances (for conformance testing)conformance— Run SDK conformance test suitesdk— SDK code generation commandsextract— Extract text and structure from a PDF fileclassify— Classify document type (runs metadata + signal extraction, not full text extraction)inspect— Inspect a PDF file in a local web browser with debugging overlaysverify-receipt— Verify a receipt against a PDF filehash— Compute the PDF structural fingerprint (hash)cache— Manage the extraction cacheprofiles— Manage document type profilesserve— Start the HTTP server for extractionmcp— Start the MCP (Model Context Protocol) servervalidate— Validate a JSON file against the pdftract schemamigrate-schema— Migrate JSON output between schema versionsdoctor— Check environment health and dependencies
pdftract list-diagnostics
List all diagnostic codes with their metadata
Usage: pdftract list-diagnostics
pdftract explain-diagnostic
Explain a specific diagnostic code in detail
Usage: pdftract explain-diagnostic <CODE>
Arguments:
<CODE>— Diagnostic code to explain (e.g., STRUCT_MISSING_KEY, STREAM_BOMB)
pdftract compare
Compare actual results against expected values with tolerances (for conformance testing)
Usage: pdftract compare [OPTIONS] <ACTUAL> <EXPECTED>
Arguments:
<ACTUAL>— Path to the actual results JSON<EXPECTED>— Path to the expected results JSON
Options:
-
-t,--tolerances <TOLERANCES>— Path to the tolerances JSON (optional) -
-f,--format <FORMAT>— Output format (text, json)Default value:
text
pdftract conformance
Run SDK conformance test suite
Usage: pdftract conformance [OPTIONS]
Options:
-
-s,--suite <SUITE>— Path to the conformance suite JSONDefault value:
tests/sdk-conformance/cases.json -
-k,--sdk <SDK>— SDK nameDefault value:
pdftract -
-v,--version <VERSION>— SDK versionDefault value:
0.1.0 -
-o,--output <OUTPUT>— Output report pathDefault value:
conformance-report.json
pdftract sdk
SDK code generation commands
Usage: pdftract sdk <COMMAND>
Subcommands:
codegen— Generate SDK skeleton from templatesvalidate— Validate existing SDK against current generator output
pdftract sdk codegen
Generate SDK skeleton from templates
Usage: pdftract sdk codegen --lang <LANG> --out <OUT>
Options:
-
-l,--lang <LANG>— Target languagePossible values:
python,rust,node,go,java,dotnet,ruby,php,swift -
-o,--out <OUT>— Output directory -
-v,--version <VERSION>— Version string (defaults to current pdftract version)Default value:
0.1.0
pdftract sdk validate
Validate existing SDK against current generator output
Usage: pdftract sdk validate --lang <LANG> --sdk-dir <SDK_DIR>
Options:
-
-l,--lang <LANG>— Target languagePossible values:
python,rust,node,go,java,dotnet,ruby,php,swift -
-s,--sdk-dir <SDK_DIR>— Path to existing SDK directory
pdftract extract
Extract text and structure from a PDF file
Usage: pdftract extract [OPTIONS] <INPUT>
Arguments:
<INPUT>— Path to the PDF file (use ‘-’ for stdin)
Options:
-
--password-stdin— Read password from stdin (one line, terminated by newline) -
--password <PASSWORD>— PDF password (INSECURE: rejected unless PDFTRACT_INSECURE_CLI_PASSWORD=1) -
--header <HEADER:VALUE>— Custom HTTP headers for remote sources (repeatable; format: HEADER:VALUE) -
--pages <RANGE>— Page range to extract (1-based, comma-separated: 1-5,7,12-) -
--json <PATH>— Output JSON to PATH (use ‘-’ for stdout) -
--md <PATH>— Output Markdown to PATH (use ‘-’ for stdout) -
--text <PATH>— Output plain text to PATH (use ‘-’ for stdout) -
--ndjson— Output NDJSON to stdout (mutually exclusive with other formats) -
--format <FORMATS>— Output formats (comma-separated: json,markdown,text,ndjson) -
-o,--output <BASE>— Base path for auto-named outputs (used with –format) -
--receipts <MODE>— Receipt mode: off (default), lite, or svgDefault value:
offPossible values:
off,lite,svg -
--ocr— Enable OCR for scanned pages (requires ‘ocr’ feature) -
--ocr-language <OCR_LANGUAGE>— OCR language codes (comma-separated, e.g., ‘eng,fra,deu’) -
--cache-dir <DIR>— Enable cache at this directory (creates if absent) -
--cache-size <SIZE>— Set cache size limit (default 1 GiB; accepts KiB, MiB, GiB suffixes)Default value:
1 GiB -
--no-cache— Disable cache for this extraction (even if –cache-dir is set) -
--md-anchors— Emit HTML comment anchors before each block in Markdown output -
--md-no-page-breaks— Suppress page-break horizontal rules between pages -
--auto— Auto-detect document type and apply appropriate profile -
--profile <NAME|PATH>— Force-apply a specific profile (by name or YAML file path) -
--include-headers— Include header blocks in output -
--include-footers— Include footer blocks in output -
--include-headers-footers— Include both header and footer blocks in output -
--include-invisible-text— Include invisible text spans in output (rendering_mode == 3) -
--include-hidden-layers— Include hidden-layer text spans in output (OCG-controlled) -
--include-watermarks— Include watermark blocks in output (no-op until Phase 7)
pdftract classify
Classify document type (runs metadata + signal extraction, not full text extraction)
Usage: pdftract classify [OPTIONS] <INPUT>
Arguments:
<INPUT>— Path to the PDF file
Options:
-
--password-stdin— Read password from stdin (one line, terminated by newline) -
--password <PASSWORD>— PDF password (INSECURE: rejected unless PDFTRACT_INSECURE_CLI_PASSWORD=1) -
--profiles <DIR>— Directory containing custom profile YAML files -
--pretty— Pretty-print JSON output -
--top-k <TOP_K>— Number of top reasons to include (default: all)Default value:
0 -
--exit-on-unknown— Exit with code 1 if document type is unknown
pdftract inspect
Inspect a PDF file in a local web browser with debugging overlays
Usage: pdftract inspect [OPTIONS] <FILE>
Arguments:
<FILE>— Path to the PDF file to inspect
Options:
-
-p,--port <PORT>— Port to bind the inspector server (default: 7676)Default value:
7676 -
-b,--bind <BIND>— Bind address for the inspector server (default: 127.0.0.1)Binding to a non-loopback address requires –auth-token for security.
Default value:
127.0.0.1 -
--auth-token <AUTH_TOKEN>— Authentication token for non-loopback bindsRequired when –bind is not a loopback address (127.0.0.1 or ::1).
-
--no-open— Suppress automatic browser launchUseful for CI environments or when you want to manually open the browser.
-
--compare <FILE>— Optional second PDF file for comparative debuggingWhen provided, the inspector shows side-by-side comparison.
-
--audit-log <FILE>— Write per-request audit log to FILE (NDJSON; use “-” for stdout, “/dev/stderr” for stderr)Rotation: pdftract does NOT rotate logs; configure logrotate on the audit-log file. When FILE is “-”, rotation is the responsibility of the supervisor (e.g., journald).
pdftract verify-receipt
Verify a receipt against a PDF file
Usage: pdftract verify-receipt [OPTIONS] <FILE.pdf> <RECEIPT.json>
Arguments:
<FILE.pdf>— Path to the PDF file to verify against<RECEIPT.json>— Path to the receipt JSON file, or “-” for stdin
Options:
--stdin— Read receipt from stdin (alternative to “-”)--inline <INLINE>— Receipt JSON as inline string (alternative to file path)--json— Output machine-readable JSON result--quiet— Suppress human-readable output (exit code only)--password <PASSWORD>— PDF password (INSECURE: rejected unless PDFTRACT_INSECURE_CLI_PASSWORD=1)--password-stdin— Read password from stdin (one line, terminated by newline)
pdftract hash
Compute the PDF structural fingerprint (hash)
Usage: pdftract hash [OPTIONS] <INPUT>
Arguments:
<INPUT>— Path to the PDF file or URL
Options:
--password <PASSWORD>— PDF password (INSECURE: rejected unless PDFTRACT_INSECURE_CLI_PASSWORD=1)--header <HEADER:VALUE>— Custom HTTP headers for remote sources (repeatable; format: HEADER:VALUE)
pdftract cache
Manage the extraction cache
Usage: pdftract cache <COMMAND>
Subcommands:
stats— Show cache statisticsclear— Clear all cache entries (preserves index.json and sentinel)purge— Purge old cache entries
pdftract cache stats
Show cache statistics
Usage: pdftract cache stats [OPTIONS] <DIR>
Arguments:
<DIR>— Path to the cache directory
Options:
--json— Output in JSON format
pdftract cache clear
Clear all cache entries (preserves index.json and sentinel)
Usage: pdftract cache clear [OPTIONS] <DIR>
Arguments:
<DIR>— Path to the cache directory
Options:
-y,--yes— Skip confirmation prompt
pdftract cache purge
Purge old cache entries
Usage: pdftract cache purge [OPTIONS] <DIR>
Arguments:
<DIR>— Path to the cache directory
Options:
--older-than <DURATION>— Delete entries older than this duration (e.g., “30d”, “7d”, “1h”)--version <CONSTRAINT>— Delete entries matching this version constraint (e.g., “<1.0.0”)
pdftract profiles
Manage document type profiles
Usage: pdftract profiles <COMMAND>
Subcommands:
list— List all available profilesshow— Show a profile’s YAML contentexport— Export a built-in profile to stdoutinstall— Install a profile to the user config directoryvalidate— Validate a profile file
pdftract profiles list
List all available profiles
Usage: pdftract profiles list
pdftract profiles show
Show a profile’s YAML content
Usage: pdftract profiles show <NAME_OR_PATH>
Arguments:
<NAME_OR_PATH>— Profile name or path to YAML file
pdftract profiles export
Export a built-in profile to stdout
Usage: pdftract profiles export <NAME>
Arguments:
<NAME>— Name of the built-in profile to export
pdftract profiles install
Install a profile to the user config directory
Usage: pdftract profiles install <PATH>
Arguments:
<PATH>— Path to the profile YAML file to install
pdftract profiles validate
Validate a profile file
Usage: pdftract profiles validate <PATH>
Arguments:
<PATH>— Path to the profile YAML file to validate
pdftract serve
Start the HTTP server for extraction
Security Model
pdftract serve has no built-in authentication. Deploy behind a reverse proxy (nginx, Traefik, Caddy) for production use. The server accepts PDFs via multipart upload only; no endpoint accepts file paths from server filesystem.
Concurrency
The server uses a two-level concurrency architecture:
- tokio: Per-request concurrency via the async executor. Each HTTP request is handled asynchronously on tokio’s multi-threaded runtime. - rayon: Per-document parallelism within each extraction. PDF pages are processed in parallel using rayon’s work-stealing thread pool.
The bridge between async (tokio) and sync (rayon) is tokio::task::spawn_blocking. Each POST handler wraps the synchronous extraction call in spawn_blocking, which runs the work on tokio’s blocking thread pool (separate from the async reactor).
This design ensures: - The async reactor is never blocked by extraction work - Multiple PDFs can be extracted concurrently (one per request) - Within each PDF, pages are processed in parallel (rayon) - Thread pools are sized appropriately (tokio: 512 blocking threads; rayon: num_cpus)
Endpoints
POST /extract- Extract PDF and return JSON with metadata -POST /extract/text- Extract PDF and return plain text -POST /extract/stream- Extract PDF and return streaming NDJSON -GET /health- Health check (responds within 100ms even during concurrent extractions)
Cache
Cache is optional. When enabled, extracted results are stored on disk and reused for identical PDFs. Cache status is reported via the X-Pdftract-Cache response header.
Usage: pdftract serve [OPTIONS]
Options:
-
-b,--bind <BIND>— Bind address (e.g., “127.0.0.1:8080”, “[::1]:9000”, “0.0.0.0:3000”)Default value:
127.0.0.1:8080 -
--cache-dir <DIR>— Enable cache at this directory -
--cache-size <SIZE>— Set cache size limit (default 1 GiB; accepts KiB, MiB, GiB suffixes)Default value:
1 GiB -
--no-cache— Disable cache -
--max-upload-mb <MAX_UPLOAD_MB>— Maximum request body size in MB (default: 256, max: 4096)Default value:
256 -
--max-decompress-gb <GB>— Maximum decompression size in GB (default: 1, overrides per-request max_decompress_gb)Default value:
1 -
--audit-log <FILE>— Write per-request audit log to FILE (NDJSON; use “-” for stdout, “/dev/stderr” for stderr)Rotation: pdftract does NOT rotate logs; configure logrotate on the audit-log file. When FILE is “-”, rotation is the responsibility of the supervisor (e.g., journald).
-
--trust-forwarded-for— Trust X-Forwarded-For header for client IP detection (DANGER: enables IP spoofing if not behind a trusted proxy) -
--profile-dir <DIR>— Directory containing custom profile YAML files (repeatable) -
--profile-hot-reload— Enable hot-reload for profiles (re-read directory on every request)
pdftract mcp
Start the MCP (Model Context Protocol) server
Per ADR-006: stdio and HTTP transports are mutually exclusive because they have opposite stdout discipline (stdio: JSON-RPC sink; HTTP: log channel). Exactly one transport must be selected per invocation.
Usage: pdftract mcp [OPTIONS]
Options:
-
--stdio— Use stdio transport (for Claude Desktop, Claude Code, Continue, Cursor)This is the default transport mode if neither –stdio nor –bind is specified.
-
-b,--bind <ADDR>— Bind address for the MCP server (e.g., “127.0.0.1:8080”, “[::1]:9000”, “0.0.0.0:3000”)Enables HTTP+SSE transport mode. Mutually exclusive with –stdio.
-
--auth-token-file <AUTH_TOKEN_FILE>— Path to a file containing the bearer token (RECOMMENDED) -
--auth-token <AUTH_TOKEN>— Bearer token for authentication (INSECURE: rejected unless PDFTRACT_INSECURE_CLI_TOKEN=1) -
--max-upload-mb <MAX_UPLOAD_MB>— Maximum request body size in MB (default: 256)Default value:
256 -
--root <DIR>— Root directory for local filesystem access (enforces path-traversal protection)When set, all local-path tool arguments are resolved relative to DIR and any path that escapes DIR is rejected with JSON-RPC error code -32602. HTTPS URLs are not affected by this flag. Without –root, the server runs in trust-the-caller mode (no path-check applied).
-
--audit-log <FILE>— Write per-request audit log to FILE (NDJSON; use “-” for stdout, “/dev/stderr” for stderr)Rotation: pdftract does NOT rotate logs; configure logrotate on the audit-log file. When FILE is “-”, rotation is the responsibility of the supervisor (e.g., journald).
pdftract validate
Validate a JSON file against the pdftract schema
Usage: pdftract validate [OPTIONS] <FILE>
Arguments:
<FILE>— Path to the JSON file to validate (use ‘-’ for stdin)
Options:
-s,--schema <PATH>— Path to a custom schema file (default: bundled v1.0 schema)-q,--quiet— Quiet mode - suppress error output (only exit code matters)
pdftract migrate-schema
Migrate JSON output between schema versions
Usage: pdftract migrate-schema [OPTIONS] --from <FROM> --to <TO> [INPUT]
Arguments:
-
<INPUT>— Input JSON file (use ‘-’ for stdin)Default value:
-
Options:
-
--from <FROM>— Source schema version (e.g., “1.0”, “1.1”) -
--to <TO>— Target schema version (e.g., “1.0”, “1.1”) -
-o,--output <OUTPUT>— Output JSON file (use ‘-’ for stdout)Default value:
- -
-p,--pretty— Pretty-print output JSON
pdftract doctor
Check environment health and dependencies
Exit code policy: exits 0 if no checks FAIL (WARN does not affect exit code); exits 1 if any check FAILs; exits 2 on argument parse errors.
Usage: pdftract doctor [OPTIONS]
Options:
-
--features— Print compiled features and exit -
--json— Output results as JSON -
--no-color— Disable colored output -
--exit-on-fail— Explicit form of the default policy (exit 1 if any check FAILs).This flag is the default behavior and is provided for CI script readability. WARN does not affect exit code regardless of this flag.
-
--profile-dir <DIR>— Verify the profile search path includes DIR -
--cache-dir <DIR>— Verify DIR is writable and has sufficient space -
--lang <LANG>— Requested OCR languages (default: eng)
This document was generated automatically by
clap-markdown.
Hand-Curated Content
Note: Any content added after this marker will be preserved when the CLI reference is regenerated. This section is for additional context that doesn’t fit in the auto-generated sections.
Common Patterns
Basic Extraction
pdftract extract document.pdf
JSON Output
pdftract extract --json output.json document.pdf
Markdown with Anchors
pdftract extract --md-anchors --md output.md document.pdf
Exit Codes
0: Success1: General error (extraction failed, file not found, etc.)2: Usage error (invalid arguments, conflicting flags)3: Decryption error (wrong or missing password)
Global Options
Draft — This page is a placeholder for future content.
See the main pdftract repository for CLI usage details.
extract
Draft — This page is a placeholder for future content.
Extract text and structure from a PDF file.
serve
Draft — This page is a placeholder for future content.
Start an HTTP server for PDF extraction.
grep
Draft — This page is a placeholder for future content.
Search for text across multiple PDF files.
inspect
Draft — This page is a placeholder for future content.
Inspect PDF structure and metadata.
mcp
Draft — This page is a placeholder for future content.
Run pdftract as an MCP (Model Context Protocol) server.
JSON Schema Reference
Schema version: 1.0
Schema URL: https://pdftract.com/schema/v1.0/pdftract.schema.json
Source of truth:docs/schema/v1.0/pdftract.schema.json
This page provides a human-readable rendering of the pdftract output schema. The JSON Schema is the authoritative definition (per INV-11), validated in CI for all test fixtures.
Top-Level Structure
{
"fingerprint": "pdftract-v1:a7f3c8d9...",
"pages": [...],
"metadata": {...},
"signatures": [...],
"form_fields": [...]
}
| Field | Type | Required | Description |
|---|---|---|---|
fingerprint | string | Yes | Phase 1.7 fingerprint of the source PDF. Format: "pdftract-v1:" + hex(SHA-256). Used for receipt verification. |
pages | array | Yes | Extracted pages, each containing spans and blocks. |
metadata | object | Yes | ExtractionMetadata object with page count, diagnostics, receipts mode, etc. |
signatures | array | Yes | Digital signatures extracted from the document. Empty when no signature fields exist. |
form_fields | array | Yes | Interactive form fields from AcroForm/XFA. Empty when no form fields exist. |
Document Metadata
The metadata object contains extraction-level information:
{
"page_count": 10,
"span_count": 842,
"block_count": 156,
"error_count": 0,
"receipts_mode": "off",
"diagnostics": ["WARN: page 3: low coverage (54%) - possible scanned content"],
"cache_status": "hit",
"cache_age_seconds": 1240,
"reading_order_algorithm": "robust-topo"
}
| Field | Type | Description |
|---|---|---|
page_count | integer | Total number of pages in the document. |
span_count | integer | Number of spans extracted across all pages. |
block_count | integer | Number of blocks extracted across all pages. |
error_count | integer | Number of pages that failed to extract. |
receipts_mode | string | Receipts mode used: "off", "lite", or "svg". |
diagnostics | array | Diagnostic messages emitted during extraction (coverage warnings, etc.). |
cache_status | string/null | Cache status: "hit", "miss", or "skipped". |
cache_age_seconds | integer/null | Cache entry age in seconds (only present when cache_status == "hit"). |
reading_order_algorithm | string/null | Reading order algorithm used for this extraction. |
Page Result
Each page in the pages array contains:
{
"index": 0,
"spans": [...],
"blocks": [...],
"tables": [...],
"error": null
}
| Field | Type | Required | Description |
|---|---|---|---|
index | integer | Yes | Zero-based page index. This is the canonical identifier for programmatic use. |
spans | array | Yes | Extracted spans (text fragments with consistent styling). |
blocks | array | Yes | Extracted blocks (semantic units like paragraphs, headings). |
tables | array | Yes | Extracted tables with cell-level structure. Empty when no tables detected. |
error | string/null | Yes | Error message if extraction failed for this page. |
Span
A span is the smallest unit of extracted text, representing a contiguous run of text with consistent font and styling.
{
"text": "The quick brown fox",
"bbox": [72.0, 612.0, 245.5, 624.3],
"font": "Helvetica-Bold",
"size": 12.0,
"column": 0,
"confidence": 0.98,
"receipt": null
}
| Field | Type | Required | Description |
|---|---|---|---|
text | string | Yes | The extracted text content. |
bbox | array | Yes | Bounding box in PDF user-space points. Format: [x0, y0, x1, y1] where (x0, y0) is the bottom-left corner and (x1, y1) is the top-right corner. Units are 1/72 inch. |
font | string | Yes | Font name or identifier. |
size | number | Yes | Font size in points. |
column | integer/null | No | Column index (0-based) assigned by Phase 4.3 column detection. Null for spans outside any detected column. |
confidence | number/null | No | Confidence score (0.0 to 1.0). Present when OCR is used or extraction has uncertainty. |
receipt | object/null | No | Cryptographic receipt for verification. Present when --receipts=lite or --receipts=svg is enabled. |
Block
A block is a higher-level semantic unit composed of one or more spans.
{
"kind": "paragraph",
"text": "The quick brown fox jumps over the lazy dog.",
"bbox": [72.0, 600.0, 540.0, 650.0],
"level": null,
"table_index": null
}
| Field | Type | Required | Description |
|---|---|---|---|
kind | string | Yes | The block kind/type. Common values: "paragraph", "heading", "list", "table", "figure". |
text | string | Yes | The concatenated text content of all spans in the block. |
bbox | array | Yes | Bounding box in PDF user-space points. Same format as spans. |
level | integer/null | No | Heading level (1-6) for "heading" kind blocks. Null for other block types. |
table_index | integer/null | No | Table index for "table" kind blocks. Points to the corresponding entry in the page’s tables array. |
receipt | object/null | No | Cryptographic receipt for verification. Present when receipts are enabled. |
Block Kind Enum
| Value | Description |
|---|---|
paragraph | A paragraph block. |
heading | A heading block (with level field 1-6). |
list | A list item block. |
table | A table block (references tables array via table_index). |
figure | A figure or image block. |
code | A code block or monospace text. |
formula | A mathematical formula. |
header | A page header block. |
footer | A page footer block. |
watermark | A watermark block. |
caption | A caption for a figure or table. |
quote | A blockquote. |
Table
Tables provide detailed cell-level structure for table blocks.
{
"id": "table_0",
"page_index": 2,
"bbox": [72.0, 400.0, 540.0, 550.0],
"detection_method": "line_based",
"header_rows": 1,
"continued": false,
"continued_from_prev": false,
"rows": [...]
}
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier for this table (e.g., "table_0"). |
page_index | integer | Yes | Zero-based page index where this table appears. |
bbox | array | Yes | Bounding box in PDF user-space points. |
detection_method | string | Yes | Detection method: "line_based" (ruling lines) or "borderless" (x0 alignment heuristics). |
header_rows | integer | Yes | Number of contiguous header rows at the top of the table. |
continued | boolean | Yes | Whether this table continues on the next page. |
continued_from_prev | boolean | Yes | Whether this table is a continuation from the previous page. |
rows | array | Yes | Rows in this table, ordered top-to-bottom. |
Row
Each row contains cells ordered left-to-right:
{
"bbox": [72.0, 520.0, 540.0, 540.0],
"is_header": true,
"cells": [...]
}
| Field | Type | Required | Description |
|---|---|---|---|
bbox | array | Yes | Bounding box in PDF user-space points. |
is_header | boolean | Yes | Whether this row is a header row. |
cells | array | Yes | Cells in this row, ordered left-to-right. |
Cell
{
"text": "Revenue",
"bbox": [72.0, 520.0, 180.0, 540.0],
"row": 0,
"col": 0,
"rowspan": 1,
"colspan": 1,
"is_header_row": true,
"spans": [0, 1]
}
| Field | Type | Required | Description |
|---|---|---|---|
text | string | Yes | The concatenated text content of all spans in the cell. |
bbox | array | Yes | Bounding box in PDF user-space points. |
row | integer | Yes | Zero-based row index within the table. |
col | integer | Yes | Zero-based column index within the table. |
rowspan | integer | Yes | Number of rows this cell spans (default 1). |
colspan | integer | Yes | Number of columns this cell spans (default 1). |
is_header_row | boolean | Yes | Whether this cell is in a header row. |
spans | array | Yes | References to spans in the page’s spans array (indices). |
Form Fields (Phase 7.4)
Form fields represent interactive form fields from the PDF’s AcroForm or XFA data.
Note: Phase 7 placeholders are documented here for forward-compatibility. Fields are present in the schema but return empty arrays until Phase 7 implementation.
{
"name": "employer_signature",
"type": "text",
"value": "John Doe",
"default": null,
"read_only": false,
"required": true,
"page_index": 2,
"rect": [72.0, 400.0, 288.0, 420.0],
"multiline": true,
"max_length": 100
}
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | The absolute (dot-joined) field name from the AcroForm. |
type | string | Yes | Field type: "text", "button", "choice", or "signature". |
value | varies | Yes | The current value (structure varies by type). |
default | varies | No | The default value (/DV entry). |
read_only | boolean | Yes | Whether this field is read-only (bit 1 of /Ff flags). |
required | boolean | Yes | Whether this field is required (bit 2 of /Ff flags). |
page_index | integer/null | No | Zero-based page index where this field’s widget appears. |
rect | array/null | No | Bounding box in PDF user-space points. |
multiline | boolean/null | No | Whether this text field supports multiple lines (text fields only). |
max_length | integer/null | No | Maximum length for text fields (/MaxLen entry). |
multi_select | boolean/null | No | Whether this choice field supports multiple selections. |
options | array/null | No | Available options for choice fields ([export_value, display_name] pairs). |
radio | boolean/null | No | Whether this button is a radio button (button fields only). |
pushbutton | boolean/null | No | Whether this button is a pushbutton (button fields only). |
selected | boolean/null | No | Selected state for button fields. |
state_name | string/null | No | Appearance state name for button fields (e.g., "Yes", "Off"). |
Signatures (Phase 7.3)
Digital signatures extracted from signature fields.
{
"field_name": "employer_signature",
"signer_name": "Jane Corporation",
"signing_date": "2024-03-15T14:23:51Z",
"location": "New York, NY",
"reason": "Contract approval",
"sub_filter": "adbe.pkcs7.detached",
"byte_range": [0, 12345, 67890, 456],
"coverage_fraction": 0.95,
"validation_status": "not_checked"
}
| Field | Type | Required | Description |
|---|---|---|---|
field_name | string | Yes | The absolute (dot-joined) field name from the AcroForm. |
signer_name | string | Yes | The signer’s name from the /Name entry. Empty string if absent. |
validation_status | string | Yes | Validation status — always "not_checked" in v1. Future versions may add "valid", "invalid", "indeterminate". |
signing_date | string/null | No | The signing date as an ISO 8601 string (RFC 3339 format). |
location | string/null | No | The location of signing from the /Location entry. |
reason | string/null | No | The reason for signing from the /Reason entry. |
sub_filter | string/null | No | The signature format/filter from the /SubFilter entry. |
byte_range | array/null | No | The /ByteRange array defining which bytes of the file are signed. |
coverage_fraction | number/null | No | Fraction of the file covered by the signature (0.0 to 1.0). |
Receipts (Phase 6.8)
Visual citation receipts provide cryptographic proof that extracted text originated from a specific region in a specific PDF.
{
"pdf_fingerprint": "pdftract-v1:a7f3c8d9...",
"page_index": 14,
"bbox": [220.0, 412.0, 412.0, 432.0],
"content_hash": "sha256:9b21c4e5...",
"extraction_version": "1.0.0",
"svg_clip": null
}
| Field | Type | Required | Description |
|---|---|---|---|
pdf_fingerprint | string | Yes | Phase 1.7 fingerprint of the source PDF. |
page_index | integer | Yes | Zero-based page index in the source PDF. |
bbox | array | Yes | Bounding box in PDF user-space points. |
content_hash | string | Yes | SHA-256 hash of the NFC-normalized text content. Format: "sha256:" + hex(SHA-256). |
extraction_version | string | Yes | The pdftract version that produced this receipt (semver string). |
svg_clip | string/null | No | SVG clip rendering the glyphs (present only in SVG mode). |
Receipts Mode
| Mode | Description |
|---|---|
off | No receipts generated (default). |
lite | Minimal receipts (~120 bytes each) with fingerprint, page index, bbox, and content hash. |
svg | Extended receipts that include an SVG clip rendering the glyphs. |
Phase 7 Placeholders
The following fields are included in the schema for forward compatibility but are not yet populated in Phase 6. They will be populated in Phase 7:
pages[].annotations- Highlights, stamps, notes, links from/Annots(Phase 7)attachments- From/EmbeddedFilesname tree (Phase 7.5)links- Document-scoped URI and internal destination links (Phase 7.6)threads- Article thread chains (Phase 7.7)
These fields are present in the schema as empty arrays or null values, allowing consumers to pre-allocate space for future data without breaking when Phase 7 features are added.
Diagnostics
Diagnostic messages provide visibility into extraction quality and issues:
| Severity | Description |
|---|---|
WARN | Warning - extraction succeeded but with potential quality issues (e.g., low coverage suggesting scanned content). |
ERROR | Error - extraction failed for a specific page or region. |
Example diagnostics:
[
"WARN: page 3: low coverage (54%) - possible scanned content",
"ERROR: page 7: failed to extract - corrupt content stream"
]
Coordinate System
All bbox values use PDF user-space coordinates:
- Units: PDF points (1/72 inch, approximately 0.353 mm)
- Origin: Lower-left corner of the page (x=0, y=0)
- Format:
[x0, y0, x1, y1]where (x0, y0) is bottom-left and (x1, y1) is top-right
Example: For a US Letter page (8.5 × 11 inches):
- Width: 612 points (8.5 × 72)
- Height: 792 points (11 × 72)
- Full page bbox:
[0, 0, 612, 792]
Schema Validation
Per INV-11, all JSON output must validate against the schema. CI runs a schema validation step on every fixture:
# Python validation example
pip install jsonschema
jsonschema -i output.json docs/schema/v1.0/pdftract.schema.json
Plan References
- Phase 6.1 (lines 2018-2051): JSON output full schema implementation
- Phase 6.8 (lines 2400+): Visual citation receipts
- Phase 7.3 (lines 2750+): Digital signatures
- Phase 7.4 (lines 2800+): Form fields
- INV-11 (line 841): Schema validation invariant
For the complete field-by-field rationale, see the extraction output schema research doc.
JSON Schema Reference
Draft — This section is a placeholder for future content.
Complete JSON output format documentation.
Output Format
Draft — This page is a placeholder for future content.
Describes the JSON schema for pdftract output.
Block Types
Draft — This page is a placeholder for future content.
Describes the semantic block types (heading, paragraph, list, table, etc.).
Metadata
Draft — This page is a placeholder for future content.
Describes the document metadata fields.
Error Handling
Draft — This page is a placeholder for future content.
Describes how errors are reported in the JSON output.
Profiles
Draft — This section is a placeholder for future content.
Document-type-specific extraction profiles.
Available Profiles
Draft — This page is a placeholder for future content.
Lists all available document profiles.
invoice Profile
Draft — This page is a placeholder for future content.
Extraction configuration for invoice documents.
receipt Profile
Draft — This page is a placeholder for future content.
Extraction configuration for receipt documents.
bank_statement Profile
Draft — This page is a placeholder for future content.
Extraction configuration for bank statement documents.
contract Profile
Draft — This page is a placeholder for future content.
Extraction configuration for contract documents.
legal_filing Profile
Draft — This page is a placeholder for future content.
Extraction configuration for legal filing documents.
form Profile
Draft — This page is a placeholder for future content.
Extraction configuration for form documents.
scientific_paper Profile
Draft — This page is a placeholder for future content.
Extraction configuration for scientific paper documents.
book_chapter Profile
Draft — This page is a placeholder for future content.
Extraction configuration for book chapter documents.
slide_deck Profile
Draft — This page is a placeholder for future content.
Extraction configuration for slide deck documents.
Custom Profiles
Draft — This page is a placeholder for future content.
How to create and use custom extraction profiles.
SDK Quickstarts
Getting started guides for using pdftract from various programming languages. Each SDK implements the same 9-method contract: extract, extract_text, extract_markdown, extract_stream, search, get_metadata, hash, classify, and verify_receipt.
Available SDKs
- Rust — The
pdftract-corecrate with native zero-copy PDF processing - Python — Native Python bindings with PyO3, plus subprocess fallback
- JavaScript/TypeScript — npm package with Node.js and browser support
- Go — Go module with native bindings
Choosing an SDK
- Rust — Best for performance-critical applications and CLI tools
- Python — Best for data science, ML pipelines, and scripting
- JavaScript — Best for web applications and serverless functions
- Go — Best for microservices and cloud-native applications
All SDKs support:
- Remote PDFs via HTTP/HTTPS URLs
- Encrypted PDFs with password
- OCR for scanned documents (with feature flag)
- Streaming extraction for large documents
- Cryptographic receipt verification
See Also
Python SDK
The Python SDK (pdftract) provides native Python bindings with idiomatic ergonomics including an exception hierarchy, dataclass types, and optional asyncio wrappers.
Installation
pip install pdftract
The package includes a precompiled native module for your platform. If the native module fails to import, a subprocess fallback is automatically used (with significantly degraded performance).
Basic Extraction
import pdftract
doc = pdftract.extract("document.pdf")
print(f"Extracted {len(doc.pages)} pages")
for page in doc.pages:
for span in page.spans:
print(span.text)
Text-Only Extraction
For RAG pipelines that just need the text body:
import pdftract
text = pdftract.extract_text("document.pdf")
print(text)
Streaming
For large PDFs, stream pages one at a time to keep memory usage bounded:
import pdftract
for page in pdftract.extract_stream("large_document.pdf"):
print(f"Page {page.page_index}: {len(page.spans)} spans")
# Process page while only one page is resident in memory
Markdown Extraction
Extract Markdown with optional anchor links for mapping back to PDF locations:
import pdftract
# Basic Markdown
markdown = pdftract.extract_markdown("document.pdf")
# With anchor links (HTML comments)
markdown = pdftract.extract_markdown("document.pdf", anchors=True)
Options
Pass extraction options as keyword arguments:
import pdftract
doc = pdftract.extract(
"document.pdf",
pages="1-5,7", # Page range
password="secret123", # PDF password
receipts="lite" # Receipt generation mode
)
Available Options
| Option | Type | Default | Use Case |
|---|---|---|---|
pages | str | None | None | Page range (e.g., "1-5,7,12-") |
password | str | None | None | PDF password for encrypted documents |
receipts | str | None | None | Receipt mode: "off", "lite", or "full" |
ocr | bool | False | Enable OCR for scanned documents |
ocr_language | list[str] | ["eng"] | OCR language codes |
include_invisible | bool | False | Include invisible text in output |
extract_forms | bool | True | Extract AcroForm fields |
extract_attachments | bool | True | Extract embedded attachments |
readability_threshold | float | 0.0 | Minimum readability score |
max_decompress_gb | int | 512 | Max decompressed GB per stream |
full_render | bool | False | Enable full rendering |
Error Handling
The SDK provides a structured exception hierarchy:
import pdftract
try:
doc = pdftract.extract("encrypted.pdf", password="wrong")
except pdftract.EncryptionError as e:
print(f"Encryption error: {e.code} - {e.hint}")
except pdftract.CorruptPdfError as e:
print(f"Corrupt PDF: {e}")
except pdftract.SourceUnreachableError as e:
print(f"File not found: {e}")
except pdftract.PdftractError as e:
print(f"Extraction failed: {e}")
Exception Hierarchy
All exceptions inherit from PdftractError:
PdftractError— Base exception for all extraction errorsEncryptionError— PDF encryption/password errorsCorruptPdfError— Malformed or corrupted PDFSourceUnreachableError— File or URL unreachableRemoteFetchInterruptedError— Network interruption during fetchTlsError— TLS/certificate errorsReceiptVerifyError— Receipt verification failedUnsupportedOperationError— Requested operation not available
Exception Attributes
All exceptions have the following attributes:
code— Diagnostic code (e.g.,"ENCRYPTION_WRONG_PASSWORD")page_index— Page number where error occurred (if applicable)hint— Suggested action for resolution
Metadata
Get document metadata without full extraction:
import pdftract
metadata = pdftract.get_metadata("document.pdf")
print(f"Pages: {metadata.page_count}")
print(f"Title: {metadata.title}")
print(f"Author: {metadata.author}")
print(f"Fingerprint: {metadata.fingerprint}")
Search
Search for a regex pattern in the PDF:
import pdftract
for match in pdftract.search("document.pdf", r"\b\d{3}-\d{2}-\d{4}\b"):
print(f"Found SSN at page {match.page_index}: {match.text}")
Fingerprint
Compute the structural fingerprint of a PDF:
import pdftract
fingerprint = pdftract.hash("document.pdf")
print(f"Fingerprint: {fingerprint.value}")
Classify
Classify a PDF page type:
import pdftract
classification = pdftract.classify("document.pdf")
print(f"Type: {classification.class_name}")
print(f"Confidence: {classification.confidence}")
Verify Receipt
Verify a cryptographic receipt:
import pdftract
# Extract with receipts enabled
doc = pdftract.extract("document.pdf", receipts="lite")
receipt = doc.pages[0].receipt
# Verify later
verified = pdftract.verify_receipt("document.pdf", receipt)
print(f"Verified: {verified}")
Remote PDFs
Extract from HTTP/HTTPS URLs:
import pdftract
doc = pdftract.extract("https://example.com/document.pdf")
MCP Integration
For AI-assisted PDF extraction, pdftract provides an MCP (Model Context Protocol) server. The Python SDK can be used alongside MCP clients like Claude Desktop:
pdftract mcp --stdio
See MCP Server Documentation for setup instructions.
Types
The SDK provides typed wrappers for all output structures:
from pdftract.types import Document, Page, Span, Block, Metadata
# All extraction functions return typed objects
doc: Document = pdftract.extract("document.pdf")
page: Page = doc.pages[0]
span: Span = page.spans[0]
block: Block = page.blocks[0]
metadata: Metadata = pdftract.get_metadata("document.pdf")
Async API
For asyncio-based applications, use the async API:
import pdftract.asyncio as pdftract_async
async def extract_async():
doc = await pdftract_async.extract("document.pdf")
print(f"Extracted {len(doc.pages)} pages")
See Also
Rust SDK
The Rust SDK is the pdftract-core crate. It provides native PDF text extraction with zero-copy memory mapping and streaming support.
Installation
Add to your Cargo.toml:
[dependencies]
pdftract-core = "1.0"
For OCR support, enable the ocr feature:
[dependencies]
pdftract-core = { version = "1.0", features = ["ocr"] }
Basic Extraction
use pdftract_core::{extract, ExtractionOptions};
fn main() -> anyhow::Result<()> {
let opts = ExtractionOptions::default();
let result = extract("document.pdf", &opts)?;
for (i, page) in result.pages.iter().enumerate() {
println!("Page {}: {} spans", i + 1, page.spans.len());
for span in &page.spans {
println!(" {}", span.text);
}
}
Ok(())
}
Streaming Extraction
For large PDFs, stream pages one at a time to keep memory usage bounded:
use pdftract_core::{extract_stream, ExtractionOptions};
use std::path::Path;
fn main() -> anyhow::Result<()> {
let opts = ExtractionOptions::default();
let pages = extract_stream(Path::new("large_document.pdf"), &opts)?;
for page_result in pages {
let page = page_result?;
println!("Page {}: {} spans", page.index, page.spans.len());
}
Ok(())
}
Options
ExtractionOptions
| Field | Type | Default | Use Case |
|---|---|---|---|
receipts | ReceiptsMode | Off | Generate cryptographic receipts |
max_parallel_pages | usize | 4 | Control memory for concurrent page processing |
memory_budget_mb | usize | 512 | Target peak RSS in MB |
full_render | bool | false | Enable PDFium rendering (requires full-render feature) |
ocr_dpi_override | Option<u32> | None | Override automatic DPI selection |
ocr_language | Vec<String> | vec!["eng"] | Tesseract language codes |
markdown_anchors | bool | false | Emit HTML comment anchors in Markdown |
max_decompress_bytes | u64 | 512 MiB | Bomb limit for decompressed streams |
output | OutputOptions | default() | Output filtering options |
pages | Option<String> | None | Page range (e.g., "1-5,7,12-") |
password | Option<SecretString> | None | PDF password for encrypted documents |
OutputOptions
| Field | Type | Default | Use Case |
|---|---|---|---|
include_invisible | bool | false | Include invisible text in output |
extract_forms | bool | true | Extract AcroForm fields |
extract_attachments | bool | true | Extract embedded attachments |
Receipts
Generate cryptographic receipts for verification:
use pdftract_core::{extract, ExtractionOptions};
use pdftract_core::options::ReceiptsMode;
fn main() -> anyhow::Result<()> {
let opts = ExtractionOptions {
receipts: ReceiptsMode::Lite,
..Default::default()
};
let result = extract("document.pdf", &opts)?;
// Receipts are embedded in page metadata
if let Some(receipt) = &result.pages[0].receipt {
println!("Receipt: {}", receipt);
}
Ok(())
}
Remote PDFs
With the remote feature, fetch PDFs via HTTP:
use pdftract_core::{extract, ExtractionOptions};
use std::path::Path;
fn main() -> anyhow::Result<()> {
let opts = ExtractionOptions::default();
let result = extract(Path::new("https://example.com/document.pdf"), &opts)?;
Ok(())
}
Error Handling
Most functions return anyhow::Result<T> which wraps various error types:
use pdftract_core::{extract, ExtractionOptions};
use std::path::Path;
fn main() {
let opts = ExtractionOptions::default();
match extract(Path::new("document.pdf"), &opts) {
Ok(result) => {
println!("Extracted {} pages", result.pages.len());
}
Err(e) => {
eprintln!("Extraction failed: {}", e);
// Inspect error chain
for cause in e.chain() {
eprintln!(" caused by: {}", cause);
}
}
}
}
Feature Flags
| Feature | Adds | Default |
|---|---|---|
serde | JSON serialization support | ✓ |
decrypt | Decryption of encrypted PDFs | ✓ |
quick-xml | Conformance detection via XML metadata | ✓ |
ocr | Tesseract OCR for scanned documents | - |
full-render | PDFium-based rendering (requires ocr) | - |
remote | HTTP range fetching for remote PDFs | - |
profiles | Extraction profiles | - |
receipts | Cryptographic receipt generation | - |
cjk | CJK text extraction via predefined CMap registry | - |
schemars | JSON Schema generation | - |
Source Types
The SDK supports multiple source types via the PdfSource trait:
#![allow(unused)]
fn main() {
use pdftract_core::source::{FileSource, MmapSource, MemorySource};
// Memory-mapped source (zero-copy for large files)
let source = MmapSource::open("document.pdf")?;
// In-memory source (for byte buffers)
let data = std::fs::read("document.pdf")?;
let source = MemorySource::new(data);
// Standard file source
let source = FileSource::open("document.pdf")?;
}
See Also
JavaScript/TypeScript SDK
Draft — This page is a placeholder for future content.
Using pdftract from JavaScript/TypeScript (Node.js).
Go SDK
Draft — This page is a placeholder for future content.
Using pdftract from Go.
Advanced Topics
Draft — This section is a placeholder for future content.
Deep dives into pdftract’s internals and advanced configuration.
OCR Configuration
Draft — This page is a placeholder for future content.
Configuring Tesseract and OCR settings.
Font Encoding Recovery
Draft — This page is a placeholder for future content.
How pdftract recovers text from fonts with broken or missing ToUnicode mappings.
Structure Tree Extraction
Draft — This page is a placeholder for future content.
Extracting logical structure from tagged PDFs.
Hybrid Routing
Draft — This page is a placeholder for future content.
How pdftract routes each page to the optimal extraction pipeline.
Provenance and Confidence
Draft — This page is a placeholder for future content.
Understanding bounding boxes, font metadata, and confidence scores.
Troubleshooting
This guide maps common pdftract failures to their causes and fixes. Each error is associated with a diagnostic code that appears in extraction output (see diagnostics in the JSON response or CLI stderr).
For the authoritative diagnostic code catalog, see the Diagnostics Reference.
Symptom → Diagnostic Lookup
| Symptom | Likely Diagnostic Code |
|---|---|
| PDF won’t open, “encrypted” error | ENCRYPTION_UNSUPPORTED |
| Text extraction incomplete or missing | XREF_REPAIRED, OCR_*_UNSUPPORTED |
| Process hangs or runs very long | STREAM_BOMB |
| “Path outside root” (MCP mode) | MCP_PATH_TRAVERSAL |
| Cache errors / corrupted entries | CACHE_ENTRY_CORRUPT, CACHE_INTEGRITY_FAIL |
| Profile fails to load | PROFILE_INVALID, PROFILE_SECRETS_FORBIDDEN |
| Remote URL fetch blocked | URL_PRIVATE_NETWORK |
| Requested page doesn’t exist | PAGE_OUT_OF_RANGE |
| Text contains placeholder characters (⍰) | GLYPH_UNMAPPED |
| Broken vector graphics not recovered | BROKENVECTOR_OCR_UNAVAILABLE |
| JavaScript warning in output | JAVASCRIPT_PRESENT |
| Circular reference warnings | STRUCT_CIRCULAR_REF, STRUCT_XOBJECT_CYCLE |
| Stack overflow warnings | GSTATE_STACK_OVERFLOW |
XREF_REPAIRED warning
What it means: pdftract found the PDF’s cross-reference table was corrupt and ran the forward-scan fallback (Phase 1.3) to recover.
Cause: PDF created or transmitted with truncation or corruption. The startxref offset points outside the file, or the xref table is malformed.
Fix: Usually no action needed; extraction succeeds with the recovered xref. Output may be incomplete on truncated files. If extraction fails, the PDF is unsalvageable.
Severity: info (extraction continues)
STREAM_BOMB error
What it means: A compressed stream exceeded the decompression size limit (default: 512 MB).
Cause: A hostile PDF with a “compression bomb” — a small stream that expands to multi-GB size (e.g., 10 KB → 2 GB). This is a common security exploit pattern.
Fix:
- If the PDF is trusted: Increase the limit with
--max-decompress-gb 2(or higher) - If the PDF is untrusted: Treat as a hostile file; do not process
Severity: error (stream aborted; partial extraction returned)
ENCRYPTION_UNSUPPORTED fatal
What it means: The PDF is encrypted with an unsupported handler or the wrong password.
Cause:
- PDF encrypted with an unknown handler (e.g., Adobe LiveCycle policy server)
- PDF password-protected but no password (or wrong password) supplied
Fix:
# Supply password via environment variable
export PDFTRACT_PASSWORD="your-password"
pdftract extract document.pdf
# Or via stdin
echo "your-password" | pdftract extract --password-stdin document.pdf
If the handler is unsupported (e.g., Adobe LiveCycle), use an Adobe-side decryption tool first, or a dedicated password recovery tool like pdfcrack or john.
Severity: fatal (process exits with code 3)
OCR_JBIG2_UNSUPPORTED / OCR_JPX_UNSUPPORTED / OCR_CCITT_UNSUPPORTED warning
What it means: A page contains an image that requires a decoder not available in the current build.
Cause:
OCR_JBIG2_UNSUPPORTED: JBIG2-encoded image (rare)OCR_JPX_UNSUPPORTED: JPEG 2000-encoded imageOCR_CCITT_UNSUPPORTED: CCITT fax-encoded image
Fix:
# Build with full-render feature (enables all decoders via PDFium)
cargo build --release --features full-render
# Or install system libraries:
# - JPX: install libopenjp2
# - CCITT: install libtiff
Severity: warn (page skipped from OCR; extraction continues)
BROKENVECTOR_OCR_UNAVAILABLE warning
What it means: A page contains broken vector graphics that could be recovered via OCR, but the OCR feature is disabled.
Cause: Build was compiled without the ocr feature.
Fix: Rebuild with OCR enabled:
cargo build --release --features ocr
Severity: warn (broken vector graphics not recovered; extraction continues)
MCP_PATH_TRAVERSAL / PATH_OUTSIDE_ROOT error
What it means: (MCP mode) The requested path escapes the --root directory boundary.
Cause: A tool call attempted path traversal (e.g., ../../etc/passwd).
Fix:
- Adjust the requested path to stay within
--root - Or restart the MCP server without
--rootrestriction (not recommended for multi-tenant deployments)
Severity: error (request rejected)
URL_PRIVATE_NETWORK error
What it means: Remote fetch blocked because the URL targets a private network address.
Cause: URL targets localhost, private IP ranges (RFC 1918), or link-local addresses. This is an SSRF (Server-Side Request Forgery) protection.
Fix:
# If you trust the URL, allow private networks:
pdftract extract --allow-private-networks https://internal-server/docs.pdf
Severity: error (request rejected with HTTP 400 in serve mode)
CACHE_ENTRY_CORRUPT warning
What it means: A cache entry failed integrity verification.
Cause: Cache file corruption (disk error, concurrent write, etc.).
Fix: None needed — the entry is automatically deleted and extraction re-runs. If this recurs frequently, check your disk filesystem.
Severity: warn (entry deleted; extraction re-runs)
CACHE_INTEGRITY_FAIL diagnostic
What it means: A cache entry’s HMAC verification failed, indicating potential cache poisoning.
Cause: Malicious co-tenant wrote a forged cache entry (multi-user cache scenarios), or disk corruption.
Fix: The entry is treated as a cache miss and extraction re-runs. In multi-user environments, ensure per-user cache directories or verify cache permissions.
Severity: warn (entry rejected; extraction re-runs)
PROFILE_INVALID / PROFILE_SECRETS_FORBIDDEN error
What it means: Profile YAML failed validation.
Cause:
PROFILE_INVALID: YAML syntax error or schema violationPROFILE_SECRETS_FORBIDDEN: Profile contains secret-keyword keys (password:,token:,secret:,api_key:)
Fix:
# For schema errors, check the YAML syntax:
pdftract profile show --profile-path your-profile.yaml
# For secrets errors, remove secret keys from the profile.
# Secrets should be passed via environment variables, not profiles.
Severity: error (profile rejected)
PAGE_OUT_OF_RANGE warning
What it means: The --pages argument exceeds the document’s actual page count.
Cause: Page range specified (e.g., --pages 1-100) on a document with fewer pages (e.g., 10 pages).
Fix: Adjust the --pages argument to the actual page count:
# First, get the page count:
pdftract inspect document.json | jq '.page_count'
# Then extract with a valid range:
pdftract extract --pages 1-10 document.pdf
Severity: warn (pages clamped to available range)
GLYPH_UNMAPPED warning
What it means: A glyph could not be resolved by any of the four encoding levels.
Cause: Font encoding corruption, missing font embedding, or non-standard encoding.
Fix: Output contains the Unicode replacement character (⍰). No direct fix; consider re-saving the PDF through a normalizing tool (e.g., Adobe Acrobat, qpdf).
Severity: warn (character replaced with U+FFFD; extraction continues)
JAVASCRIPT_PRESENT info
What it means: PDF contains embedded JavaScript (in /AA, /OpenAction, or /JS entries).
Cause: PDF includes JavaScript actions (common in forms, interactive documents).
Fix: None needed for extraction — pdftract NEVER executes embedded JavaScript. JavaScript actions are surfaced in metadata.javascript_actions[] for downstream review.
Severity: info (JavaScript is not executed)
STRUCT_CIRCULAR_REF / STRUCT_XOBJECT_CYCLE / GSTATE_STACK_OVERFLOW warning
What it means: PDF contains circular references or malformed content streams.
Cause:
STRUCT_CIRCULAR_REF: Indirect object reference cycleSTRUCT_XOBJECT_CYCLE: XObject (image/form) reference cycleGSTATE_STACK_OVERFLOW: Graphics state stack exceeds depth limit
Fix: Usually no action needed — pdftract breaks cycles at the second visit (or depth 20 for XObjects). If output is incomplete, investigate the source PDF for a producer bug.
Severity: warn (cycle broken; extraction continues)
REMOTE_FETCH_INTERRUPTED error
What it means: Remote fetch was interrupted (network timeout, connection reset, etc.).
Cause: Network connectivity issues, server timeout, or premature connection close.
Fix: Retry the request; check network connectivity:
# Retry with increased timeout:
pdftract extract --timeout-seconds 120 https://example.com/document.pdf
Severity: error (request aborted)
REMOTE_NO_RANGE_SUPPORT warning
What it means: Remote server does not support HTTP Range requests.
Cause: Server lacks Accept-Ranges header or returns 206 Unsupported.
Fix: None needed — pdftract falls back to whole-file download. For large files, consider hosting on a Range-supporting server.
Severity: warn (fallback to whole-file download)
TAGGED_PDF_STRUCT_TREE_DEFERRED info
What it means: Tagged PDF structure tree extraction is deferred in this version.
Cause: Phase 7.1 (full structure tree extraction) is not yet implemented.
Fix: None needed — this is a temporary fallback. Structure tree extraction will be added in v1.0.0.
Severity: info (structure tree not extracted)
Getting Help
If you encounter a diagnostic code not listed here, or the suggested fix doesn’t resolve your issue:
- Check the Diagnostics Reference for the full catalog
- Search existing issues on GitHub
- Open a new issue with:
- The diagnostic code(s)
- A minimal reproducible example (PDF or command)
- The
--debugoutput if safe to share
Related Documentation
- Diagnostics Reference — Full diagnostic code catalog
- FAQ — Common questions and answers
- Advanced: OCR Configuration — OCR troubleshooting details
Troubleshooting
Draft — This section is a placeholder for future content.
Debugging and performance tuning for pdftract.
Common Issues
Draft — This page is a placeholder for future content.
Solutions to common extraction problems.
Diagnostics
Draft — This page is a placeholder for future content.
Using pdftract’s diagnostic features for debugging.
Performance Tuning
Draft — This page is a placeholder for future content.
Optimizing extraction speed and memory usage.
FAQ
Frequently asked questions about pdftract.
Table of Contents
General
What is pdftract?
pdftract is a command-line tool and library for extracting text, structure, and content from PDF files. It combines vector text extraction with OCR fallback to handle both well-formed and problematic PDFs. pdftract is written in Rust and provides Python bindings for programmatic use.
See the Introduction for a complete overview.
What’s the difference between extract and extract_text?
-
extract: The primary command that produces structured JSON output with blocks, spans, metadata, and provenance information. Use this when you need the full extraction with layout, reading order, and confidence scores. -
extract_text: A simplified command that outputs plain text only. Use this for quick text extraction when you don’t need the structured JSON output.
Example:
# Full structured extraction
pdftract extract document.pdf -o output.json
# Plain text only
pdftract extract_text document.pdf -o output.txt
Does pdftract execute JavaScript embedded in PDFs?
No. pdftract never executes JavaScript embedded in PDFs. JavaScript is detected during parsing for security analysis, but it is never executed. This design prevents malicious PDFs from exploiting JavaScript vulnerabilities.
If you need to analyze JavaScript in PDFs, pdftract can detect and report its presence, but execution must be done separately with appropriate sandboxing.
How do I cite an extracted snippet?
The JSON output from pdftract extract includes provenance information for each text block:
{
"blocks": [{
"spans": [{
"text": "Example snippet",
"bbox": [100.0, 200.0, 250.0, 215.0],
"page": 3,
"confidence": 0.98
}]
}],
"metadata": {
"path": "/path/to/document.pdf",
"fingerprint": "sha256:abc123...",
"extracted_at": "2026-05-25T12:00:00Z"
}
}
For academic citations, include:
- Document path and fingerprint
- Page number (from the
pagefield) - Extraction timestamp
- The pdftract version used
Installation and Setup
How do I install pdftract?
See the Installation guide for complete instructions. Quick summary:
With cargo (Rust toolchain):
cargo install pdftract
With pip (Python bindings):
pip install pdftract
Pre-built binaries: Download from the releases page.
How do I run pdftract behind a corporate proxy?
pdftract doesn’t have built-in proxy support, but you can use the HTTP serve mode with a reverse proxy:
- Start pdftract in serve mode:
pdftract serve --port 8080
-
Configure your reverse proxy (nginx, Apache, etc.) to handle authentication and SSL termination.
-
Access pdftract through your proxy endpoint.
See Advanced Topics: HTTP Serve for deployment guidance.
What are the system requirements?
- OS: Linux, macOS, or Windows
- Rust: 1.70+ (if building from source)
- Python: 3.8+ (for Python bindings)
- OCR (optional): Tesseract 4.0+ for OCR fallback
- Memory: 512 MB minimum for typical PDFs; more for large documents
Usage
Why is my PDF returning broken_vector?
The broken_vector classification means the PDF’s text layer is unreliable or missing. Common causes:
- Invisible text overlay: Text with rendering mode 3 (invisible) overlaid on a raster image
- Missing ToUnicode CMap: Font lacks character-to-Unicode mapping
- Encoding corruption: Character encodings don’t match the actual glyphs
Solution: pdftract automatically routes broken_vector pages to the OCR pipeline (Phase 5.5). If you see broken_vector without OCR output, check that OCR is enabled:
# Verify OCR is available
pdftract doctor tesseract-langs
# Enable OCR explicitly if needed
pdftract extract document.pdf --enable-ocr
See Troubleshooting: Broken Vector for more details.
Why is OCR slow?
OCR performance depends on several factors:
- Image resolution: Higher DPI images take longer to process
- Tesseract version: Version 4.0+ is significantly faster than 3.x
- Language data: Additional language packs increase processing time
- Hardware: CPU-bound; more cores help with batch processing
To speed up OCR:
# Reduce DPI (trade-off: accuracy)
pdftract extract document.pdf --ocr-dpi 200
# Use fewer languages
pdftract extract document.pdf --ocr-lang eng
# Disable OCR for vector-only PDFs
pdftract extract document.pdf --disable-ocr
How do I extract text from a specific page range?
Use the --pages flag:
# Single page
pdftract extract document.pdf --pages 5
# Range
pdftract extract document.pdf --pages 1-10
# Multiple ranges
pdftract extract document.pdf --pages 1-5,10,15-20
# All pages from page 5 onward
pdftract extract document.pdf --pages 5-
How do I extract images from a PDF?
pdftract automatically detects and records image XObjects during content stream processing. The output JSON includes image metadata:
{
"images": [{
"bbox": [100.0, 200.0, 400.0, 500.0],
"xobject_ref": "5 0 R",
"name": "Im1"
}]
}
For actual image extraction, use the serve mode with the /images endpoint or write a custom script using the Python SDK.
Can I process multiple PDFs at once?
Yes, use shell wildcards or write a batch script:
# Process all PDFs in a directory
for file in *.pdf; do
pdftract extract "$file" -o "output/$(basename "$file" .json)"
done
# With parallel processing (GNU parallel)
ls *.pdf | parallel -j 4 pdftract extract {} -o output/{/.}.json
Configuration
How do I add a custom profile?
Create a YAML file defining your profile:
# custom-profile.yaml
name: my_custom
description: "Custom extraction profile"
extraction:
preserve_tables: true
preserve_columns: true
ocr_fallback: true
output:
format: json
include_provenance: true
confidence_threshold: 0.7
Then use it:
pdftract extract document.pdf --profile custom-profile.yaml
See Custom Profiles for complete documentation.
How do I adjust OCR accuracy?
Adjust Tesseract parameters via environment variables or the OCR configuration:
# Set OCR engine mode
export TESSERACT_OEM=1 # LSTM only
export TESSERACT_PSM=6 # Assume single column block of text
# Adjust page segmentation mode
pdftract extract document.pdf --tesseract-psm 6
Higher accuracy settings may slow down processing. See OCR Configuration for details.
How do I disable OCR for faster processing?
If you know your PDFs have reliable text layers:
pdftract extract document.pdf --disable-ocr
Or set a confidence threshold to skip low-confidence text:
pdftract extract document.pdf --min-confidence 0.9
What are confidence scores and how do I use them?
Each text span has a confidence score (0.0 to 1.0):
- 1.0: High confidence (ToUnicode CMap lookup succeeded)
- 0.3: Medium confidence (encoding + AGL fallback)
- 0.0: No confidence (PositionHint mode or failed resolution)
Filter by confidence:
pdftract extract document.pdf --min-confidence 0.5
Or filter in post-processing using jq:
pdftract extract document.pdf | jq '.blocks[].spans[] | select(.confidence > 0.5)'
Output and Formats
How do I get output in Markdown format?
Use the --format flag:
pdftract extract document.pdf --format markdown -o output.md
The Markdown output preserves headings, lists, tables, and code blocks where detected.
How do I preserve table structure?
pdftract includes table detection (Phase 4.2). Ensure table preservation is enabled:
pdftract extract document.pdf --preserve-tables
Tables are output with structured cell information:
{
"type": "table",
"rows": 3,
"columns": 4,
"cells": [...]
}
Can I extract metadata from PDFs?
Yes, metadata is automatically extracted and included in the output:
{
"metadata": {
"title": "Document Title",
"author": "Author Name",
"subject": "Subject",
"keywords": ["keyword1", "keyword2"],
"creator": "Application",
"producer": "PDF Producer",
"creation_date": "2026-01-01T00:00:00Z",
"modified_date": "2026-05-25T12:00:00Z"
}
}
How do I handle password-protected PDFs?
Provide the password via the --password flag:
pdftract extract document.pdf --password secret123
For security, avoid passing passwords on the command line in production. Use environment variables or a config file:
export PDFTRACT_PASSWORD=secret123
pdftract extract document.pdf
Troubleshooting
Why is extraction failing with an error?
Check the error message and consult the Troubleshooting Guide. Common issues:
- Encrypted PDFs: Use
--passwordto decrypt - Corrupted PDFs: pdftract attempts recovery; check diagnostics
- Missing dependencies: Verify Tesseract and language packs are installed
Run diagnostics:
pdftract doctor
Why is my output empty or incomplete?
Possible causes:
- No text layer: PDF may be image-only. Enable OCR.
- Encoding issues: Check diagnostics for
FONT_GLYPH_UNMAPPEDwarnings - Page range issue: Verify your
--pagesargument - Confidence filter: Lower
--min-confidenceif set too high
Check diagnostics output:
pdftract extract document.json --verbose
How do I debug extraction issues?
Enable verbose output and diagnostics:
# Full diagnostic output
pdftract extract document.pdf --verbose --diagnostics
# Save diagnostics for analysis
pdftract extract document.pdf --diagnostics -o diagnostics.json
Common diagnostic codes:
FONT_GLYPH_UNMAPPED: Glyph couldn’t be mapped to UnicodeSTREAM_DECODE_ERROR: Stream decompression failedSTRUCT_INVALID_TYPE: Unexpected object type
See Diagnostics Reference for a complete list.
Why does extraction use so much memory?
Memory usage depends on:
- PDF size: Larger PDFs with many images use more memory
- OCR: Tesseract loads image data into memory
- Output buffering: Large JSON outputs are buffered in memory
To reduce memory usage:
# Process page-by-page
for page in {1..100}; do
pdftract extract document.pdf --pages $page -o "page-$page.json"
done
# Disable OCR if not needed
pdftract extract document.pdf --disable-ocr
# Stream output (if supported)
pdftract extract document.pdf --stream-output
Still have questions?
- Check the Troubleshooting Guide
- Review the CLI Reference
- Open an issue on GitHub