# How to Use ScanStrategy (EarlyExit, Full, Sample, Pages) for Faster PDF Detection in pdf‑inspector

> Boost PDF detection speed in pdf-inspector using ScanStrategy options like EarlyExit, Full, Sample, and Pages. Optimize performance for your specific needs.

- Repository: [Firecrawl/pdf-inspector](https://github.com/firecrawl/pdf-inspector)
- Tags: how-to-guide
- Published: 2026-08-10

---

**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)](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)](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`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs) 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)](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:

```rust
// 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<u32>): 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:

```rust
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)](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:

```rust
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):

```rust
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:

```rust
let streaming_cfg = DetectionConfig {
    strategy: ScanStrategy::EarlyExit,
    ..Default::default()
};

```

## Applying Custom Strategies in Code

Import the configuration types and construct your `DetectionConfig`:

```rust
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)](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)](https://github.com/firecrawl/pdf-inspector/blob/main/src/bin/detect_pdf.rs) exposes strategy selection via command‑line flags:

```bash

# 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)](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)](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)](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.