rasgapdf 0.3.2

Blazing-fast spatial 2D PDF parser in pure Rust with multi-language bindings (Python, Node.js, Go, C#) for RAG, LLMs, bounding boxes, and table extraction
Documentation

language:

  • en
  • pt license: agpl-3.0 tags:
  • pdf
  • pdf-parser
  • spatial
  • spatial-pdf
  • parser
  • rust
  • python
  • nodejs
  • layout-analysis
  • document-parsing
  • bounding-box
  • table-extraction
  • rag
  • llm
  • pdf-to-json
  • document-ai pipeline_tag: document-question-answering

⚡ RasgaPDF

The Blazing-Fast 2D Spatial PDF Parser powered by Pure Rust.
Extract exact physical coordinates (Raw X/Y) or structured blocks & tables at native hardware speeds.

Hugging Face Space PyPI version PyPI Downloads npm version npm Downloads Crates.io Crates.io Downloads NuGet version NuGet Downloads License: AGPL v3 OpenSSF Scorecard Commercial License

GitHub Repo • Web Visualizer • HF Space Demo • Docs Map (Diátaxis) • Two Modes • CLI Tool • Architecture • Spatial Schema • llms.txt


🎯 The Philosophy: Pure Spatial Parsing

Most PDF extraction tools make fragile guesses: they flatten multi-column layouts into corrupted text streams, mangle tables, and strip away 2D positional geometry.

RasgaPDF does one thing with uncompromising precision:
It returns the exact 2D physical spatial geometry of the PDF.

  • Bounding Boxes Everywhere: Every character, word span, line, block, and table has exact coordinates [x0, y0, x1, y1].
  • Zero Lossy Heuristics: No broken markdown assumptions. Downstream LLMs, RAG pipelines, or vision-language models receive the true physical layout.
  • Microsecond Rayon Parallelism: Multi-threaded page processing in pure Rust utilizing AVX2/AVX-512 SIMD.
  • Polyglot First: Native C-ABI FFI bindings for Python, Node.js, Go, and C# (.NET).

⚡ Two Extraction Modes

RasgaPDF offers two distinct modes for different engineering needs:

⚡ Mode 1: Flat Physical Coordinates (Raw X/Y)

The fastest, most direct extraction possible. Returns an unnested list of physical 2D coordinates for every text span on the page, with zero block or table overhead:

  • Latency: ~3 to 8 ms per page
  • Supported Formats: Flat JSON, Formatted Text, TSV, or CSV
  • Best For: Spatial RAG, 2D visualizers, vector indexing, OCR alignment, Unix pipelines with awk/grep.
[Page 1] (X0:  50.00, Y0:  67.00, X1: 244.00, Y1:  83.00) [12.0pt] The Revolution of Artificial Intelligence
[Page 1] (X0:  50.00, Y0: 103.00, X1: 478.00, Y1: 119.00) [12.0pt] Artificial Intelligence (AI) has transformed...

🎯 Mode 2: Hierarchical Structured Document

Reconstructs the visual hierarchy into visual paragraphs (text_blocks), text lines (lines), spans, and auto-detects matrix tables via horizontal column projection:

  • Latency: ~8 to 15 ms per page
  • Output: Hierarchical tree SpatialDocument -> pages -> text_blocks -> lines -> tables.

⚡ Performance Benchmark

Measured on Intel Core i7-1365U (10 Cores / 12 Threads, AVX2):

Library / Tool Language Single Page 50 Pages Memory Footprint Output Type
⚡ RasgaPDF (Raw X/Y) Rust (Native) 7.7 ms 95 ms ~14 MB Flat Raw Coordinates
🚀 RasgaPDF (Structured) Rust (Native) 8.5 ms 142 ms ~18 MB Spatial Blocks & Tables
PyMuPDF (fitz) C / Python 28.0 ms 620 ms ~45 MB Text / Pixmap
pdfplumber Python 410.0 ms 9,800 ms ~140 MB Python dicts
pypdf Python 95.0 ms 2,100 ms ~85 MB Flat text string
Apache Tika Java 650.0 ms 12,400 ms ~320 MB XHTML

💻 Standalone CLI Tool

Install or build the standalone CLI binary:

cargo build --release
./target/release/rasgapdf --help

# ⚡ MODE 1: Raw Physical Coordinates (Raw X/Y)
./target/release/rasgapdf sample.pdf --raw
./target/release/rasgapdf sample.pdf --raw --format text
./target/release/rasgapdf sample.pdf --raw --format tsv | awk -F'\t' '$1 == 1 {print $2, $3, $8}'
./target/release/rasgapdf sample.pdf --raw --format csv -o coordinates.csv

# 🎯 MODE 2: Hierarchical Structured Document
./target/release/rasgapdf sample.pdf --pretty
./target/release/rasgapdf sample.pdf -o structured.json

# 🖼️ GRAPHICS (opt-in): embedded images and vector paths
./target/release/rasgapdf sample.pdf --images --drawings --pretty
./target/release/rasgapdf sample.pdf --extract-images ./out   # writes ./out/*.jpg + manifest.json

🚀 Rust Quickstart

Add rasgapdf to your Cargo.toml:

[dependencies]
rasgapdf = "0.3.1"

⚡ Mode 1: Raw Physical Coordinates (Raw X/Y)

Extract exact 2D bounding boxes [x0, y0, x1, y1] for every text span on the page with zero block overhead (~3 to 8 ms):

use rasgapdf::parse_raw_file;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let raw = parse_raw_file("sample.pdf")?;
    println!("Extracted {} spans in {:.2} ms", raw.total_spans, raw.parse_time_ms);

    for span in &raw.spans {
        println!(
            "[Page {}] bbox=({:.2}, {:.2}, {:.2}, {:.2}) font={} ({:.1}pt) \"{}\"",
            span.page, span.x0, span.y0, span.x1, span.y1,
            span.font_name, span.font_size, span.text
        );
    }
    Ok(())
}

