MRZ Check Digits, Worked Through: The ICAO Doc 9303 Algorithm for TD1, TD2 and TD3 Documents

Document verification and OCR

For: Developer, QA engineer or fraud analyst who writes, tests or relies on a machine readable zone parser

The character values, the 7-3-1 weights and the composite check digit in the three document formats, calculated on ICAO's own specimen data, and what a passing check does and does not prove.

Every passport and identity card with a machine readable zone carries a handful of single digits whose only job is to let a reader test its own work. This article calculates them by hand. It takes the algorithm from the International Civil Aviation Organization (ICAO), applies it field by field to the specimen documents that ICAO prints in the specification itself, for the three document formats, and then asks what a passing result does and does not tell a verifier. Nothing here uses a real person's data: every example string comes from ICAO's specimens of the invented state "Utopia", from the informative appendix on check digits, or from the appendix on chip access keys.

The two articles closest to this one cover other ground. Document checks compared sets the zone beside visual inspection and the chip, and automated document validation covers the error rates of an automated check. Neither one shows the arithmetic, the position tables or the cases where the digit is missing or optional; that is the subject here. A developer can use the worked values as test vectors for a parser, and an analyst can use the same tables to see which parts of a zone no check digit protects.

Where the check digits sit: three layouts

ICAO Doc 9303 describes three sizes of machine readable travel document. Part 4 covers passports and other documents of the TD3 size, Part 5 covers TD1 size official travel documents, and Part 6 covers TD2 size official travel documents. Part 3 holds what is common to all three, including the character set, the date format and the check digit method.

The machine readable data are arranged from left to right in fixed-length fields in two lines, except for TD1 size documents, where there are three lines. A TD3 passport has two lines of 44 characters. A TD2 document has two lines of 36 characters. A TD1 document has three lines of 30 characters. In the European Union, Article 3 of Council Regulation (EU) 2025/1208 of 12 June 2025 requires identity cards issued by Member States to be produced in the ID-1 format, which is the TD1 size, and to contain a machine-readable zone based on the specifications of ICAO Document 9303. That regulation rests on Article 77(3) of the Treaty on the Functioning of the European Union. An earlier regulation on the same subject, Regulation (EU) 2019/1157, was declared invalid by the Court of Justice on 21 March 2024 in Case C-61/22 because it had been adopted on the wrong legal basis, while maintaining its effects until a new regulation based on Article 77(3) entered into force, within a period not exceeding two years from 1 January of the following year. The statement above is limited to the documents within that regulation's scope: under its scope provision these are identity cards issued by Member States to their own nationals, and provisional identification documents valid for six months or less are excluded; it says nothing about other documents.

Only a defined set of characters may appear in the zone: the digits 0 to 9, the capital letters A to Z and the filler character <. ICAO says the zone uses a subset of the OCR-B typeface, that national characters and diacritical marks are not permitted, and that punctuation is not allowed. Where the data do not fill a field, the symbol < fills the unoccupied positions. Dates are written as six digits, YYMMDD, so that 12 July 1942 appears as 420712, and unknown parts of a date of birth are completed with fillers.

The tables below, which restate the data structure tables of Parts 4, 5 and 6, show where each check digit sits and which positions it covers. Positions count from 1 at the left of the line.

TD3 (passport), lower line, 44 characters
  check digit at 10  covers 1-9    document number
  check digit at 20  covers 14-19  date of birth
  check digit at 28  covers 22-27  date of expiry
  check digit at 43  covers 29-42  personal number or other optional data
  check digit at 44  composite: covers 1-10, 14-20, 22-43
  not covered by the composite: 11-13 (nationality), 21 (sex)
  the upper line (document code, issuing state, name) has no check digit

TD2, lower line, 36 characters
  check digit at 10  covers 1-9    document number
  check digit at 20  covers 14-19  date of birth
  check digit at 28  covers 22-27  date of expiry
  check digit at 36  composite: covers 1-10, 14-20, 22-35
  not covered by the composite: 11-13 (nationality), 21 (sex)
  positions 29-35 (optional data) have no check digit of their own
  the upper line (document code, issuing state, name) has no check digit

