Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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-goalAlternative
PDF authoring or writinglopdf, pdfium-render, printpdf
Full PDF rendering / printingPDFium, MuPDF, Poppler
Cryptographic signature validationopenssl smime, dedicated PKI libraries
Translation of extracted textLibreTranslate, DeepL, Argos
SummarizationLLM tools via the MCP server integration
OCR engine trainingTesseract’s tesstrain tooling
Filling out PDF formsForm-filling tools with authoring support
Watermark removalDetected and excluded from output, not removed from PDF
Password crackingpdfcrack, 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_64 and arm64
  • 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

TagDescription
latestDefault features (vector extraction, basic OCR)
ocrIncludes Tesseract for full OCR support
fullAll features including PDFium for rasterization

Multi-arch manifests support amd64 and arm64 platforms.

Platform Support

Supported Platforms

PlatformCI StatusNotes
Linux x86_64 (glibc)Fully CI-testedPrimary development platform
Linux x86_64 (musl)Fully CI-testedAlpine-compatible
Linux arm64 (glibc)Fully CI-testedARM64 servers (e.g., Graviton)
Linux arm64 (musl)Fully CI-testedAlpine ARM64
macOS x86_64Build-testedSee caveat below
macOS arm64Build-testedSee caveat below
Windows x86_64Build-testedSee 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 with blocks and spans
  • blocks — Semantic elements (headings, paragraphs, lists) with reading order
  • spans — Text fragments with bounding boxes, font metadata, and confidence scores
  • metadata — 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

OptionDescription
--output FILEWrite output to file instead of stdout
--textOutput plain text instead of JSON
--output-dir DIRDirectory for batch output (with * glob)
--autoAuto-detect and apply document profile
--profile NAMEUse specific profile (skip auto-detection)
--password PASSPassword for encrypted PDFs
--pages N-MExtract specific page range
--ocrForce OCR mode for all pages

See CLI Reference for complete command documentation.

What’s Next?

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-reference to regenerate.

Command-Line Help for pdftract

This document contains the help content for the pdftract command-line program.

Command Overview:

pdftract

pdftract CLI - PDF extraction and conformance testing

Usage: pdftract <COMMAND>

Subcommands:
  • list-diagnostics — List all diagnostic codes with their metadata
  • explain-diagnostic — Explain a specific diagnostic code in detail
  • compare — Compare actual results against expected values with tolerances (for conformance testing)
  • conformance — Run SDK conformance test suite
  • sdk — SDK code generation commands
  • extract — Extract text and structure from a PDF file
  • classify — Classify document type (runs metadata + signal extraction, not full text extraction)
  • inspect — Inspect a PDF file in a local web browser with debugging overlays
  • verify-receipt — Verify a receipt against a PDF file
  • hash — Compute the PDF structural fingerprint (hash)
  • cache — Manage the extraction cache
  • profiles — Manage document type profiles
  • serve — Start the HTTP server for extraction
  • mcp — Start the MCP (Model Context Protocol) server
  • validate — Validate a JSON file against the pdftract schema
  • migrate-schema — Migrate JSON output between schema versions
  • doctor — 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 JSON

    Default value: tests/sdk-conformance/cases.json

  • -k, --sdk <SDK> — SDK name

    Default value: pdftract

  • -v, --version <VERSION> — SDK version

    Default value: 0.1.0

  • -o, --output <OUTPUT> — Output report path

    Default value: conformance-report.json

pdftract sdk

SDK code generation commands

Usage: pdftract sdk <COMMAND>

