A fast Rust library that tells text-based PDFs from scanned ones, then extracts position-aware text and clean Markdown — locally, in milliseconds. Skip the OCR bill for the ~54% of PDFs that never needed it.
TextBased, Scanned, ImageBased, or Mixed in ~10–50ms by sampling content streams. Returns a confidence score and per-page OCR routing.
Extraction with font info, X/Y coordinates, and automatic multi-column reading order.
Headings, bullet/numbered lists, code blocks, tables, bold/italic, URL linking, and page breaks.
Rectangle-based detection from drawing ops plus heuristic alignment detection. Financial tables, footnotes, and cross-page continuations.
ToUnicode CMap decoding for Type0/Identity-H fonts, with UTF-16BE, UTF-8, and Latin-1 encodings.
Newspaper-style column detection, sequential reading order, and right-to-left text support.
Flags broken font encodings automatically so callers can fall back to OCR only when it's actually needed.
Pure Rust. No ML models, no external services. A single parse shared between detection and extraction.
Evaluated on the opendataloader-bench corpus (200 PDFs). Local engines without model-based PDF parsing; OCR disabled. Higher is better.
| Engine | Overall | Reading order | Tables | Headings | 200 docs |
|---|---|---|---|---|---|
| pdf-inspector | 0.875 | 0.915 | 0.814 | 0.788 | 2.8s |
| liteparse | 0.870 | 0.908 | 0.693 | 0.811 | 13.9s |
| opendataloader | 0.843 | 0.912 | 0.489 | 0.760 | 9.8s |
| pymupdf4llm | 0.735 | 0.886 | 0.401 | 0.424 | 15.5s |
| markitdown | 0.583 | 0.879 | 0.000 | 0.000 | 6.7s |
Native-text PDFs where speed, reading order, and table structure matter. pdf-inspector delivered the highest overall, reading-order, and table scores, along with the fastest complete run in this benchmark. That makes it a strong local default for reports, research papers, financial documents, invoices, and legal PDFs that need clean, structured Markdown without adding OCR latency or infrastructure.
use pdf_inspector::process_pdf; let result = process_pdf("document.pdf")?; println!("Type: {:?}", result.pdf_type); if let Some(markdown) = &result.markdown { println!("{}", markdown); } // full reference → docs/rust-api.md
import pdf_inspector result = pdf_inspector.process_pdf("document.pdf") print(result.pdf_type) # "text_based" | "scanned" | "image_based" | "mixed" print(result.markdown) # Markdown string or None # full reference → docs/python.md
import { readFileSync } from 'fs'; import { processPdf } from '@firecrawl/pdf-inspector'; const result = processPdf(readFileSync('document.pdf')); console.log(result.pdfType); // "TextBased" | "Scanned" | ... console.log(result.markdown); // Markdown string or null // full reference → napi/README.md
# install the CLI tools cargo install pdf-inspector # convert a PDF to Markdown pdf2md document.pdf # classify only — is it scanned? detect-pdf document.pdf --analyze --json # structured output for pipelines pdf2md document.pdf --json
Run the classifier locally for text-based PDFs; hand the scanned, OCR, and at-scale work to Firecrawl.
Pure-Rust library and CLI. Classify and extract text-based PDFs on your own machine in milliseconds — no external calls, no OCR bill, MIT licensed.
Scanned documents, OCR, DOCX / XLSX / HTML, and parsing at scale — clean, LLM-ready Markdown from one API call. The downstream route for everything local parsing can't reach.