How well does OCR read Persian? We tested six engines

The best engine in our test, Runemic's Gemma 4 preview model, got 3.1% of characters wrong across eight Persian pages. EasyOCR came second on characters (7.2%) but got almost half the words wrong (42.6%), because it often splits or joins words. Tesseract and Mistral Small got roughly one character in six wrong.

EngineCharacter errorsWord errors
Runemic preview: Gemma 4 26B3.1%4.9%
EasyOCR 1.7.27.2%42.6%
Runemic preview: Llama 4 Scout7.7%9.9%
PaddleOCR 3.7.09.6%26.6%
Tesseract 5.3.417.9%28.6%
Runemic preview: Mistral Small 3.118.5%31.6%

Lower is better. Every engine ran with its default settings.

The test pages

We made each page from text we already had, so every mistake can be counted exactly. The eight pages cover what Persian documents actually look like:

  • modern prose in two common fonts (Vazirmatn and Naskh)
  • a ghazal by Hafez set in Nastaliq, the slanted calligraphic style
  • an invoice table with Persian digits
  • a page of Saadi's Golestan, photographed with a phone
  • Persian mixed with English words and numbers
  • a tiny 13-pixel screenshot
  • a filled-in form

How we score

The character error rate is how many characters you would have to add, remove or change to turn the output into the correct text, divided by the length of the correct text. The word error rate is the same count over whole words.

Before scoring, every engine's output is cleaned the same way. Arabic and Persian forms of ی and ک count as the same letter, digits are unified, short vowel marks and Markdown symbols are removed. Spaces and zero-width non-joiners are left out of the character count, because Persian writers use them inconsistently, and we did not want to punish an engine for a choice a human typist would also make.

What went wrong, engine by engine

  • Nastaliq is the hardest page for everyone. Even the best engine got about a quarter of the Hafez page's characters wrong. Most models are trained on Naskh-style text and print, not calligraphy.
  • EasyOCR reads letters well but breaks words. Its character score is good, its word score is the worst: it often splits a word at the joins between letters, or runs two words together.
  • Tesseract struggles with tables and mixed text. It got more than half of the invoice table wrong and almost a quarter of the Persian-English page, while doing reasonably on clean prose and the phone photo.
  • Mistral Small sometimes drifts into another alphabet. On one plain Naskh page it wrote Persian words with Kurdish letters (ە instead of the Persian vowels), so almost every word came out wrong. It also reversed the column order of the invoice table.

Rerun it yourself

Everything is public in RuneBench: the pages, the correct text, the scoring code and every engine's raw output. If you think a result is wrong, you can check the exact text the engine returned. The full table, with every page, is on Best OCR for Persian, tested.

We will add more engines and more scripts: Arabic, Urdu and Hindi are next.

More from the blog

Know-how

Why OCR struggles with Persian, Arabic and Urdu

Connected letters, dots that change the letter, calligraphic styles and mixed directions. What makes Arabic-script text hard for OCR, and how to get better results from any engine.

Read
Product update

Four open OCR models, now in the console

GLM-OCR, LightOnOCR-3, dots.mocr and KDL Frontier Parser nano now run on Runemic's own GPUs. What each is good at, what they cost, and why the first page can take a few minutes.

Read

Try Runemic OCR free

Read your own pages in the browser, with no account. When you want more, sign in with GitHub or Hugging Face.

  • Free at runemic.com/try, no sign-up
  • Sign in for 2,500 free credits, no card needed
  • Compare up to three models, and get an API key with cURL, Python and JavaScript examples
# one page in, Markdown out
curl https://api.runemic.com/v1/ocr \
  -H "Authorization: Bearer $RUNEMIC_KEY" \
  -F "file=@page.png"

# → { "text": "# Invoice No. 4821 …",
    "usage": { "credits_used": 2 } }