Skip to main content

🛂 Passport OCR

🛂 พาสปอร์ต

Version Status New

Welcome to iApp Passport OCR API, an AI product developed by iApp Technology Co., Ltd. Our API is designed to automatically recognize and extract information from scanned passport images with high accuracy and speed. The system specifically focuses on reading the Machine Readable Zone (MRZ) at the bottom of passport pages, extracting crucial information like the holder's name, nationality, date of birth, and more.

Try Demo!

Example Images (Click to try)

Example 1

Demo key is limited to 10 requests per day per IP
Click here to get your API key

Getting Started

  1. Prerequisites

    • An API key from iApp Technology
    • Scanned passport images (profile page)
    • Supported file formats: JPEG, JPG, PNG, PDF
    • Maximum file size: 10MB
  2. Quick Start

    • Fast processing (1-2 seconds per image)
    • High accuracy text extraction (95.51%)
    • Support for multiple file formats
  3. Key Features

    • Extracts information from TD3 type MRZ
    • OCR accuracy scoring and validation
    • Face image extraction in base64 format
    • Support for multiple page PDF documents
    • Handles rotated and skewed images
    • Image segmentation pre-processing for skewed images
    • Supports Thai and English language
  4. Security & Compliance

    • GDPR and PDPA compliant
    • No data retention after processing
How to get API Key?

Please visit API Portal to view your existing API key or request a new one.

Example

Profile Page

Example Passport Profile Page

Request:

curl -X POST https://api.iapp.co.th/passport-ocr/v2/ocr \
-H "apikey: YOUR_API_KEY" \
-F "file=@/path/to/passport.jpg"

Response:

{
"check_composite": "4",
"check_date_of_birth": "4",
"check_expiration_date": "4",
"check_number": "6",
"check_personal_number": "3",
"country": "THA",
"date_of_birth": "930710",
"expiration_date": "250304",
"method": "direct",
"mrz_type": "TD3",
"names": "MATHANIDA",
"nationality": "THA",
"number": "AC1062346",
"personal_number": "0012345678913",
"raw_text": "P<THAPOSHNASWADIWONG<<MATHANIDA<<<<<<<<<<<<<\nAC10623466THA9307104F25030440012345678913<34",
"sex": "F",
"surname": "POSHNASWADIWONG",
"type": "P",
"valid_composite": true,
"valid_date_of_birth": true,
"valid_expiration_date": true,
"valid_number": true,
"valid_personal_number": true,
"valid_score": 100,
"face": "/9j/4AAQSkZJRgABAQAAAQABAAD/..."
}

Response Fields Explanation

FieldDescriptionFormatExample
check_compositeOverall check digit for upper and middle machine readable linesSingle digit"4"
check_date_of_birthCheck digit for date of birth fieldSingle digit"4"
check_expiration_dateCheck digit for expiration date fieldSingle digit"4"
check_numberCheck digit for document numberSingle digit"6"
check_personal_numberCheck digit for personal numberSingle digit"3"
countryCountry code of passport issuance3 letters"THA"
date_of_birthDate of birthYYMMDD"930710"
expiration_dateDocument expiry dateYYMMDD"250304"
methodReading method usedString"direct"
mrz_typeType of machine readable zoneString"TD3"
namesFirst/given name(s)String"MATHANIDA"
nationalityNationality of holder3 letters"THA"
numberPassport numberString"AC1062346"
personal_numberNational ID numberString"0012345678913"
raw_textRaw MRZ text from passportString"P<THAPOSHNASWADIWONG..."
sexGenderSingle letter"F"
surnameLast/family nameString"POSHNASWADIWONG"
typeDocument typeString"P"
valid_compositeOverall MRZ validity checkBooleantrue
valid_date_of_birthDate of birth check digit validityBooleantrue
valid_expiration_dateExpiry date check digit validityBooleantrue
valid_numberDocument number check digit validityBooleantrue
valid_personal_numberPersonal number check digit validityBooleantrue
valid_scoreOverall validity scoreInteger 0-100100
faceExtracted face imageBase64 string"/9j/4AAQSkZJRgABA..."

PDF File Processing

When processing PDF files, the response format differs slightly:

  1. The response will be a JSON array containing results for each page
  2. Each page result includes:
    • page: Page number
    • info: Contains all the standard fields as shown above
  3. A process_time field shows total processing duration

Example PDF response structure:

[
{
"page": 1,
"info": {
"sex": "F",
"number": "AC1062346",
"expiration_date": "04/03/25",
"raw_text": "P<THAPOSHNASWADIWONG<<MATHANIDA<<<<<<<<<<<<<\nAC10623466THA9307104F25030440012345678913<34",
"personal_number": "0012345678913",
"surname": "POSHNASWADIWONG",
"nationality": "THA",
"date_of_birth": "10/07/93",
"names": "MATHANIDA",
"country": "THA",
"face": "iVBORw0...CYII=",
"inference": "3.888",
"file_name": "1676365480.3823211_thai_passport_page_1.png",
"message": "Success",
"status_code": 200
}
},
{
"process_time": "4.918s"
}
]

Features & Capabilities

Core Features

  • MRZ (Machine Readable Zone) text extraction
  • Face image extraction
  • Multiple page PDF support
  • Automatic image orientation correction
  • Image segmentation for skewed images
  • High accuracy validation checks

Supported Fields

  • Document type
  • Issuing country
  • Document number
  • Holder's name
  • Nationality
  • Date of birth
  • Gender
  • Expiration date
  • Personal number
  • Face image (base64)
  • Raw MRZ text
  • Validation scores

API Reference

Recognizing Passport

POST https://api.iapp.co.th/passport-ocr/v2

Performs OCR on passport profile page and extracts MRZ data

