---
title: "pdf-inspector Review: Local PDF Parsing Before OCR"
canonical: https://wavect.io/blog/pdf-inspector-ocr-routing/
language: en
description: "Review Firecrawl pdf-inspector for local PDF-to-Markdown and OCR routing. Verify its benchmark, limits, browser support, costs and production fit."
image: "https://wavect.io/img/blog/headers/header_pdf-inspector-ocr-routing.png"
---

[**Back**](/blog/overview/)

[![Kevin Riedl](/img/team/kevin.webp)](/team/kevin-riedl/)

[Kevin Riedl](/team/kevin-riedl/) https://linkedin.com/in/wsdt

13 min read · 6 Aug 2026

[**Next**](/blog/local-multimodal-ai-coding-assistant/)

# pdf-inspector review: route PDFs before OCR

TL;DR

pdf-inspector is an MIT-licensed Rust library that classifies PDFs and extracts native text as Markdown without OCR. Firecrawl's 31 July 2026 benchmark reports 0.470 seconds for 200 documents on an Apple M4 Pro, but OCR was disabled, so this is a direct-text benchmark rather than proof that scanned PDFs finish in milliseconds. Use it as the first stage of a hybrid pipeline: validate and isolate the upload, extract high-confidence text locally, send only flagged pages or regions to OCR, preserve page provenance, and measure quality on your own corpus. Node.js, Python, Rust and browser WebAssembly bindings are available.

**pdf-inspector is a fast local PDF parser and OCR router, not an OCR engine.** Firecrawl's open-source Rust library classifies a document as text-based, scanned, image-based or mixed, extracts usable native text as Markdown, and returns the pages that still need OCR. That distinction is the product opportunity. A pipeline can stop paying the slowest, most expensive processing path for pages that already contain machine-readable text.

The viral claim says 0.002 seconds per page. The repository contains a strong benchmark, but not that exact universal promise. This review separates the measured result from the social post, explains where native parsing ends, and gives you a production decision framework for RAG ingestion, invoice extraction, legal-document search and AI-agent workflows.

## What does pdf-inspector actually do?

**It reads the PDF's internal structure before anyone renders a page or calls a model.** The detector looks for text and image operators across the page tree. The extractor then reconstructs text with positions, font information, columns, links, lists, headings and tables. The result includes a confidence score, layout flags and a list of pages that need OCR.

| PDF result | Recommended route | Why |
| --- | --- | --- |
| TextBased, high confidence | Extract locally to Markdown | The file already has a usable text layer. OCR adds latency and can introduce recognition errors. |
| Mixed | Extract native pages, OCR only flagged pages or regions | A single document may combine exported reports, signatures, scanned appendices and image pages. |
| Scanned or ImageBased | Render and send to an OCR or vision pipeline | There is no usable native text to recover. |
| Encoding issues or low confidence | Fallback to OCR, then validate | A text operator can exist while the decoded characters are still garbage. |