🎯 Mode 2: Hierarchical Structured Document

Reconstruct the visual hierarchy into visual paragraphs (text_blocks), text lines (lines), and auto-detect matrix tables:

use rasgapdf::{parse_file, ParserOptions};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let options = ParserOptions {
        detect_tables: true,
        min_table_columns: 3,
        column_tolerance: 16.0,
        row_tolerance: 6.0,
        ..Default::default()
    };

    let doc = parse_file("document.pdf", &options)?;
    println!("Processed {} pages in {:.2} ms", doc.total_pages, doc.parse_time_ms);

    for page in &doc.pages {
        println!("--- Page {} ({}x{} pt) ---", page.page_number, page.width, page.height);

        // 1. Text blocks and lines
        for block in &page.text_blocks {
            println!("Block #{} at {:?}", block.block_id, block.bbox);
            for line in &block.lines {
                println!("  Line: {}", line.text);
            }
        }

        // 2. Reconstructed tables
        for table in &page.tables {
            println!("Table ({} cols x {} rows):", table.col_count, table.row_count);
            println!("  Headers: {:?}", table.headers);
            for row in &table.rows {
                println!("  Row: {:?}", row);
            }
        }
    }
    Ok(())
}

🖼️ Embedded Images & Vector Graphics (opt-in)

Both extras are off by default, so the JSON shape is byte-for-byte unchanged unless you ask for them. Image bytes are never embedded in the JSON: metadata (dimensions, colour space, filter, SHA-256) stays in the tree, while the original encoded stream can be written to disk.

use rasgapdf::{extract_images, parse_file, write_images_to_dir, ParserOptions};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let options = ParserOptions {
        extract_images: true,
        extract_drawings: true,
        ..Default::default()
    };

    let doc = parse_file("document.pdf", &options)?;

    for page in &doc.pages {
        for image in &page.images {
            println!(
                "image {} on page {}: {}x{} px, filter={:?}, bbox={:?}",
                image.name, page.page_number, image.pixel_width, image.pixel_height,
                image.filter, image.bbox
            );
        }

        for drawing in &page.drawings {
            println!(
                "path {} on page {}: {} ({} items, stroke={:?})",
                drawing.drawing_id, page.page_number, drawing.drawing_type,
                drawing.item_count, drawing.stroke_color
            );
        }
    }

    // Original encoded streams (e.g. `.jpg` for DCTDecode) plus a `manifest.json`.
    let mut images = extract_images("document.pdf")?;
    let written = write_images_to_dir(&mut images, std::path::Path::new("./out"))?;
    println!("wrote {written} image files");

    Ok(())
}

Equivalent CLI flags: --images, --drawings, --extract-images DIR, and --keep-backgrounds (keeps full-page background fills, which are dropped by default). See docs/SCHEMA.md for the full field reference.


📦 Native Bindings for Other Ecosystems

RasgaPDF provides native C-ABI bindings for other languages, each published with its own language-specific package and documentation:

Language Registry Package / Installation Total Downloads Documentation
🐍 Python PyPI pip install rasgapdf PyPI Python Guide & Examples
📦 Node.js npm npm install rasgapdf npm Node.js Guide & Examples
🦀 Rust crates.io cargo add rasgapdf crates.io docs.rs Reference
🔷 C# / .NET NuGet dotnet add package RasgaPdf NuGet C# Guide & Examples
🐹 Go Go Module go get github.com/MartinsMessias/rasgapdf/bindings/go (via Go Proxy) Go Guide & Examples

🦜️🔗 Official AI & RAG Integrations (LangChain & LlamaIndex)

RasgaPDF provides out-of-the-box loaders for LangChain and LlamaIndex with zero external setup:

🦜️ LangChain Document Loader (RasgaPDFLoader)

Preserves reading flow, exact 2D coordinates [x0, y0, x1, y1], and turns tables into structured Markdown matrices for LLM prompting:

from rasgapdf import RasgaPDFLoader

# Mode 1: "pages" (Default — 1 LangChain Document per PDF page with markdown tables)
loader = RasgaPDFLoader("contract.pdf", mode="pages")
docs = loader.load()
for doc in docs:
    print(f"Page {doc.metadata['page']} (Tables: {doc.metadata['table_count']})")
    print(doc.page_content)