TD1, three lines of 30 characters
  upper line, check digit at 15  covers 6-14   document number
  middle line, check digit at 7  covers 1-6    date of birth
  middle line, check digit at 15 covers 9-14   date of expiry
  middle line, check digit at 30 composite: covers upper 6-30,
                                 middle 1-7, 9-15 and 19-29
  not covered by the composite: upper 1-5, middle 8 (sex) and 16-18
  (nationality), and the whole lower line (the name)

The first thing to take from the tables is what is missing. In all three formats the name, the document code, the issuing state, the nationality and the sex sit outside every check digit, as ICAO's notes on the composite state. The second thing is the pattern: the date fields and the document number each get their own digit, and one composite digit then covers the fields that matter most, together with the earlier check digits themselves.

The algorithm

ICAO describes the check digit as a single digit computed from the other digits in a series, and says the check digits in the zone are calculated on specified numerical data elements. They let readers verify that the data in the zone is correctly interpreted. That sentence states the purpose, and the purpose is narrow: the digit tests whether the characters were read correctly, not whether the document is genuine.

The method is a special calculation adopted for travel documents: modulus 10 with a continuously repeating weighting of 731 731 and so on. It takes four steps.

  1. Going from left to right, multiply each digit of the data element by the weighting figure in the corresponding position.
  2. Add the products.
  3. Divide the sum by 10, the modulus.
  4. The remainder is the check digit.

Two rules cover characters that are not digits. Where a number does not occupy all the available positions, the filler < completes the vacant positions and has the value zero for the calculation. Where the data element contains letters, the letters A to Z have the values 10 to 35 consecutively, so that A is 10, B is 11 and Z is 35.

Three details trip up first implementations, and each follows from the wording above.

  • The weights run on. The pattern 7, 3, 1 keeps repeating across the whole string; it does not restart for each field when the string is a composite.
  • The filler is zero in the sum, but it is not the digit zero. A field of fillers sums to zero, yet the character < is not a digit, so a parser that converts characters to numbers has to map it explicitly.
  • The digit itself is data. In the composite, the earlier check digits are part of the string that is summed, which is why the position tables list the check digit positions inside the ranges.

Worked example one: a date

ICAO's informative appendix on check digit calculation starts with a date. The date is 27 July 1952, written as 520727.

digits     5   2   0   7   2   7
weights    7   3   1   7   3   1
products  35   6   0  49   6   7
sum = 35 + 6 + 0 + 49 + 6 + 7 = 103
103 divided by 10 leaves a remainder of 3
the field and its check digit are written 5207273

The appendix gives the result as the check digit 3, so the date with its digit is written 5207273.

Worked example two: a document number with letters and fillers

The second example in the appendix is the number AB2134 in a nine-character field, as in a passport number. Here the letters take their values and the three vacant positions are filled with <, which count as zero.

characters   A   B   2   1   3   4   <   <   <
values      10  11   2   1   3   4   0   0   0
weights      7   3   1   7   3   1   7   3   1
products    70  33   2   7   9   4   0   0   0
sum = 70 + 33 + 2 + 7 + 9 + 4 = 125
125 divided by 10 leaves a remainder of 5
the field and its check digit are written AB2134<<<5

The number and its check digit are written AB2134<<<5, as the appendix states.

Worked example three: the TD3 specimen passport

Part 4 of the specification prints a specimen passport of the state of Utopia. Its lower machine readable line is the string below, and the fields are the ones in the TD3 table above.

L898902C36UTO7408122F3404159ZE184226B<<<<<16

document number   L898902C3      check digit 6
nationality       UTO
date of birth     740812         check digit 2
sex               F
date of expiry    340415         check digit 9
personal number   ZE184226B<<<<< check digit 1
composite check digit 6

The document number first. The letters take the values from the alphabet table: L is 21 and C is 12. The block below shows the products and the remainder.

document number  L   8   9   8   9   0   2   C   3
values          21   8   9   8   9   0   2  12   3
weights          7   3   1   7   3   1   7   3   1
products       147  24   9  56  27   0  14  36   3
sum = 316  ->  check digit 6   (printed: 6)

