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

Visit our API Portal to test the Passport OCR API with your own images.

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