Arabic Image OCR & Saudi Invoice QR Reader avatar

Arabic Image OCR & Saudi Invoice QR Reader

Pricing

Pay per event

Go to Apify Store
Arabic Image OCR & Saudi Invoice QR Reader

Arabic Image OCR & Saudi Invoice QR Reader

Fast Arabic + English OCR for screenshots, documents and images (normalised and raw text, lines with confidence, RTL order), plus exact fields from Saudi ZATCA e-invoice QR codes (signature not checked). For receipts and Arabic-Indic digits use Arabic Receipt Reader.

Pricing

Pay per event

Rating

0.0

(0)

Developer

saif alnuaimi

saif alnuaimi

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a day ago

Last modified

Share

Fast Arabic + English OCR for screenshots, web pages, chat messages and typed or scanned documents, plus the exact fields from Saudi ZATCA e-invoice QR codes.

  • Plain-text mode (text): low-cost OCR that handles dense, small print well. Lines come with a confidence score and in right-to-left reading order.
  • Exact QR fields (qr): the seller name, VAT number, timestamp, invoice total and VAT total, decoded from the e-invoice QR. These are the values encoded in the QR, never guesses from OCR text.

Each image gives you the text exactly as read (textRaw) and a normalised copy (text). In the normalised copy, digits become 0-9, ٫ becomes ., ٬ becomes , and tatweel is removed.

Receipts, invoices, prices or Arabic-Indic digits? Use Arabic Receipt Reader (arabic-receipt-reader) instead. It reads Arabic-Indic digits much better, gives every number a confidence score, finds the total, subtotal, VAT and line items, checks they add up, and tells you which receipts need a human check.

This tool reads and reports the fields on an invoice. It doesn't issue, send or receive e-invoices, isn't an accredited service provider, and doesn't confirm compliance with ZATCA or UAE rules.

Which mode should I use?

You haveUse
Screenshots, chat messages, web pages, scanned or typed documentstext (this actor)
Only the Saudi e-invoice QR valuesqr (this actor). Images without a ZATCA QR cost nothing.
Receipts, invoices, price lists, anything where the numbers matterArabic Receipt Reader
Photos of signs, shop fronts or menusArabic Receipt Reader (copes better with real-world photos)

Plain-text mode (text)

This mode runs Tesseract (Arabic + English, tessdata_best models) with automatic upscaling, deskewing and QR masking. A second pass re-reads Arabic-Indic and Persian digits with a dedicated digit classifier.

Warning: plain-text mode reads Arabic-Indic digits (٠-٩) poorly. The digit pass improves them a lot on clean, printed images. On photos, low-resolution images or unusual fonts, digits are still often wrong or dropped. For receipts, invoices, prices or any number you rely on, use Arabic Receipt Reader. Plain-text mode also handles photos of signs badly. Treat it as a tool for screenshots and documents.

Image size: every image is downscaled to at most 4 megapixels before OCR (and upscaling for small text never goes past 4 MP). imageSize in each row shows the original and processed sizes. Line boxes are always in original-image pixels.

Exact QR fields (qr, optional in text with includeQrFields)

When an image contains a Saudi e-invoice QR (ZATCA TLV, base64), you get exactQrFields:

TagField
1sellerName
2vatNumber (plus vatNumberFormatValid: 15 digits, starts and ends with 3; this is a flag, never a rejection)
3timestamp (plus timestampIso)
4invoiceTotal (with VAT)
5vatTotal
6–9reported as present, with their lengths (hash, signature, public key, certificate signature)

tagsFound lists the tags in the QR. qrFormat is an informational label: phase1 (tags 1–5, before 2023), phase2-standard (tags 1–7 or 1–8), phase2-simplified (tags 1–9) or other.

We decode the QR TLV but do NOT verify its cryptographic signature/stamp (signatureChecked is always false). A QR that decodes cleanly can still be forged or belong to another invoice. These are the exact fields stored in the QR, not proof that the invoice is genuine or registered.

