Skip to main content

Passport OCR

Mobile & Web SDK available

Skip the camera work — our free open-source eKYC SDK (Web, Flutter, iOS, Android & React Native) auto-captures documents and faces and calls this API for you. View on GitHub.

The Passport OCR API reads the machine-readable zone (MRZ) of any ICAO 9303 passport and returns the holder's details — number, names, dates, nationality — together with the face photograph and a set of verification flags. A passport MRZ is self-validating: every key field carries its own check digit, and the valid_* flags report whether each returned value satisfies it, so a read can be trusted arithmetically rather than on faith. The production service answers in 0.4 seconds (median) and sustains 15,000 passports per hour; on the 266-passport benchmark, 95.5 percent of reads return the number, date of birth, and expiry all verified against their check digits, and 100 percent of MRZs parse. See Accuracy.

Live Demo

Upload a passport photo page, or use the specimen below.

Try Our AI Demo

Login or create a free account to use this AI service demo and explore our powerful APIs.

Get 100 Free Credits (IC) when you sign up!

Offer ends December 31, 2025

Example Images (Click to try)

Example 1
Try Demo

Try the SDK (Live Camera)

Prefer not to upload a file? The free open-source iApp eKYC Web SDK captures the passport data page automatically from your camera — it detects the page boundary, waits for a sharp stable frame, perspective-corrects the image, and submits it to this API. See more flows on the full SDK live demo page.

Loading live demo…

Quick Start

You need an API key from the API Key Management page. Send the image as multipart/form-data:

curl -X POST https://api.iapp.co.th/v3/store/ekyc/passport \
-H "apikey: YOUR_API_KEY" \
-F "file=@passport.jpg"
{
"number": "AC1062346",
"valid_number": true,
"surname": "POSHNASWADIWONG",
"names": "MATHANIDA",
"date_of_birth": "10/07/93",
"valid_date_of_birth": true,
"expiration_date": "04/03/25",
"valid_expiration_date": true,
"nationality": "THA",
"valid_composite": true
}

valid_number is the field to act on: when it is false, the returned number cannot belong to any real passport and the image should be re-captured rather than the value trusted. The full response schema is in the Technical Reference.

Endpoints and Pricing

EndpointOutputPrice
POST /v3/store/ekyc/passportJSON with holder details, check-digit verification flags, and the face photograph0.75 IC per page

The legacy paths /passport-ocr, /passport-ocr/v2, and /passport-ocr/v2/ocr remain supported at the same price and reach the same service. For on-premise deployment, see Data Security.

Performance

Measured on the production service, August 2026.

MetricValue
Median processing time0.4 s per passport
Sustained throughput4.3 passports per second (15,000 passports per hour)
Supported input formatsJPEG, JPG, PNG, WEBP, PDF (one result per page)
CoverageAny ICAO 9303 machine-readable passport

Accuracy

A passport MRZ carries its own check digits, so correctness is measured arithmetically on the 266-passport benchmark — no reference transcription and no judgement calls: a returned field either satisfies the check digit printed on the passport or it does not.

Measurev2.0.3
MRZ parsed100%
Document number verified96.2%
Date of birth verified99.2%
Expiry date verified98.1%
Personal number verified98.5%
Number, birth date, and expiry all verified95.5%

The August 2026 release raised the fully-verified rate from 58.6 percent to 95.5 percent — a returned document number that fails its check digit cannot be real, and such reads dropped from 30 percent of passports to under 4. The measure is deliberately conservative: a check digit is one decimal digit, so roughly one wrong read in ten passes it by coincidence, meaning true accuracy is slightly below these figures in any release measured this way. Full methodology, the engine and validation contributions measured separately, and the safety properties of the repair logic are published in the whitepaper:

Download the benchmark whitepaper (PDF)

Data Security and Compliance

  • The service is GDPR and PDPA compliant.
  • Uploaded images are processed in memory and are not retained after the response is returned.
  • A fully self-contained on-premise deployment is available, in which no passport data leaves your infrastructure. Contact us for details.

Technical Reference

Request

POST with multipart/form-data and the apikey header.

ParameterRequiredDescription
fileYesPassport image or PDF (JPG, JPEG, PNG, WEBP, PDF). A PDF returns one entry per page, each with page and info
fieldsNoComma-separated subset of fields to return; all are returned if omitted
optionsNoComma-separated. segmentation corrects badly oriented images (roughly 2× slower); no_thresh skips pre-processing of the MRZ crop

Response

200 with a flat JSON object.

Holder details

FieldDescription
numberPassport number
surnameSurname, as printed in the MRZ
namesGiven names
date_of_birthDD/MM/YY
expiration_dateDD/MM/YY
sexM, F, or < if unspecified
nationalityISO 3166-1 alpha-3
countryIssuing country, ISO 3166-1 alpha-3
personal_numberOptional personal number; blank on many passports
typeDocument type as printed in the MRZ, P< for an ordinary passport
mrz_typeMRZ layout, TD3 for passports
faceFace photograph, Base64 JPEG

Verification — whether each field agrees with its check digit, and the check digits as printed.

FieldDescription
valid_numberPassport number agrees with its check digit
valid_date_of_birthDate of birth agrees with its check digit
valid_expiration_dateExpiry date agrees with its check digit
valid_personal_numberPersonal number agrees with its check digit
valid_compositeThe MRZ as a whole agrees with its composite check digit
valid_scorePercentage of the check digits that verified, 0100
check_number, check_date_of_birth, check_expiration_date, check_personal_number, check_compositeThe printed check digits

Diagnostics

FieldDescription
raw_textThe two MRZ lines, 44 characters each
methodHow the MRZ band was located
inferenceProcessing time in seconds
file_name, message, status_codeSuccess / 200 on the happy path

When no MRZ can be located the request still returns 200 with an Error Message field; options=segmentation usually resolves badly oriented images.

Response Codes

Status CodeDescription
200Success (including no-MRZ-found, reported in the body)
415Unsupported file type
461No file attached
462Request form did not contain a file key

Code Examples

curl -X POST https://api.iapp.co.th/v3/store/ekyc/passport \
-H "apikey: YOUR_API_KEY" \
-F "file=@passport.jpg"

Limitations

  • Reads the machine-readable zone only; visual-zone text outside the MRZ is not extracted.
  • Two-digit years in the DD/MM/YY dates are a property of the MRZ standard, which does not encode the century.
  • Badly oriented or skewed captures may need options=segmentation, at roughly double the processing time.

Changelog

VersionDateChanges
v2.0.5-2026082525 Aug 2026The public endpoint now serves the unified passport service. Dates return as DD/MM/YY — the format this service has returned to its integrators since 2023; callers that parsed the interim YYMMDD form must update. Adds type, mrz_type, method, and valid_score (percentage of check digits verified). Sustained throughput increased to 15,000 passports per hour.
v2.0.3-2026082525 Aug 2026Upgraded recognition and added structural MRZ validation. Fully check-digit-verified reads (number, birth date, and expiry together) rose from 58.6% to 95.5% on the 266-passport benchmark, and every MRZ now parses. Median processing time reduced from 0.26 s to 0.2 s. The documented valid_date_of_birth and valid_expiration_date fields are now actually returned. Fully self-contained on-premise deployment available.
v2.0Feb 2023MRZ extraction with face image and check-digit flags.