Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Extract text from PDFs/scans (pymupdf, marker-pdf).
.claude/skills/nousresearch-ocr-and-documents/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-05 | ✗→✓ | ▲ Improved | 14% | 0% |
| case-15 | ✗→✓ | ▲ Improved | 2% | 0% |
| case-04 | ✗→✓ | ▲ Improved | 41% | 0% |
| case-19 | ✗→✓ | ▲ Improved | 59% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 15% | 0% |
For DOCX: see the docx skill (create/edit) or use python-docx for structured reads. For PPTX: see the powerpoint skill (full create/read/edit support). For PDF manipulation (merge, split, forms, watermarks, creation): see the pdf skill. This skill covers text extraction from PDFs and scanned documents.
> Coming from a read_file EXTRACTION COVERAGE WARNING? read_file auto-converts local PDFs but reads the text layer only; the warning footer lists the pages that yielded no text (scanned images). For a handful of pages, render + vision is fastest: pdftoppm -jpeg -r 150 -f N -l N file.pdf /tmp/page then vision_analyze each image. For bulk OCR of many pages, use marker-pdf below (Step 2).
If the document has a URL, always try web_extract first:
web_extract(urls=["https://arxiv.org/pdf/2402.03300"])
web_extract(urls=["https://example.com/report.pdf"])This handles PDF-to-markdown conversion via Firecrawl with no local dependencies.
Only use local extraction when: the file is local, web_extract fails, or you need batch processing.
| Feature | pymupdf (~25MB) | marker-pdf (~3-5GB) | |---------|-----------------|---------------------| | Text-based PDF | ✅ | ✅ | | Scanned PDF (OCR) | ❌ | ✅ (90+ languages) | | Tables | ✅ (basic) | ✅ (high accuracy) | | Equations / LaTeX | ❌ | ✅ | | Code blocks | ❌ | ✅ | | Forms | ❌ | ✅ | | Headers/footers removal | ❌ | ✅ | | Reading order detection | ❌ | ✅ | | Images extraction | ✅ (embedded) | ✅ (with context) | | Images → text (OCR) | ❌ | ✅ | | EPUB | ✅ | ✅ | | Markdown output | ✅ (via pymupdf4llm) | ✅ (native, higher quality) | | Install size | ~25MB | ~3-5GB (PyTorch + models) | | Speed | Instant | ~1-14s/page (CPU), ~0.2s/page (GPU) |
Decision: Use pymupdf unless you need OCR, equations, forms, or complex layout analysis.
If the user needs marker capabilities but the system lacks ~5GB free disk: > "This document needs OCR/advanced extraction (marker-pdf), which requires ~5GB for PyTorch and models. Your system has X]GB free. Options: free up space, provide a URL so I can use web_extract, or I can try pymupdf which works for text-based PDFs but not scanned documents or equations."
bashpip install pymupdf pymupdf4llm
Via helper script:
bashpython scripts/extract_pymupdf.py document.pdf # Plain text python scripts/extract_pymupdf.py document.pdf --markdown # Markdown python scripts/extract_pymupdf.py document.pdf --tables # Tables python scripts/extract_pymupdf.py document.pdf --images out/ # Extract images python scripts/extract_pymupdf.py document.pdf --metadata # Title, author, pages python scripts/extract_pymupdf.py document.pdf --pages 0-4 # Specific pages
Inline:
bashpython -c " import pymupdf doc = pymupdf.open('document.pdf') for page in doc: print(page.get_text()) "
bash# Check disk space first python scripts/extract_marker.py --check pip install marker-pdf
Via helper script:
bashpython scripts/extract_marker.py document.pdf # Markdown python scripts/extract_marker.py document.pdf --json # JSON with metadata python scripts/extract_marker.py document.pdf --output_dir out/ # Save images python scripts/extract_marker.py scanned.pdf # Scanned PDF (OCR) python scripts/extract_marker.py document.pdf --use_llm # LLM-boosted accuracy
CLI (installed with marker-pdf):
bashmarker_single document.pdf --output_dir ./output marker /path/to/folder --workers 4 # Batch
# Abstract only (fast)
web_extract(urls=["https://arxiv.org/abs/2402.03300"])
# Full paper
web_extract(urls=["https://arxiv.org/pdf/2402.03300"])
# Search
web_search(query="arxiv GRPO reinforcement learning 2026")pymupdf handles these natively — use execute_code or inline Python:
python# Split: extract pages 1-5 to a new PDF import pymupdf doc = pymupdf.open("report.pdf") new = pymupdf.open() for i in range(5): new.insert_pdf(doc, from_page=i, to_page=i) new.save("pages_1-5.pdf")
python# Merge multiple PDFs import pymupdf result = pymupdf.open() for path in ["a.pdf", "b.pdf", "c.pdf"]: result.insert_pdf(pymupdf.open(path)) result.save("merged.pdf")
python# Search for text across all pages import pymupdf doc = pymupdf.open("report.pdf") for i, page in enumerate(doc): results = page.search_for("revenue") if results: print(f"Page {i+1}: {len(results)} match(es)") print(page.get_text("text"))
No extra dependencies needed — pymupdf covers split, merge, search, and text extraction in one package.
web_extract is always first choice for URLs--help for full usage~/.cache/huggingface/ on first usepip install python-docx (better than OCR — parses actual structure)powerpoint skill (uses python-pptx)| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-05 | fail→pass | 8,364 | 1,802 | -78% | 1 | 1 | 0% | 1,750 | 2,000 | +14% | 0 | 0 | — |
case-15 | fail→pass | 8,984 | 1,269 | -86% | 1 | 1 | 0% | 1,829 | 1,858 | +2% | 0 | 0 | — |
case-01 | fail→fail | 22,421 | 3,824 | -83% | 1 | 1 | 0% | 4,143 | 1,890 | -54% | 0 | 0 | — |
case-02 | fail→fail | 4,985 | 10,010 | +101% | 1 | 1 | 0% | 1,085 | 2,397 | +121% | 0 | 0 | — |
case-03 | pass→pass | 11,201 | 4,074 | -64% | 1 | 1 | 0% | 2,077 | 2,386 | +15% | 0 | 0 | — |
case-04 | fail→pass | 12,469 | 7,630 | -39% | 1 | 1 | 0% | 2,183 | 3,086 | +41% | 0 | 0 | — |
case-06 | pass→pass | 9,432 | 6,713 | -29% | 1 | 1 | 0% | 1,834 | 2,953 | +61% | 0 | 0 | — |
case-07 | pass→pass | 2,834 | 3,079 | +9% | 1 | 1 | 0% | 575 | 2,209 | +284% | 0 | 0 | — |
case-08 | pass→pass | 10,773 | 2,998 | -72% | 1 | 1 | 0% | 1,720 | 2,174 | +26% | 0 | 0 | — |
case-09 | pass→pass | 11,538 | 3,959 | -66% | 1 | 1 | 0% | 2,187 | 2,393 | +9% | 0 | 0 | — |
case-10 | pass→pass | 3,007 | 2,652 | -12% | 1 | 1 | 0% | 513 | 2,133 | +316% | 0 | 0 | — |
case-11 | pass→pass | 12,282 | 5,510 | -55% | 1 | 1 | 0% | 2,235 | 2,558 | +14% | 0 | 0 | — |
case-12 | pass→pass | 3,958 | 2,740 | -31% | 1 | 1 | 0% | 800 | 2,197 | +175% | 0 | 0 | — |
case-13 | pass→pass | 5,175 | 2,336 | -55% | 1 | 1 | 0% | 1,013 | 2,150 | +112% | 0 | 0 | — |
case-14 | pass→pass | 2,707 | 2,750 | +2% | 1 | 1 | 0% | 620 | 2,266 | +265% | 0 | 0 | — |
case-16 | pass→pass | 5,473 | 4,052 | -26% | 1 | 1 | 0% | 1,147 | 2,440 | +113% | 0 | 0 | — |
case-17 | pass→pass | 9,487 | 2,979 | -69% | 1 | 1 | 0% | 1,964 | 2,206 | +12% | 0 | 0 | — |
case-18 | pass→pass | 9,085 | 2,755 | -70% | 1 | 1 | 0% | 1,804 | 2,209 | +22% | 0 | 0 | — |
case-19 | fail→pass | 7,414 | 2,187 | -71% | 1 | 1 | 0% | 1,328 | 2,117 | +59% | 0 | 0 | — |
case-20 | pass→pass | 3,488 | 2,728 | -22% | 1 | 1 | 0% | 721 | 2,187 | +203% | 0 | 0 | — |
case-21 | pass→pass | 26,599 | 15,728 | -41% | 1 | 1 | 0% | 6,181 | 5,184 | -16% | 0 | 0 | — |
case-22 | pass→pass | 7,389 | 4,246 | -43% | 1 | 1 | 0% | 1,375 | 2,475 | +80% | 0 | 0 | — |
case-23 | pass→pass | 14,198 | 13,232 | -7% | 1 | 1 | 0% | 2,974 | 4,702 | +58% | 0 | 0 | — |
case-24 | pass→pass | 6,132 | 5,846 | -5% | 1 | 1 | 0% | 1,376 | 2,976 | +116% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 24 cases were attempted, and 22 counted toward the lift figure. The other 2 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +17 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 8/11/2026 | +36% |
| gemini-3.6-flash | verified | 8/8/2026 | +27% |
Other measured skills in the registry, with their headline benchmark lift.