Hebrew Documents to AI and OCR: Confidence, Source, and an Exceptions Route
Back to blog
automation·September 6, 2026·6 min read·By Yehonatan Saadia

Hebrew Documents to AI and OCR: Confidence, Source, and an Exceptions Route

Hebrew OCR returns a value, a confidence score and a source region. What the score misses, where gershayim break matching, and how the exceptions route works.

Key takeaways

  • Unicode stores text in logical order and the flip is display only. A string saved from what the screen drew rather than from what was read is broken in a way that looks perfect in every screenshot and matches nothing in any search.
  • Neutral and weak characters - full stop, comma, colon, currency signs and European digits - take their position from their neighbours. A shekel sign on the wrong side of a number is not a misread; it is the bidirectional algorithm doing its job.
  • The gershayim inside מע"מ, ח"פ, ת"ז and בע"מ is the single character most likely to come back wrong: as a straight double quote, as two apostrophes, or as a tilde. The form בע~מ shows up in real Israeli datasets.
  • Hebrew has no capital letters, so the cue English pipelines lean on for proper nouns, acronyms and headings simply does not exist. Entity boundaries have to be found some other way.
  • Four items are stored per field: the value, the score, the page number and the bounding box. Without all four the approval screen is a guess rather than a check.

An engine that read a Hebrew document returns three things: the text, a confidence score per field, and the page region each value came from. Without the score there is no routing, without the region there is nothing to show a reviewer, and without an exceptions route everything lands inside at high confidence and in the wrong character order.

Why Hebrew text is stored correctly and displayed backwards

The Unicode Standard prescribes a memory representation called logical order, and UAX #9 states it plainly: characters are still interpreted in logical order, and only the display is affected. The first letter of a Hebrew word is the first character in the string, even though it is painted at the right-hand end of the line. So two different strings exist for the same document, and picking the wrong one is the bug:

  • Logical order - what the author typed. This belongs in the database, comparisons run against it, and a search index can find it.
  • Display order - what the screen painted after running the bidirectional algorithm. A tool that exports what it saw rather than what was read hands you a Hebrew name with its letters reversed.

That failure is invisible to a reviewer, because a browser handed an already-reversed string runs the bidirectional algorithm over it again and may render it correctly. The only check that catches it compares code points, not screenshots.

UAX #9 also explains the punctuation landing on the wrong side. Its character-type table classifies the Hebrew alphabet as type R, European digits as the weak type EN, currency symbols as ET (European Number Terminator), and colon, comma, full stop and no-break space as CS (Common Number Separator). Weak and neutral types carry no direction of their own and inherit it from their surroundings. A shekel price inside a Hebrew sentence is therefore exactly where the currency sign or the decimal point turns up somewhere you did not expect, and the zero-width marks U+200F and U+200E are a display fix - never a fix applied to the stored value.

What does a confidence score not measure on a Hebrew document?

It measures how sure the engine is that it read the characters correctly, not whether the value is sensible. Amazon Textract returns a percentage Confidence on every detected block and notes in its documentation that low-confidence detections may need visual confirmation by a human. That is a statement about reading quality and nothing more.

In Hebrew the gap between read correctly and correct is unusually wide:

  • Look-alike letter pairs. ד against ר, ה against ח, ב against כ, ג against נ, ו against ן. In a tight typeface or a skewed scan the difference is a few pixels, and the engine returns high confidence on the wrong reading because the shape it recognised really was crisp.
  • Final forms. ך ם ן ף ץ against כ מ נ פ צ. Swapping one produces a plausible non-word and breaks every exact comparison against a record you already hold.
  • Full and defective spelling. The same name is written דוד or דויד, the same noun תכנה or תוכנה. Not a reading error at all - two valid spellings of one thing, and no threshold will ever touch it.
  • An empty field. A blank tax-ID line does not return low confidence. It returns no field at all, a third state needing its own handling rather than being folded into weak.

Field table: what breaks in Hebrew, and where it routes

Thresholds are set against the documents you actually receive; only the method transfers.

FieldWhat breaks specifically in HebrewWhat the score will not catchStored as sourceRoute on failure
Business nameGershayim in בע"מ, full vs defective spellingTwo valid spellings of one entityBox and pageMatch on a numeric id, never on the name
ח"פ or VAT numberLatin digits inside a right-to-left lineA display flip saved as the valueBox and raw stringReject: nine digits or nothing
Amount and currencyThe shekel sign is type ET and movesA decimal point read as a commaBox and the full line textApproval queue, always
Date6/9/26 is day-month-year in IsraelA valid date under the wrong readingBox and raw stringQueue whenever the day is 12 or less
AddressHebrew street name plus a Latin house numberA house number glued to its neighbourBox and pageLogistics queue
Line descriptionFree text mixing Hebrew and EnglishA fragment cut at a direction boundaryBox and pageNo route: a description is not a key
Document numberHebrew label and Latin value on one lineThe label absorbed into the valueBox and pageUniqueness check, then queue

