Use case · Machine-readable zone
MRZ reader API with ICAO 9303 check digits
An MRZ reader turns the two or three lines of machine-readable text at the bottom of a passport, ID card or visa into structured fields. Mahad OCR parses TD3 (passport), TD1 (ID card) and MRV-A (visa) zones and recomputes every ICAO 9303 check digit on its own server, so a value is marked proven only when its digit actually passes.
Fields returned
| Key | What it holds |
|---|---|
| document type | Passport (TD3), ID card (TD1) or visa (MRV-A) |
| issuing_country, nationality | Three-letter codes from the MRZ |
| surname, given_names | Split from the SURNAME<<GIVEN<NAMES field |
| document_number | With its check digit |
| date_of_birth, expiry_date | With their check digits, returned as ISO dates |
| sex | M / F as encoded |
| checks | Per-field pass/fail of each check digit, plus the composite digit on TD3 passports |
How ✓ and ⚠ work here
- ✓ A value whose check digit passes carries evidence mrz_checksum (field_evidence “deterministic”).
- ⚠ A failed check digit marks that field for review — the value is not corrected or guessed.
- On an ID card the MRZ number is the card number, not the holder’s ID number, so it is never used to “prove” the ID number.
- On an MRV-A visa the MRZ number is the visa number; there is no composite digit.
Example request and response
Fictional data, real response shape (trimmed to the keys that matter here). Full field list in the API reference.
# 1) Before uploading: is this camera frame good enough? (local, no AI, nothing stored)
curl -X POST https://api.mahadocr.com/v1/capture/check \
-H "X-MahadDoc-API-Key: mk_live_YOUR_KEY" \
-F "[email protected]"
# 2) Upload the proven frame and read the full result
curl -X POST https://api.mahadocr.com/v1/documents/upload \
-H "X-MahadDoc-API-Key: mk_live_YOUR_KEY" \
-F "[email protected]"
# 202 Accepted
# { "id": "DOC_3f9a1c7e2b40", "status": "processing", ... }
curl https://api.mahadocr.com/v1/documents/DOC_3f9a1c7e2b40 \
-H "X-MahadDoc-API-Key: mk_live_YOUR_KEY"// POST /v1/capture/check
{
"mrz": { "found": true, "passed": true,
"checks": { "document_number": true, "date_of_birth": true,
"expiry_date": true, "composite": true } },
"codes": { "found": 0 },
"proven": true,
"ms": 850
}Limits
- Supported MRZ formats: TD3 (passports, 2 × 44), TD1 (ID cards, 3 × 30) and MRV-A (visas). TD2 and MRV-B zones are not parsed.
- Check digits prove the number and dates were read correctly. They do not prove the document itself is real, and Mahad OCR makes no such claim.
- The frame check is rate limited and reads locally only; the full read (POST /v1/documents/upload) counts toward your plan.
How to do it
- 1Capture a frame of the document with the MRZ fully visible and without glare.
- 2Optionally POST it to /v1/capture/check until proven is true.
- 3Upload that image to /v1/documents/upload and poll GET /v1/documents/{id}.
- 4Read result.field_evidence: “deterministic” means the MRZ check digit proved the value.
Frequently asked questions
What is an MRZ?
The machine-readable zone: two or three lines of capital letters, digits and < fillers printed at the bottom of passports, many ID cards and visas, defined by ICAO Document 9303. Key fields each carry a check digit.
How are MRZ check digits calculated?
Each character gets a value (digits as themselves, A–Z as 10–35, < as 0), multiplied in turn by 7, 3 and 1; the sum modulo 10 is the check digit. Mahad OCR recomputes this for every protected field.
Which MRZ formats are supported?
TD3 passports, TD1 ID cards and MRV-A visas. TD2 and MRV-B are not parsed today.
Does a passing check digit mean the document is genuine?
No. It proves the characters were read consistently with the digit. It says nothing about whether the document was issued by an authority, and Mahad OCR does not claim it does.
Is there a cost for the frame check?
The frame check (POST /v1/capture/check) reads locally, calls no AI and stores nothing. It is rate limited. Reading a document with /v1/documents/upload counts toward your plan.