OCRmyPDF

Adds a searchable OCR text layer to scanned PDFs and images, producing validated PDF/A output by default.

Tool
PyPI
v17.11.0
34,618stars
Mozilla Public License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
88/100Excellent
Development Activity100
Maintenance84
Community68
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
89/100Excellent
Architecture85
Code Quality90
Innovation82
Learning Curve100

OCRmyPDF is a command-line tool and Python library that adds an invisible, accurately positioned OCR text layer to scanned PDF and image files, making them searchable and copy-paste friendly without altering their visual appearance. It wraps Tesseract OCR, Ghostscript, and a battery of PDF/A validation and image-optimization steps into a single pipeline that produces standards-compliant output by default.

Beyond text recognition, OCRmyPDF automatically deskews and cleans scanned pages, optimizes embedded images to shrink file size, validates both input and output PDFs, and distributes work across all available CPU cores to handle documents with thousands of pages. A pluggy-based plugin system lets you swap in alternative OCR engines such as EasyOCR, PaddleOCR, or Apple Vision, and it supports more than 100 languages through Tesseract’s language packs.

What You Get

  • Searchable PDF/A output generated by default and validated against the PDF/A standard
  • Accurate OCR text placement beneath the original page image for reliable copy-paste
  • Automatic page deskewing and image cleanup before recognition
  • Image optimization that frequently produces output smaller than the input file
  • Multi-core processing that scales to documents with thousands of pages
  • A pluggy-based plugin interface for swapping in alternative OCR engines

Common Use Cases

  • Making scanned archives and paper records full-text searchable
  • Preparing scanned PDFs for long-term digital archiving via PDF/A
  • Batch-processing large volumes of incoming scanned documents
  • Integrating OCR into document-management systems like Paperless-ngx

Under The Hood

Architecture OCRmyPDF is organized as a page-synchronous pipeline coordinated through _pipelines/ocr.py: input is triaged and parsed into a PdfContext (src/ocrmypdf/_jobcontext.py), then fanned out per page via an Executor abstraction (_concurrent.py) so OCR, image cleanup, and text-layer generation run concurrently across CPU cores before results are grafted back into a single PDF by OcrGrafter (_graft.py) and finalized through PDF/A conversion (pdfa.py) and image optimization (optimize.py). An OcrmypdfPluginManager built on pluggy (_plugin_manager.py, pluginspec.py) mediates every extensible step — OCR engine selection, image filters, PDF rendering — with a readers-writer lock guarding the interpreter-global state that plugin installation mutates, so concurrent jobs sharing a plugin set can run without racing paths that swap the active engine underneath an in-flight job. This is a clean example of a synchronous core wrapped in a well-defined extension seam rather than a monolith.

Tech Stack The project is pure Python (3.11+) built with hatchling, using pikepdf for low-level PDF manipulation, pypdfium2 for rasterization, Pillow and pi-heif for image handling, fpdf2/uharfbuzz for direct OCR-text rendering, pydantic for options modeling, and rich for CLI progress/output. It shells out to external Ghostscript and Tesseract OCR binaries rather than binding them natively, keeping those heavyweight dependencies swappable and independently upgradable. Optional extras add watchfiles/cyclopts for a watch-folder mode and streamlit for an experimental web UI.

Code Quality The repository ships an extensive test suite (71 files under tests/) run with pytest in parallel (-n auto), enforces mypy and ruff (lint + format) as pinned dev dependencies, and mirrors those exact checks in both a prek pre-commit/pre-push config and GitHub Actions CI (.github/workflows/build.yml) so local and CI checks can’t drift. The package ships a py.typed marker, uses typed dataclasses/enums (e.g. a typed ExitCode IntEnum in exceptions.py mapped to specific exit codes rather than bare exception strings), and follows consistent docstring conventions enforced via ruff’s pydocstyle rules — this is a mature, well-tooled codebase.

API Design Alongside the CLI (cli.py, exposed via the ocrmypdf console script), api.py offers a small, well-documented Python surface centered on a single ocr() function whose docstring explicitly documents concurrency caveats (plugin sets and max_image_mpixels are process-global, so differing configurations need separate processes) — an unusually candid piece of API documentation. The plugin specification (pluginspec.py) gives third-party engine authors a narrow, well-typed contract to implement, evidenced by real community plugins (OCRmyPDF-EasyOCR, OCRmyPDF-PaddleOCR, OCRmyPDF-AppleOCR) built against it without needing to touch core code.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search