Using pdf-inspector in Python - pdf-inspector Guide
API ReferencePython
The Python binding is pdf-inspector (import name pdf_inspector), built on PyO3. The GIL is released during processing — safe to mix with asyncio and threads without stalling the interpreter.
Install
pip install pdf-inspectorPrebuilt wheels cover CPython ≥3.8 on Linux (x86_64, aarch64), macOS (Intel, Apple Silicon), and Windows x64. Type stubs (pdf_inspector.pyi) ship with the package so type hints work out of the box; in a repo checkout use maturin develop --release.
Core APIs
import pdf_inspector
# 1. All-in-one: detect + extract + Markdown
result = pdf_inspector.process_pdf("document.pdf")
print(result.pdf_type) # "text_based" | "scanned" | "image_based" | "mixed"
print(result.confidence) # 0.0 - 1.0
print(result.page_count)
print(result.markdown)
# 2. Classification only (no extraction)
info = pdf_inspector.detect_pdf("document.pdf")
# 3. Plain text
text = pdf_inspector.extract_text("document.pdf")
# 4. Positioned text items with full 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}")Byte inputs: process_pdf_bytes(data), detect_pdf_bytes(data), etc. — skip the filesystem when your file is already in memory.
Function cheat sheet
| Function | Description |
|---|---|
process_pdf(path, pages=None) | Full processing (detect + extract + Markdown) |
detect_pdf(path) | Classification only, fastest |
classify_pdf(path) | Lightweight classification (OCR pages + confidence) |
extract_text(path) | Plain-text extraction |
extract_text_with_positions(path) | X/Y coordinates and font info |
extract_pages_markdown(path, pages=None) | Per-page Markdown + layout metadata |
extract_text_in_regions(path, regions) | Bounding-box extraction with needs_ocr flags |
process_pdf_with_ocr(path, **opts) | Selective OCR with per-page provenance |
extract_structure_elements(path) | Structure-tree elements from tagged PDFs |
Key result fields
result = pdf_inspector.process_pdf("document.pdf")
result.pdf_type # document type
result.markdown # Markdown string (None for detect_pdf)
result.confidence # classification confidence 0.0-1.0
result.pages_needing_ocr # pages needing OCR (1-indexed)
result.has_encoding_issues # True = broken font encodings — consider OCR fallback
result.pages_with_tables # pages containing tables
result.pages_with_columns # multi-column pagesCommon scenarios
Classify-first bulk ingestion
from pathlib import Path
import pdf_inspector
for pdf in Path("./pdfs").glob("*.pdf"):
result = pdf_inspector.process_pdf(pdf)
if result.pdf_type != "text_based":
print(f"Skipping {pdf.name}: {result.pdf_type}, OCR needed on {result.pages_needing_ocr}")
continue
out = pdf.with_suffix(".md")
out.write_text(result.markdown or "", encoding="utf-8")Selected pages only
result = pdf_inspector.process_pdf("big-report.pdf", pages=[1, 3, 5])
# extract_pages_markdown takes a pages parameter too (0-indexed)
per_page = pdf_inspector.extract_pages_markdown("big-report.pdf", pages=[0, 2])Selective OCR
ocr = pdf_inspector.process_pdf_with_ocr(
"mixed.pdf",
page_numbers=[1, 3], # 1-indexed
model_directory="/opt/models/pp-ocrv6-small",
offline=True, # prohibit downloads
)
for page in ocr.pages:
print(page.page_number, page.provenance.source) # native | ocr | fusedThe OCR runtime needs PDFium and ONNX Runtime shared libraries (PDFIUM_LIB_PATH, ORT_DYLIB_PATH); see the official OCR runtime guide. The default wheel embeds none of these components — they never load unless you opt into OCR.
Tips
- Don't call
process_pdfwhen you only need the verdict —detect_pdf/classify_pdfare an order of magnitude faster pages_needing_ocris 1-indexed while thepagefield fromextract_pages_markdownis 0-indexed — mind the difference in routing logic- The official docs/python.md is the source of truth