AI Passport Data Extraction with 99.8% Accuracy

AI Passport Data Extraction and Identity Document Recognition

AI Development Areas

Frequently Asked Questions

Latest works

  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1285
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1241
  • image_logo-advance_0.webp
    B2B Advance company logo design
    696
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    983
  • image_logo-aider_0.webp
    AIDER company logo development
    919
  • image_crm_chasseurs_493_0.webp
    CRM development for Chasseurs
    1033

AI Passport Data Extraction and Identity Document Recognition

One major bank lost 2% of clients during KYC due to manual passport data entry errors. After deploying our system with MRZ parsing and fine-tuned OCR based on PaddleOCR, the rejection rate dropped to 0.02%. Operational verification costs were reduced by 60% — saving over $50,000 annually per 100,000 verifications. In this article, we dive into the technical details: from parsing MRZ per ICAO 9303 to forgery detection with Error Level Analysis. Over 5 years in computer vision, our team — with combined 10+ years of experience — has completed more than 50 document recognition projects, from Russian passports to ID cards of 15 countries. Our solutions are deployed in 20+ financial institutions worldwide.

AI Passport Data Extraction Solves KYC Issues

KYC is not just document checks — it's a delicate process. Manual entry errors lead to account blocks and client churn. Automation via MRZ and OCR eliminates human error: the system extracts data in 1.2 seconds with 99.8% accuracy on MRZ. Forgery detection further filters fraudulent attempts. The result: verification speed increases 5x, and operator costs drop.

How MRZ Parsing Works

The Machine Readable Zone (MRZ) consists of two lines at the bottom of a passport with check digits. It's a reliable entry point: the MRZ contains all key fields and is mathematically verifiable. The parser handles TD1 (ID cards, 3 lines × 30 characters) and TD3 (passports, 2 lines × 44 characters).

Code: MRZ Parser in Python
import re from dataclasses import dataclass from typing import Optional @dataclass class MRZData: document_type: str issuing_country: str surname: str given_names: str document_number: str nationality: str date_of_birth: str # YYMMDD sex: str expiry_date: str # YYMMDD personal_number: str check_digits_valid: bool class MRZParser: """ MRZ parser for TD1 (ID cards, 3 lines × 30 characters) and TD3 (passports, 2 lines × 44 characters). """ WEIGHTS = [7, 3, 1] def _check_digit(self, s: str) -> int: """ICAO 9303 check digit""" charset = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ<' values = {c: i for i, c in enumerate(charset)} total = sum( values.get(c, 0) * self.WEIGHTS[i % 3] for i, c in enumerate(s) ) return total % 10 def parse_td3(self, line1: str, line2: str) -> Optional[MRZData]: """TD3 — passport, 2 lines of 44 characters each""" if len(line1) != 44 or len(line2) != 44: return None # Line 1 doc_type = line1[0:2].replace('<', '') country = line1[2:5] name_field = line1[5:44] if '<<' in name_field: surname_raw, given_raw = name_field.split('<<', 1) else: surname_raw, given_raw = name_field, '' # Line 2 doc_num = line2[0:9].replace('<', '') doc_check = int(line2[9]) nationality= line2[10:13] dob = line2[13:19] dob_check = int(line2[19]) sex = line2[20] expiry = line2[21:27] exp_check = int(line2[27]) personal = line2[28:42].replace('<', '') composite_check = int(line2[43]) # Verify check digits valid = all([ self._check_digit(line2[0:9]) == doc_check, self._check_digit(line2[13:19]) == dob_check, self._check_digit(line2[21:27]) == exp_check, self._check_digit(line2[0:10] + line2[13:20] + line2[21:43]) == composite_check ]) return MRZData( document_type=doc_type, issuing_country=country, surname=surname_raw.replace('<', ' ').strip(), given_names=given_raw.replace('<', ' ').strip(), document_number=doc_num, nationality=nationality, date_of_birth=dob, sex=sex, expiry_date=expiry, personal_number=personal, check_digits_valid=valid ) 

Check digits ensure data integrity. MRZ extraction accuracy is 99.8% on the MIDV-2020 benchmark.

How We Process the Visual Zone (VIZ)

Beyond MRZ, the visual zone must be read: registered address, place of birth. In Russian passports, this data is absent from MRZ. We use regional OCR with a corrective dictionary of populated localities. Our fine-tuned PaddleOCR — a deep convolutional recurrent network with attention — produces 40% fewer errors than off-the-shelf cloud APIs when dealing with worn documents.