Subcommands:
  • codegen — Generate SDK skeleton from templates
  • validate — 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 language

    Possible 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 language

    Possible 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 svg

    Default value: off

    Possible 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 binds

    Required when –bind is not a loopback address (127.0.0.1 or ::1).

  • --no-open — Suppress automatic browser launch

    Useful for CI environments or when you want to manually open the browser.

  • --compare <FILE> — Optional second PDF file for comparative debugging

    When 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 statistics
  • clear — 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 profiles
  • show — Show a profile’s YAML content
  • export — Export a built-in profile to stdout
  • install — Install a profile to the user config directory
  • validate — 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: Success
  • 1: 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": [...]
}
FieldTypeRequiredDescription
fingerprintstringYesPhase 1.7 fingerprint of the source PDF. Format: "pdftract-v1:" + hex(SHA-256). Used for receipt verification.
pagesarrayYesExtracted pages, each containing spans and blocks.
metadataobjectYesExtractionMetadata object with page count, diagnostics, receipts mode, etc.
signaturesarrayYesDigital signatures extracted from the document. Empty when no signature fields exist.
form_fieldsarrayYesInteractive 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"
}
FieldTypeDescription
page_countintegerTotal number of pages in the document.
span_countintegerNumber of spans extracted across all pages.
block_countintegerNumber of blocks extracted across all pages.
error_countintegerNumber of pages that failed to extract.
receipts_modestringReceipts mode used: "off", "lite", or "svg".
diagnosticsarrayDiagnostic messages emitted during extraction (coverage warnings, etc.).
cache_statusstring/nullCache status: "hit", "miss", or "skipped".
cache_age_secondsinteger/nullCache entry age in seconds (only present when cache_status == "hit").
reading_order_algorithmstring/nullReading order algorithm used for this extraction.

Page Result

Each page in the pages array contains:

{
  "index": 0,
  "spans": [...],
  "blocks": [...],
  "tables": [...],
  "error": null
}
FieldTypeRequiredDescription
indexintegerYesZero-based page index. This is the canonical identifier for programmatic use.
spansarrayYesExtracted spans (text fragments with consistent styling).
blocksarrayYesExtracted blocks (semantic units like paragraphs, headings).
tablesarrayYesExtracted tables with cell-level structure. Empty when no tables detected.
errorstring/nullYesError 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
}
FieldTypeRequiredDescription
textstringYesThe extracted text content.
bboxarrayYesBounding 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.
fontstringYesFont name or identifier.
sizenumberYesFont size in points.
columninteger/nullNoColumn index (0-based) assigned by Phase 4.3 column detection. Null for spans outside any detected column.
confidencenumber/nullNoConfidence score (0.0 to 1.0). Present when OCR is used or extraction has uncertainty.
receiptobject/nullNoCryptographic 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
}
FieldTypeRequiredDescription
kindstringYesThe block kind/type. Common values: "paragraph", "heading", "list", "table", "figure".
textstringYesThe concatenated text content of all spans in the block.
bboxarrayYesBounding box in PDF user-space points. Same format as spans.
levelinteger/nullNoHeading level (1-6) for "heading" kind blocks. Null for other block types.
table_indexinteger/nullNoTable index for "table" kind blocks. Points to the corresponding entry in the page’s tables array.
receiptobject/nullNoCryptographic receipt for verification. Present when receipts are enabled.

Block Kind Enum