date of birth  740812   products 49 12 0 56 3 2    sum 122  ->  2  (printed: 2)
date of expiry 340415   products 21 12 0 28 3 5    sum 69   ->  9  (printed: 9)

personal number  Z  E  1  8  4  2  2  6  B  and five fillers
values          35 14  1  8  4  2  2  6 11  0 0 0 0 0
weights          7  3  1  7  3  1  7  3  1  7 3 1 7 3
products       245 42  1 56 12  2 14 18 11  0 0 0 0 0
sum = 401  ->  check digit 1   (printed: 1)

All four digits agree with the specimen. The personal number is the instructive field: it is fourteen characters long, filled with the nine characters ZE184226B and five fillers, and the fillers add nothing to the sum.

Now the composite. It runs over positions 1 to 10, 14 to 20 and 22 to 43, in that order, with one unbroken run of weights. That is thirty-nine characters: the document number and its digit, the date of birth and its digit, and then the date of expiry, its digit, the personal number and its digit. The nationality and the sex are skipped.

segment                  characters        weights start   sum
positions 1-10           L898902C36        7               358
positions 14-20          7408122           3               70
positions 22-28          3404159           1               66
positions 29-42          ZE184226B<<<<<    7               401
position 43              1                 1               1
total = 358 + 70 + 66 + 401 + 1 = 896  ->  composite check digit 6

The remainder of the total on division by ten is 6, and the specimen line ends in 16: a personal number digit of 1 followed by a composite digit of 6. Note that each segment starts where the previous one stopped in the repeating pattern of weights, not at 7 each time; the fourth happens to start at 7 because twenty-four characters, a multiple of three, precede it.

For the personal number field, ICAO adds an option. When the field is not used and positions 29 to 42 hold fillers, the check digit in position 43 may be zero or the filler character, at the option of the issuing State. A validator therefore has to accept both forms for an empty personal number, and in the composite the filler counts as zero in either case.

Worked example four: the TD1 specimen identity card

Part 5 prints a TD1 specimen of the same invented state. Its three lines are these.

I<UTOD231458907<<<<<<<<<<<<<<<
7408122F1204159UTO<<<<<<<<<<<6
ERIKSSON<<ANNA<MARIA<<<<<<<<<<

The document number sits on the upper line, positions 6 to 14, and is D23145890, with its digit 7 in position 15. Its products are 91, 6, 3, 7, 12, 5, 56, 27 and 0, the sum is 207 and the digit is 7. The middle line carries the date of birth 740812 with the digit 2 in position 7, the sex F in position 8, the date of expiry 120415 with the digit 9 in position 15, and the nationality UTO in positions 16 to 18. The date of expiry products are 7, 6, 0, 28, 3 and 5, so the sum is 49 and the digit is 9.

The composite digit, in position 30 of the middle line, is the one that crosses lines. It covers positions 6 to 30 of the upper line, then positions 1 to 7, 9 to 15 and 19 to 29 of the middle line.

segment                          characters          weights start   sum
upper line, positions 6-30       D231458907 + 15 x <  7              256
middle line, positions 1-7       7408122              3              70
middle line, positions 9-15      1204159              1              50
middle line, positions 19-29     11 x <               (zero)         0
total = 256 + 70 + 50 + 0 = 376  ->  composite check digit 6   (printed: 6)

The sum is 376 and the digit is 6, which is the last character of the middle line. The nationality in positions 16 to 18 and the sex in position 8 were skipped, and so were the first five characters of the upper line and the whole name line.

ICAO's own appendix on composite check digits works a TD1 example on different data and arrives at the digit 2 for a sum of 392. The data there are an upper line I<YTOD231458907<<<<<<<<<<<<<<< and a middle line 3407127M9507122YTO<<<<<<<<<<<. Use it as a second test vector.

Worked example five: the TD2 specimen

