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

> Master the pdf-inspector Rust API to convert PDFs to Markdown or build custom extraction pipelines with process_pdf and region-based functions. Get started now.

- Repository: [Firecrawl/pdf-inspector](https://github.com/firecrawl/pdf-inspector)
- Tags: how-to-guide
- Published: 2026-08-31

---

**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`](https://github.com/firecrawl/pdf-inspector/blob/main/src/lib.rs), with practical code examples and direct links to source implementations.

## Installing pdf-inspector

Add the crate to your [`Cargo.toml`](https://github.com/firecrawl/pdf-inspector/blob/main/Cargo.toml) as a Git dependency:

```toml
[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:

```toml
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.

```rust
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`](https://github.com/firecrawl/pdf-inspector/blob/main/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:

```rust
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`](https://github.com/firecrawl/pdf-inspector/blob/main/src/lib.rs)).

## Custom Processing with `PdfOptions`

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

```rust
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`](https://github.com/firecrawl/pdf-inspector/blob/main/src/lib.rs), supporting `mode`, `pages`, and `password` configuration.

## Per-Page Markdown Extraction

For hybrid OCR pipelines that process pages individually:

```rust
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`](https://github.com/firecrawl/pdf-inspector/blob/main/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.

```rust
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`](https://github.com/firecrawl/pdf-inspector/blob/main/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:

```rust
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`](https://github.com/firecrawl/pdf-inspector/blob/main/src/tables/detect_rects.rs).

## Extracting Tagged-PDF Structure Elements

For semantic-rich extraction from PDFs with structure trees:

```rust
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`](https://github.com/firecrawl/pdf-inspector/blob/main/src/lib.rs)). Core logic resides in [`src/structure_tree.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/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:

- **`detector`** ([`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs)) — PDF type classification and OCR routing
- **`extractor`** ([`src/extractor/mod.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/extractor/mod.rs)) — Content-stream parsing, font handling, text-item generation
- **`markdown`** ([`src/markdown/convert.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/markdown/convert.rs)) — `TextItem` to Markdown conversion with column/heading detection
- **`tables`** ([`src/tables/detect_rects.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/tables/detect_rects.rs)) — Three-stage table detection (rect-based → line-based → heuristic)
- **`vision`** ([`src/vision/mod.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/vision/mod.rs)) — Optional PDFium OCR, compiled only with `ocr` feature
- **`types`** ([`src/types.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/types.rs)) — Core data structures: `TextItem`, `PdfRect`, `PdfLine`

## 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`](https://github.com/firecrawl/pdf-inspector/blob/main/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.