Document Verification: Passport, License, ID Card Turnkey

Clients lose trust and revenue when verification systems fail, rejecting genuine documents or accepting forgeries. We build comprehensive solutions for recognizing and authenticating passports, driver's licenses, and ID cards, using cascaded checks and MRZ reading. Our team delivers turnkey projects—from audit to deployment and ongoing support—ensuring reliable protection against fraud.

AI Development Areas

Frequently Asked Questions

Latest works

  • Development of a web application for FEEDME
    Development of a web application for FEEDME
    1344
  • Development of an online store for the company FURNORO
    Development of an online store for the company FURNORO
    1307
  • B2B Advance company logo design
    B2B Advance company logo design
    754
  • Development of a web application for Enviok
    Development of a web application for Enviok
    1049
  • AIDER company logo development
    AIDER company logo development
    994
  • CRM development for Chasseurs
    CRM development for Chasseurs
    1097

Document Verification: Passport, License, ID Card Turnkey

Financial and car-sharing services lose up to 30% of clients at the KYC stage due to poor verification. Typical problem: the system rejects real documents or passes fakes. Central Bank data indicates that up to 15% of forgeries go undetected by single-layer OCR. That means direct financial losses and reputational risks. Over the past years, we have developed an approach that minimizes such scenarios — verification accuracy exceeds 98% with a false rejection rate below 1%.

Document verification is the task of checking the authenticity of a physical document based on its digital image. It is used in KYC processes (banks, fintech, car-sharing, mobile operators). The task is more complex than simple OCR: you need not only to read the data but also to confirm its authenticity. Errors at this stage lead to direct financial losses and reputational risks.

How to Ensure Verification Accuracy Above 98%?

Single-layer OCR is not enough. Modern forgeries contain machine-readable zones that are visually indistinguishable from real ones. Therefore, we use a cascade of checks, each filtering a certain class of fraud. According to Central Bank data, up to 15% of forgeries are not detected by single-layer OCR — our pipeline reduces this figure to 1%.

class DocumentVerificationSystem:
    def __init__(self):
        self.ocr = PaddleOCR(use_angle_cls=True, lang='ru')
        self.mrz_reader = MRZReader()
        self.authenticity_checker = AuthenticityChecker()

    def verify(self, image_path: str, doc_type: str = 'passport_ru') -> VerificationResult:
        result = VerificationResult()

        # 1. Image quality
        quality = self.assess_image_quality(image_path)
        if quality.score < 0.6:
            result.rejected = True
            result.reason = 'low_image_quality'
            return result

        # 2. OCR all visible fields
        result.ocr_fields = self.extract_fields(image_path, doc_type)

        # 3. MRZ (Machine Readable Zone) for passports
        if doc_type in ['passport_ru', 'foreign_passport']:
            mrz_data = self.mrz_reader.read(image_path)
            result.mrz_data = mrz_data

            # Cross-check MRZ vs OCR fields
            result.mrz_consistency = self.cross_check_mrz(
                result.ocr_fields,
                mrz_data
            )

        # 4. Security features check
        result.security_features = self.authenticity_checker.check(image_path)

        # 5. Final verdict
        result.verified = self._make_verdict(result)
        return result

Why Is Multi-Level Document Check Critical for KYC?

Each level solves its own task: image quality detection filters blurry photos, MRZ checks data integrity, and analysis of security elements (guilloches, microtext, UV glow) detects forgeries. In practice, this gives accuracy >98% with a false rejection rate below 1%. For comparison, standard OCR solutions without MRZ validation yield about 85% accuracy on real data.

How Do We Read MRZ and Check Checksums?

MRZ is a standardized zone at the bottom of the passport with encoded data. Checksums allow verifying data correctness. The passporteye library gives a baseline accuracy of about 95%, but after our refinement with post-processing and cross-validation, it reaches 99%+. Our processing pipeline is 3 times faster than standard solutions thanks to GPU optimization (batch inference on Triton Server).

from passporteye import read_mrz

