Skip to main content
Glama

pdfmux

CI PyPI Python 3.11+ License: MIT Downloads

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 pdfmux

Eso 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]"            # everything

Requiere 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

pdfmux convert file.pdf

Fragmentación RAG

Fragmentos conscientes de la sección con estimaciones de tokens

pdfmux convert file.pdf --chunk --max-tokens 500

Modos de coste

economy / balanced / premium con límites de presupuesto

pdfmux convert file.pdf --mode economy --budget 0.50

Extracción de esquema

5 preajustes integrados (factura, recibo, contrato, currículum, artículo)

pdfmux convert file.pdf --schema invoice

LLM BYOK

Gemini, Claude, GPT-4o, Ollama, cualquier API compatible con OpenAI

pdfmux convert file.pdf --llm-provider claude

Benchmark

Evalúa todos los extractores instalados contra la verdad fundamental

pdfmux benchmark

Doctor

Muestra backends instalados, brechas de cobertura, recomendaciones

pdfmux doctor

Servidor MCP

Los agentes de IA leen PDFs vía stdio o HTTP

pdfmux serve

Procesamiento por lotes

Convierte directorios completos

pdfmux convert ./docs/

Streaming

Iteración de páginas con memoria limitada para archivos grandes

for page in ext.extract("500pg.pdf")

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 file

pdfmux 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 mode

pdfmux 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-assisted

Extracció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 file

Streaming (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 PDFs

Tipos 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-pdfmux
from langchain_pdfmux import PDFMuxLoader

loader = PDFMuxLoader("report.pdf", quality="standard")
docs = loader.load()  # -> list[Document] with confidence metadata

LlamaIndex

pip install llama-index-readers-pdfmux
from 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-mcp

Herramientas 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 cap

Proveedores 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

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

  1. Haz un fork del repositorio

  2. Crea una rama (git checkout -b feature/tu-caracteristica)

  3. Escribe pruebas para la nueva funcionalidad

  4. Asegúrate de que pytest y ruff check pasen

  5. Abre un PR

Licencia

MIT

Install Server
A
security – no known vulnerabilities
A
license - permissive license
A
quality - A tier

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