PDF to text extraction with confidence scoring — born-digital, scanned, and hybrid PDFs
Project description
pdfpeek
PDF to text — with a confidence score.
Most PDF tools dump text and leave you guessing whether it worked. pdfpeek runs a 10-stage pipeline and tells you exactly how confident it is in every extraction.
$ pdfpeek extract report.pdf
pdfpeek → report.pdf
✔ Triage 2 page(s) text_native: 1 hybrid: 1
✔ Extraction 47 blocks
✔ Warnings 1 warning(s)
Confidence 0.893
Time 1.4s
Output → report.txt
Install
# Born-digital PDFs only (~50 MB)
pip install pdfpeek
# + Scanned PDF support via Tesseract (~100 MB)
pip install pdfpeek[ocr]
# + AI layout detection via surya (~5 GB)
pip install pdfpeek[layout]
Tesseract (system package) is required for
[ocr]:
- macOS:
brew install tesseract- Ubuntu/Debian:
sudo apt install tesseract-ocr- Windows: UB-Mannheim installer
Usage
CLI
# Extract to plain text (default)
pdfpeek extract document.pdf
# Extract to markdown
pdfpeek extract document.pdf --format markdown --out result.md
# Batch a whole folder
pdfpeek extract ./pdfs/ --out ./txts/
# Password-protected PDF
pdfpeek extract encrypted.pdf --password secret
# Inspect a PDF before extracting
pdfpeek info document.pdf
Python API
from pdf_engine import extract
result = extract("document.pdf")
print(result.text) # extracted text
print(result.confidence) # 0.0 – 1.0 document-level confidence
print(result.warnings) # any issues found during extraction
# Full structured output
for page in result.ir.pages:
for block in page.blocks:
print(block.text, block.confidence.final, block.block_type)
How it works
pdfpeek runs every PDF through a 10-stage pipeline:
| Stage | Name | What it does |
|---|---|---|
| 0 | Triage | Classifies each page: text-native, scanned, or hybrid |
| 1 | Extraction | Pulls embedded text with phantom-layer detection |
| 2 | Layout | Detects block types (heading, body, table, figure) via surya |
| 3 | Reading Order | XY-cut partitioning, RTL-aware |
| 4 | Tables | Explicit (ruled) and implicit (whitespace) table detection |
| 5 | OCR | Tesseract + surya for scanned/hybrid pages |
| 6 | Assembly | Merges pymupdf and surya outputs; de-duplicates |
| 7 | Cross-page | Strips headers/footers; builds heading hierarchy |
| 8 | Post-processing | Rejoins hyphenation; corrects OCR errors |
| 9 | Confidence | Scores every block on text quality, method trust, order, and type |
Each block gets a confidence score from 0 to 1. The document score is the mean of all block scores.
Comparison
| pdfpeek | pdfplumber | pypdf | unstructured | |
|---|---|---|---|---|
| Born-digital | ✅ | ✅ | ✅ | ✅ |
| Scanned (OCR) | ✅ [ocr] |
❌ | ❌ | ✅ |
| Hybrid pages | ✅ | ⚠️ partial | ❌ | ✅ |
| Confidence score | ✅ | ❌ | ❌ | ❌ |
| Install size | 50 MB | ~20 MB | ~5 MB | 5 GB+ |
| Python API | ✅ | ✅ | ✅ | ✅ |
| CLI | ✅ | ❌ | ❌ | ✅ |
Confidence scoring
Every TextBlock has a BlockConfidence with four dimensions:
| Dimension | Set by | Meaning |
|---|---|---|
text_quality |
Stage 9 | Fraction of printable, non-garbled characters |
method_score |
Stage 9 | Trust in the extraction method (pymupdf=1.0, tesseract=0.7) |
order_quality |
Stage 3 | Confidence in reading-order placement |
type_quality |
Stage 2 | Confidence in block-type classification |
final |
Stage 9 | Geometric mean of the four above |
A document-level score above 0.8 means reliable extraction. Below 0.6 means you should check the output manually or try [layout].
Known limitations (v0.1)
- Very complex multi-column layouts (magazines, newspapers) may have reading-order issues
- Non-English OCR error correction is not yet implemented
- Documents > 1000 pages will be slow (surya processes ~2–3 pages/sec)
- Equations, handwriting, and deeply nested table-in-sidebar structures are best-effort
These are on the roadmap for v0.2.
Contributing
git clone https://github.com/ibrah5em/pdfpeek
cd pdfpeek
pip install -e ".[ocr,dev]"
pytest tests/
PRs welcome. Please add a test for any bug fix.
License
MIT — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pdfpeek-0.1.0.tar.gz.
File metadata
- Download URL: pdfpeek-0.1.0.tar.gz
- Upload date:
- Size: 133.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b258c5a46fe2334de2744888447d61be22575fc5239dc4349550cd46c2c8515c
|
|
| MD5 |
05f0994fa0b6019b17fec9e92438484a
|
|
| BLAKE2b-256 |
d1a836d14b75dd7c9057c99fbe86adc66cd43f332cf4ba8c7a88ab7774c234b6
|
File details
Details for the file pdfpeek-0.1.0-py3-none-any.whl.
File metadata
- Download URL: pdfpeek-0.1.0-py3-none-any.whl
- Upload date:
- Size: 80.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
94d85745b07be11f5bbfcc2d6768bf5408a3a3a1934106aef72051728c23ffa9
|
|
| MD5 |
bb3b221a40bc2125fb5c8a384e607639
|
|
| BLAKE2b-256 |
d598fba113226ecc0d7e9a9d47f9ee582bb44ff3ac9f26267eb6b45a40dc7e24
|