How to Use the pdf-inspector Rust API: Complete Guide with Examples

Use process_pdf() for simple PDF-to-Markdown conversion, or leverage PdfOptions and region-based functions like extract_text_in_regions_mem() for custom extraction pipelines.

The pdf-inspector Rust library transforms PDFs into structured Markdown while exposing low-level building blocks for custom processing workflows. This guide covers every public API function in src/lib.rs, with practical code examples and direct links to source implementations.

Installing pdf-inspector

Add the crate to your Cargo.toml as a Git dependency:

[dependencies]
pdf_inspector = { git = "https://github.com/firecrawl/pdf-inspector", rev = "main" }

The library compiles without default features. Enable the ocr feature for PDFium-based OCR support:

pdf_inspector = { git = "https://github.com/firecrawl/pdf-inspector", rev = "main", features = ["ocr"] }

High-Level PDF Processing

Simple Full Extraction with process_pdf()

The fastest path from PDF to Markdown uses the process_pdf function. It automatically detects the PDF type, extracts text, and converts to Markdown in one call.

use pdf_inspector::{process_pdf, PdfError};

fn main() -> Result<(), PdfError> {
    let result = process_pdf("sample.pdf")?;
    println!("PDF type: {:?}, pages: {}", result.pdf_type, result.page_count);

    if let Some(md) = result.markdown {
        println!("--- Markdown output ---\n{md}");
    }
    Ok(())
}

Implementation detail: In src/lib.rs lines 66-71, process_pdf forwards to process_pdf_with_options with default PdfOptions.

Detection-Only with detect_pdf()

When you only need to classify the PDF (text-based, scanned, or mixed) without full extraction:

use pdf_inspector::{detect_pdf, PdfError};

fn main() -> Result<(), PdfError> {
    let info = detect_pdf("sample.pdf")?;
    println!("Detected type: {:?}, pages: {}", info.pdf_type, info.page_count);
    Ok(())
}

Implementation detail: detect_pdf calls process_pdf_with_options with PdfOptions::detect_only() (lines 74-78 in src/lib.rs).

Custom Processing with PdfOptions

For fine-grained control, use process_pdf_with_options() with the builder-style PdfOptions struct.

use pdf_inspector::{PdfOptions, ProcessMode, process_pdf_with_options, PdfError};

fn main() -> Result<(), PdfError> {
    let opts = PdfOptions::new()
        .mode(ProcessMode::Analyze)      // detection + extraction, skip markdown
        .pages([1, 3, 5]);               // 1-indexed page filter

    let result = process_pdf_with_options("sample.pdf", opts)?;
    println!("Pages needing OCR: {:?}", result.pages_needing_ocr);
    Ok(())
}

Available ProcessMode variants:

  • Analyze — detection and extraction only, no Markdown generation
  • Extract — full extraction to Markdown
  • DetectOnly — classification only

Implementation detail: The PdfOptions builder spans lines 65-88 in src/lib.rs, supporting mode, pages, and password configuration.

Per-Page Markdown Extraction

For hybrid OCR pipelines that process pages individually:

use pdf_inspector::{extract_pages_markdown, PdfError};

fn main() -> Result<(), PdfError> {
    let pages = extract_pages_markdown("sample.pdf", None)?;
    for page_md in pages.pages {
        println!("--- Page {} ---\n{}", page_md.page + 1, page_md.markdown);
    }
    Ok(())
}

Returns: PagesExtractionResult containing per-page markdown plus layout metadata (pages_with_tables, pages_with_columns, OCR flags).

Implementation detail: extract_pages_markdown reads the file into a buffer and delegates to extract_pages_markdown_mem (lines 78-89 in src/lib.rs).

Region-Based Text Extraction

Extract text from specific bounding-box regions using extract_text_in_regions_mem(). This enables focused extraction for tables, forms, or document sections.

use pdf_inspector::{extract_text_in_regions_mem, PdfError};

fn main() -> Result<(), PdfError> {
    // Bounding boxes: [x1, y1, x2, y2] in PDF points, top-left origin
    let regions = vec![
        (0, vec![[50.0, 700.0, 300.0, 750.0]]), // page 0, one region
        (2, vec![[100.0, 100.0, 500.0, 200.0]]) // page 2, one region
    ];

    let pdf_bytes = std::fs::read("sample.pdf")?;
    let page_results = extract_text_in_regions_mem(&pdf_bytes, &regions)?;

    for pr in page_results {
        for (i, rt) in pr.regions.iter().enumerate() {
            println!(
                "Page {}, Region {}: {} (needs OCR = {})",
                pr.page + 1,
                i + 1,
                rt.text,
                rt.needs_ocr
            );
        }
    }
    Ok(())
}