# Mode 2: "elements" (Spatial RAG — 1 Document per text block/table with exact bounding box!)
spatial_loader = RasgaPDFLoader("invoice.pdf", mode="elements")
elements = spatial_loader.load()
for el in elements:
    # Each chunk carries its true physical coordinates [x0, y0, x1, y1]
    print(f"Type: {el.metadata['type']} | BBox: {el.metadata['bbox']}")
    print(el.page_content)

🦙 LlamaIndex Reader (RasgaPDFReader)

Native high-throughput reader for LlamaIndex vector indices and query engines:

from rasgapdf import RasgaPDFReader
from llama_index.core import VectorStoreIndex

reader = RasgaPDFReader(mode="pages", detect_tables=True)
documents = reader.load_data("financial_report.pdf")

# Build lightning-fast vector index with exact spatial context
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
response = query_engine.query("What was the net profit in table 3?")
print(response)

🎨 Interactive Web Visualizer

🌐 Live Hugging Face Space (Zero Server Quota / Client-Side)

Test RasgaPDF instantly without installing anything:

  • Live Demo: https://huggingface.co/spaces/martinsmessias/rasgapdf
  • Zero Server Costs: Runs directly in your browser using pure client-side Rust WebAssembly.
  • Run on Your Personal Quota: Click Duplicate this Space to clone into your own Hugging Face account with your personal compute quota.

🤖 AI Agents, Spatial RAG & LLM Grounding (llms.txt)

RasgaPDF provides first-class machine-readable documentation following the llms.txt standard so coding agents (Cursor, Claude Code, GitHub Copilot, Windsurf, Perplexity, ChatGPT) can index and integrate the full API in a single pass:

❓ Frequently Asked Questions (FAQ)

🇬🇧 English

  • When should I choose RasgaPDF over PyMuPDF (fitz), pdfplumber, or pypdf?
    Choose RasgaPDF when you need exact 2D bounding-box coordinates [x0, y0, x1, y1], automatic matrix table reconstruction, opt-in embedded image/vector extraction, or high-throughput multi-threaded Rust speed (~3–8 ms/page — up to 50x faster than pdfplumber and 4x faster than PyMuPDF) with an identical JSON schema across Rust, Python, Node.js, Go, and C#.
  • Does RasgaPDF require external C dependencies or PDF.js?
    No. RasgaPDF is 100% pure Rust with zero external C dependencies. The browser visualizer runs on pure client-side WebAssembly compiled from the same Rust codebase.

🇧🇷 Português (Brasil)

  • Como extrair texto, tabelas e coordenadas X/Y (bounding boxes) de PDF rápido em Python, Rust, Node.js ou C#?
    Instale o RasgaPDF via pip install rasgapdf, npm install rasgapdf, dotnet add package RasgaPdf ou cargo add rasgapdf. Use parse_raw("arquivo.pdf") para obter coordenadas físicas [x0, y0, x1, y1] em ~3–8 ms por página, ou parse_pdf("arquivo.pdf", detect_tables=True, extract_images=True, extract_drawings=True) para reconstruir blocos de texto, tabelas, imagens embutidas e gráficos vetoriais.
  • O RasgaPDF funciona no navegador em WebAssembly sem servidor?
    Sim. Todo o core em Rust compila diretamente para wasm32-unknown-unknown, permitindo processamento 100% local no navegador com segurança e privacidade total (Zero Data Transmission).

🤝 Contributing & Community

Contributions are what make the open-source community thrive!


📄 License

RasgaPDF is licensed under the GNU Affero General Public License v3.0 or later.
Copyright (c) 2026 Messias Martins.

RasgaPDF is an independent, 100% pure Rust implementation of the ISO 32000-1 PDF specification. It contains zero external C library dependencies and zero MuPDF bindings. All lexical analysis, cross-reference table/stream decoding, Flate decompression, Type 1/TrueType/Type0 CID font decoding, and 2D spatial coordinate tracking are natively executed in pure Rust.


💼 Commercial & Enterprise Licensing (AGPL-3.0 Waiver)

Need to use RasgaPDF in closed-source commercial software, proprietary SaaS platforms, private cloud environments, or corporate applications without releasing your source code under the AGPL-3.0?

A Commercial / Enterprise License is available directly from the author:

  • Complete AGPL-3.0 Exemption: Keep your intellectual property, backend code, and SaaS infrastructure 100% closed-source and proprietary.
  • Enterprise SLA & Support: Direct architecture advisory, guaranteed response times, and priority bug resolution.
  • On-Premise & Air-Gapped Appliances: Ready-to-deploy private Docker containers for confidential banking, healthcare, and legal compliance (LGPD / GDPR).
  • Custom Spatial Features: Tailored table extractors for bank statements, invoices, and court proceedings.

📬 Inquiries & Licensing:
👉 Click here to Request a Commercial License & Pricing with details about your organization, use case, and estimated volume.