Open source · Worked example
Repair the Arabic text of a PDF: a worked example
A sample certificate whose Arabic looks right on screen but copies as boxes and wrong letters, repaired with arabic-pdf-repair in one command. Download both files, compare what they paste as, and run the same code on your own PDFs.
1. Download the sample files
Both files are a one-page certificate made for this example: the names and details in it are fictional. The original's text layer is broken the way old Windows tools left it; the repaired file is the original after the command below. The pages look exactly the same.
Before repair (certificate.pdf)After repair (certificate.repaired.pdf)
2. Copy the text of the original
These are its first lines as pdf.js, the PDF reader in Firefox and many web apps, extracts them. Each □ is a control character: invisible or a box, depending on where you paste it.
□دة إ □□م دورة
□ □□ ا□□ر□□□□دة □□ر □□□□
□ □ إدارة ا□□□□□ □□ن
□ري
□□□"! ا□□رة □"
'□ أ □% □□$□ح دورة3. Repair it with one command
With Node.js 20 or newer, and nothing to install. The command names each font it fixed and writes the repaired copy next to the original, which it never changes:
$ npx arabic-pdf-repair certificate.pdf
fixed CertArabic: 65 codes
wrote certificate.repaired.pdf4. Copy the text again
The same lines, copied from certificate.repaired.pdf:
شهادة إتمام دورة
مركز ريادة للتدريب المهني
تشهد إدارة المركز بأن
سارة يوسف المنصوري
قد أتمت بنجاح دورة
أساسيات تحرير المستندات الرقميةSearch works too: the word التعلم has no match in the original and one in the repaired file.
5. The same repair in your code
In Node.js, install the package (npm install arabic-pdf-repair) and pass the file's bytes to repairTextLayer. It returns the repaired file and the fonts it fixed, or null when there is nothing to repair:
import { readFile, writeFile } from "node:fs/promises";
import { repairTextLayer } from "arabic-pdf-repair";
const input = new Uint8Array(await readFile("certificate.pdf"));
const result = await repairTextLayer(input);
if (result) {
await writeFile("certificate.repaired.pdf", result.bytes);
console.log(result.fonts); // [{ name: "CertArabic", codes: 65 }]
}The library uses no Node.js APIs, so it also runs in the browser or a web worker, on a file the user picks, without uploading it:
import { repairTextLayer } from "arabic-pdf-repair";
const picker = document.querySelector("input[type=file]");
picker.addEventListener("change", async () => {
const file = picker.files[0];
const result = await repairTextLayer(new Uint8Array(await file.arrayBuffer()));
if (!result) return; // nothing to repair
const url = URL.createObjectURL(new Blob([result.bytes], { type: "application/pdf" }));
window.open(url); // the repaired copy; the file never left the browser
});Why the original copies as gibberish
- A PDF draws each letter as a shape (a glyph) from a font. To copy it, a reader needs a table in the file, called ToUnicode, that says which letter each shape stands for.
- The original's font has no such table. Its glyphs carry only Microsoft's Arabic glyph names (afii62753 and onward), which readers do not take for letters, so copying gives control characters and stray letters.
- arabic-pdf-repair reads those names, writes the missing table and changes nothing else: the same glyphs in the same places, so the page looks the same.
Next steps
- What else it fixes (Windows-1256 text that copies as ÇáÚÑÈíÉ, Diwan XT fonts, encrypted files) and its licence: the arabic-pdf-repair page.
- A scanned page is a picture, with no text to repair: use GenPDF's OCR instead.
- To change the words of an Arabic PDF, not only copy them: edit Arabic text in a PDF with GenPDF.