Part 6 prints a TD2 specimen whose lower line is D231458907UTO7408122F1204159<<<<<<<6. It shares its data with the TD1 specimen: the same document number, dates and nationality. The composite covers positions 1 to 10, 14 to 20 and 22 to 35, so it sums the document number with its digit, the date of birth with its digit, and the date of expiry with its digit followed by the seven fillers of the optional data field.

segment                       characters        weights start   sum
positions 1-10                D231458907        7               256
positions 14-20               7408122           3               70
positions 22-35               1204159 + 7 x <   1               50
total = 256 + 70 + 50 = 376  ->  composite check digit 6   (printed: 6)

The sum equals the TD1 sum because the same characters meet the same weights in the same order, with the line breaks and the skipped fields removed. That is a useful property to test: two documents of different formats that carry the same data produce the same composite sum. The appendix of Part 3 has a TD2 example of its own and a TD3 example on other data, and both give the digit 8 for a sum of 448.

A set of test vectors

The values below are all taken from or checked against the ICAO texts cited in the sources. A parser should reproduce every one of them.

field value           expected check digit   source of the value
520727                3                      Part 3, appendix, example 1
AB2134<<<             5                      Part 3, appendix, example 2
L898902C3             6                      Part 4, specimen
L898902C<             3                      Part 11, appendix D, TD2 example
740812                2                      Parts 4, 5, 6, specimens
340415                9                      Part 4, specimen
120415                9                      Parts 5, 6, specimens
ZE184226B<<<<<        1                      Part 4, specimen
D23145890             7                      Parts 5, 6, specimens
D23145890734          9                      Part 11, appendix D, long number
HA672242<             6                      Part 3, appendix, example 3
580225                4                      Part 3, appendix, example 3
960108                6                      Part 3, appendix, example 3

Negative vectors

A parser should also be tested on inputs that it must reject, and on inputs that the digit cannot reject. The rows below are our arithmetic, using the weights 7, 3 and 1 and the character values of Part 3.

field value    printed digit   expected result   why
520727         4               reject            the correct digit is 3
520728         3               reject            the last character changed by one, weight 1, so the sum moved by 1
D23145890      <               rejected by a     in the long-number layout the filler sits where the digit
                               naive parser      would be, and the check digit is read after the remainder
AB2134<<<      5               accept            the printed digit is right
A12134<<<      5               accept, wrongly   B read as 1: values differ by 10, so the digit does not move
520277         3               accept, wrongly   two characters swapped, the sum moved by 20

The last two rows are not errors of the parser. They show where the digit stops and the next test has to take over: the second is caught if a format check on the date rejects day 77, and the first only by comparison with the printed text or the chip.

One row of the first table deserves a note. The value D23145890734 is a document number of twelve characters, which brings us to the cases where the layout bends.

When the layout bends

A document number longer than nine characters. The TD1 and TD2 specifications say that if the document number has more than nine characters, the nine principal characters appear in the zone, followed by a filler character instead of a check digit to indicate that the number is truncated. The remaining characters appear at the beginning of the optional data field, followed by a check digit and a filler. For the TD1 the check digit is calculated over the nine principal characters in positions 6 to 14 followed by the remainder that starts in position 16, in the order in which they appear, leaving out the filler in position 15. ICAO's table shows the span 6 to 14 and 16 to 28 for the characters that can be used and says the last character of a long document number lies in the range 16 to 28. The check digit follows that last character, so it sits somewhere in positions 17 to 29 and is itself not part of the sum, and a filler follows it. A parser that sums every character from 16 to 28 would pull the check digit into the sum and get the wrong answer. In the Part 11 example, the upper line reads I<UTOD23145890<7349<<<<<<<<<<<: the principal characters D23145890, a filler in position 15, the remainder 734, the digit 9 and then fillers to the end of the line. A parser that always reads the digit at position 15 would take the filler as a failed check on exactly these documents.

An unused or unknown field. The date of birth may carry fillers where part of it is unknown, and the check digit is then computed with those fillers as zeros. The sex field may hold the filler where the issuing State does not want to identify the sex. These cases are rare and the formal rule is short, but a parser written only for the common case rejects them.