Implementation detail: Located at lines 28-33 in src/lib.rs. The function:

  • Parses only pages appearing in page_regions
  • Uses a fast ToUnicode-only font map
  • Flags needs_ocr when text is empty, garbled, or from GID-encoded fonts

Region-Based Table Extraction

For table-specific extraction within defined regions:

use pdf_inspector::{extract_tables_in_regions_mem, PdfError};

fn main() -> Result<(), PdfError> {
    let pdf = std::fs::read("sample.pdf")?;
    let regions = vec![(0, vec![[50.0, 500.0, 550.0, 750.0]])];

    let tables = extract_tables_in_regions_mem(&pdf, &regions)?;
    for pr in tables {
        for (i, rt) in pr.regions.iter().enumerate() {
            if rt.needs_ocr {
                println!("Region {} needs OCR", i + 1);
            } else {
                println!("Region {} table markdown:\n{}", i + 1, rt.text);
            }
        }
    }
    Ok(())
}

Implementation detail: extract_tables_in_regions_mem (lines 41-46) runs three-stage table detection and returns pipe-table Markdown when successful. The detection pipeline lives in src/tables/detect_rects.rs.

Extracting Tagged-PDF Structure Elements

For semantic-rich extraction from PDFs with structure trees:

use pdf_inspector::{extract_structure_elements, PdfError};

fn main() -> Result<(), PdfError> {
    let elements = extract_structure_elements("sample.pdf", None)?;
    for el in elements {
        println!("Page {}, MCID {} → {}", el.page, el.mcid, el.role);
    }
    Ok(())
}

Returns: Vec<StructureElement> containing page number, MCID (marked-content identifier), and semantic role (headings, paragraphs, tables, etc.).

Implementation detail: extract_structure_elements reads the file and calls extract_structure_elements_mem (lines 52-57 in src/lib.rs). Core logic resides in src/structure_tree.rs.

Understanding Result Types

Type Purpose Returned By
PdfProcessResult Full processing output with PDF type, Markdown, OCR flags, layout complexity process_pdf, process_pdf_with_options, detect_pdf
PagesExtractionResult Per-page Markdown with layout metadata extract_pages_markdown, extract_pages_markdown_mem
RegionText Text from a single region plus OCR requirement flag Region-based *_mem functions
StructureElement Tagged-PDF semantic element (page, MCID, role) extract_structure_elements, extract_structure_elements_mem

All result types convey OCR needs, layout complexity, and OCR reasons to drive downstream processing decisions.

Core Module Architecture

Understanding these modules helps when extending or debugging:

Summary

  • process_pdf() provides the simplest PDF-to-Markdown workflow with automatic type detection.
  • PdfOptions builder enables page filtering, password handling, and mode selection via process_pdf_with_options().
  • Region-based functions (extract_text_in_regions_mem, extract_tables_in_regions_mem) support targeted extraction for hybrid OCR pipelines.
  • extract_structure_elements() exposes semantic PDF structure for accessibility-aware processing.
  • All functions return rich result types that flag OCR requirements and layout characteristics.

Frequently Asked Questions

What is the difference between process_pdf and detect_pdf?

process_pdf performs full detection, extraction, and Markdown conversion. detect_pdf runs only classification logic via PdfOptions::detect_only(), returning PDF type and metadata without extracting text. Use detect_pdf for quick routing decisions and process_pdf for complete conversion.

When should I use region-based extraction instead of process_pdf?

Use extract_text_in_regions_mem or extract_tables_in_regions_mem when you need targeted extraction from specific document areas, such as form fields, invoice tables, or header sections. These functions also support in-memory processing (*_mem variants) for applications handling PDF bytes directly without filesystem access.

How does pdf-inspector determine if OCR is needed?

The detector in src/detector.rs and extraction functions flag OCR requirements based on multiple signals: empty text extraction results, garbled output from encoding issues, GID-encoded fonts without proper ToUnicode maps, and image-based page content. The needs_ocr boolean in result types allows downstream systems to route pages to OCR engines like PDFium when compiled with the ocr feature.

Can I process password-protected PDFs?

Yes. Use PdfOptions::new().password("secret") with process_pdf_with_options. The password is passed through to the underlying PDF parser for decryption before content extraction begins.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →