Turn any document into structured data.

One async Python interface over 20+ parsing engines — PDF, DOCX, XLSX, HTML, images → LLM-ready markdown/JSON, with extension-aware routing and automatic fallback. Open source, MIT.

or just tell your agent: fetch https://docfold.xyz/install.md

20+ engines · local, OCR & cloud tiers · built-in evaluation framework · 350+ tests · MIT

One-click install for AI agents

docfold ships a CLI (docfold) and an MCP server (docfold-mcp) with four tools — parse_document, extract_tables, list_engines, classify_document. All four definitions cost your agent under 1000 tokens (budget-tested). Failures come back structured ({error, failures}) — never garbage posing as content. One command registers it in your client:

$ pip install "docfold[mcp,pymupdf]"
$ docfold install claude   # Claude Code
$ docfold install codex    # Codex CLI
$ docfold install cursor   # Cursor
$ docfold install vscode   # VS Code
Add to Cursor

Any other client: paste the config JSON above into its MCP settings. Full agent instructions live at install.md — fetchable by any agent.

Why Docfold?

Every document parser has trade-offs — speed, tables, scans, cost. Docfold lets you switch between them with one line, and falls back automatically when an engine fails on a file.

Try a new parser

Before: rewrite your pipeline for each SDK
After: change one string — engine_hint="docling"

Scanned or born-digital?

Before: guess, then watch OCR mangle clean PDFs
After: pre_analyze() → pdf_text vs pdf_scanned routing

Engine fails on a file

Before: hand-roll try/except chains
After: router auto-falls back down the priority chain

Pick the best engine for YOUR docs

Before: trust vendor benchmarks
After: docfold evaluate — WER/CER on your own dataset

20+ engines, one interface

Local engines are free and fast; OCR engines handle scans; cloud engines add managed accuracy. Every engine is an optional extra — install only what you use.

PyMuPDF local
Fast text + layout from born-digital PDFs
Docling local · IBM
Layout, tables, reading order
Marker local · gpu
High-fidelity PDF → markdown
MinerU local · gpu
Scientific PDFs, formulas
MarkItDown local · microsoft
Office, HTML, CSV → markdown
Unstructured local
Broad format coverage, chunking
Tesseract local · ocr
Classic OCR for scans and images
PaddleOCR local · ocr
Multilingual OCR, strong on CJK
EasyOCR local · ocr
80+ languages, simple setup
Surya local · ocr · gpu
Modern OCR + layout detection
Nougat local · gpu
Academic PDFs → LaTeX-aware markdown
Chandra local · gpu
VLM-based OCR for hard scans
Mistral OCR cloud
LLM-grade OCR API
LlamaParse cloud
Managed parsing for RAG
Azure Doc Intelligence cloud
Forms, invoices, prebuilt models
Google Document AI cloud
Enterprise OCR + entity extraction
AWS Textract cloud
Tables and forms at scale
OpenDataLoader local · java
Open-source PDF structure extraction
Firecrawl cloud
Web pages → markdown
Zerox · LiteParse · … more
See docfold engines for the full list

How to choose

Or skip the decision entirely — call router.process(file) and let extension-aware routing pick.

  • Born-digital PDF (has a text layer)PyMuPDF — sub-second, zero GPU
  • Complex layout, tables, reading orderDocling or Marker
  • Scanned PDF or photo of a documentTesseract (free) → Surya / Mistral OCR (better)
  • Office files (DOCX, XLSX, PPTX)MarkItDown or Unstructured
  • Scientific papers with formulasMinerU or Nougat
  • Invoices and forms with key-value fieldsAzure Doc Intelligence / AWS Textract
  • Not sure which engine is best for your corpusdocfold evaluate — benchmark them on your own files
  • Need an MCP server for AI agentsdocfold-mcp — built-in; register with docfold install claude

Quickstart

Install one extra per engine, or docfold[all] for everything.

import asyncio
from docfold import EngineRouter, OutputFormat
from docfold.engines.pymupdf_engine import PyMuPDFEngine
from docfold.engines.docling_engine import DoclingEngine

async def main():
    router = EngineRouter([PyMuPDFEngine(), DoclingEngine()])

    # Auto-routed by extension; falls back if an engine fails
    result = await router.process("report.pdf")
    print(result.content)         # LLM-ready markdown
    print(result.engine_name)     # which engine actually parsed it

    # Force an engine, get JSON with tables and bounding boxes
    result = await router.process(
        "invoice.pdf",
        output_format=OutputFormat.JSON,
        engine_hint="docling",
    )

asyncio.run(main())
# CLI
$ docfold convert report.pdf                 # auto-routed → markdown
$ docfold convert scan.pdf -e tesseract -f json
$ docfold compare report.pdf -e pymupdf,docling  # side-by-side quality check
$ docfold engines
$ docfold doctor            # health check: engines, MCP extra
$ docfold update --check    # self-update via PyPI

Built by & ecosystem

Docfold is built and maintained by Mike Sadofyev (CEO, Datatera.ai) — the document engine behind Datatera — alongside a small ecosystem of AI-data tooling. Connect on LinkedIn, X, or GitHub.