Back to the blog

How to Read a Passport MRZ Line by Line (Position Map)

A complete map of all 88 MRZ positions on a passport: what every character of both lines contains, how names are encoded, why the dates carry no century, and how to decode one by hand.

Extract Passport Data
MRZread MRZmachine readable zoneICAO 9303TD3passport

A passport's MRZ isn't free text — it's a fixed-width format where every position is defined by the ICAO 9303 standard. Once you know what sits where, you can decode a passport by hand, with no software at all.

This is the complete map of those 88 positions. It's the reference worth keeping open when you're debugging an integration and need to know why field 7 came back empty.

The TD3 format

Passports use TD3: two lines of exactly 44 characters each, printed at the foot of the data page. The alphabet is restricted to A-Z, 0-9 and < (the filler character). No lowercase, no accents, no spaces.

We'll work from this real, valid example:

P<MEXGOMEZ<VELAZQUEZ<<MARGARITA<<<<<<<<<<<<<
G123456786MEX8007050F3307054<<<<<<<<<<<<<<08

Line 1: document, country and name

PositionsContentsIn the example
1Document type — P for passportP
2Subtype, at the issuer's discretion; almost always filler<
3-5Issuing country, 3-letter codeMEX
6-44Name field, 39 charactersGOMEZ<VELAZQUEZ<<MARGARITA<<<...

How the name is encoded

The name field causes more integration bugs than anything else in the MRZ, because its structure isn't obvious:

  • Surnames come first.
  • A double << separates surnames from given names.
  • A single < separates words within either block.
  • The remainder is padded with < out to 39 characters.

So GOMEZ<VELAZQUEZ<<MARGARITA reads: surnames Gomez Velazquez, given name Margarita.

Two practical consequences:

Accents and non-English letters disappear. ICAO 9303 permits only A-Z, so transliteration is mandatory: VelázquezVELAZQUEZ, MüllerMUELLER, ØOE. If you compare an MRZ name against your database character by character, every name with a diacritic will fail. Normalize both sides first.

Long names get truncated. 39 characters run out fast with two surnames and two given names. When it doesn't fit, the issuer truncates — and the truncated name is the official MRZ data, not a misread. This is one reason to read the visual inspection zone (VIZ) as well, where the full name appears.

Line 2: the data that matters

PositionsContentsIn the example
1-9Passport numberG12345678
10Passport number check digit6
11-13Nationality, 3-letter codeMEX
14-19Date of birth, YYMMDD800705
20Date of birth check digit0
21Sex — M, F, X or <F
22-27Date of expiry, YYMMDD330705
28Expiry check digit4
29-42Personal number, 14 characters<<<<<<<<<<<<<<
43Personal number check digit0
44Composite check digit over all of the above8

Decoded: passport G12345678 issued by Mexico, holder born 5 July 1980, sex F, valid until 5 July 2033.

The dates carry no century

YYMMDD is six digits: 800705 is 5 July — but of 1980 or 2080? The MRZ doesn't say. The working convention:

  • Expiry: always in the future, so always 20xx.
  • Date of birth: if the two digits exceed the current year's, it's 19xx; otherwise 20xx.

The heuristic fails in exactly one realistic case: people over 100. If your system serves the very elderly, resolve the century against the expiry date rather than assuming it.

The personal number is a free field

Positions 29-42 are the most misread part of the MRZ. Each country decides what goes there, and many put nothing at all — hence the fourteen < in the example. Never assume that field carries a national identifier.

One hard limit worth knowing: the field is 14 characters, which is shorter than a good many national ID numbers. Whatever your source country puts on the data page, don't count on finding it here. A serious extraction reads the visual zone too, not just the two lines at the foot.

The < padding is not optional

A common mistake when building test MRZs: trimming the trailing <. A 41-character line is not a valid MRZ, and any standards-respecting validator will reject it before looking at the contents. Both lines are exactly 44 characters, always.

Reading goes the other way: < becomes a space or is discarded depending on the field. Inside a name, a single < is a word separator; at the end of a field, it's just padding.

The four digits that verify everything

You'll have noticed four check digits on line 2. They're what makes the MRZ the most trustworthy field on any identity document: they let you detect a misread before you store it, using arithmetic alone, with no external lookup.

The algorithm is public and fits in ten lines of code. We work through it completely, with the arithmetic on this same example, in ICAO 9303 check digits: how they're calculated.

Try it on a real MRZ

You can paste any MRZ into our free MRZ validator: it decodes the fields, recomputes all four check digits and points at exactly the one that doesn't add up. No account needed, and it runs the same code as our extraction engine — so what you see there is literally what we apply in production.

If you'd rather have an API return the fields already structured and verified from a photo, the free demo processes a passport with no signup, and the documentation shows full integration in JavaScript, Python and PHP.

Need to extract passport data automatically?

Try our API with 20 free extractions. Integrate in minutes, get results in seconds.

Start for free