qr.status is zatca_tlv (decoded), not_zatca_tlv (a QR that isn't a ZATCA invoice QR, e.g. a menu link; its text is in qr.codes[].rawText) or no_qr_found. The QR fields are never filled in from the OCR text.

Input

FieldDefaultNotes
modetexttext or qr
imageUrlsPublic image links (JPEG, PNG, WebP, GIF, BMP, TIFF)
keyValueStoreRecordsUploaded images: record-key for this run's store, or store-name-or-id/record-key
includeQrFieldsfalseText mode: also read ZATCA QR fields
languagesara+engara, eng or ara+eng
pageLayout, upscale, deskew, thresholdsensible defaultsImage preprocessing
digitSecondPasstrueArabic-Indic digit classifier
maskQrCodestrueBlanks QR codes before OCR so they don't become junk text
outputLines, outputWords, stripTatweeltrue, false, trueOutput detail
maxImageSizeMb, maxConcurrency20, 2Limits

No images in the input? The actor reads a small bundled sample image (an Arabic/English text sample in text mode, a sample ZATCA QR in qr mode) so you can see the output. The same happens if the example link in the input form can't be downloaded. Sample rows have sample: true and are free. The run's status message and OUTPUT.note say so too (for example "Input image failed to download; returned built-in sample instead").

Example: QR fields only, from files uploaded to a key-value store:

{ "mode": "qr", "keyValueStoreRecords": ["my-invoices/inv-0001.png", "my-invoices/inv-0002.jpg"] }

Output

One row per image. The views are Overview and Exact QR fields. A shortened text row:

{
"source": "https://example.com/screenshot.png",
"sample": false,
"status": "ok",
"mode": "text",
"text": "فاتورة ضريبية Tax Invoice\nCustomer service: support@example.com\nالعنوان: شارع الملك فهد، الرياض",
"textRaw": "فاتورة ضريبية Tax Invoice\n...",
"meanConfidence": 88.4,
"primaryScript": "arabic",
"digitSystems": [],
"lines": [{"text": "فاتورة ضريبية Tax Invoice", "textRaw": "فاتورة ضريبية Tax Invoice", "confidence": 91.2, "direction": "rtl", "bbox": [212, 38, 476, 46]}],
"width": 900, "height": 320,
"imageSize": {"original": [900, 320], "processed": [1800, 640], "downscaledBy": 1.0, "maxProcessedMegapixels": 4.0},
"qr": {"status": "no_qr_found", "count": 0, "codes": []},
"exactQrFields": null,
"chargedEvents": ["plain-text-ocr"]
}

A decoded QR adds "exactQrFields": {"sellerName": "...", "vatNumber": "310122393500003", "vatNumberFormatValid": true, "timestamp": "...", "invoiceTotal": "172.50", "vatTotal": "22.50", "qrFormat": "phase1", "tagsFound": [1, 2, 3, 4, 5], "signatureChecked": false}.

Images that can't be read (a broken link, a file that isn't an image, a file that is too large) get a row with status: "error" and an error message. Error rows are free. The OUTPUT record summarises the run: images processed, failed and skipped, sample rows, the events charged and how long it took.

Pricing (pay per event)

EventWhenPrice
plain-text-ocrEach image read in text mode$0.003
exact-qr-fieldsEach invoice whose ZATCA QR was decoded, in qr mode or in text mode with includeQrFields$0.01
  • chargedEvents in each row lists only the events actually charged for that row.
  • One exact-qr-fields charge per invoice, never a separate "QR read" charge. In qr mode, images without a ZATCA QR are free. Error rows and sample rows are always free.
  • Spending limit: if you set a maximum cost per run, the actor checks before each image that the image's maximum possible price still fits. If it doesn't, the actor stops cleanly and keeps every row saved so far (OUTPUT.stoppedByChargeLimit, skippedSources). You are never charged for a row that wasn't saved. In text mode with includeQrFields, each image needs $0.013 of headroom, because we only know whether it has a QR after reading it.

Limitations

  • OCR is not perfect. On our synthetic test set, plain-text mode with the digit pass read about 84% of Arabic-Indic digits correctly (plain Tesseract: about 23%). Real photos score lower. For numbers, use the Receipt Reader.
  • Handwriting, decorative calligraphy, heavy diacritics (tashkeel) and stretched display lettering are read poorly.
  • Lines that mix Arabic and Latin are put into reading order with heuristics. Word order around the script change can be off.
  • Only Saudi ZATCA QR codes are decoded into fields. Other QR codes are reported as not_zatca_tlv with their raw text.
  • Only the first frame of multi-page TIFF and GIF files is read.

Privacy

Images are downloaded into the run's own container, processed in memory and not sent to any third-party service. All OCR runs inside the actor. Results are stored only in your run's dataset and key-value store, under your Apify account and its retention settings. Invoices can contain personal data (names, VAT numbers), so make sure you have the right to process the images you submit, and delete runs you no longer need.