RapidOCR, tested on scanned pages
1,894
of 1,955 words found
Run RapidOCR on a scanned PDF
55 s for 10 pages, Mac CPU, 2 threads
32 MB of models, inside the wheel
On a Mac, in a folder with scan.pdf:
python3 -m venv ro && source ro/bin/activate
pip install rapidocr onnxruntime pypdfium2
python ocr.py scan.pdf > scan.txt
ocr.py:
import sys
import pypdfium2 as pdfium
from rapidocr import RapidOCR
engine = RapidOCR()
for page in pdfium.PdfDocument(sys.argv[1]):
out = engine(page.render(scale=300 / 72).to_pil())
print("\n".join(out.txts or ()))
RapidOCR reads images, not PDFs, so pypdfium2 draws each page at 300 dpi. A run with no network gave the same text.
The onnxruntime error
pip install rapidocr does not install onnxruntime.
RapidOCR() starts fine. The first page stops:
ImportError: onnxruntime is not installed.
Install both, as above. A PDF path in place of an image stops too:
PIL.UnidentifiedImageError: cannot identify image file 'scan.pdf'
rapidocr vs rapidocr_onnxruntime
| Package | Words found | Time |
|---|---|---|
| rapidocr 3.10.0 | 1,894 | 55 s |
| rapidocr_onnxruntime 1.4.4 | 1,823 | 66 s |
| 1.2.3, on Python 3.13 | 1,809 | 81 s |
The old package stopped at 1.4.4, which needs Python below 3.13. On 3.13, pip quietly installs 1.2.3, from March 2023.
Old code fails on the new package:
TypeError: cannot unpack non-iterable RapidOCROutput object
Read out.txts in place of
result, elapse = engine(img).
Pick a model size
| Models | Words found | Time | Download |
|---|---|---|---|
| PP-OCRv6 tiny | 1,864 | 21 s | 6 MB |
| PP-OCRv6 small (default) | 1,894 | 55 s | none |
| PP-OCRv5, English | 1,910 | 55 s | 13 MB |
| PP-OCRv6 medium | 1,917 | 259 s | 139 MB |
The English model found 16 more words than the default, in the same time. Medium found 7 more again, at almost 5 times the time.
from rapidocr import LangRec, ModelType, OCRVersion, RapidOCR
engine = RapidOCR(
params={
"Det.ocr_version": OCRVersion.PPOCRV5,
"Det.model_type": ModelType.MOBILE,
"Rec.ocr_version": OCRVersion.PPOCRV5,
"Rec.model_type": ModelType.MOBILE,
"Rec.lang_type": LangRec.EN,
}
)
Plain strings in place of these enums stop with:
TypeError: The value of Det.model_type must be Enum Type.
RapidOCR vs Tesseract and PaddleOCR
| Tool | Words found | Time |
|---|---|---|
| RapidOCR 3.10.0 | 1,894 | 55 s |
| Tesseract 5.5.4 | 1,877 | 47 s |
| PaddleOCR 3.7.0 | 1,908 | 333 s |
| Our Actor | 1,874 |
RapidOCR runs PaddleOCR models in onnxruntime, with no PaddlePaddle. The PaddleOCR row is from my PaddleOCR on a Mac test, on November 12.
Photos, tilted pages and numbers: 4 OCR engines, tested.
What the text looks like
86
The BoyScouts of the Air
"Keep your head, Hatton," commanded
Hardy;“don't talk tommyrot. What in the
One line per text box. It keeps page numbers and running heads, and drops a space now and then.
Need text with nothing to install?
Our Actor runs Tesseract, and RapidOCR on English pages that Tesseract reads badly. It takes PDF, JPG and PNG files and returns Markdown. On the same 10 pages, inside a PDF, it found 1,874 words.
curl -s -X POST "https://api.apify.com/v2/acts/brasspage~pdf-ocr-to-markdown/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"documentUrls": ["https://api.apify.com/v2/key-value-stores/sTnmNrGoSsi7tLQvs/records/anythingllm-mixed-11-pages.pdf"]}' \
| jq -r '.[].markdown' > book.md
It costs $0.006 a page.
How I tested it
- Pages: the 10 scans of OCR in n8n, proofread Wikisource book pages, 1,955 true words. Each page is one color JPEG, 1,920 x 3,079 pixels, at 300 ppi.
- rapidocr 3.10.0, onnxruntime 1.32.0 and pypdfium2 5.15.2 on an Apple Silicon Mac, Python 3.13. The lines above, as written, on Python 3.14: the same text, a venv of 332 MB. The old package: Python 3.12, and a clean 3.13 venv.
- CPU, 2 threads, lowest priority, other jobs on the Mac. Times are rough. Peak memory: 2.0 GB with the default models.
- Tesseract 5.5.4 alone: the CLI on the 10 JPEGs, English, default settings.
- Score: true words found in order, with the scorer of the tessdata test.
- The Actor: one real run, build 0.1.65, on November 12. Its file holds the same 10 pages plus a typed cover page.
What I did not test
- Other languages, and word or character boxes.
- CUDA, CoreML, OpenVINO and the other engines.
- Windows and Linux.
Sources
Two ways to skip the work
Run it yourself. Our Apify Actor turns scanned PDFs into Markdown, tables included.
Or send us the scan. Tack, our AI, does the job for $29, up to 50 pages. First page free.
Questions people ask
Is RapidOCR better than Tesseract?
A little, on scanned book pages. RapidOCR 3.10.0 found 1,894 of 1,955 words in 55 s, and Tesseract 5.5.4 found 1,877 in 47 s. The medium models found 1,917, in 259 s.
What is the difference between rapidocr and rapidocr_onnxruntime?
rapidocr is the current package. rapidocr_onnxruntime is the old one: its last release, 1.4.4, needs Python below 3.13. On Python 3.13, pip installs 1.2.3 from March 2023, with no warning.
Why does RapidOCR say onnxruntime is not installed?
pip install rapidocr does not install onnxruntime. Install both: pip install rapidocr onnxruntime.
Related guides
- Video OCR: subtitles and slides, tested
- Manga OCR in Python: manga-ocr, tested
- MRZ OCR in Python: PassportEye and RapidOCR
- OCR in Rust: ocrs tested vs Tesseract and RapidOCR
- PaddleOCR on a Mac: CPU setup and results, tested
- Pix2Text OCR: the install fix, tested on scans and math
- Receipt OCR in Python: Tesseract 33%, RapidOCR 84%
- EasyOCR vs Tesseract vs PaddleOCR vs RapidOCR, tested