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)

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 in pdf‑inspector
  • ScanStrategy::Full eliminates sampling error when distinguishing Mixed from Scanned PDFs
  • ScanStrategy::EarlyExit optimizes latency for text‑heavy pipelines but risks false negatives on image‑first documents
  • ScanStrategy::Pages gives precise control for custom integration scenarios
  • Configure via DetectionConfig in code or --strategy flag 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →