Image OCR, Explained
After reading this, you will understand how optical character recognition turns pixels into text, what makes an image easy or hard to read, and how to prepare a screenshot or scan so the extracted text is accurate.
What OCR does and one quick example
Optical character recognition (OCR) reads text out of an image. The image is just a grid of colored pixels. OCR analyzes that grid, finds shapes that look like letters, and outputs the characters those shapes represent. The engine here is Tesseract, compiled to WebAssembly so it runs inside your browser rather than on a server.
Suppose you photograph a receipt that shows TOTAL 42.90. The camera stores that region as roughly 1,200 pixels, each a brightness value. OCR groups the dark pixels into connected blobs, recognizes six glyphs plus a space and a decimal point, and returns the string TOTAL 42.90. You can now copy, search, or paste it. No retyping.
The accuracy of that result depends almost entirely on the input image. Clean black text on white, upright and sharp, recognizes near perfectly. Skewed, low-contrast, or blurry text produces errors. The rest of this guide explains why, and how to measure it.
When to use it, and when not to
OCR is the right tool when the text you want already exists as an image and you cannot select it directly. Common cases: a screenshot of an error message, a scanned page, a photo of a sign, a slide from a video, or a PDF that stores pages as images.
It is the wrong tool in three situations. First, if the text is already selectable (a normal web page or a text-based PDF), copy it directly and skip the error-prone recognition step. Second, for handwriting, Tesseract performs poorly; it is trained on printed type. Third, for artistic or heavily stylized fonts, expect low accuracy because the glyph shapes stray far from the training data.
If you only need part of an image, crop to that region before running OCR. A 300 by 80 pixel crop of one line recognizes faster and with fewer stray characters than a full 4,000 by 3,000 pixel photo that includes background clutter.
How recognition works, step by step
Tesseract runs a pipeline. Understanding the stages tells you which image problems break which stage.
- Binarization
- Each pixel is classified as ink or background. Tesseract uses adaptive thresholding, so a pixel darker than its local neighborhood becomes ink. Low contrast collapses this step: if text and background differ by only 20 brightness levels out of 255, the threshold cannot separate them cleanly.
- Layout analysis
- The page is split into blocks, lines, and words by finding gaps of whitespace. Rotated or curved text confuses the line finder, because it expects roughly horizontal rows.
- Character segmentation
- Each word is cut into candidate glyphs. Touching letters (common in low resolution) get merged, and a single letter split by noise gets counted twice.
- Classification
- Each glyph is matched against trained shape models for the selected language, producing a character and a confidence score.
- Language modeling
- A dictionary and character-frequency model nudge ambiguous results toward real words. This is why picking the correct language matters: an English model reading French text loses the accented-letter corrections.
The math of resolution and confidence
The single most useful number to control is the pixel height of a capital letter, often called the x-height in typography but here measured cap to baseline. Tesseract works best when that height is about 30 to 40 pixels. Below roughly 20 pixels, segmentation errors climb sharply.
Here h_{px} is the glyph height in pixels, \text{DPI} is the scan resolution in dots per inch, s_{pt} is the font size in points, and 72 is the number of points in an inch. A 12 point font scanned at 300 DPI gives h_{px} = 300 \times 12 / 72 = 50 pixels, comfortably in range. The same font scanned at 96 DPI gives only 96 \times 12 / 72 = 16 pixels, which is too small.
The engine also reports a confidence per word, on a 0 to 100 scale. It is an internal estimate from the classifier, not a true probability, but it ranks reliability well. Words below about 60 deserve a manual check. A useful summary is the mean confidence across all recognized words:
where c_i is the confidence of word i and n is the number of words. A page averaging \bar{c} = 92 is usually clean; one averaging 55 needs a better image.
A worked example with the demo image
Reading a clean screenshot
Load the default sample and press Calculate. The demo uses a high-contrast horizontal line of English text, the exact case the engine handles best. Trace what happens.
- The image loads locally. On first use the engine and English data (a few megabytes) download from a CDN and cache, so later runs start instantly.
- Binarization separates the dark glyphs from the white background. With near-maximum contrast (ink near brightness 20, background near 250), the threshold is unambiguous.
- Layout analysis finds one horizontal line and splits it into words at the space gaps.
- Each glyph is classified. Because the text is upright, sharp, and above 30 pixels tall, every character matches cleanly.
- The language model confirms the words against the English dictionary and returns the string with per-word confidence.
The output reproduces the sample text with mean confidence in the low 90s. Copy it directly from the result panel.
Reading and interpreting the results
The output is the recognized text plus, in detailed modes, per-word confidence. Read both together. High confidence on a wrong word is rare but happens when a glyph genuinely resembles another: a lowercase l, a capital I, and the digit 1 share nearly identical shapes in many fonts. Context and the language model usually resolve these, but numbers standing alone (like l0 versus 10) get no dictionary help.
Expect these systematic confusions and scan your output for them:
| Seen as | Actually | Cause |
|---|---|---|
0 | O | Similar oval shape, weak font distinction |
1 | l or I | Vertical strokes, no dictionary context in numbers |
rn | m | Touching letters merged at low resolution |
5 | S | Curved shapes, noise on thin strokes |
If whole lines come out as gibberish, the problem is usually structural: wrong language, rotated text, or a background pattern that binarization read as ink. Fix the image, do not edit the output word by word.
Common mistakes
Selecting the wrong language is the most frequent error. Reading German with the English model discards the umlaut corrections and misreads ü as ii or u. Match the language to the text before you run it.
Three more traps. First, downscaled screenshots: a phone screenshot resized to fit a chat window may drop below 20 pixel glyphs, so recognize from the original file. Second, JPEG artifacts: heavy compression smears letter edges, and the blocky 8 by 8 pixel artifacts confuse segmentation. Prefer PNG for screenshots of text. Third, colored or textured backgrounds: text over a photo binarizes badly. Crop to a region where the background is plain, or increase contrast before running.
Related tools on this site
OCR pairs naturally with other image utilities here. To inspect or remove the camera, GPS, and date metadata that scanned photos carry, use the EXIF Viewer & Remover. If you are studying the colors that hurt contrast for OCR, the Image Color Picker & Palette reads exact pixel values, and the Dominant & Average Color tool summarizes the background tone. To confirm that a cleaned-up image still matches the original, compare them with Image Diff.
Frequently asked questions
Are my images uploaded anywhere?
No. Recognition runs entirely in your browser through WebAssembly. Only the engine and language data download once from a CDN. Your images never leave your device.
Why is the first run slow?
On first use the browser downloads the Tesseract engine and the selected language data, a few megabytes total, then caches them. The next run starts without that download.
Can it read handwriting?
Not reliably. Tesseract is trained on printed type. Neat block capitals sometimes work, but cursive and casual handwriting produce mostly errors. This tool is built for printed and rendered text.
What resolution should I aim for?
Enough that capital letters are about 30 to 40 pixels tall. For a 12 point document, that means scanning near 300 DPI. Going much higher wastes time without improving accuracy.
Why does accuracy vary between languages?
Each language has its own trained models and dictionary. Languages with large character sets or complex scripts have harder classification and weaker dictionary support, so error rates on identical image quality can differ.