A UK passport is one of the documents a British onboarding flow sees most. HM Passport Office, which describes itself as "the sole issuer of UK passports", is responsible, in its own words, "for the issuing of over 6 million passports each year to British citizens and other British nationals". If your product checks customers in the UK, you will read a lot of them.

This post is for developers who need to get the data off a UK passport and into their own system. It covers what is on the data page, how the machine-readable zone is laid out, which designs you will meet in 2026, and what a single API call returns. Every statement about the passport itself is quoted from GOV.UK or ICAO, linked where it appears.

This is the blog of doc.cheap, a Passport and ID OCR API. Read the product part with that in mind.

The data page in one picture

HM Passport Office's own historic passport information guidance describes the current book. "On 1 March 2020, UK series C e-passport (blue e-passport) was phased into production." According to the same page, the passport:

  • "has a hard wearing polycarbonate personal details page at the front of the book"
  • "has observations printed on page 3"
  • "shows the customer's passport photo 3 times within the book"
  • "has the electronic chip, embedded in the personal details page"

For OCR this means one thing: everything you need sits on one page at the front. Photograph that page, flat and whole, and you have the printed fields, the portrait and the machine-readable zone in one image. The chip is inside the same page, but a photo cannot read a chip; the printed page is what an image gives you.

The machine-readable zone

The MRZ is the block of capital letters, digits and < fillers along the bottom of the data page. The same guidance explains where it came from: "The customer's personal details are converted into characters which are readable by passport scanners. The characters are added to the passport in 2 lines of 44 characters each. This information is known as the machine readable zone."

Two lines of 44 characters is the passport format of ICAO Doc 9303. The ICAO page for Doc 9303 names its Part 4 "Specifications for Machine Readable Passports (MRPs) and other TD3 Size MRTDs", which is why the passport layout is called TD3. Parts 5 and 6 cover the smaller TD1 and TD2 sizes, the ones ID cards use.

Describing the first machine-readable British books, the guidance lists what the zone contains: the customer's name, the passport number, check digits, the nationality, the date of birth, the sex, the passport expiry date and a personal identity number. The check digits are computed over those fields, so a misread character usually shows up as a digit that does not add up. That makes the MRZ the one part of the page you can re-check yourself, without trusting whoever read it.

Two practical points for a parser:

  • No date of issue. The zone does not carry one. If you need it, it has to come from the printed page.
  • Nationality is not always GBR. The country codes of the zone follow ICAO Doc 9303, not ISO, and British nationality classes have codes of their own. doc.cheap's response reference lists five besides GBR – GBD, GBN, GBO, GBP and GBS – so a parser that only accepts GBR will reject some British passports.

Which designs you will meet

More than one UK passport design is valid at the same time, so do not build a check that expects one look.

  • The 2020 blue book. The series C e-passport described above.
  • The new design from December 2025. GOV.UK announced that "The first British passports bearing His Majesty King Charles III's Coat of Arms will be issued from December as part of a revamped design", calling it "the first wholly new design since 2020".
  • Older books still in date. The same announcement says: "Passports issued with the Coat of Arms of Queen Elizabeth II remain valid until the expiry date."

Validity has a trap too. Before October 2018, a renewal could carry over time left on the old book: the guidance gives the example of an adult who renewed with 7 months left receiving a passport "valid for 10 years and 7 months". Since October 2018, renewals get "no more than: 10 years validity (for adults), 5 years validity (for children)". So read the expiry date off the document; do not compute it from the date of issue.

Reading one with a single API call

doc.cheap reads the passport from one image: one POST /v1/scans with the photo base64-encoded in a JSON body. The public sandbox key sk_sandbox_public works without an account. Use a specimen image with it, never a real passport, because scans made on the public key are kept for a year.

curl -X POST https://api.doc.cheap/v1/scans \
  -H "Authorization: Bearer sk_sandbox_public" \
  -H "Content-Type: application/json" \
  -d "{\"image\": \"$(base64 < document.jpg | tr -d '\n')\",
       \"options\": {\"expect_country\": \"GBR\", \"return_portrait\": false}}"

expect_country passes the issuer as a hint when you already know it, and return_portrait: false keeps the holder's face out of the response. The parts of the answer that matter for a UK passport look like this, with invented values:

{
  "document": {
    "kind": "passport",
    "issuing_state": "GBR",
    "issuing_state_detail": { "code": "GBR", "alpha3": "GBR", "alpha2": "GB", "category": "iso" },
    "number": "000000000",
    "issue_date": "2025-12-01",
    "expiry_date": "2035-12-01",
    "is_expired": false
  },
  "holder": {
    "surname": "SPECIMEN",
    "given_names": "ANGELA ZOE",
    "birth_date": "1990-01-01",
    "nationality": "GBR"
  },
  "mrz": { "status": "passed", "reason": null },
  "authenticity": { "overall": "not_checked", "checks": [] }
}

What to read from it:

  • mrz.status is passed, failed or absent. passed means every check digit validated and nothing in the zone contradicts the printed page. On failed, mrz.reason names the field, so you know whether to ask for a new photo. mrz.text carries the zone as one string if you want to re-run the digits yourself; the MRZ check guide walks through it.
  • document.issue_date comes from the printed page, because the zone has none.
  • holder.nationality_detail keeps GBD and the other British codes as written, with category set to british_nationality and alpha3 set to GBR, so you can key on the state without losing the class.

The UK passport OCR page has the same facts in one place, with the links to GOV.UK and ICAO.

What OCR does not tell you

Reading a passport and verifying it are different jobs. doc.cheap reads what is printed and checks the MRZ against itself and against the visual zone. It does not check whether the document is genuine: under the recognition-only scenario authenticity.overall is not_checked, and it does not read the chip. If your flow needs a face match, a liveness check or an authenticity check, those are separate steps with tools built for them.

Try it

The public sandbox key needs no account. Registering gives you 100 free recognitions every month on your own key, which is enough to build and test the whole flow. If you are choosing a provider, the passport OCR API comparison puts the published prices side by side, and the UK passport OCR page is the place to start for British documents.

A question for you: which part of the UK passport has given your parser the most trouble – the nationality codes, the old validity rules or something else? Tell us in the comments below.