Tools,

RapidOCR, tested on scanned pages

1,894

of 1,955 words found

Get the script

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

Same 10 pages, 1,955 words
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

Same 10 pages, 1,955 words
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

Same 10 pages, 1,955 words
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.

Try the Actor

Or send us the scan. Tack, our AI, does the job for $29, up to 50 pages. First page free.

Get one 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.