# How pdf-inspector Detects Tables in PDFs: A Three-Stage Strategy

> Discover how pdf-inspector employs a three-stage strategy for accurate table detection in PDFs. Learn about rectangle-based, line-based, and text-flow analysis techniques.

- Repository: [Firecrawl/pdf-inspector](https://github.com/firecrawl/pdf-inspector)
- Tags: deep-dive
- Published: 2026-08-13

---

**pdf-inspector uses a tiered pipeline that attempts rectangle-based detection first, falls back to line-based analysis, and finally applies text-flow heuristics to identify tabular structures in PDF documents.**

The `firecrawl/pdf-inspector` repository implements a sophisticated table detection system written in Rust that processes PDF documents through three distinct algorithms. Each strategy targets different structural cues—ranging from explicit graphics to implicit text patterns—to maximize extraction accuracy across diverse PDF formats. This article examines the technical implementation of these table detection strategies, including source file locations and optimization logic.

## The Three-Stage Detection Pipeline

pdf-inspector orchestrates table detection through a fixed priority order defined in [`src/tables/mod.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/tables/mod.rs). The pipeline invokes **rectangle-based detection** first, proceeds to **line-based detection** if no tables are found, and finally attempts **heuristic detection** as a fallback. This approach stops as soon as any method yields a valid table layout, ensuring that the most reliable graphics-based methods take precedence over text inference.

The public API in [`src/tables/mod.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/tables/mod.rs) exposes the three detectors:

```rust
pub use detect_rects::{detect_tables_from_rects, RectHintRegion};
pub use detect_lines::{detect_tables_from_lines};
pub use detect_heuristic::{detect_tables_heuristically};

```

During PDF processing, the `process_pdf_with_options` function in [`src/lib.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/lib.rs) executes this logic sequentially, checking for empty results between each stage.

## Rectangle-Based Detection with Union-Find Clustering

The most reliable method analyzes PDF drawing rectangles to reconstruct table grids. Implemented in [`src/tables/detect_rects.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/tables/detect_rects.rs), this strategy collects filled boxes, cell backgrounds, and rule lines from the page content stream. It then applies a **union-find algorithm** to cluster these rectangles into coherent cell boundaries.

This method excels when PDFs encode table structure explicitly as vector graphics or background fills. The `detect_tables_from_rects` function accepts tolerance parameters for rectangle clustering, allowing fine-tuning for documents with slight misalignments.

## Line-Based Detection Using H/V Grid Analysis

When rectangle detection returns empty results, pdf-inspector falls back to line-based detection in [`src/tables/detect_lines.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/tables/detect_lines.rs). This strategy scans the page for horizontal and vertical line operators, building an H/V line grid from the intersection points. Cell boundaries are inferred where these lines cross, making this approach effective for PDFs that draw tables with straight rules but lack filled backgrounds.

The `detect_tables_from_lines` function constructs this grid without requiring explicit rectangle objects, capturing tables defined purely by stroked paths.

## Heuristic Detection via Text Flow Analysis

The final fallback method, implemented in [`src/tables/detect_heuristic.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/tables/detect_heuristic.rs), operates entirely on text properties when no graphics cues exist. This strategy analyzes **gap-histograms** between text items, monitors font size variations, and clusters content by body-font characteristics to infer tabular structures.

`detect_tables_heuristically` handles PDFs where tables exist only as aligned text columns without visible borders. While less precise than graphics-based methods, this ensures pdf-inspector can extract data from scanned documents or minimally formatted reports.

## Orchestrating the Detection Pipeline

The integration logic resides in the main processing flow within [`src/lib.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/lib.rs). Rather than running all three detectors simultaneously, pdf-inspector implements a short-circuit evaluation:

1. Call `detect_tables_from_rects` with page geometry data
2. If results are empty, invoke `detect_tables_from_lines`
3. If still empty, execute `detect_tables_heuristically`

This tiered approach balances accuracy with performance, avoiding the computational overhead of heuristic analysis when graphical table markers are present.

## Usage Examples

### Command-Line Interface

The CLI automatically runs the full detection pipeline during Markdown conversion:

```bash

# Extract PDF to Markdown with automatic table detection

pdf2md my-report.pdf > my-report.md

# Output structured JSON including detected table cells

pdf2md --json my-report.pdf > my-report.json

```

### Direct Library Integration

For programmatic control, import the table detection modules directly:

```rust
use pdf_inspector::lib::process_pdf_with_options;
use pdf_inspector::tables::{detect_rects, detect_lines, detect_heuristic};

fn main() -> anyhow::Result<()> {
    let pdf = pdf_inspector::pdf::PdfDocument::load("my-report.pdf")?;
    
    // Full pipeline with automatic table detection
    let markdown = process_pdf_with_options(&pdf, Default::default())?;
    
    // Manual pipeline control for custom logic
    let page_rects = pdf.page_rects(0)?;
    let rect_tables = detect_rects::detect_tables_from_rects(&page_rects, 3.0, 6)?;
    
    if rect_tables.is_empty() {
        let line_tables = detect_lines::detect_tables_from_lines(&page_rects)?;
        if line_tables.is_empty() {
            let heuristic_tables = detect_heuristic::detect_tables_heuristically(&page_rects)?;
        }
    }
    Ok(())
}

```

## Summary

- pdf-inspector implements **three distinct table detection algorithms** in separate Rust modules: rectangle-based, line-based, and heuristic.
- **Detection priority** follows a fixed order: rectangles first (most reliable), then lines, then text heuristics (fallback).
- **Rectangle detection** ([`src/tables/detect_rects.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/tables/detect_rects.rs)) uses union-find clustering on PDF drawing operations.
- **Line detection** ([`src/tables/detect_lines.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/tables/detect_lines.rs)) builds grids from horizontal and vertical line operators.
- **Heuristic detection** ([`src/tables/detect_heuristic.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/tables/detect_heuristic.rs)) analyzes text gaps and font sizes when graphics cues are absent.
- The pipeline short-circuits at the first successful detection to optimize performance.

## Frequently Asked Questions

### What order does pdf-inspector try table detection methods?

pdf-inspector attempts detection in the following order: rectangle-based detection first, line-based detection second, and heuristic detection last. This sequence is hardcoded in the pipeline logic to prioritize methods with higher structural certainty over inference-based approaches.

### Which method works best for PDFs with visible borders?

Rectangle-based detection yields the most accurate results for PDFs containing explicit borders, filled cell backgrounds, or rule lines. This method analyzes the actual PDF drawing commands rather than inferring structure from text positioning.

### How does pdf-inspector handle tables without visible lines?

When neither rectangles nor lines are detected, pdf-inspector falls back to heuristic detection in [`src/tables/detect_heuristic.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/tables/detect_heuristic.rs). This method examines text flow patterns, gap distributions between text elements, and font size clustering to identify columnar data structures.

### Can I use a specific detection method instead of the full pipeline?

Yes. While `process_pdf_with_options` runs the complete pipeline, you can import individual detectors from [`src/tables/mod.rs`](https://github.com/firecrawl/pdf-inspector/blob/main/src/tables/mod.rs) and invoke `detect_tables_from_rects`, `detect_tables_from_lines`, or `detect_tables_heuristically` directly on page geometry data for custom extraction logic.