Python OCR libraries: choose by output and deployment
Compare PaddleOCR, Tesseract, EasyOCR, RapidOCR, Surya and docTR by their documented interfaces and the work you need them to do.
Choose by workload
| Library | Start here when | Check before choosing |
|---|---|---|
| PaddleOCR | You need a configurable detection and recognition pipeline, bounding boxes, or a route into document parsing. | Install a compatible PaddlePaddle runtime; select the language and checkpoint explicitly. PP-OCR and PaddleOCR-VL are different pipelines. |
| Tesseract + pytesseract | You need a CPU baseline for printed scans and an established command-line engine. | Install the native Tesseract binary and language data separately. Tune page segmentation and preprocessing. |
| EasyOCR | You want a short PyTorch-based image OCR integration. | Reader language combinations, downloaded checkpoints and CPU/GPU settings affect coverage and cost. |
| RapidOCR | You want an ONNX-oriented deployment path with Paddle-derived models. | The current package is rapidocr, alongside your chosen inference runtime; do not assume the old tuple API. |
| Surya | You need page OCR, layout or tables and can operate its inference backend. | Current v2 uses an inference manager. Code is Apache-2.0; weights have separate commercial conditions. |
| docTR | You want a trainable Python detection/recognition pipeline and structured document output. | Use python-doctr and inspect the selected detector and recognizer, orientation settings and model license. |
Candidate shortlist; row order does not represent an accuracy or speed ranking.
PaddleOCR: use the documented predict interface
The current documentation uses PaddleOCR().predict(), with result objects that can print or save JSON. The old use_angle_cls constructor example belongs to a different API generation. Choose a supported runtime from the installation guide before running this example; record the resolved package and model versions.
Documentation-based example; no runtime measurement is claimed.
from paddleocr import PaddleOCR
ocr = PaddleOCR(
lang="en",
use_doc_orientation_classify=False,
use_doc_unwarping=False,
use_textline_orientation=False,
)
for result in ocr.predict("invoice.png"):
result.print()
result.save_to_json("output")PaddleOCR Python integration and runtime installation ↗Tesseract and EasyOCR: simple text baselines
pytesseract wraps the separately installed native engine. EasyOCR loads its detector and recognizer through Reader. Neither short example reconstructs invoice line items or proves field extraction accuracy.
Documentation-based example; no runtime measurement is claimed.
# pip install pytesseract pillow easyocr
# Install native Tesseract and English language data separately.
import pytesseract
from PIL import Image
import easyocr
print(pytesseract.image_to_string(Image.open("invoice.png"), lang="eng"))
reader = easyocr.Reader(["en"], gpu=False)
for box, text, confidence in reader.readtext("invoice.png"):
print(text, confidence)EasyOCR installation and Reader examples ↗RapidOCR: replace the legacy package example
The current quickstart installs rapidocr with onnxruntime and returns a result object. Its models and language coverage depend on the configuration; the default Chinese/English model is not a universal language choice.
Documentation-based example; no runtime measurement is claimed.
# pip install rapidocr onnxruntime
from rapidocr import RapidOCR
engine = RapidOCR()
result = engine("invoice.png")
print(result)
result.vis("invoice-ocr.jpg")RapidOCR current quickstart ↗Surya: current v2 API and separate weight license
The checked upstream v2 API uses SuryaInferenceManager and returns page results with blocks, including HTML. It requires a supported inference backend: vLLM on NVIDIA or llama-server for CPU/Apple Silicon. The code uses Apache-2.0; the modified AI Pubs Open Rail-M weight license has eligibility limits, including a $5M funding/revenue threshold. Review the model license for broader commercial use.
Documentation-based example; no runtime measurement is claimed.
# pip install surya-ocr pillow
# Configure the backend described in the upstream installation guide.
from PIL import Image
from surya.inference import SuryaInferenceManager
from surya.recognition import RecognitionPredictor
manager = SuryaInferenceManager()
recognizer = RecognitionPredictor(manager)
pages = recognizer([Image.open("invoice.png")])
for page in pages:
for block in page.blocks:
print(block.html)Surya v2 migration, backend and licensing ↗docTR: document-level OCR output
docTR exposes a pretrained OCR predictor and document loaders. Keep the model architecture and checkpoint in your evaluation manifest rather than treating every ocr_predictor configuration as the same system.
Documentation-based example; no runtime measurement is claimed.
# pip install python-doctr
from doctr.io import DocumentFile
from doctr.models import ocr_predictor
predictor = ocr_predictor(pretrained=True)
result = predictor(DocumentFile.from_images("invoice.png"))
print(result.render())docTR official getting started ↗Run a comparison that can support a recommendation
Use the same held-out pages and ground truth for every candidate. Include clean scans, phone photos, rotation, small text and the languages you serve. Keep invoice templates out of both tuning and test sets to expose generalization failures.
Report CER/WER for text, reading-order errors for pages, cell structure for tables, and exact match or field F1 for invoice extraction. Time model loading, warm inference and full pipeline latency separately; record CPU/GPU, batch size, peak memory, retries and failures. Publish inputs or hashes, outputs, package locks, checkpoint IDs and normalization rules before calling a result reproducible.
Primary sources
Documentation and licensing were checked on 7 October 2026. Pin package versions, model checkpoints and configuration in your own environment; upstream defaults can change.