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 generationExtract— full extraction to MarkdownDetectOnly— 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, ®ions)?;
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_ocrwhen 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, ®ions)?;
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:
detector(src/detector.rs) — PDF type classification and OCR routingextractor(src/extractor/mod.rs) — Content-stream parsing, font handling, text-item generationmarkdown(src/markdown/convert.rs) —TextItemto Markdown conversion with column/heading detectiontables(src/tables/detect_rects.rs) — Three-stage table detection (rect-based → line-based → heuristic)vision(src/vision/mod.rs) — Optional PDFium OCR, compiled only withocrfeaturetypes(src/types.rs) — Core data structures:TextItem,PdfRect,PdfLine
Summary
process_pdf()provides the simplest PDF-to-Markdown workflow with automatic type detection.PdfOptionsbuilder enables page filtering, password handling, and mode selection viaprocess_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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →