# How to Change the PDF Classification Strategy in pdf-inspector: A Complete Guide

> Learn how to change the PDF classification strategy in pdf-inspector. This guide shows you how to create a custom DetectionConfig for precise PDF type detection using ScanStrategy variants.

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

---

**You can change the PDF classification strategy in pdf-inspector by creating a custom `DetectionConfig` with your desired `ScanStrategy` variant and passing it to `detect_pdf_type_with_config()`.**

The **pdf-inspector** repository by Firecrawl provides Rust-based PDF analysis that classifies documents into four types: *TextBased*, *Scanned*, *ImageBased*, or *Mixed*. The classification behavior is controlled through configurable scanning strategies that trade speed for accuracy. This article explains how to customize these strategies using the detector API exported from [`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs).

---

## Understanding the Classification Workflow

Before changing strategies, it helps to understand how pdf-inspector analyzes documents. The detection pipeline runs through six distinct phases as implemented in [`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs):

1. **Document loading** – `detect_pdf_type()` opens the PDF via `lopdf::Document`
2. **Page selection** – The `ScanStrategy` resolves to specific page indices and an `allow_early_exit` flag
3. **Per-page analysis** – `analyze_page_content()` extracts text operators, image counts, vector-text flags, and font decodability signals
4. **Signal aggregation** – Ratios like `text_ratio` (text pages ÷ sampled pages) are computed
5. **Heuristic classification** – Rules in `detect_from_document()` (lines 101–134) determine the final `PdfType`
6. **Optional refinement phases** – Newspaper layout detection and per-page OCR recommendations

The `ScanStrategy` you choose directly affects step 2, controlling which pages contribute to the aggregated signals.

---

## The Four ScanStrategy Variants

The `ScanStrategy` enum in [`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs) defines four approaches for page sampling:

| Variant | Behavior | Best For |
|---------|----------|----------|
| **`EarlyExit`** | Scan sequentially, stop at first non-text page | Fast routing of clearly TextBased documents |
| **`Full`** | Analyze every page, never exit early | Maximum accuracy for Mixed vs. Scanned discrimination |
| **`Sample(u32)`** | Scan N evenly distributed pages (first, last, middle) | Large PDFs where speed outweighs perfection |
| **`Pages(Vec<u32>)`** | Scan exact page numbers you specify | Deterministic testing or metadata-driven selection |

The default configuration uses `Sample(8)` as defined near line 84 in [`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs).

---

## Changing the Strategy in Rust Code

To override the default strategy, construct a `DetectionConfig` and pass it to `detect_pdf_type_with_config()`.

### Example 1: Full Scan for Maximum Accuracy

Use `ScanStrategy::Full` when you cannot afford misclassification on documents with text-only covers followed by scanned content:

```rust
use pdf_inspector::detector::{detect_pdf_type_with_config, DetectionConfig, ScanStrategy};

fn main() -> Result<(), pdf_inspector::PdfError> {
    let cfg = DetectionConfig {
        strategy: ScanStrategy::Full,
        ..Default::default()
    };
    let result = detect_pdf_type_with_config("example.pdf", cfg)?;
    println!("PDF type: {:?}, confidence: {}", result.pdf_type, result.confidence);
    Ok(())
}

```

### Example 2: Sample 4 Pages for Large Documents

Reduce runtime on hundred-page PDFs by sampling just 4 representative pages:

```rust
use pdf_inspector::detector::{detect_pdf_type_with_config, DetectionConfig, ScanStrategy};

fn main() -> Result<(), pdf_inspector::PdfError> {
    let cfg = DetectionConfig {
        strategy: ScanStrategy::Sample(4),
        ..Default::default()
    };
    let result = detect_pdf_type_with_config("big.pdf", cfg)?;
    println!("Detected as {:?} ({}% confidence)", result.pdf_type, result.confidence * 100.0);
    Ok(())
}

```

### Example 3: Specific Pages Only

Pass exact page numbers when external metadata (like a table of contents) indicates relevant sections:

```rust
let cfg = DetectionConfig {
    strategy: ScanStrategy::Pages(vec![1, 2, 3, 4, 5]),
    ..Default::default()
};
let result = detect_pdf_type_with_config("document.pdf", cfg)?;

```

---

## Adjusting Classification Thresholds

Beyond page selection, `DetectionConfig` exposes thresholds that affect heuristics in lines 101–134 of [`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs):

| Field | Default Purpose | When to Change |
|-------|---------------|--------------|
| `min_text_ops_per_page` | Minimum PDF text operators to count a page as "having text" | Raise for stricter TextBased classification |
| `text_page_ratio_threshold` | Proportion of text pages required for TextBased result | Raise to reduce false TextBased positives |

### Example 4: Strict TextBased Requirements

```rust
use pdf_inspector::detector::{detect_pdf_type_with_config, DetectionConfig, ScanStrategy};

fn main() -> Result<(), pdf_inspector::PdfError> {
    let cfg = DetectionConfig {
        strategy: ScanStrategy::Sample(8),
        min_text_ops_per_page: 7,       // default is lower; requires more text operators
        text_page_ratio_threshold: 0.8, // default is 0.7; demands 80% text pages
        ..Default::default()
    };
    let result = detect_pdf_type_with_config("strict.pdf", cfg)?;
    println!("Result: {:?}", result);
    Ok(())
}

```

---

## CLI Integration Notes

The `detect_pdf` binary in [`src/bin/detect_pdf.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/bin/detect_pdf.rs) serves as the command-line interface. It constructs a `DetectionConfig` from parsed arguments and forwards it to `detect_pdf_type_with_config()`.

To add a new CLI flag like `--full-scan`, modify [`src/bin/detect_pdf.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/bin/detect_pdf.rs) to:

1. Parse the flag from arguments
2. Build `DetectionConfig { strategy: ScanStrategy::Full, ..Default::default() }`
3. Pass that config to the detector function

No changes to [`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs) are required for basic strategy switching via CLI.

---

## Key Source Files for Customization

| File | Role | Key Locations |
|------|------|---------------|
| [`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs) | Core detection logic, `DetectionConfig`, `ScanStrategy`, `PdfType` enum | Definitions from line 12; strategy handling at lines 92–110; classification rules at lines 101–134 |
| [`src/bin/detect_pdf.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/bin/detect_pdf.rs) | CLI entry point | Arguments parsed here, config constructed, `detect_pdf_type_with_config` invoked |
| [`src/lib.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/lib.rs) | Public API exports | Re-exports detector functions for library consumers |
| `src/extractor/` | Content stream analysis | `analyze_page_content()` feeds signals to the detector |

---

## Summary

- **pdf-inspector** classifies PDFs via configurable `ScanStrategy` variants in [`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs)
- **Four strategies** exist: `EarlyExit`, `Full`, `Sample(N)`, and `Pages(Vec<u32>)`
- **Default is `Sample(8)`** — override via `DetectionConfig` passed to `detect_pdf_type_with_config()`
- **Threshold fields** (`min_text_ops_per_page`, `text_page_ratio_threshold`) fine-tune heuristics without code changes to classification rules
- **CLI customization** requires modifying [`src/bin/detect_pdf.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/bin/detect_pdf.rs) to construct and forward custom configs

---

## Frequently Asked Questions

### What is the fastest PDF classification strategy in pdf-inspector?

**`ScanStrategy::EarlyExit` is fastest** for documents that start with text pages, as it stops at the first non-text page. For documents known to be large and mixed, `ScanStrategy::Sample(4)` provides predictable, bounded runtime regardless of content distribution.

### When should I use Full scanning instead of the default Sample strategy?

**Use `ScanStrategy::Full`** when your pipeline cannot tolerate false *TextBased* classifications on documents with text covers followed by scanned interiors. The default `Sample(8)` may miss late-occurring scanned pages in very long PDFs.

### Can I change classification thresholds without modifying the source code?

**Yes, through `DetectionConfig` fields.** Adjust `min_text_ops_per_page` to require more text operators before counting a page as textual, or raise `text_page_ratio_threshold` above 0.7 to demand a higher proportion of text pages for *TextBased* results. These apply regardless of which `ScanStrategy` you select.

### How do I specify exact pages to analyze for classification?

**Use `ScanStrategy::Pages(Vec<u32>)`** with 1-indexed page numbers. This bypasses all sampling logic in lines 92–110 of [`src/detector.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/detector.rs) and analyzes only your specified pages, giving you deterministic, reproducible classification behavior ideal for testing or metadata-driven workflows.