class MRZReader:
    def read(self, image_path: str) -> dict | None:
        mrz = read_mrz(image_path)
        if mrz is None:
            return None
        data = mrz.to_dict()
        return {
            'surname': data.get('surname', ''),
            'names': data.get('names', ''),
            'country': data.get('country', ''),
            'number': data.get('number', ''),
            'nationality': data.get('nationality', ''),
            'date_of_birth': data.get('date_of_birth', ''),
            'sex': data.get('sex', ''),
            'expiry_date': data.get('expiry_date', ''),
            'personal_number': data.get('personal_number', ''),
            'valid_composite': data.get('valid_composite', False),
            'valid_number': data.get('valid_number', False),
            'valid_dob': data.get('valid_dob', False),
            'valid_expiry_date': data.get('valid_expiry_date', False),
        }

What About Expiry Date and Format Check?

def validate_passport_fields(fields: dict) -> dict:
    """Check Russian passport field formats"""
    errors = []
    # Series and number: 4 digits series, 6 digits number
    if fields.get('series'):
        if not re.match(r'^\d{4}$', fields['series']):
            errors.append({'field': 'series', 'error': 'invalid_format'})
    if fields.get('number'):
        if not re.match(r'^\d{6}$', fields['number']):
            errors.append({'field': 'number', 'error': 'invalid_format'})
    # Issue date: not later than today, not earlier than 2000 (acceptable for existing documents)
    if fields.get('issue_date'):
        issue_date = parse_date(fields['issue_date'])
        if issue_date:
            from datetime import date
            if issue_date > date.today():
                errors.append({'field': 'issue_date', 'error': 'future_date'})
            if issue_date.year < 2000:
                errors.append({'field': 'issue_date', 'error': 'too_old'})
    # Date of birth
    if fields.get('birth_date'):
        birth_date = parse_date(fields['birth_date'])
        if birth_date:
            age = (date.today() - birth_date).days / 365
            if age < 14 or age > 120:
                errors.append({'field': 'birth_date', 'error': 'invalid_age'})
    return {'valid': len(errors) == 0, 'errors': errors}

How to Set Up a Verification Pipeline in 5 Steps?

  1. Requirements gathering — analyze document types, acceptable image formats, speed requirements.
  2. Component selection — OCR (PaddleOCR, Tesseract), quality detector, MRZ reader (passporteye), authenticity check module.
  3. Pipeline development — implement DocumentVerificationSystem class with cascade checks, integrate GPU inference.
  4. Integration — REST API or gRPC endpoint, support for batch requests for high throughput.
  5. Testing and monitoring — run on your data (at least 1000 samples), record metrics (latency p99, accuracy, false positives).

Case Study: Bank with 1M Clients Reduced KYC Time from 10 Minutes to 30 Seconds

After implementing our pipeline, the client achieved a one-time verification in 20 seconds, and repeat verification in 2 seconds (using result caching). The false rejection rate dropped from 12% to 1.5%, reducing operator workload by 8x. Contact us to achieve similar results — reduce operational costs by up to 45% through automation. We will estimate your project in 2 days.

Supported Document Types and Implementation Timelines

Document Extracted Fields MRZ
Russian Passport Series, number, full name, date of birth, gender, place of birth, issue date, issued by No (internal)
Russian International Passport Full name, number, date of birth, expiry date Yes
SNILS Number, full name, date of birth No
Driver's License Series/number, categories, full name, expiry date No
INN Number No
Task Timeline
Verification of 1 document type 3–4 weeks
Full KYC (passport + SNILS + photo) 5–8 weeks
Anti-fraud verification 7–12 weeks
Checklist of Typical Implementation Mistakes
  • Not checking image quality before OCR — degrades results by 30%.
  • Ignoring MRZ validation: 20% of forgeries pass through simple OCR solutions.
  • Not setting a timeout during integration — clients leave when delays exceed 3 seconds.
  • Forgetting to test edge cases: rotation >15°, shadows, glare.
  • Not recording metrics — impossible to improve the pipeline.

What's Included in Turnkey Work?

We provide the full cycle: requirements analysis, architecture selection (RAG, classifier, or hybrid), pipeline implementation, REST API integration, testing on your document pool (at least 1000 samples), documentation, operator training, and 1 month post-launch support. We guarantee verification accuracy of at least 98% with a false rejection rate below 1%. Typical ROI is 6–9 months.

Our experience includes 15+ projects in fintech, banking, and government sectors. Order a pilot — we will verify 100 of your documents and show the result. Get demo access to an already running system.