The library does not include an OCR model. That is deliberate. The [official pdf-inspector README](https://github.com/firecrawl/pdf-inspector) describes a pure Rust parser with no ML model or external service. Firecrawl's hosted [Fire-PDF pipeline](https://www.firecrawl.dev/blog/fire-pdf-launch) is a broader product: it uses pdf-inspector for classification and native extraction, then applies layout detection and GLM-OCR to regions that need it. Do not evaluate one as if it were the other.

## Does it really process 200 PDFs in 0.470 seconds?

**Yes, in Firecrawl's published direct-text benchmark. No, that does not mean every PDF page finishes in two milliseconds.**

| Published detail | What it means | What it does not prove |
| --- | --- | --- |
| 200-document opendataloader-bench corpus | A shared evaluation corpus, processed sequentially in one process | Your invoices, contracts, scans and languages will match the corpus |
| 0.470 seconds total | About 2.35 milliseconds per document as a simple corpus average | Two milliseconds per page, p95 latency, upload time or OCR time |
| Apple M4 Pro, median of five runs | A documented machine and repeat-run method | The same speed in a browser, container, low-cost VM or cold start |
| OCR disabled | A fair comparison between local non-model parsers | Accuracy or speed on scanned pages |
| Overall 0.875, reading order 0.915, tables 0.814 | Strong reported structure scores for version 0.2.6 on that benchmark | Perfect extraction or superiority on every document type |

The results were refreshed on 31 July 2026. They compare pdf-inspector 0.2.6 with LiteParse, OpenDataLoader, PyMuPDF4LLM and MarkItDown, with the full configuration and artifacts linked from the repository. The responsible buying conclusion is not "fastest PDF parser everywhere." It is "a promising local default for native-text PDFs that deserves a corpus-specific bake-off."

Firecrawl also says roughly 54% of the PDFs in its workload do not need OCR. Treat that as a vendor workload estimate, not a universal distribution. Run detection over your own last 30 to 90 days of documents before building the business case.

## The production architecture: classify first, escalate second

1. **Accept safely.** Enforce file and page limits, verify the signature rather than trusting the MIME header, replace user-controlled filenames, and store uploads outside the web root.
2. **Parse in isolation.** Give the parser a CPU, memory and wall-clock budget. Treat every supplier PDF, email attachment and public upload as untrusted input.
3. **Classify once.** Record document type, confidence, page count, encoding warnings, complex-layout flags and pages needing OCR.
4. **Use the cheap path.** Convert high-confidence native text to Markdown without a network call.
5. **Escalate narrowly.** Render only flagged pages or regions and send those to the approved OCR service or local model.
6. **Assemble with provenance.** Merge results in original page order. Preserve page numbers, parser version, route, confidence and any human correction.
7. **Gate the output.** Check empty pages, character quality, table shape, totals, dates, identifiers and required fields before indexing or triggering an agent action.

This is where the savings come from. If a 100-page document has 82 usable native pages, the pipeline avoids 82 OCR-page calls. The planning formula is simple:

Estimated routing value = avoided OCR pages × marginal OCR-page cost, minus parser compute, engineering and correction cost.

Keep failed documents in the denominator. Our [AI agent cost-per-action framework](/blog/ai-agent-cost-per-action-2026/) explains why a cheap extraction that later needs manual repair is not a successful action. For systems that index the Markdown, continue with the [EU RAG production-readiness checklist](/blog/rag-production-readiness-checklist-eu/). That page owns retrieval, permissions, evaluation and answer citations. This page owns the PDF ingestion route before chunking.

## Node.js, Python, Rust or browser WebAssembly?

| Binding | Best fit | Production caveat |
| --- | --- | --- |
| Node.js or Bun | API services, queues and TypeScript products | Prebuilt native packages cover listed platforms. Verify your deployment architecture and keep the binary patched. |
| Python | Data engineering, evaluation and RAG ingestion | Result types use both zero-indexed and one-indexed page lists in different APIs. Normalize page numbering at your boundary. |
| Rust or CLI | High-throughput services and controlled batch jobs | You own process isolation, resource limits, observability and upgrades. |
| Browser WebAssembly | Private local conversion and preflight before upload | Extraction is synchronous after initialization. Use a Web Worker for large files so the interface stays responsive. |

The [official WebAssembly documentation](https://github.com/firecrawl/pdf-inspector/blob/main/wasm/README.md) says PDF bytes remain local, the build is single-threaded, CMaps are embedded, and image-only files still need a separate OCR step. That makes the browser version useful for privacy-sensitive preflight, but it does not turn the browser into a complete document-intelligence stack.

A Node.js route can stay small. The OCR and merge functions below are application code, not pdf-inspector APIs:

```
const result = classifyPdf(pdfBuffer)

if (result.pdfType === "TextBased" && result.confidence >= 0.9) {
  return processPdf(pdfBuffer).markdown
}

const native = processPdf(pdfBuffer).markdown
const scanned = await ocrOnly(pdfBuffer, result.pagesNeedingOcr)
return mergeByPage(native, scanned)
```

Do not hard-code 0.9 because it looks safe. Tune the threshold against false negatives, especially pages that appear to contain text but decode into noise. In invoice or legal workflows, one missed page can cost more than thousands of correctly avoided OCR calls.

## Where pdf-inspector is a poor fit

- **Scans, handwriting and photographs:** it can route them, but it cannot read them without another OCR or vision component.
- **Visual semantics that are not encoded as text:** diagrams, checkboxes, signatures, stamps and spatial relationships may require layout or vision models.
- **Perfect reconstruction:** headings and tables are inferred from fonts, drawing operations and alignment. Heuristics can be wrong.
- **Unbounded public uploads:** Rust reduces some memory-safety risk, but a parser still needs limits, isolation and dependency updates. The project's [security policy](https://github.com/firecrawl/pdf-inspector/blob/main/SECURITY.md) explicitly includes crafted-PDF memory and denial-of-service issues in scope.
- **A zero-operations requirement:** an open library gives you control, not a service-level agreement, review queue or automatic recovery.

OWASP's [file-upload guidance](https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html) recommends defense in depth: allowlisted types, signature checks, size limits, isolated storage, parser updates, malware scanning and sandboxing where available. Local processing can reduce data transfer. It does not make uploaded PDFs trustworthy.

## Build, buy or run a hybrid PDF pipeline?

| Choice | Choose it when | You own |
| --- | --- | --- |
| Embed pdf-inspector directly | Most files have native text, privacy matters, and your team can operate the pipeline | Routing thresholds, OCR integration, security, quality gates and upgrades |
| Buy a managed full parser | Documents are unpredictable, scans and complex layouts dominate, and speed to production matters | Vendor evaluation, data-processing terms, fallback and output acceptance |
| Hybrid local plus managed OCR | You want local handling for routine pages and specialist accuracy only on exceptions | Two data paths, page-level assembly, observability and cost governance |
| Keep the current parser | Extraction is already accurate, cheap and operationally boring | Proving that a rewrite would create material value before funding it |

## A ten-day evaluation before you commit

1. **Sample reality:** select at least 200 representative PDFs across languages, sources, page counts and failure cases. Keep a separate hostile and malformed set.
2. **Label the route:** mark which pages have reliable native text, need OCR, need layout processing or should be rejected.
3. **Run a baseline:** measure the current parser's quality, p50 and p95 latency, OCR pages, correction minutes and cost per accepted document.
4. **Run pdf-inspector:** pin the version and machine. Measure classification recall first, then Markdown structure and end-to-end throughput.
5. **Price the exceptions:** calculate avoided OCR pages, extra engineering, human repair and the cost of a missed scan.
6. **Attack the boundary:** test oversized, encrypted, malformed, misleading and resource-intensive PDFs in an isolated environment.
7. **Choose with a gate:** ship only if the hybrid route improves cost or latency without breaching the agreed extraction and safety thresholds.

If this becomes product infrastructure, use our [AI enablement service](/services/ai-enablement/) to benchmark the corpus, build the routing layer and put evaluation around it. [Twinsoft AI](/case-studies/twinsoft-ai/) shows the same principle applied to production AI: quality gates and traceable evidence around model output. The [MVP technology-selection guide](/software-development-guide/how-to-choose-a-tech-stack-for-mvp/) helps decide which parts to own and which to buy before architecture hardens.

## Frequently asked questions

### Is pdf-inspector an OCR engine?

No. It classifies PDFs and extracts native text without an OCR model. Scanned, image-based, low-confidence or broken-encoding pages still need a separate OCR or vision step.

### Is pdf-inspector really the fastest PDF parser?

It was the fastest complete run in Firecrawl's published 31 July 2026 comparison of five local, non-model parsers on 200 documents. That benchmark used an Apple M4 Pro and disabled OCR. Reproduce it on your own corpus before making a general claim.

### Can pdf-inspector run fully in the browser?

Yes. The WebAssembly package classifies and extracts locally from a Uint8Array, and the official docs say the bytes are not uploaded. The extraction call is synchronous, so large files should run inside a Web Worker. Image-only files still need OCR.

### How much OCR cost can routing save?

It depends on the share of pages with reliable native text. Count avoided OCR pages on your own corpus, multiply by marginal OCR-page cost, then subtract parser compute, engineering, monitoring and human correction. Firecrawl's roughly 54% figure describes its workload, not yours.

### Should I use pdf-inspector for a RAG pipeline?

It is a strong candidate for the ingestion gate before chunking when many PDFs contain native text. Keep page provenance, route scans to OCR, validate structure, and separately test retrieval, permissions and answer citations.

## Primary sources and benchmark date

- [Firecrawl pdf-inspector repository and benchmark](https://github.com/firecrawl/pdf-inspector), refreshed 31 July 2026.
- [Official Node.js and Bun API documentation](https://github.com/firecrawl/pdf-inspector/blob/main/napi/README.md).
- [Official Python API documentation](https://github.com/firecrawl/pdf-inspector/blob/main/docs/python.md).
- [Official browser WebAssembly documentation](https://github.com/firecrawl/pdf-inspector/blob/main/wasm/README.md).
- [Firecrawl's Fire-PDF architecture announcement](https://www.firecrawl.dev/blog/fire-pdf-launch).
- [OWASP File Upload Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/File_Upload_Cheat_Sheet.html).

## Final thoughts

pdf-inspector is interesting because it puts a cheap decision before an expensive operation. The published benchmark makes it a credible candidate for native-text PDF extraction, while its page-level routing makes mixed corpora commercially useful. The caveat is equally important: it does not perform OCR, and its 0.470-second result does not describe scanned-document processing.

Use it as a router, not a miracle. Pin the version, isolate untrusted files, benchmark your own documents, send only uncertain pages to OCR, and judge the system by accepted documents, correction time and total cost. That is how a viral speed claim becomes production architecture.

## You may also like..

[**RAG Production-Readiness Checklist for EU Companies** The retrieval, permission, evaluation and citation controls that start after PDF extraction.](/blog/rag-production-readiness-checklist-eu/) [**AI Enablement vs a Generic AI Consultancy** Compare a working AI setup on your infrastructure with a strategy-only engagement.](/compare/ai-enablement-vs-generic-ai-consultancy/)

Models and infrastructure

## Continue through this cluster

[Start with the cornerstone**Self-Hosting LLMs in the EU: When Open Weights Actually Pay Off**](/blog/self-hosting-llms-eu-cost/)

- [Local Multimodal AI Coding Assistant: Voice, OCR and Privacy](/blog/local-multimodal-ai-coding-assistant/)
- [DeepSeek V4 Flash 0731 on One AI PC: What Actually Works?](/blog/deepseek-v4-flash-0731-local-ai-pc/)
- [Fine-Tune Gemma 4 Free with Unsloth and Colab](/blog/fine-tune-gemma-4-free-unsloth-colab/)
- [Taalas HC1 Review: Is a Hardwired LLM ASIC Worth It?](/blog/taalas-hc1-llm-asic-review/)
- [llmfit Guide: Which Local LLM Fits Your Hardware?](/blog/llmfit-local-llm-hardware-guide/)

Inbox, without the noise

## Follow the work that matters to you

Get a short email when we publish something new. Follow the whole blog or only the problems you care about.

[**Back**](/blog/overview/)

[![Kevin Riedl](/img/team/kevin.webp)](/team/kevin-riedl/)

[Kevin Riedl](/team/kevin-riedl/) https://linkedin.com/in/wsdt

13 min read · 6 Aug 2026

[**Next**](/blog/local-multimodal-ai-coding-assistant/)

New posts by email ×

×

Get new posts by email

A short email when we publish. Free, no tracking.

## Structured Data

```json
{
  "@context": "https://schema.org",
  "@graph": [
    {
      "@id": "https://wavect.io/#organization",
      "@type": [
        "Organization",
        "ProfessionalService",
        "LocalBusiness"
      ],
      "employee": [
        {
          "@id": "https://wavect.io/team/kevin-riedl/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Kevin Riedl",
          "url": "https://wavect.io/team/kevin-riedl/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        },
        {
          "@id": "https://wavect.io/team/christof-jori/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Christof Jori",
          "url": "https://wavect.io/team/christof-jori/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        }
      ],
      "founder": [
        {
          "@id": "https://wavect.io/team/kevin-riedl/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Kevin Riedl",
          "url": "https://wavect.io/team/kevin-riedl/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        },
        {
          "@id": "https://wavect.io/team/christof-jori/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Christof Jori",
          "url": "https://wavect.io/team/christof-jori/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        }
      ],
      "legalRepresentative": [
        {
          "@id": "https://wavect.io/team/kevin-riedl/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Kevin Riedl",
          "url": "https://wavect.io/team/kevin-riedl/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        },
        {
          "@id": "https://wavect.io/team/christof-jori/#person",
          "@type": "Person",
          "jobTitle": "Managing Director",
          "name": "Christof Jori",
          "url": "https://wavect.io/team/christof-jori/",
          "worksFor": {
            "@id": "https://wavect.io/#organization",
            "@type": [
              "Organization",
              "ProfessionalService",
              "LocalBusiness"
            ]
          }
        }
      ],
      "name": "Wavect GmbH",
      "subjectOf": {
        "@id": "https://wavect.io/verified-claims.json#dataset",
        "@type": "Dataset",
        "name": "Wavect verified publication claims",
        "url": "https://wavect.io/verified-claims.json"
      },
      "url": "https://wavect.io/"
    },
    {
      "@id": "https://wavect.io/team/kevin-riedl/#person",
      "@type": "Person",
      "jobTitle": "Managing Director",
      "name": "Kevin Riedl",
      "sameAs": [
        "https://www.wikidata.org/wiki/Q139796365",
        "https://www.linkedin.com/in/wsdt",
        "https://github.com/wsdt"
      ],
      "url": "https://wavect.io/team/kevin-riedl/",
      "worksFor": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      }
    },
    {
      "@id": "https://wavect.io/team/christof-jori/#person",
      "@type": "Person",
      "jobTitle": "Managing Director",
      "name": "Christof Jori",
      "sameAs": [
        "https://www.wikidata.org/wiki/Q139796367",
        "https://www.linkedin.com/in/jocr77/",
        "https://github.com/jo-chris"
      ],
      "url": "https://wavect.io/team/christof-jori/",
      "worksFor": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      }
    },
    {
      "@id": "https://wavect.io/#website",
      "@type": "WebSite",
      "inLanguage": [
        "en",
        "de",
        "es",
        "zh"
      ],
      "name": "Wavect",
      "potentialAction": {
        "@type": "SearchAction",
        "query-input": "required name=search_term_string",
        "target": {
          "@type": "EntryPoint",
          "urlTemplate": "https://wavect.io/search/?q={search_term_string}"
        }
      },
      "publisher": {
        "@id": "https://wavect.io/#organization",
        "@type": [
          "Organization",
          "ProfessionalService",
          "LocalBusiness"
        ]
      },
      "url": "https://wavect.io/"
    },
    {
      "@id": "https://wavect.io/blog/pdf-inspector-ocr-routing/#webpage",
      "@type": "WebPage",
      "dateModified": "2026-08-06",
      "inLanguage": "en",
      "isPartOf": {
        "@id": "https://wavect.io/#website",
        "@type": "WebSite"
      },
      "lastReviewed": "2026-08-06",
      "url": "https://wavect.io/blog/pdf-inspector-ocr-routing/"
    }
  ]
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "BlogPosting",
  "abstract": "pdf-inspector is an MIT-licensed Rust library that classifies PDFs and extracts native text as Markdown without OCR. Firecrawl's 31 July 2026 benchmark reports 0.470 seconds for 200 documents on an Apple M4 Pro, but OCR was disabled, so this is a direct-text benchmark rather than proof that scanned PDFs finish in milliseconds. Use it as the first stage of a hybrid pipeline: validate and isolate the upload, extract high-confidence text locally, send only flagged pages or regions to OCR, preserve page provenance, and measure quality on your own corpus. Node.js, Python, Rust and browser WebAssembly bindings are available.",
  "articleBody": " Blog overview/AI and agents/Models and infrastructure pdf-inspector review: route PDFs before OCR TL;DR pdf-inspector is an MIT-licensed Rust library that classifies PDFs and extracts native text as Markdown without OCR. Firecrawl's 31 July 2026 benchmark reports 0.470 seconds for 200 documents on an Apple M4 Pro, but OCR was disabled, so this is a direct-text benchmark rather than proof that scanned PDFs finish in milliseconds. Use it as the first stage of a hybrid pipeline: validate and isolate the upload, extract high-confidence text locally, send only flagged pages or regions to OCR, preserve page provenance, and measure quality on your own corpus. Node.js, Python, Rust and browser WebAssembly bindings are available. pdf-inspector is a fast local PDF parser and OCR router, not an OCR engine. Firecrawl's open-source Rust library classifies a document as text-based, scanned, image-based or mixed, extracts usable native text as Markdown, and returns the pages that still need OCR. That distinction is the product opportunity. A pipeline can stop paying the slowest, most expensive processing path for pages that already contain machine-readable text. The viral claim says 0.002 seconds per page. The repository contains a strong benchmark, but not that exact universal promise. This review separates the measured result from the social post, explains where native parsing ends, and gives you a production decision framework for RAG ingestion, invoice extraction, legal-document search and AI-agent workflows. What does pdf-inspector actually do? It reads the PDF's internal structure before anyone renders a page or calls a model. The detector looks for text and image operators across the page tree. The extractor then reconstructs text with positions, font information, columns, links, lists, headings and tables. The result includes a confidence score, layout flags and a list of pages that need OCR. PDF resultRecommended routeWhy TextBased, high confidenceExtract locally to MarkdownThe file already has a usable text layer. OCR adds latency and can introduce recognition errors. MixedExtract native pages, OCR only flagged pages or regionsA single document may combine exported reports, signatures, scanned appendices and image pages. Scanned or ImageBasedRender and send to an OCR or vision pipelineThere is no usable native text to recover. Encoding issues or low confidenceFallback to OCR, then validateA text operator can exist while the decoded characters are still garbage. The library does not include an OCR model. That is deliberate. The official pdf-inspector README describes a pure Rust parser with no ML model or external service. Firecrawl's hosted Fire-PDF pipeline is a broader product: it uses pdf-inspector for classification and native extraction, then applies layout detection and GLM-OCR to regions that need it. Do not evaluate one as if it were the other. Does it really process 200 PDFs in 0.470 seconds? Yes, in Firecrawl's published direct-text benchmark. No, that does not mean every PDF page finishes in two milliseconds. Published detailWhat it meansWhat it does not prove 200-document opendataloader-bench corpusA shared evaluation corpus, processed sequentially in one processYour invoices, contracts, scans and languages will match the corpus 0.470 seconds totalAbout 2.35 milliseconds per document as a simple corpus averageTwo milliseconds per page, p95 latency, upload time or OCR time Apple M4 Pro, median of five runsA documented machine and repeat-run methodThe same speed in a browser, container, low-cost VM or cold start OCR disabledA fair comparison between local non-model parsersAccuracy or speed on scanned pages Overall 0.875, reading order 0.915, tables 0.814Strong reported structure scores for version 0.2.6 on that benchmarkPerfect extraction or superiority on every document type The results were refreshed on 31 July 2026. They compare pdf-inspector 0.2.6 with LiteParse, OpenDataLoader, PyMuPDF4LLM and MarkItDown, with the full configuration and artifacts linked from the repository. The responsible buying conclusion is not \"fastest PDF parser everywhere.\" It is \"a promising local default for native-text PDFs that deserves a corpus-specific bake-off.\" Firecrawl also says roughly 54% of the PDFs in its workload do not need OCR. Treat that as a vendor workload estimate, not a universal distribution. Run detection over your own last 30 to 90 days of documents before building the business case. The production architecture: classify first, escalate second Accept safely. Enforce file and page limits, verify the signature rather than trusting the MIME header, replace user-controlled filenames, and store uploads outside the web root. Parse in isolation. Give the parser a CPU, memory and wall-clock budget. Treat every supplier PDF, email attachment and public upload as untrusted input. Classify once. Record document type, confidence, page count, encoding warnings, complex-layout flags and pages needing OCR. Use the",
  "articleSection": "Engineering",
  "author": {
    "@id": "https://wavect.io/team/kevin-riedl/#person",
    "@type": "Person",
    "name": "Kevin Riedl",
    "sameAs": [
      "https://www.wikidata.org/wiki/Q139796365",
      "https://www.linkedin.com/in/wsdt",
      "https://github.com/wsdt"
    ],
    "url": "https://wavect.io/team/kevin-riedl/"
  },
  "dateModified": "2026-08-06",
  "datePublished": "2026-08-06",
  "description": "pdf-inspector is an MIT-licensed Rust library that classifies PDFs and extracts native text as Markdown without OCR. Firecrawl's 31 July 2026 benchmark reports 0.470 seconds for 200 documents on an Apple M4 Pro, but OCR was disabled, so this is a direct-text benchmark rather than proof that scanned PDFs finish in milliseconds. Use it as the first stage of a hybrid pipeline: validate and isolate the upload, extract high-confidence text locally, send only flagged pages or regions to OCR, preserve page provenance, and measure quality on your own corpus. Node.js, Python, Rust and browser WebAssembly bindings are available.",
  "headline": "pdf-inspector Review: Route PDFs Before OCR",
  "image": "https://wavect.io/img/blog/headers/header_pdf-inspector-ocr-routing.svg",
  "inLanguage": "en",
  "keywords": "PDF Parsing, OCR Routing",
  "mainEntityOfPage": {
    "@id": "https://wavect.io/blog/pdf-inspector-ocr-routing/",
    "@type": "WebPage"
  },
  "publisher": {
    "@id": "https://wavect.io/#organization",
    "@type": [
      "Organization",
      "ProfessionalService",
      "LocalBusiness"
    ]
  },
  "url": "https://wavect.io/blog/pdf-inspector-ocr-routing/",
  "wordCount": 2239
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "item": "https://wavect.io/",
      "name": "Home",
      "position": 1
    },
    {
      "@type": "ListItem",
      "item": "https://wavect.io/blog/overview/",
      "name": "Blog",
      "position": 2
    },
    {
      "@type": "ListItem",
      "item": "https://wavect.io/blog/pdf-inspector-ocr-routing/",
      "name": "pdf-inspector Review: Route PDFs Before OCR",
      "position": 3
    }
  ]
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "BreadcrumbList",
  "itemListElement": [
    {
      "@type": "ListItem",
      "item": "https://wavect.io/",
      "name": "Home",
      "position": 1
    },
    {
      "@type": "ListItem",
      "item": "https://wavect.io/blog/overview/",
      "name": "Blog overview",
      "position": 2
    },
    {
      "@type": "ListItem",
      "item": "https://wavect.io/blog/topics/ai-agents/",
      "name": "AI and agents",
      "position": 3
    },
    {
      "@type": "ListItem",
      "item": "https://wavect.io/blog/clusters/models-infrastructure/",
      "name": "Models and infrastructure",
      "position": 4
    },
    {
      "@type": "ListItem",
      "item": "https://wavect.io/blog/pdf-inspector-ocr-routing/",
      "name": "pdf-inspector Review: Local PDF Parsing Before OCR | ",
      "position": 5
    }
  ]
}
```

```json
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "No. It classifies PDFs and extracts native text without an OCR model. Scanned, image-based, low-confidence or broken-encoding pages still need a separate OCR or vision step."
      },
      "name": "Is pdf-inspector an OCR engine?"
    },
    {
      "@type": "Question",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "It was the fastest complete run in Firecrawl's published 31 July 2026 comparison of five local, non-model parsers on 200 documents. That benchmark used an Apple M4 Pro and disabled OCR. Reproduce it on your own corpus before making a general claim."
      },
      "name": "Is pdf-inspector really the fastest PDF parser?"
    },
    {
      "@type": "Question",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Yes. The WebAssembly package classifies and extracts locally from a Uint8Array, and the official docs say the bytes are not uploaded. The extraction call is synchronous, so large files should run inside a Web Worker. Image-only files still need OCR."
      },
      "name": "Can pdf-inspector run fully in the browser?"
    },
    {
      "@type": "Question",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "It depends on the share of pages with reliable native text. Count avoided OCR pages on your own corpus, multiply by marginal OCR-page cost, then subtract parser compute, engineering, monitoring and human correction. Firecrawl's roughly 54% figure describes its workload, not yours."
      },
      "name": "How much OCR cost can routing save?"
    },
    {
      "@type": "Question",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "It is a strong candidate for the ingestion gate before chunking when many PDFs contain native text. Keep page provenance, route scans to OCR, validate structure, and separately test retrieval, permissions and answer citations."
      },
      "name": "Should I use pdf-inspector for a RAG pipeline?"
    }
  ]
}
```
