How to Use ScanStrategy (EarlyExit, Full, Sample, Pages) for Faster PDF Detection in pdf‑inspector
Use ScanStrategy::Sample(8) for balanced speed and accuracy, ScanStrategy::Full for definitive classification, and ScanStrategy::EarlyExit for maximum speed on text‑heavy PDF pipelines.
The pdf‑inspector crate from Firecrawl classifies PDFs as TextBased, Scanned, ImageBased, or Mixed by scanning pages for text operators (Tj/TJ). The ScanStrategy enum in [src/detector.rs](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs#L25-L40) controls which pages are examined, letting you trade detection speed against classification precision.
Understanding the Four Scan Strategies
Each strategy implements a different page‑selection algorithm. Choose based on your tolerance for speed versus accuracy.
EarlyExit: Stop at First Non‑Text Page
ScanStrategy::EarlyExit scans pages sequentially and stops immediately when it encounters a page without sufficient text operators.
- Speed: Fastest for truly text‑based PDFs
- Risk: Misclassifies documents that start with an image‑only cover (common in annual reports or scanned books)
- Best for: Pipelines that route TextBased PDFs to fast extractors and treat everything else as "needs OCR"
In [src/detector.rs](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs#L25-L40), this strategy triggers an early return from the detection loop, skipping analysis of remaining pages.
Full: Examine Every Page
ScanStrategy::Full disables early exit and processes all pages regardless of content.
- Speed: Slowest (linear with page count)
- Accuracy: Highest—reliably distinguishes Mixed from Scanned by computing exact text‑page ratios
- Best for: Precision‑critical workflows, pre‑OCR classification, or small PDFs where overhead is acceptable
The detection algorithm in detect_from_document accumulates text operator counts across every page when this strategy is active.
Sample(N): Evenly Distributed Sampling
ScanStrategy::Sample(N) selects N evenly‑distributed pages using the helper distribute_pages defined at lines 80‑113 of [src/detector.rs](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs#L80-L113).
- Speed: Very fast (bounded by N, not page count)
- Accuracy: Reliable for most real‑world documents; edge case failures on highly heterogeneous PDFs
- Best for: Large PDFs (> 100 pages) where speed outweighs marginal classification gains
The distribute_pages function guarantees first and last pages are always included, with remaining samples spread across the document interior:
// From src/detector.rs, lines 80-88
fn distribute_pages(total: u32, sample: u32) -> Vec<u32> {
let sample = sample.min(total) as usize;
let mut pages: Vec<u32> = Vec::with_capacity(sample);
// First page always included
pages.push(1);
// Intermediate pages distributed evenly
for i in 1..sample-1 {
let page = 1 + ((total - 1) * i as u32) / (sample as u32 - 1);
pages.push(page);
}
// Last page always included if sample > 1
if sample > 1 {
pages.push(total);
}
pages
}
Pages(Vec): Explicit Page Selection
ScanStrategy::Pages(Vec<u32>) scans only the 1‑indexed page numbers you specify.
- Speed: Depends entirely on list length
- Accuracy: Exact control—no assumptions about document structure
- Best for: Custom workflows where you already know representative pages (e.g., page 1 and page 2 for cover + body classification)
Recommended Configurations by Use Case
Default: Balanced Sampling
The library's DetectionConfig::default() provides a production‑ready starting point:
DetectionConfig {
strategy: ScanStrategy::Sample(8), // 8 pages evenly spread
min_text_ops_per_page: 3,
text_page_ratio_threshold: 0.6,
}
This configuration appears in [src/lib.rs](https://github.com/firecrawl/pdf-inspector/blob/main/src/lib.rs) as the default for detect_pdf_type.
Maximum Speed for Large PDFs
For PDFs exceeding 500 pages, reduce sample count while preserving boundary coverage:
let fast_cfg = DetectionConfig {
strategy: ScanStrategy::Sample(4), // First, last, and 2 interior pages
..Default::default()
};
Maximum Accuracy for Mixed/Scanned Distinction
When you must reliably identify Mixed PDFs (partially scanned documents):
let accurate_cfg = DetectionConfig {
strategy: ScanStrategy::Full,
..Default::default()
};
Ultra‑Fast Text‑Heavy Pipelines
If your input stream is predominantly text‑based PDFs with occasional outliers:
let streaming_cfg = DetectionConfig {
strategy: ScanStrategy::EarlyExit,
..Default::default()
};
Applying Custom Strategies in Code
Import the configuration types and construct your DetectionConfig:
use pdf_inspector::detector::{DetectionConfig, ScanStrategy};
// Fast sampling with 6 representative pages
let fast_cfg = DetectionConfig {
strategy: ScanStrategy::Sample(6),
..Default::default()
};
// Execute detection with custom configuration
let result = pdf_inspector::detect_pdf_type_with_config("document.pdf", fast_cfg)?;
The function detect_pdf_type_with_config is exported from [src/lib.rs](https://github.com/firecrawl/pdf-inspector/blob/main/src/lib.rs) as the primary API entry point for custom strategies.
CLI Usage Without Code Changes
The binary [src/bin/detect_pdf.rs](https://github.com/firecrawl/pdf-inspector/blob/main/src/bin/detect_pdf.rs) exposes strategy selection via command‑line flags:
# Default sampling strategy
detect-pdf document.pdf
# Full document scan
detect-pdf --strategy=full document.pdf
# Sample 4 pages
detect-pdf --strategy=sample:4 document.pdf
# Specific pages
detect-pdf --strategy=pages:1,5,10 document.pdf
Key Source Files Reference
| File | Purpose |
|---|---|
[src/detector.rs](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs) |
ScanStrategy enum definition, DetectionConfig struct, distribute_pages helper, core detect_from_document algorithm |
[src/lib.rs](https://github.com/firecrawl/pdf-inspector/blob/main/src/lib.rs) |
Public API: detect_pdf_type, detect_pdf_type_with_config |
[src/bin/detect_pdf.rs](https://github.com/firecrawl/pdf-inspector/blob/main/src/bin/detect_pdf.rs) |
CLI wrapper with --strategy flag parsing |
Summary
ScanStrategy::Sample(N)(default: N=8) provides the best speed/accuracy trade‑off for most production workloads inpdf‑inspectorScanStrategy::Fulleliminates sampling error when distinguishing Mixed from Scanned PDFsScanStrategy::EarlyExitoptimizes latency for text‑heavy pipelines but risks false negatives on image‑first documentsScanStrategy::Pagesgives precise control for custom integration scenarios- Configure via
DetectionConfigin code or--strategyflag in the CLI
Frequently Asked Questions
What happens if Sample(N) picks only image pages in a Mixed PDF?
The distribute_pages algorithm always includes first and last pages, reducing this risk. For documents where interior pages are predominantly images while boundaries are text (or vice versa), lower accuracy is possible—use ScanStrategy::Full when this edge case matters.
How does EarlyExit interact with the text_page_ratio_threshold?
EarlyExit stops at the first page falling below min_text_ops_per_page, returning early without computing a full ratio. This means text_page_ratio_threshold is effectively ignored; the PDF is classified based on the early exit condition alone.
Can I change strategies between PDFs in the same process?
Yes. DetectionConfig is passed by value to detect_pdf_type_with_config, so each call uses its own independent configuration. Create strategy‑specific configs and select them based on file size, source, or other heuristics at runtime.
Why does Sample include both first and last pages?
Cover pages and appendices often differ structurally from document bodies. Including boundaries ensures pdf‑inspector detects footer‑heavy text documents and image‑only covers that might otherwise skew sampling.
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 →