Extract data from a passport

Extract data from a passport scan or photo — passport OCR that returns structured fields, not flat text.

Drop a PDF or image here, or browse
PDF up to 50 MB · images up to 20 MB
Processed in-flight — temporary uploads are deleted after processing.

What should we pull from this passport?

Or pick specific fields

Or describe it yourself

Get surname, given names, passport number, nationality, dates, issuing authority, and both MRZ lines as JSON, CSV, or Excel.

By ExtractFox team · Updated · How we test

A real run, checked digit by digit

The data page below uses the specimen that ICAO itself publishes in Doc 9303, the passport standard: a passport from the fictional state of Utopia issued to Anna Maria Eriksson. Nobody's real document was used. We ran it through this page on September 25, 2026.

Specimen passport data page for Utopia, Anna Maria Eriksson, passport number L898902C3, with the two-line machine readable zone at the bottom
Input: data page built from the ICAO Doc 9303 specimen.
ExtractFox JSON output for the specimen passport with identity fields, both MRZ lines, all five check digits valid and no uncertain fields
Output: every field, both MRZ lines, and the result of each check digit.

The model's job is only to read: the printed fields and the two MRZ lines, character for character. Whether the passport number and dates can be trusted is then decided in code, by the five check digits the MRZ carries. Here all five match, so the number and both dates are taken from the MRZ, where they're printed in a fixed format.

The five checks on line 2 of the specimen, recomputed independently of the extractor.

CheckDataDigit on the passportComputedResult
Document numberL898902C366Valid
Date of birth74081222Valid
Date of expiry12041599Valid
Personal numberZE184226B<<<<<11Valid
Composite (number, birth, expiry, personal)—00Valid

When a check digit fails

To show what happens when something doesn't add up, we changed one character of the document number, C3 to C8, in both the printed field and the MRZ, and left the check digit alone. That's what a mistyped or tampered document looks like.

The same specimen passport with the document number changed to L898902C8 while its check digit still reads 6
Input: the altered copy. Passport No. L898902C8, check digit still 6.
{
  "passport_number": "L898902C8",
  "mrz_line_2": "L898902C86UTO7408122F1204159ZE184226B<<<<<10",
  "mrz_check_digits": {
    "document_number": "invalid",
    "date_of_birth": "valid",
    "date_of_expiry": "valid",
    "personal_number": "valid",
    "composite": "invalid"
  },
  "uncertain_fields": [
    "passport_number"
  ]
}
Output for the altered copy (the relevant fields, unedited).
  1. The model read both lines exactly as printed, including the wrong character.
  2. The document number check failed (the digit for L898902C8 is 1, not 6), and so did the composite check that covers it.
  3. A failed check gets one more read with a stronger model, in case the first read was the problem. It read the same thing, because the document really says C8.
  4. The passport number is returned as printed but listed in uncertain_fields. The dates still passed their own checks, so they stand.

In a KYC flow that list is the useful part: anything in uncertain_fields goes to a person, everything else doesn't have to.

The passport data page and its MRZ

The data page is the page with the photo. It has two zones: the visual inspection zone, the printed fields a person reads (name, nationality, dates, place of birth, authority), and the machine readable zone, two lines of 44 characters at the bottom meant for scanners. Passports use the TD3 format; ID cards use shorter three-line formats and belong on the ID document extractor.

TD3 layout, from ICAO Doc 9303 Part 4, with the specimen's values.

LinePositionsFieldSpecimen
11Document typeP
12Subtype (or <)<
13–5Issuing stateUTO
16–44Surname << given names, < for spacesERIKSSON<<ANNA<MARIA<<<…
21–9Document numberL898902C3
210Check digit6
211–13NationalityUTO
214–19 · 20Date of birth YYMMDD · check740812 · 2
221Sex (F, M or <)F
222–27 · 28Date of expiry YYMMDD · check120415 · 9
229–42 · 43Personal number · checkZE184226B<<<<< · 1
244Composite check0

How a check digit is computed

Each character gets a value (0–9 as themselves, A=10 through Z=35, < = 0), is multiplied by 7, 3, 1, 7, 3, 1… in turn, and the digit is the sum modulo 10. For the specimen's document number:

L898902C3
Value21898902123
Weight731731731
Product1472495627014363

147 + 24 + 9 + 56 + 27 + 0 + 14 + 36 + 3 = 316, and 316 mod 10 = 6, the digit printed after the number. Dates in the MRZ have two-digit years; a birth year later than the current year belongs to the previous century, and expiry years are read as 20xx.

Extract data from a passport

  1. Photograph or scan the data page flat, with the whole MRZ in frame. Glare across the MRZ is the most common reason a check fails.
  2. Drop it above. The default returns every printed field, both MRZ lines, the check results and uncertain_fields.
  3. Download JSON, Excel or CSV. For onboarding at volume, send each image to the REST API; the output schema is the same.
  4. Send anything in uncertain_fields, or any passport where a line couldn't be read, to manual review.

What happens to the file

The image is sent to Google's Gemini API for the reading step and isn't used for training. Small files are processed in memory; larger ones sit in private temporary storage only while they're processed and are then deleted. The extracted fields are kept briefly so the page can show them. Details are in the privacy policy.

Sources

Frequently asked questions

How do I extract data from a passport scan or photo?+

Drop a photo or scan of the data page above. You get the printed fields, both MRZ lines, the result of each MRZ check digit, and a list of any fields that couldn't be confirmed. Export as JSON, Excel or CSV.

Does it check the MRZ?+

Yes, in code rather than by asking the model. The five ICAO 9303 check digits (document number, date of birth, date of expiry, personal number, composite) are recomputed; a failure triggers a second read with a stronger model, and anything that still fails is listed in uncertain_fields.

Can I trust the dates and passport number?+

When their check digits pass, they come from the MRZ and the digit confirms them. When a check fails, the field is still returned as read but flagged in uncertain_fields, so it can go to a person instead of straight into your records.

Does it work for ID cards and residence permits?+

This page is set up for passports (the two-line TD3 MRZ). ID cards and residence permits use shorter three-line formats; use the ID document extractor for those.

Is there a passport extraction API?+

Yes. The REST API on paid plans takes the same image and returns the same fields, check results and uncertain_fields. Keys are created on the developers page.

Is it safe to upload a passport here?+

The image goes to Google's Gemini API for reading and isn't used for training; larger files are held in private temporary storage only while processed and then deleted. See the privacy policy for the full detail.

Related extractors

Used by