Letters in the document number. Document numbers are alphanumeric, so letters are valid there and take the values 10 to 35. The sex field takes F for female, M for male or the filler for unspecified. The date fields take digits; the filler is allowed only in the date of birth, where all or part of that date is unknown, and not in the date of expiry. A letter in a date field, or any other letter in the sex field, is outside the specification, and a format check catches it before any arithmetic.

Other quirks of the data structure. A name longer than the field is truncated by a defined procedure, and the last character of the name field is then a letter, to signal that truncation may have occurred. No check digit covers the name field, so that letter is the only signal.

Why the check digit also matters for the chip

The check digits are not only a visual-inspection aid. In the chip access protocols, the zone doubles as a password: ICAO's appendix on the derivation of access keys builds a string called the MRZ information from the document number, its check digit, the date of birth, its check digit, the date of expiry and its check digit. For the specimen whose document number is L898902C< followed by a filler to fill the field, the string is L898902C<369080619406236, from a document number L898902C< with the digit 3, a date of birth 690806 with the digit 1 and a date of expiry 940623 with the digit 6. So a wrong digit in what is typed or read means a wrong key, and the chip does not open. This is a reason to test the digits before the phone is held against the document, and to use a failed test as a prompt to re-capture. How the chip protocols themselves work is the subject of how NFC chip verification works.

What a failed check digit means, and what it does not

ICAO's section on deviations from the specification says the conformity of the zone is routinely tested by inspection systems through comparison with the data on the visual page and the recalculation of the check digits. A mismatch is thus a standard signal, and the first thing to do with it is to find out whether the reading or the document is at fault.

There are at least three causes, and the reading comes first. The camera or the OCR may have misread a character. The person may have typed a value wrongly. And the document may itself carry a wrong digit: ICAO's deviation framework includes a deviation type for a check digit of a field of the zone "calculated wrong", and another for wrong data in a field. The same text says that, in most cases, a travel document with a non-conforming zone will be recalled by the issuing State, but that, because a gap exists between issuance and reissuance, travellers may be forced to use the deviating document, and that a published deviation may ease problems for them. The framework lets States publish signed deviation lists, which are distributed through ICAO's public key directory or through the issuing authority. It also says that non-conformities that affect single documents or small numbers should be handled by the issuing State directly.

So a failed digit is a reason to look again, not a verdict. A flow should retry the capture first, then ask for a clearer image, and escalate to a person if the failure persists. It should not silently correct the characters until the digit passes, because with a single digit the odds that a wrong reading passes by luck are not small (see below).

What a passing check digit proves

A passing digit proves one thing: the characters in the field are arithmetically consistent with the digit that follows them. The sections above support five limits.

It is public arithmetic. The method is published, uses no key and has no secret. Anyone who alters a field on a forged document can recompute the digit in a few seconds, so a passing result cannot distinguish a genuine zone from a forged one whose maker did the sum. The ICAO text itself describes the purpose as verifying that the data is correctly interpreted, not as protection against alteration.

It leaves several fields outside. The name, the issuing state, the nationality and the sex are not covered, in any of the three formats, so an alteration of those needs no recalculation and a passing check says nothing about them.

It is one digit, so it lets one reading in ten through by chance. This is our arithmetic, not a figure from a source: a check digit takes one of ten values, so a random wrong string agrees with the printed digit about one time in ten. The several digits of a line are not independent tests, because the composite digit is calculated over characters that the field digits also cover, so an error that one of them cannot see is often invisible to the composite as well. We do not give a combined probability, because it would need an error model that the standard does not supply, and the next paragraphs show why misreads are not random.

Some plausible misreads pass. Again our arithmetic, from the values above. Because every weight is coprime to ten, the substitution of one character for another changes the sum by the difference of their values multiplied by the weight, and the digit is unchanged only when the difference is a multiple of ten. The common confusions of the letter O with the digit zero, I with 1, Z with 2 and S with 5 differ in value by amounts that are not multiples of ten, so the digit catches them. The confusions of G (16) with 6, S (28) with 8 and B (11) with 1 differ by exactly ten or twenty, so the digit does not catch them. In a document number, which may hold letters, those three pairs can pass unseen.

