- โก RasgaPDF
- ๐ฏ The Philosophy: Pure Spatial Parsing
- โก Two Extraction Modes
- โก Performance Benchmark
- ๐ป Standalone CLI Tool
- ๐ Rust Quickstart
- ๐ฆ Native Bindings for Other Ecosystems
- ๐ฆ๏ธ๐ Official AI & RAG Integrations (LangChain & LlamaIndex)
- ๐จ Interactive Web Visualizer
- ๐ค AI Agents, Spatial RAG & LLM Grounding (
llms.txt) - ๐ค Contributing & Community
- ๐ License
- ๐ผ Commercial & Enterprise Licensing (AGPL-3.0 Waiver)
- ๐ฏ The Philosophy: Pure Spatial Parsing
โก 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.
GitHub Repo โข Web Visualizer โข 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.
๐ Deterministic Coordinate Contract (CropBox & Rotation Aware)
Every bounding box [x0, y0, x1, y1] emitted by RasgaPDF obeys an explicit, mathematically deterministic coordinate contract:
- Origin
(0, 0): Normalized to the Top-Left of the visible page viewport (CropBoxwith automatic fallback toMediaBox), matching web DOM and HTML5 Canvas standards. $+X$ points right, $+Y$ points downward. - Units: Standard PostScript / PDF typographic points ($1/72$ inch).
- Non-zero CropBox Offsets: Correctly subtracted ($ ext{norm_x} = x - ext{origin_x}$, $ ext{norm_y} = ext{max_y} - y$), so citations map to true visible screen pixels without drift.
- Rotation Awareness: Pages expose native
rotation(0, 90, 180, 270). You can also setapply_rotation=True(or call.with_applied_rotation()) to get pre-rotated bounding boxes that align directly with rotated document canvases.
โก 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 (Natural Reading Order via XY-Cut)
./target/release/rasgapdf sample.pdf --pretty
./target/release/rasgapdf sample.pdf --reading-order natural # default: Recursive XY-Cut multi-column
./target/release/rasgapdf sample.pdf --apply-rotation # normalize coordinates to rotated viewport
./target/release/rasgapdf sample.pdf -o structured.json
# ๐ค Built-in Model Context Protocol (MCP) Server for AI Assistants
./target/release/rasgapdf mcp
# ๐ผ๏ธ 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
๐ Model Context Protocol (MCP) Server
RasgaPDF ships with a native, zero-dependency MCP Server (rasgapdf mcp) exposing JSON-RPC 2.0 tools over stdio for Claude Desktop, Cursor, Antigravity, and AI agents:
{
"mcpServers": {
"rasgapdf": {
"command": "rasgapdf",
"args": ["mcp"]
}
}
}
parse_pdf: Extracts structured 2D text blocks, tables, and bounding boxes.search_document: Locates queries and returns precise bounding boxes for visual citations.get_chunks: Emits semantic RAG chunks with constituent bounding boxes and token counts.get_triage: Scans for complex layouts (is_complex_layout == true/ $S(R) \ge 0.45$) for selective Vision Model (VLM) routing.
๐ Rust Quickstart
Add rasgapdf to your Cargo.toml:
[dependencies]
rasgapdf = "0.3.4"
โก 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 |
Python Guide & Examples | |
| ๐ฆ Node.js | npm | npm install rasgapdf |
Node.js Guide & Examples | |
| ๐ฆ Rust | crates.io | cargo add rasgapdf |
docs.rs Reference | |
| ๐ท C# / .NET | NuGet | dotnet add package RasgaPdf |
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: "chunks" (Dense RAG Chunking โ preserves multi-rect bounding boxes per chunk!)
chunk_loader = RasgaPDFLoader("paper.pdf", mode="chunks", chunk_max_chars=1200, chunk_overlap_blocks=1)
chunks = chunk_loader.load()
for ch in chunks:
# Rich semantic text for embedding models + full list of constituent boxes for visual citation!
print(f"Page {ch.metadata['page']} | BBoxes: {len(ch.metadata['bboxes'])} | Overall: {ch.metadata['overall_bbox']}")
print(ch.page_content)
# Mode 3: "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)
๐งฉ Native Spatial Chunking (rasgapdf.to_spatial_chunks)
For custom RAG pipelines, extract semantic chunks with preserved multi-rect highlight boundaries in one call:
import rasgapdf
doc = rasgapdf.parse_pdf("annual_report.pdf")
chunks = rasgapdf.to_spatial_chunks(doc, max_chars=1200, overlap_blocks=1)
for ch in chunks:
# Embed ch["text"] into vector database (Pinecone, Qdrant, Chroma, pgvector)
# Store ch["bboxes"] in metadata -> frontend draws multi-rect highlights upon retrieval!
print(f"Chunk #{ch['chunk_id']} (Page {ch['page_number']}) โ {ch['block_count']} blocks, {ch['token_estimate']} tokens")
print(f"Highlight quads: {ch['bboxes']}")
๐จ 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
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:
- Concise LLM Index:
llms.txt - Complete Technical Reference (
llms-full.txt):llms-full.txt - Coding Agent Instructions:
AGENTS.md
โ Frequently Asked Questions (FAQ)
๐ฌ๐ง English
- When should I choose RasgaPDF over PyMuPDF (
fitz),pdfplumber, orpypdf?
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 thanpdfplumberand 4x faster thanPyMuPDF) 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 viapip install rasgapdf,npm install rasgapdf,dotnet add package RasgaPdfoucargo add rasgapdf. Useparse_raw("arquivo.pdf")para obter coordenadas fรญsicas[x0, y0, x1, y1]em ~3โ8 ms por pรกgina, ouparse_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 parawasm32-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!
- Read our Contributing Guide to get started.
- Adhere to our Code of Conduct.
๐ 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.