Guide

Arabic PDF accessibility: what breaks and why

Arabic adds contextual letter shaping and ligatures on top of every right-to-left problem Hebrew has. What that does to extracted text, and how to check it.

About 14 minutes · involved

Everything in the Hebrew case, plus shaping

If you have read the Hebrew guide, you already know the three failures that matter, and all three apply to Arabic without modification:

  1. Text stored in visual order — the run is pre-reversed, the page looks perfect, the extracted text is mirrored. TG-RTL-001.
  2. No language declaration — Arabic paragraphs inheriting en-US are read by a synthesiser with no Arabic phonemes. TG-RTL-002.
  3. Left-to-right column order — auto-tagging walks the page the wrong way, so a two-column layout reads as two interleaved halves. TG-RTL-004.

Arabic then adds a fourth problem that Hebrew does not have, and it is the one that catches people who have solved the first three.

Contextual shaping and presentation forms

Arabic letters change shape depending on their position in a word. The letter ع has four forms — isolated ع, initial عـ, medial ـعـ, final ـع — and a correct rendering pipeline selects among them at draw time from a single stored character, U+0639.

Some producers do not work that way. They store the shaped form: a character from Unicode’s Arabic Presentation Forms blocks, U+FB50–U+FDFF and U+FE70–U+FEFF. These blocks exist for round-tripping legacy encodings and Unicode’s own documentation discourages their use in new text.

The result renders identically and is broken in every other respect:

  • Search fails. Searching for a word in its normal spelling does not match the presentation-form spelling.
  • Copy-paste produces unusable text. It pastes as a string of compatibility characters that most systems will not re-shape.
  • Screen readers stumble. Behaviour varies by engine; some read presentation forms correctly, some read letter names, some fall silent.
  • Ligatures collapse words. The lam-alef ligature ﻻ is a single character in presentation form and two characters — ل + ا — in correctly stored text. A word containing it has the wrong length and the wrong letters.

How to check for it

Copy a paragraph out of the PDF and inspect the code points:

python3 -c "
import sys
s = sys.stdin.read()
pf = [c for c in s if 0xFB50 <= ord(c) <= 0xFDFF or 0xFE70 <= ord(c) <= 0xFEFF]
print(f'{len(pf)} presentation-form characters out of {len(s)}')
"

Any non-zero count in body text is a defect. A handful may be legitimate — some documents use presentation forms deliberately for typographic reasons — but a paragraph made of them is a producer problem.

How to fix it

Unicode normalisation form NFKC maps presentation forms back to their base characters:

import unicodedata
logical = unicodedata.normalize('NFKC', extracted_text)

The normalised string goes into /ActualText on the structure element. The glyphs on the page are untouched, so the document still looks exactly as it did — which is the whole reason /ActualText is the right mechanism here rather than rewriting the content stream.

Note the order of operations: normalise after repairing visual order, not before. NFKC decomposition changes string length, and a reversal applied to a normalised string does not map cleanly back onto the original glyph runs.

The tatweel problem

The tatweel or kashida ـ (U+0640) is a stretching character used to justify Arabic text. It carries no phonetic value.

Justification engines insert them freely, and they end up in the stored text. A screen reader may announce them as a pause, may extend the preceding sound, or may say nothing — but the word is no longer the word, so searching for it fails and any downstream text processing sees a different string.

Strip them for the logical text, keep them on the page:

logical = extracted_text.replace('ـ', '')

Again: /ActualText, not the content stream. The justification stays; the extracted text becomes the word.

Diacritics

Arabic diacritics — fatha, damma, kasra, sukun, shadda (U+064B–U+0652) — are usually absent from ordinary text and present in Qur’anic, liturgical, pedagogical and poetic material, where they are not optional.

If the document has them, keep them. Stripping vowel marks from a text where they carry meaning changes the text. If the document does not have them, do not add them; a synthesiser handles unvocalised Modern Standard Arabic perfectly well, which is what readers expect.

The one thing to check is that they have not been separated from their base letters by a reversal. A diacritic is a combining character and must follow its base in the stored string. In a reversed run it precedes it, which some engines announce as a stray mark before every letter.

A checking sequence that works

Five minutes, no licence required:

  1. Select all, copy, paste into a plain-text editor that does not reapply bidi.
  2. Is anything there? No → it is a scan; see the scanned-PDF guide.
  3. Count presentation forms with the snippet above. Non-zero in body text → shaping problem.
  4. Check word order against the rendered page for one sentence you can verify. Mirrored → visual order.
  5. Check digits. A number you can read off the page coming out with its digits reversed confirms a character-level reversal.
  6. Check /Lang. File → Properties → Advanced → Language in any Acrobat, free Reader included. en-US on an Arabic document is a blocker.

Steps 3 and 5 are the ones no mainstream checker performs, which is why an Arabic PDF can pass PAC and veraPDF cleanly and still be unreadable.

What Taggart does with it

The right-to-left analysis runs on Arabic exactly as it runs on Hebrew: paint order is compared against page geometry per line, and a run whose two orders disagree for its script is reported as stored in visual order. The morphological corroboration differs — Hebrew’s final letters have no Arabic equivalent — so Arabic detection leans on presentation-form density and on joining-behaviour consistency instead.

Repairs are /ActualText only. Presentation forms are normalised, tatweel is stripped, the logical order is reconstructed, and every output is re-rendered and compared against the original at structural similarity ≥ 0.999 before it is returned. No glyph moves; a justified Arabic page justified with kashidas still looks precisely as it did.

None of it is applied unattended. Each repaired run is shown to you as original, repaired and confidence, and your decision is recorded in the remediation report — because a tool that is confidently wrong about a language it cannot read is the worst possible outcome here.

Frequently asked questions

Is Arabic harder than Hebrew in a PDF?

Yes, in one specific way. Both scripts suffer the visual-order problem identically. Arabic adds contextual shaping: most letters have four forms depending on their position in a word, and a producer that stores the shaped presentation forms rather than the base characters produces text that renders correctly and is not searchable, not copyable, and not readable by a synthesiser.

What are presentation forms?

Unicode blocks U+FB50–U+FDFF and U+FE70–U+FEFF contain pre-shaped Arabic glyphs — initial, medial, final and isolated forms of each letter, plus ligatures. They exist for compatibility with older encodings. Text should be stored as base characters in U+0600–U+06FF and shaped by the renderer; text stored as presentation forms is a broken file that happens to look right.

Does my Arabic PDF need lang=ar or a regional variant?

ar is normally correct. A regional tag such as ar-EG or ar-MA changes the synthesiser's pronunciation, which matters for dialectal content and does not for Modern Standard Arabic. Do not use a regional tag to describe where the document was produced — it describes how the text should be read.

Do Arabic-Indic digits need special handling?

They need to be stored as what they are. Arabic-Indic digits (U+0660–U+0669) and Latin digits are different characters, and a document that uses ٤ should store U+0664, not 4. Both are weak-direction under the bidi algorithm and both keep left-to-right internal order inside right-to-left text, which surprises people every time.

Related failure conditions

Check your own file. Taggart's validator is free and unlimited — no page cap, no watermark, and no account at all up to 60 pages.

Check a PDF free

Last updated .