pdfmux
pdfmux
Orquestador universal de extracción de PDF. Dirige cada página al mejor backend, audita el resultado y vuelve a extraer los fallos. 5 extractores basados en reglas + fallback de LLM BYOK (trae tu propia clave). Una CLI. Una API. Configuración cero.
PDF ──> pdfmux router ──> best extractor per page ──> audit ──> re-extract failures ──> Markdown / JSON / chunks
|
├─ PyMuPDF (digital text, 0.01s/page)
├─ OpenDataLoader (complex layouts, 0.05s/page)
├─ RapidOCR (scanned pages, CPU-only)
├─ Docling (tables, 97.9% TEDS)
├─ Surya (heavy OCR fallback)
└─ YOUR LLM (Gemini / Claude / GPT-4o / Ollama — BYOK via 5-line YAML)Instalación
pip install pdfmuxEso es todo. Maneja PDFs digitales de forma nativa. Añade backends para documentos más complejos:
pip install "pdfmux[ocr]" # RapidOCR — scanned/image pages (~200MB, CPU-only)
pip install "pdfmux[tables]" # Docling — table-heavy docs (~500MB)
pip install "pdfmux[opendataloader]" # OpenDataLoader — complex layouts (Java 11+)
pip install "pdfmux[llm]" # LLM fallback — Gemini, Claude, GPT-4o, Ollama
pip install "pdfmux[all]" # everythingRequiere Python 3.11+.
Inicio rápido
CLI
# zero config — just works
pdfmux convert invoice.pdf
# invoice.pdf -> invoice.md (2 pages, 95% confidence, via pymupdf4llm)
# RAG-ready chunks with token limits
pdfmux convert report.pdf --chunk --max-tokens 500
# cost-aware extraction with budget cap
pdfmux convert report.pdf --mode economy --budget 0.50
# schema-guided structured extraction (5 built-in presets)
pdfmux convert invoice.pdf --schema invoice
# BYOK any LLM for hardest pages
pdfmux convert scan.pdf --llm-provider claude
# batch a directory
pdfmux convert ./docs/ -o ./output/Python
import pdfmux
# text -> markdown
text = pdfmux.extract_text("report.pdf")
# structured data -> dict with tables, key-values, metadata
data = pdfmux.extract_json("report.pdf")
# RAG chunks -> list of dicts with token estimates
chunks = pdfmux.chunk("report.pdf", max_tokens=500)Arquitectura
┌─────────────────────────────┐
│ Segment Detector │
│ text / tables / images / │
│ formulas / headers per page │
└─────────────┬───────────────┘
│
┌────────────────────────────────────────┐
│ Router Engine │
│ │
│ economy ── balanced ── premium │
│ (minimize $) (default) (max quality)│
│ budget caps: --budget 0.50 │
└────────────────────┬───────────────────┘
│
┌──────────┬──────────┬────────┴────────┬──────────┐
│ │ │ │ │
PyMuPDF OpenData RapidOCR Docling LLM
digital Loader scanned tables (BYOK)
0.01s/pg complex CPU-only 97.9% any provider
layouts TEDS
│ │ │ │ │
└──────────┴──────────┴────────┬────────┴──────────┘
│
┌────────────────────────────────────────┐
│ Quality Auditor │
│ │
│ 4-signal dynamic confidence scoring │
│ per-page: good / bad / empty │
│ if bad -> re-extract with next backend│
└────────────────────┬───────────────────┘
│
┌────────────────────────────────────────┐
│ Output Pipeline │
│ │
│ heading injection (font-size analysis)│
│ table extraction + normalization │
│ text cleanup + merge │
│ confidence score (honest, not inflated)│
└────────────────────────────────────────┘Decisiones clave de diseño
Enrutador, no extractor. pdfmux no compite con PyMuPDF o Docling. Elige el mejor para cada página.
Multi-pasada agéntica. Extrae, audita la confianza y vuelve a extraer los fallos con un backend más potente. Las páginas erróneas se reintentan automáticamente.
Detección a nivel de segmento. Cada página se clasifica por tipo de contenido (texto, tablas, imágenes, fórmulas, encabezados) antes del enrutamiento.
Confianza de 4 señales. Puntuación de calidad dinámica basada en densidad de caracteres, ruido de OCR, integridad de tablas y estructura de encabezados. Sin umbrales codificados.
Caché de documentos. Cada PDF se abre una vez, no una vez por extractor. Compartido en todo el pipeline.
Volante de datos. La telemetría local rastrea qué extractores ganan por tipo de documento. El enrutamiento mejora con el uso.
Características
Característica | Qué hace | Comando |
Extracción sin configuración | Enruta al mejor backend automáticamente |
|
Fragmentación RAG | Fragmentos conscientes de la sección con estimaciones de tokens |
|
Modos de coste | economy / balanced / premium con límites de presupuesto |
|
Extracción de esquema | 5 preajustes integrados (factura, recibo, contrato, currículum, artículo) |
|
LLM BYOK | Gemini, Claude, GPT-4o, Ollama, cualquier API compatible con OpenAI |
|
Benchmark | Evalúa todos los extractores instalados contra la verdad fundamental |
|
Doctor | Muestra backends instalados, brechas de cobertura, recomendaciones |
|
Servidor MCP | Los agentes de IA leen PDFs vía stdio o HTTP |
|
Procesamiento por lotes | Convierte directorios completos |
|
Streaming | Iteración de páginas con memoria limitada para archivos grandes |
|
Referencia de CLI
pdfmux convert
pdfmux convert <file-or-dir> [options]
Options:
-o, --output PATH Output file or directory
-f, --format FORMAT markdown | json | csv | llm (default: markdown)
-q, --quality QUALITY fast | standard | high (default: standard)
-s, --schema SCHEMA JSON schema file or preset (invoice, receipt, contract, resume, paper)
--chunk Output RAG-ready chunks
--max-tokens N Max tokens per chunk (default: 500)
--mode MODE economy | balanced | premium (default: balanced)
--budget AMOUNT Max spend per document in USD
--llm-provider PROVIDER LLM backend: gemini | claude | openai | ollama
--confidence Include confidence score in output
--stdout Print to stdout instead of filepdfmux serve
Inicia el servidor MCP para la integración de agentes de IA.
pdfmux serve # stdio mode (Claude Desktop, Cursor)
pdfmux serve --http 8080 # HTTP modepdfmux doctor
pdfmux doctor
# ┌──────────────────┬─────────────┬─────────┬──────────────────────────────────┐
# │ Extractor │ Status │ Version │ Install │
# ├──────────────────┼─────────────┼─────────┼──────────────────────────────────┤
# │ PyMuPDF │ installed │ 1.25.3 │ │
# │ OpenDataLoader │ installed │ 0.3.1 │ │
# │ RapidOCR │ installed │ 3.0.6 │ │
# │ Docling │ missing │ -- │ pip install pdfmux[tables] │
# │ Surya │ missing │ -- │ pip install pdfmux[ocr-heavy] │
# │ LLM (Gemini) │ configured │ -- │ GEMINI_API_KEY set │
# └──────────────────┴─────────────┴─────────┴──────────────────────────────────┘pdfmux benchmark
pdfmux benchmark report.pdf
# ┌──────────────────┬────────┬────────────┬─────────────┬──────────────────────┐
# │ Extractor │ Time │ Confidence │ Output │ Status │
# ├──────────────────┼────────┼────────────┼─────────────┼──────────────────────┤
# │ PyMuPDF │ 0.02s │ 95% │ 3,241 chars │ all pages good │
# │ Multi-pass │ 0.03s │ 95% │ 3,241 chars │ all pages good │
# │ RapidOCR │ 4.20s │ 88% │ 2,891 chars │ ok │
# │ OpenDataLoader │ 0.12s │ 97% │ 3,310 chars │ best │
# └──────────────────┴────────┴────────────┴─────────────┴──────────────────────┘API de Python
Extracción de texto
import pdfmux
text = pdfmux.extract_text("report.pdf") # -> str (markdown)
text = pdfmux.extract_text("report.pdf", quality="fast") # PyMuPDF only, instant
text = pdfmux.extract_text("report.pdf", quality="high") # LLM-assistedExtracción estructurada
data = pdfmux.extract_json("report.pdf")
# data["page_count"] -> 12
# data["confidence"] -> 0.91
# data["ocr_pages"] -> [2, 5, 8]
# data["pages"][0]["key_values"] -> [{"key": "Date", "value": "2026-02-28"}]
# data["pages"][0]["tables"] -> [{"headers": [...], "rows": [...]}]Fragmentación RAG
chunks = pdfmux.chunk("report.pdf", max_tokens=500)
for c in chunks:
print(f"{c['title']}: {c['tokens']} tokens (pages {c['page_start']}-{c['page_end']})")Extracción guiada por esquema
data = pdfmux.extract_json("invoice.pdf", schema="invoice")
# Uses built-in invoice preset: extracts date, vendor, line items, totals
# Also accepts a path to a custom JSON Schema fileStreaming (memoria limitada)
from pdfmux.extractors import get_extractor
ext = get_extractor("fast")
for page in ext.extract("large-500-pages.pdf"): # Iterator[PageResult]
process(page.text) # constant memory, even on 500-page PDFsTipos y errores
from pdfmux import (
# Enums
Quality, # FAST, STANDARD, HIGH
OutputFormat, # MARKDOWN, JSON, CSV, LLM
PageQuality, # GOOD, BAD, EMPTY
# Data objects (frozen dataclasses)
PageResult, # page: text, page_num, confidence, quality, extractor
DocumentResult, # document: pages, source, confidence, extractor_used
Chunk, # chunk: title, text, page_start, page_end, tokens
# Errors
PdfmuxError, # base -- catch this for all pdfmux errors
FileError, # file not found, unreadable, not a PDF
ExtractionError, # extraction failed
ExtractorNotAvailable,# requested backend not installed
FormatError, # invalid output format
AuditError, # audit could not complete
)Integraciones de Framework
LangChain
pip install langchain-pdfmuxfrom langchain_pdfmux import PDFMuxLoader
loader = PDFMuxLoader("report.pdf", quality="standard")
docs = loader.load() # -> list[Document] with confidence metadataLlamaIndex
pip install llama-index-readers-pdfmuxfrom llama_index.readers.pdfmux import PDFMuxReader
reader = PDFMuxReader(quality="standard")
docs = reader.load_data("report.pdf") # -> list[Document]Servidor MCP (Agentes de IA)
Listado en mcpservers.org. Configuración en una línea:
{
"mcpServers": {
"pdfmux": {
"command": "npx",
"args": ["-y", "pdfmux-mcp"]
}
}
}O vía Claude Code:
claude mcp add pdfmux -- npx -y pdfmux-mcpHerramientas expuestas: convert_pdf, analyze_pdf, extract_structured, get_pdf_metadata, batch_convert.
Configuración de LLM BYOK
pdfmux admite cualquier LLM mediante 5 líneas de YAML. Trae tus propias claves: nada sale de tu máquina a menos que lo configures para ello.
# ~/.pdfmux/llm.yaml
provider: claude # gemini | claude | openai | ollama | any OpenAI-compatible
model: claude-sonnet-4-20250514
api_key: ${ANTHROPIC_API_KEY}
base_url: https://api.anthropic.com # optional, for custom endpoints
max_cost_per_page: 0.02 # budget capProveedores admitidos:
Proveedor | Modelos | ¿Local? | Coste |
Gemini | 2.5 Flash, 2.5 Pro | No | ~$0.01/página |
Claude | Sonnet, Opus | No | ~$0.015/página |
GPT-4o | GPT-4o, GPT-4o-mini | No | ~$0.01/página |
Ollama | Cualquier modelo local | Sí | Gratis |
Personalizado | Cualquier API compatible con OpenAI | Configurable | Varía |
Benchmark
Probado en opendataloader-bench -- 200 PDFs del mundo real incluyendo informes financieros, documentos legales, artículos académicos y documentos escaneados.
Motor | General | Orden de lectura | Tablas (TEDS) | Encabezados | Requiere |
opendataloader hybrid | 0.909 | 0.935 | 0.928 | 0.828 | Llamadas API ($) |
pdfmux | 0.905 | 0.920 | 0.911 | 0.852 | Solo CPU, $0 |
docling | 0.877 | 0.900 | 0.887 | 0.802 | Modelos ~500MB |
marker | 0.861 | 0.890 | 0.808 | 0.796 | GPU recomendada |
opendataloader local | 0.844 | 0.913 | 0.494 | 0.761 | Solo CPU |
mineru | 0.831 | 0.857 | 0.873 | 0.743 | GPU + modelos ~2GB |
#2 en general, #1 entre las herramientas gratuitas. 99.5% de la puntuación del #1 de pago a coste cero por página. La mejor detección de encabezados de cualquier motor probado. El OCR de tablas de imágenes extrae tablas incrustadas como imágenes.
Puntuación de confianza
Cada resultado incluye una puntuación de confianza de 4 señales:
95-100% -- texto digital limpio, totalmente extraíble
80-95% -- buena extracción, ruido de OCR menor en algunas páginas
50-80% -- extracción parcial, algunas páginas irrecuperables
<50% -- contenido significativo faltante, advertencias incluidas
Cuando la confianza cae por debajo del 80%, pdfmux te dice exactamente qué salió mal y cómo solucionarlo:
Page 4: 32% confidence. 0 chars extracted from image-heavy page.
-> Install pdfmux[ocr] for RapidOCR support on 6 image-heavy pages.Modos de coste
Modo | Comportamiento | Coste típico |
economy | Solo backends basados en reglas. Sin llamadas LLM. | $0/página |
balanced | LLM solo para páginas que fallan en la extracción basada en reglas. | ~$0.002/página prom. |
premium | LLM en cada página para máxima calidad. | ~$0.01/página |
Establece un límite de presupuesto estricto: --budget 0.50 detiene las llamadas LLM cuando el gasto alcanza $0.50 por documento.
¿Por qué pdfmux?
pdfmux no es otro extractor de PDF. Es la capa de orquestación que elige el extractor correcto por página, verifica el resultado y reintenta los fallos.
Herramienta | Bueno en | Limitación |
PyMuPDF | Texto digital rápido | No puede manejar escaneos o diseños de imagen |
Docling | Tablas (97.9% precisión) | Lento en documentos sin tablas |
Marker | Extracción ML con GPU | Necesita GPU, excesivo para PDFs digitales |
Unstructured | Plataforma empresarial | Configuración compleja, niveles de pago |
LlamaParse | Nativo en la nube | Requiere claves API, no local |
Reducto | Alta precisión | $0.015/página, código cerrado |
pdfmux | Orquesta todo lo anterior | Enruta por página, audita, re-extrae |
Alternativa de código abierto a Reducto: lo que cuesta $0.015/página en otros lugares es gratis con los backends basados en reglas de pdfmux, o ~$0.002/página de promedio con el fallback de LLM BYOK.
Desarrollo
git clone https://github.com/NameetP/pdfmux.git
cd pdfmux
python3.12 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest # 151 tests
ruff check src/ tests/
ruff format src/ tests/Contribución
Haz un fork del repositorio
Crea una rama (
git checkout -b feature/tu-caracteristica)Escribe pruebas para la nueva funcionalidad
Asegúrate de que
pytestyruff checkpasenAbre un PR
Licencia
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/NameetP/pdfmux'
If you have feedback or need assistance with the MCP directory API, please join our Discord server