The date row is cheapest to fix and most expensive to ignore. 6/9/26 is valid under two readings, so no confidence score will flag it. Only a business rule - day component 12 or less, therefore ambiguous - takes it out of the straight-through path.

Gershayim, abbreviations and final letters: where tokenisation breaks

מע"מ, ח"פ, ת"ז and בע"מ are abbreviations containing gershayim, and gershayim is the character most likely to change shape between the page and the field. The engine may hand back a straight double quote, two consecutive apostrophes, the Unicode gershayim character itself, or a tilde. The form בע~מ genuinely appears in Israeli datasets, and anybody comparing strings without normalising will not find the company.

UAX #29, which defines how text is segmented into words, shows a word boundary is more than a space. In Hebrew that surfaces three ways, all handled before any comparison runs:

  • Normalise the gershayim. Every variant collapses to one canonical form before storage, and the original form is kept separately as evidence.
  • Attached one-letter prefixes. ו, ה, ב, ל, מ, כ and ש glue onto the following word. בחשבונית and חשבונית are one word for search and two for exact comparison.
  • The hyphen between Hebrew and Latin. ל-OCR is the correct spelling, the glued form is what engines hand back, and the difference turns an exact match into a silent miss.

Related: Hebrew and RTL in business software, PDF order intake with an approval queue, Hebrew PDF quality checks.

What does an exceptions route a person can actually approve in look like?

A screen showing a suspect value without the document it came from asks someone to guess. Google's Document AI response attaches to every paragraph, token and block a layout object carrying confidence, a boundingPoly with vertices and normalizedVertices, and an orientation such as PAGE_UP. At page level it returns detectedLanguages with languageCode and confidence, and the Enterprise Document OCR processor additionally returns imageQualityScores with a qualityScore between 0 and 1 plus a detectedDefects list with entries like quality/defect_glare or quality/defect_text_cutoff.

From that you get an exceptions screen someone can work in:

  1. Show the source, focused. The page opens on the box the suspect field came from, not at the top of the document.
  2. Mark only what failed. Fields that cleared should not draw attention or be editable by default.
  3. Show the raw string beside the normalised one. In Hebrew that is the difference between בע~מ and בע"מ, and the reviewer has to see both.
  4. Separate an image defect from a low score. Glare across a whole page is a scanning problem, and the fix is to request a new file rather than send a person to decipher it.
  5. Two buttons only. Approve as read, or correct and approve. A skip button produces drafts that sit in the queue forever.

What is stored per field so you can get back to the source

An audit record that is never deleted or updated, only appended to. Per field:

  • The original file exactly as received, uncompressed, never quietly replaced by a processed copy.
  • The page number and the normalised bounding box, so the display works at any resolution.
  • The raw value in logical order, before gershayim normalisation and before whitespace trimming.
  • The score, plus the engine name and version that returned it. Thresholds calibrated on one engine do not transfer to another.
  • The approved value, even when byte-identical to what was read, and who approved it and when.

The pair value read against value approved is what lets you calibrate. A field nobody ever touches has a threshold set too high and is delaying healthy work. A field people correct even above the threshold is missing a business check, not in need of a higher threshold.

Sources

#Hebrew OCR#data controls#confidence score#RTL#document intake#AI

Frequently asked questions

Should a Hebrew reversal be fixed by reversing the string in code?

No. A manual reversal produces a string that looks right in one place and is broken everywhere else, including in search and in exports. Store logical order always and set direction at the display layer only. If your tool exports display order, replace the tool or run reversal detection over its output.

How do you check that a stored value is not reversed?

By comparing code points, not by eye. A practical test: take a known Hebrew field from the document, type it by hand, and compare bytes against what was stored. A screenshot is not evidence, because an interface handed a reversed string may render it correctly after running the bidirectional algorithm.

What do you do when the document is a phone photo from the customer?

Run it through exactly the same route, but expect lower scores and a higher share of queued items. If the engine returns an image-quality measure and a defect list, block a page with a severe defect up front and request a new file, rather than sending a person to decipher a bad scan.

Does a high confidence score let you skip storing the bounding box?

No, because the box does not exist for the fields that failed. It exists for the ones that turn out to be wrong two months later. When a customer disputes an amount, being able to open the original page on the exact region is the difference between a one-minute check and an argument nobody can settle.

Keep reading

Related service

Business Automation

I build custom automations that remove repetitive work end to end.

Learn more →←

About the author

Yehonatan Saadia

Freelance automation, web & MVP developer

I'm Yehonatan Saadia, a senior developer who builds business automation, custom websites, and MVPs for small and mid-sized companies across the US, Europe, and Israel. These guides come from real client work, not theory.

Work with me

Have a project like this?

Tell me what you're trying to automate or build. I reply within 24 business hours with a few targeted questions, then we walk through it on a free 30-minute call, with no commitment. You come away with a scope, a timeline and a fixed price - or a straight answer that it isn't worth building.