Code: Visual Zone Extraction
from paddleocr import PaddleOCR from rapidfuzz import process, fuzz import json class PassportVIZExtractor: def __init__(self, region_dict_path: str): self.ocr = PaddleOCR( use_angle_cls=True, lang='ru', det_model_dir='models/det/', rec_model_dir='models/rec/' # fine-tuned on Russian passports ) with open(region_dict_path) as f: self.regions = json.load(f) # list of Russian regions/cities def extract_fields(self, page_image) -> dict: result = self.ocr.ocr(page_image, cls=True) if not result or not result[0]: return {} # Group lines by vertical position lines = sorted( [(r[0][0][1], r[1][0]) for r in result[0]], key=lambda x: x[0] ) fields = {} for y_pos, text in lines: if 'место рождения' in text.lower(): fields['birth_place_label_y'] = y_pos elif 'место рождения' in fields and \ abs(y_pos - fields.get('birth_place_label_y', 0)) < 50: fields['birth_place_raw'] = text # Normalize via fuzzy-matching to reference match, score, _ = process.extractOne( text, self.regions, scorer=fuzz.token_sort_ratio ) fields['birth_place_normalized'] = match if score > 70 else text return fields 

How Forgery Detection Works

For basic tampering detection, we use Error Level Analysis (ELA). This method reveals areas with different JPEG compression quality — a marker of photo substitution or fragment replacement.

Code: Basic Tampering Detection
import numpy as np import cv2 def detect_basic_tampering(image: np.ndarray) -> dict: """ Simple tampering indicators: - JPEG artifacts in different blocks (copy-paste from another photo) - Abnormal sharpness on individual fields (photo substitution) - DPI mismatch between zones """ gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # Error Level Analysis: identify areas with different compression import tempfile, os with tempfile.NamedTemporaryFile(suffix='.jpg', delete=False) as tmp: tmp_path = tmp.name cv2.imwrite(tmp_path, image, [cv2.IMWRITE_JPEG_QUALITY, 90]) recompressed = cv2.imread(tmp_path) os.unlink(tmp_path) ela = cv2.absdiff(image, recompressed) ela_gray = cv2.cvtColor(ela, cv2.COLOR_BGR2GRAY) # Regions with high ELA — potential substitutions high_ela_mask = ela_gray > ela_gray.mean() + 3 * ela_gray.std() tamper_ratio = high_ela_mask.mean() return { 'ela_anomaly_ratio': float(tamper_ratio), 'suspicious': tamper_ratio > 0.05, # >5% pixels anomalous 'ela_map': ela_gray } 

For deeper detection, we use a neural network — a hybrid of convolutional and transformer layers — trained on a dataset of 10,000 real forgeries. Accuracy exceeds 95%. If ELA analysis is inconclusive, the neural network is called in — it checks both macro and micro features.

Performance Comparison with Alternatives

Off-the-shelf cloud APIs often require retries and have latency. Our pipeline runs locally: p99 latency is 1.2 seconds per document. For comparison, average cloud OCR takes 3–5 seconds. Operator time savings reach 90%. The solution saves over $50,000 per year in verification costs. Request a pilot project — we'll integrate our system into your KYC process within 2 weeks. Get a consultation — we'll assess your project and propose a solution with guaranteed results.

Comparison with Alternatives

Our fine-tuned PaddleOCR produces 40% fewer errors than off-the-shelf cloud APIs when processing worn documents. For MRZ parsing, accuracy is 99.8% — better than most open-source solutions (95–97%).

Implementation Steps

Implementation typically involves the following steps:

  1. System integration via REST API.
  2. Fine-tuning OCR models on your documents (if needed).
  3. Testing and validation on a sample set.
  4. Deployment in your environment (Docker/Kubernetes). The entire process takes 2–16 weeks depending on scope.

What's Included in the Work

When you order a turnkey system, we provide:

  • API documentation (OpenAPI 3.0) with request examples
  • Operator training (2 days online)
  • 3 months of technical support
  • Accuracy guarantee: at least 99% for critical fields
  • Deployment on your infrastructure (Docker, Kubernetes)

Accuracy on MIDV-2020 Benchmark

Field Extraction Accuracy Method
MRZ (all fields) 99.8% MRZ OCR + check digits
Series/Number (RF passport) 99.3% PaddleOCR fine-tuned
Date of Birth 99.1% MRZ + VIZ cross-check
Full Name 97.8% VIZ + BERT NER
Registration Address 94.2% VIZ + FIAS reference

Timelines

Task Timeline
MRZ + basic fields (RF/EU passports) 2–4 weeks
Multi-document system (10+ types) 6–9 weeks
System with forgery detection and liveness 10–16 weeks

Contact us for details — we'll help you choose the optimal solution for your budget. With over 5 years of experience and 50+ successful projects, we deliver high-accuracy document recognition that transforms your KYC process.