Some swaps pass. Swapping two adjacent characters changes the sum by the difference of their values times the difference of their weights, and the digit survives only when the two values differ by a multiple of five. So a transposition of 0 and 5, or of 2 and 7, goes through unseen, while most other transpositions are caught. For a date, the digit therefore catches most but not all slips of this kind.

None of this makes the digit unimportant. It is a very cheap test that removes many reading errors before they reach a decision. What it cannot do is replace the other checks.

What the regulators and guidance ask for

The US identity proofing guideline, Special Publication 800-63A-4, requires that, if a machine readable zone or a barcode is present on the evidence, the optical capture and inspection compare the machine readable data to the printed data for consistency. The requirement is for a comparison across two representations of the same data. A check digit confirms the internal consistency of one representation, and the comparison with the printed page tests whether the two representations agree; both are needed.

The European Banking Authority guidelines on remote customer onboarding say that where institutions use automatic reading such as optical character recognition or machine readable zone verification, they should take the steps necessary to ensure the tools capture information accurately and consistently. For reproductions of identity documents, the same guidelines list among the points to establish whether the integrity of the algorithm used to generate the unique identification number holds where the original document has a machine readable zone.

The European Union Agency for Cybersecurity describes machine readable zone verification as a process that validates the integrity of the data encoded in the respective area of the document, which holds the personal information of the holder in a standardised format. It lists it beside visual security features, text extraction and chip scanning, and calls chip scanning the method with the highest level of assurance. It also notes that identity documents without electronic elements remain in circulation and that, although they carry printed security elements and a zone, it is easy to obtain a fake document with those elements.

The Home Office National Document Fraud Unit adds a visual side. Its guidance for people examining documents says that most passports and identity cards have a standardised machine readable zone, that only the characters of the defined font should appear, and that characters that do not match the font exactly could indicate a counterfeit or forgery. The same guidance notes that some countries have issued genuine passports with a non-compliant font in the zone, and its checklist suggests using an online checker for the zone where one is available. So a font irregularity and a failed digit are both signals to weigh against the issuing country and the document type.

A parser, step by step

The order below follows from the sources and from the worked examples. It is our design suggestion, not a requirement of any of them.

  1. Check the structure. Count the lines and the characters per line against the three layouts, and reject characters outside the digits, the capital letters and the filler.
  2. Identify the format. Three lines mean TD1; two lines of 36 or 44 characters mean TD2 or TD3.
  3. Parse the fields by position, using the tables above, and keep the raw characters so that a later review can see what was read.
  4. Check that dates are possible dates before any arithmetic, remembering that parts of a date of birth may be unknown.
  5. Calculate each check digit with the weights 7, 3, 1 and the letter values, treating the filler as zero.
  6. Handle the optional cases: the filler or zero digit for an empty personal number, and the long document number layout.
  7. Calculate the composite over the ranges for the format, with one unbroken run of weights.
  8. Record each result separately: structure, each digit, composite. A single "MRZ valid" flag loses what a later review needs.
  9. Compare the zone with the printed page and, where the document has one, with the chip.
  10. Do not auto-correct by trying substitutions until a digit passes; at most, offer a re-capture.

Questions to ask a provider

  • Which of the three formats does the parser handle, and how does it handle the long document number layout and an empty personal number?
  • Are all the check digits and the composite recomputed, or only some of them?
  • Does the result report each digit separately, and what does it report when the digit fails but the text looks right?
  • What happens when a digit fails: retry, a second capture, a person, or silent correction?
  • Is the zone compared with the printed page and with the chip, and where is the disagreement recorded?
  • Which fields does the provider treat as unprotected by a check digit, and what other check covers them?

Where this sits in a verification flow

NeuroVision document recognition detects, classifies and reads IDs, including printed and handwritten text and the machine readable zone with its checksum. See the MRZ reading page for how it appears in a session.

To test your own documents and countries, contact the team.

Sources

All sources were fetched on 26, 27 or 28 October 2026.

Ready to talk?

Tell us what you are building and we will help you plan the integration.

Talk to us