Parameters:

  • file (required): Image file (JPG, PNG, PDF)
  • apikey (required): Your API key
  • options: Enable "segmentation" for skewed image processing

Code Examples

Python

import requests

url = "https://api.iapp.co.th/passport-ocr/v2/ocr"
headers = {
"apikey": "YOUR_API_KEY"
}
files = {
"file": open("passport.jpg", "rb")
}

response = requests.post(url, headers=headers, files=files)
print(response.json())

JavaScript

const axios = require("axios")
const FormData = require("form-data")
const fs = require("fs")

let data = new FormData()
data.append("file", fs.createReadStream("passport.jpg"))

let config = {
method: "post",
url: "https://api.iapp.co.th/passport-ocr/v2/ocr",
headers: {
apikey: "YOUR_API_KEY",
...data.getHeaders(),
},
data: data,
}

axios(config)
.then((response) => console.log(response.data))
.catch((error) => console.log(error))

PHP

<?php
$curl = curl_init();

curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.iapp.co.th/passport-ocr/v2/ocr',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => array(
'apikey: YOUR_API_KEY'
),
CURLOPT_POSTFIELDS => array(
'file'=> new CURLFILE('passport.jpg')
)
));

$response = curl_exec($curl);
curl_close($curl);
echo $response;

Swift

import Foundation

let url = URL(string: "https://api.iapp.co.th/passport-ocr/v2/ocr")!
let boundary = "Boundary-\(UUID().uuidString)"

var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("YOUR_API_KEY", forHTTPHeaderField: "apikey")
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

let imageData = try! Data(contentsOf: URL(fileURLWithPath: "passport.jpg"))

var body = Data()
body.append("--\(boundary)\r\n")
body.append("Content-Disposition: form-data; name=\"file\"; filename=\"passport.jpg\"\r\n")
body.append("Content-Type: image/jpeg\r\n\r\n")
body.append(imageData)
body.append("\r\n--\(boundary)--\r\n")

let task = URLSession.shared.uploadTask(with: request, from: body) { data, response, error in
if let data = data {
let json = try? JSONSerialization.jsonObject(with: data)
print(json ?? "")
}
}
task.resume()

Kotlin

import okhttp3.*
import java.io.File

val client = OkHttpClient()

val file = File("passport.jpg")
val requestBody = MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart(
"file",
file.name,
RequestBody.create(MediaType.parse("image/jpeg"), file)
)
.build()

val request = Request.Builder()
.url("https://api.iapp.co.th/passport-ocr/v2/ocr")
.addHeader("apikey", "YOUR_API_KEY")
.post(requestBody)
.build()

client.newCall(request).execute().use { response ->
println(response.body()?.string())
}

Java

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.*;

public class PassportOCR {
public static void main(String[] args) throws IOException {
String boundary = "Boundary-" + System.currentTimeMillis();
URL url = new URL("https://api.iapp.co.th/passport-ocr/v2/ocr");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("apikey", "YOUR_API_KEY");
conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);

try (OutputStream os = conn.getOutputStream()) {
byte[] fileBytes = Files.readAllBytes(Paths.get("passport.jpg"));

os.write(("--" + boundary + "\r\n").getBytes());
os.write(("Content-Disposition: form-data; name=\"file\"; filename=\"passport.jpg\"\r\n").getBytes());
os.write(("Content-Type: image/jpeg\r\n\r\n").getBytes());
os.write(fileBytes);
os.write(("\r\n--" + boundary + "--\r\n").getBytes());
}

try (BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
}
}

Dart

import 'package:http/http.dart' as http;
import 'dart:io';

Future<void> scanPassport() async {
var url = Uri.parse('https://api.iapp.co.th/passport-ocr/v2/ocr');
var request = http.MultipartRequest('POST', url);

request.headers['apikey'] = 'YOUR_API_KEY';

request.files.add(
await http.MultipartFile.fromPath(
'file',
'passport.jpg',
),
);

var response = await request.send();
var responseBody = await response.stream.bytesToString();
print(responseBody);
}

Limitations and Best Practices

Limitations

  • Maximum file size: 10MB
  • Supported formats: JPG, PNG, PDF
  • One passport per image
  • Clear, focused images required

Best Practices

  • Ensure good lighting conditions
  • Avoid glare and reflections
  • Center the passport in frame
  • Keep the passport flat
  • Use high resolution images
  • Enable segmentation option for skewed images

Accuracy & Performance

Overall Accuracy

  • Current Version (2.0): 95.51%
  • Previous Version (1.1): 88.86%

Field-Level Accuracy (Version 1.1)

  • Name: 81.93%
  • Surname: 90.26%
  • Document Number: 84.03%
  • Nationality: 88.09%
  • Face Detection: 100%

Processing Speed

  • Single image: 1-2 seconds
  • PDF documents: 2-3 seconds per page
  • Additional time when using segmentation

Factors Affecting Accuracy

  • Image quality
  • Lighting conditions
  • Document positioning
  • Image resolution
  • Document condition
  • Image skew angle

History

Version 2.0 (February 2023)

  • Increased overall accuracy from 88.86% to 95.51%
  • Upgraded entire OCR engine
  • Added image segmentation pre-processing for skewed images

Version 1.1 (January 2023)

  • Added face extraction to base64
  • Added support for slightly tilted images
  • Added PDF file support
  • Added multiple page PDF support

Version 1.0 (February 2022)

  • Initial release
  • Support for all country passports using MRZ
  • Basic image format support (PNG, JPG, JPEG)

Pricing

AI API Service NameEndpointIC Per RequestOn-Premise
Passport OCR [v2.0]passport_ocr_v10.75 IC/RequestContact
passport_ocr_v20.75 IC/Request