One binary. Every format. No JVM · No C++ · No Python.
PDF DOCX HTML XLSX PPTX Markdown CSV SRT / VTT LaTeX EML PNG / JPEG AsciiDoc

## Built for retrieval that cites its sources

It takes the structure-extraction fast path — interpreting PDF content streams for coordinates instead of rendering pages to pixels — so output is byte-identical and parses are sub-10 ms.

🦀

### One pure-Rust binary

~29 MB, zero runtime deps, `<10 ms` warm parse (~700 pages/s). Drop it on a server, a laptop, or a CI box — no environment to set up.

📍

### RAG-native citations

Every chunk carries page + bbox + heading breadcrumbs. Reverse `locate(x, y)` lookup, with 100% coverage — answers that point back to the exact spot on the page.

🔌

### Four faces, one output

CLI · library · MCP (stdio) · REST — and the output is byte-identical across all four. Wire it straight into an agent.

🔍

### In-process OCR

`--ocr` runs ONNX on `tract` (PP-OCRv6 tiny by default). Digital-text pages pass through; routed PDF pages use embedded pixels or render their final appearance on demand. ~7 MB fetched on first use.

🧠

### Embedded models, opt-in

Merged-cell table structure, formula → LaTeX, full-page transcription (UniRec-0.1B), plus PP-DocLayoutV2 / DocLayout-YOLO layout. None of it baked into the binary.

🛡️

### Safe by default

Hidden-text filtering (flagged & auditable, never silently dropped), zip-bomb & page-count guards, per-page complexity profiling. The deterministic core stands alone.

bash

    # build once — no toolchain zoo, just cargo
    $ cargo build --release

    # full IR: provenance + coordinates
    $ docparse input.pdf -f json

    # clean Markdown
    $ docparse input.pdf -f markdown

    # RAG chunks — page + bbox + breadcrumbs
    $ docparse input.pdf -f chunks

    # OCR pages without machine-readable text
    $ docparse scan.pdf --ocr

## Up and running in one command

No JVM, no C++ build chain, no Python venv. Build the binary, point it at a file, pick an output format. Born-digital PDFs and every other format parse with zero downloads.

Full quick start →

## Plug straight into your agent

Register it as an MCP server, or run the local REST endpoint. Same parser, same byte-identical output — pick the surface that fits your stack.

Integration docs →
agent

    # MCP tools: parse_document / get_chunks / locate
    $ claude mcp add docparse -- docparse mcp

    # local REST (binds 127.0.0.1)
    $ docparse serve --port 8642
    $ curl -F "file=@doc.pdf" \
        "http://127.0.0.1:8642/parse?format=chunks"

    # Python / LangChain — zero-dep thin client
    from docparse_client.langchain import DocparseLoader
    docs = DocparseLoader("paper.pdf").load()

## Scored against human ground truth

Evaluated on OmniDocBench (CVPR 2025) using the embedded UniRec models. Text and formula land near paper level.

0.872
Text recognition
--transcribe-model · papers
0.874
Formula → LaTeX
--formula-model · papers
0.810
Table structure
--table-model · median 0.895

A proxy “Overall” ≈ 75 puts docparse-rs in the pipeline-tool tier (Marker 78, Docling ~80–85) — all from one zero-dependency binary. Full method, caveats & leaderboard →

## How it compares

The same job other tools do with a JVM, PDFium/Tesseract C++ deps, or a multi-GB Python env — in one self-contained Rust binary.

| docparse-rs | liteparse | Docling | MarkItDown
--- | --- | --- | --- | ---
Deploy | pure-Rust ~29 MB, zero deps | Rust + PDFium/Tesseract (C++) | Python + models (GB env) | Python
PDF engine | own content-stream interpreter | wraps PDFium | own | delegates
Determinism | byte-identical default path | deterministic | not strictly | deterministic
Citations | page+bbox both ways, 100% | bbox per text element | element-level | none
Output | JSON / MD / text / RAG chunks | JSON / text / PNG | Markdown / JSON | Markdown
Formats | 12, all in-process | PDF native; rest external | 15+ | 20+
Speed (born-digital) | <10 ms / ~700 pg/s | fast | seconds/page | fast

Honest about tradeoffs: Docling's neural layout has a higher ceiling on the hardest layouts; MarkItDown covers more long-tail formats; non-zh/en OCR (RTL / Korean) isn't covered yet. Detailed comparison →

## A core that owes nothing to the AI

A Cargo workspace of 17 crates. The deterministic core stands alone; neural models attach only where they earn their keep.

### 🏗️ Deterministic by design

- core depends on no PDF library — reading order & output are format-agnostic; adding a format is one trait + one registry line.
- A self-built PDF content-stream interpreter — a graphics/text matrix state machine emitting positioned chunks.
- An independent font layer (ToUnicode CMap / AFM / Encoding), with veraPDF as the algorithmic reference only — no copied code.
- Per-page rayon parallelism; identical input → byte-identical output.

### 🧩 Models at the boundary

- Neural models never enter the core — they attach per page through an `Enhancer` boundary.
- Only a hard page routed to a model is ever rendered — on demand, in pure Rust.
- Every model output carries a source tag + capped confidence, so provenance is always traceable.
- All optional models are Apache-2.0, fetched as external files — never baked into the binary.

## If this is the parser you wish you'd had,
give it a star

Open source, Apache-2.0, pure Rust. Stars help others find it — and tell us to keep pushing.

★ Star on GitHub Read the docs →