API Quick Reference - Five Bindings Compared
API Reference
The core API is just four things, consistent across all five bindings:
| API | What it does | Returns |
|---|---|---|
processPdf / process_pdf | Detect + extract + Markdown in one call | Result object (markdown, pdfType, confidence) |
detectPdf / detect_pdf | Classification only, no extraction | Result object (empty markdown) |
classifyPdf / classify_pdf | Lightweight classification | Classification object |
extractText / extract_text | Plain-text extraction | String |
"Classify first, then decide" is the recommended flow: get pagesNeedingOcr, and only route those pages to OCR.
Side by side
Rust
use pdf_inspector::{process_pdf, detect_pdf, PdfType};
// All-in-one: detect + extract + Markdown
let result = process_pdf("document.pdf")?;
println!("{:?} {:.0}%", result.pdf_type, result.confidence * 100.0);
if let Some(markdown) = &result.markdown {
println!("{}", markdown);
}
// Classification only
let info = detect_pdf("document.pdf")?;
match info.pdf_type {
PdfType::TextBased => { /* extract locally */ }
_ => { /* info.pages_needing_ocr tells you which pages */ }
}Install: cargo add pdf-inspector. More options live on the PdfOptions builder (process_pdf_with_options): selected pages, ProcessMode::Analyze for layout-only runs, custom sampling strategies; use process_pdf_mem for byte input.
Node.js
import { classifyPdf, extractPagesMarkdownAsync } from '@firecrawl/pdf-inspector'
// Lightweight classification (sync)
const c = classifyPdf(pdf)
console.log(c.pdfType) // "TextBased" | "Scanned" | "Mixed" | "ImageBased"
console.log(c.pagesNeedingOcr) // [5, 12] (0-indexed)
console.log(c.confidence) // 0.875
// Servers should prefer async variants: libuv thread pool, no blocked loop
if (c.pdfType === 'TextBased') {
const { pages } = await extractPagesMarkdownAsync(pdf)
}Install: npm install @firecrawl/pdf-inspector. The sync APIs (processPdf/classifyPdf/extractPagesMarkdown) parse on the calling thread — fine for one-off scripts; large documents on servers should use the *Async versions. Also available: processPdfWithOcr (selective OCR) and extractTextInRegions (bounding-box extraction with per-region needsOcr flags).
Python
import pdf_inspector
# All-in-one
result = pdf_inspector.process_pdf("document.pdf")
print(result.pdf_type) # "text_based"
print(result.page_count)
print(result.markdown)
# Classification only
info = pdf_inspector.detect_pdf("document.pdf")
if info.pdf_type == "text_based":
print("Extract locally!")
else:
print(f"Pages needing OCR: {result.pages_needing_ocr}")
# Positioned text items with font info
items = pdf_inspector.extract_text_with_positions("document.pdf")
for item in items[:5]:
print(f"'{item.text}' at ({item.x:.0f}, {item.y:.0f}) size={item.font_size}")Install: pip install pdf-inspector. The GIL is released during processing — safe to mix with asyncio/threads; type stubs ship with the package. Other useful calls: process_pdf_bytes, extract_pages_markdown (per-page Markdown + layout metadata), process_pdf_with_ocr (selective OCR), extract_structure_elements (tagged-PDF structure tree).
WebAssembly (browser)
import init, { processPdf, detectPdf, classifyPdf, extractText } from '@firecrawl/pdf-inspector-wasm'
await init() // load wasm once
const result = processPdf(pdfBytes, { profile: 'compact', includePageMarkers: true })
console.log(result.pdfType)
console.log(result.markdown)Install: npm install @firecrawl/pdf-inspector-wasm. Parsing runs entirely in your browser — files never leave the device. The demo on this site uses exactly this build. Single-threaded build needs no cross-origin isolation; CMaps are embedded so CJK just works; extraction is synchronous after init() — use a Web Worker for big files.
CLI
Two binaries ship with the crate (cargo install pdf-inspector; the npm package bundles them too):
pdf2md document.pdf # Markdown to stdout
pdf2md document.pdf --pages 1-3 # selected pages only
pdf2md document.pdf --compact # token-saving output
pdf2md document.pdf --json # structured JSON
detect-pdf document.pdf --analyze --json # classification + analysisResult shape at a glance (Python shown)
class PdfResult: # process_pdf / detect_pdf
pdf_type: str # "text_based" | "scanned" | "image_based" | "mixed"
markdown: str | None # None for detect_pdf
page_count: int
confidence: float # 0.0 - 1.0
pages_needing_ocr: list[int] # 1-indexed
has_encoding_issues: bool # broken font encodings — consider OCR fallback
pages_with_tables: list[int]
pages_with_columns: list[int]Node's PdfClassification mirrors it: pdfType / pageCount / pagesNeedingOcr (0-indexed) / confidence.
Things worth knowing
- Page indexing differs across bindings — that's the official reality today: Python's
pages_needing_ocris 1-indexed whileextract_pages_markdown's page field is 0-indexed. Check each binding's docs when writing routing logic. - Sync vs async: Node's sync versions occupy the event loop; servers should always use
*Async. - WASM has no OCR: scanned documents yield a type verdict and a clear message in the browser.
- Full signatures live in the official docs: napi/README, docs/python.md, docs/rust-api.md.
Go deeper per language: Node.js · Python · Rust · WebAssembly · CLI. For problems, see error handling & limits.