ValueDescription
paragraphA paragraph block.
headingA heading block (with level field 1-6).
listA list item block.
tableA table block (references tables array via table_index).
figureA figure or image block.
codeA code block or monospace text.
formulaA mathematical formula.
headerA page header block.
footerA page footer block.
watermarkA watermark block.
captionA caption for a figure or table.
quoteA 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": [...]
}
FieldTypeRequiredDescription
idstringYesUnique identifier for this table (e.g., "table_0").
page_indexintegerYesZero-based page index where this table appears.
bboxarrayYesBounding box in PDF user-space points.
detection_methodstringYesDetection method: "line_based" (ruling lines) or "borderless" (x0 alignment heuristics).
header_rowsintegerYesNumber of contiguous header rows at the top of the table.
continuedbooleanYesWhether this table continues on the next page.
continued_from_prevbooleanYesWhether this table is a continuation from the previous page.
rowsarrayYesRows 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": [...]
}
FieldTypeRequiredDescription
bboxarrayYesBounding box in PDF user-space points.
is_headerbooleanYesWhether this row is a header row.
cellsarrayYesCells 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]
}
FieldTypeRequiredDescription
textstringYesThe concatenated text content of all spans in the cell.
bboxarrayYesBounding box in PDF user-space points.
rowintegerYesZero-based row index within the table.
colintegerYesZero-based column index within the table.
rowspanintegerYesNumber of rows this cell spans (default 1).
colspanintegerYesNumber of columns this cell spans (default 1).
is_header_rowbooleanYesWhether this cell is in a header row.
spansarrayYesReferences 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
}
FieldTypeRequiredDescription
namestringYesThe absolute (dot-joined) field name from the AcroForm.
typestringYesField type: "text", "button", "choice", or "signature".
valuevariesYesThe current value (structure varies by type).
defaultvariesNoThe default value (/DV entry).
read_onlybooleanYesWhether this field is read-only (bit 1 of /Ff flags).
requiredbooleanYesWhether this field is required (bit 2 of /Ff flags).
page_indexinteger/nullNoZero-based page index where this field’s widget appears.
rectarray/nullNoBounding box in PDF user-space points.
multilineboolean/nullNoWhether this text field supports multiple lines (text fields only).
max_lengthinteger/nullNoMaximum length for text fields (/MaxLen entry).
multi_selectboolean/nullNoWhether this choice field supports multiple selections.
optionsarray/nullNoAvailable options for choice fields ([export_value, display_name] pairs).
radioboolean/nullNoWhether this button is a radio button (button fields only).
pushbuttonboolean/nullNoWhether this button is a pushbutton (button fields only).
selectedboolean/nullNoSelected state for button fields.
state_namestring/nullNoAppearance 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"
}
FieldTypeRequiredDescription
field_namestringYesThe absolute (dot-joined) field name from the AcroForm.
signer_namestringYesThe signer’s name from the /Name entry. Empty string if absent.
validation_statusstringYesValidation status — always "not_checked" in v1. Future versions may add "valid", "invalid", "indeterminate".
signing_datestring/nullNoThe signing date as an ISO 8601 string (RFC 3339 format).
locationstring/nullNoThe location of signing from the /Location entry.
reasonstring/nullNoThe reason for signing from the /Reason entry.
sub_filterstring/nullNoThe signature format/filter from the /SubFilter entry.
byte_rangearray/nullNoThe /ByteRange array defining which bytes of the file are signed.
coverage_fractionnumber/nullNoFraction 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
}
FieldTypeRequiredDescription
pdf_fingerprintstringYesPhase 1.7 fingerprint of the source PDF.
page_indexintegerYesZero-based page index in the source PDF.
bboxarrayYesBounding box in PDF user-space points.
content_hashstringYesSHA-256 hash of the NFC-normalized text content. Format: "sha256:" + hex(SHA-256).
extraction_versionstringYesThe pdftract version that produced this receipt (semver string).
svg_clipstring/nullNoSVG clip rendering the glyphs (present only in SVG mode).

Receipts Mode

ModeDescription
offNo receipts generated (default).
liteMinimal receipts (~120 bytes each) with fingerprint, page index, bbox, and content hash.
svgExtended 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 /EmbeddedFiles name 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:

SeverityDescription
WARNWarning - extraction succeeded but with potential quality issues (e.g., low coverage suggesting scanned content).
ERRORError - 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-core crate 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

OptionTypeDefaultUse Case
pagesstr | NoneNonePage range (e.g., "1-5,7,12-")
passwordstr | NoneNonePDF password for encrypted documents
receiptsstr | NoneNoneReceipt mode: "off", "lite", or "full"
ocrboolFalseEnable OCR for scanned documents
ocr_languagelist[str]["eng"]OCR language codes
include_invisibleboolFalseInclude invisible text in output
extract_formsboolTrueExtract AcroForm fields
extract_attachmentsboolTrueExtract embedded attachments
readability_thresholdfloat0.0Minimum readability score
max_decompress_gbint512Max decompressed GB per stream
full_renderboolFalseEnable 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 errors
  • EncryptionError — PDF encryption/password errors
  • CorruptPdfError — Malformed or corrupted PDF
  • SourceUnreachableError — File or URL unreachable
  • RemoteFetchInterruptedError — Network interruption during fetch
  • TlsError — TLS/certificate errors
  • ReceiptVerifyError — Receipt verification failed
  • UnsupportedOperationError — 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 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

FieldTypeDefaultUse Case
receiptsReceiptsModeOffGenerate cryptographic receipts
max_parallel_pagesusize4Control memory for concurrent page processing
memory_budget_mbusize512Target peak RSS in MB
full_renderboolfalseEnable PDFium rendering (requires full-render feature)
ocr_dpi_overrideOption<u32>NoneOverride automatic DPI selection
ocr_languageVec<String>vec!["eng"]Tesseract language codes
markdown_anchorsboolfalseEmit HTML comment anchors in Markdown
max_decompress_bytesu64512 MiBBomb limit for decompressed streams
outputOutputOptionsdefault()Output filtering options
pagesOption<String>NonePage range (e.g., "1-5,7,12-")
passwordOption<SecretString>NonePDF password for encrypted documents

OutputOptions

FieldTypeDefaultUse Case
include_invisibleboolfalseInclude invisible text in output
extract_formsbooltrueExtract AcroForm fields
extract_attachmentsbooltrueExtract 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

FeatureAddsDefault
serdeJSON serialization support
decryptDecryption of encrypted PDFs
quick-xmlConformance detection via XML metadata
ocrTesseract OCR for scanned documents-
full-renderPDFium-based rendering (requires ocr)-
remoteHTTP range fetching for remote PDFs-
profilesExtraction profiles-
receiptsCryptographic receipt generation-
cjkCJK text extraction via predefined CMap registry-
schemarsJSON 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

SymptomLikely Diagnostic Code
PDF won’t open, “encrypted” errorENCRYPTION_UNSUPPORTED
Text extraction incomplete or missingXREF_REPAIRED, OCR_*_UNSUPPORTED
Process hangs or runs very longSTREAM_BOMB
“Path outside root” (MCP mode)MCP_PATH_TRAVERSAL
Cache errors / corrupted entriesCACHE_ENTRY_CORRUPT, CACHE_INTEGRITY_FAIL
Profile fails to loadPROFILE_INVALID, PROFILE_SECRETS_FORBIDDEN
Remote URL fetch blockedURL_PRIVATE_NETWORK
Requested page doesn’t existPAGE_OUT_OF_RANGE
Text contains placeholder characters (⍰)GLYPH_UNMAPPED
Broken vector graphics not recoveredBROKENVECTOR_OCR_UNAVAILABLE
JavaScript warning in outputJAVASCRIPT_PRESENT
Circular reference warningsSTRUCT_CIRCULAR_REF, STRUCT_XOBJECT_CYCLE
Stack overflow warningsGSTATE_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 image
  • OCR_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 --root restriction (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 violation
  • PROFILE_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 cycle
  • STRUCT_XOBJECT_CYCLE: XObject (image/form) reference cycle
  • GSTATE_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:

  1. Check the Diagnostics Reference for the full catalog
  2. Search existing issues on GitHub
  3. Open a new issue with:
    • The diagnostic code(s)
    • A minimal reproducible example (PDF or command)
    • The --debug output if safe to share

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 page field)
  • 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:

  1. Start pdftract in serve mode:
pdftract serve --port 8080
  1. Configure your reverse proxy (nginx, Apache, etc.) to handle authentication and SSL termination.

  2. 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 --password to 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:

  1. No text layer: PDF may be image-only. Enable OCR.
  2. Encoding issues: Check diagnostics for FONT_GLYPH_UNMAPPED warnings
  3. Page range issue: Verify your --pages argument
  4. Confidence filter: Lower --min-confidence if 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 Unicode
  • STREAM_DECODE_ERROR: Stream decompression failed
  • STRUCT_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?