Production-Grade Passport OCR API for C#

Extract and validate ICAO 9303 MRZ data with 99.8%+ accuracy in under 1500ms via a direct HTTP request.

Diagram showing a passport image being sent to the StructOCR API, which processes the Machine Readable Zone (MRZ) and returns structured JSON data with fields like name, passport number, and date of birth.
Figure 1: StructOCR converts raw Passport images into validated JSON data.

Why Passport OCR is Difficult

Implementing reliable passport OCR extends beyond simple text extraction. Generic engines like Tesseract fail on low-resolution or noisy images common in user-submitted scans. Passports present unique challenges: holographic overlays cause glare, angled photos introduce skew and rotation, and varied lighting creates shadows that obscure characters in the Machine Readable Zone (MRZ). Furthermore, extracting data isn't enough; it requires validation. This involves parsing the fixed-width ICAO 9303 format, correctly calculating and verifying multiple check digits (for passport number, date of birth, and expiry), and maintaining complex RegEx patterns for dozens of country-specific variations. This technical debt becomes a significant maintenance burden.

Enterprise-Grade Extraction with StructOCR

StructOCR is purpose-built for identity documents. Our API utilizes pre-trained deep learning models specifically designed for the OCRA and OCRB fonts found in ICAO 9303 compliant passports, making it an ideal passport ocr software solution. Before extraction, our pipeline performs automatic image pre-processing, including deskewing, denoising, and glare removal. Unlike Tesseract which returns unstructured text strings, StructOCR parses the entire MRZ, validates all check digits, and returns a standardized, predictable JSON object. This capability is particularly beneficial for accelerating h1b visa processing by providing immediate, actionable data and eliminating the need for fragile post-processing scripts.

Production Use Cases

  • Digital Onboarding (KYC): Reduce drop-off rates by pre-filling user data from Passports in < 2 seconds.
  • Fraud Prevention: Detect tampered fonts or mismatched MRZ checksums automatically.
  • Global Compliance: Handle Passports from 200+ jurisdictions without custom rules.

Live Demo: Passport scanner

No registration required. Upload a file to test the extraction.

1
Upload
2
Results

Drop files here or click to browse

JPG · PNG · WebP  ·  up to 500 files · max 4.5 MB each

No files selected
Need more testing? Create a free account to get 200 free credits (equals 100 Passport scans).

Implementation: Raw C# (HttpClient)

The following C# code demonstrates a complete flow using `System.Net.Http`. It correctly handles `x-api-key` authentication and deserializes both MRZ and Visual Zone (VIZ) fields into strong-typed objects.

Prerequisite: .NET Core 3.1+ or .NET 5/6/7+

CODE EXAMPLE
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

public class PassportOcrExample
{
    // 💰 Save 30%+ vs competitors. Get 200 free credits instantly:
//    👉 https://structocr.com/register
    private const string ApiKey = "YOUR_API_KEY_HERE";
    private const string ApiEndpoint = "https://api.structocr.com/v1/passport";

    private static readonly HttpClient client = new HttpClient();

    public static async Task Main(string[] args)
    {
        // Note: Supports JPG, PNG, WebP (Max 4.5MB)
        string imagePath = "passport.jpg";

        if (!File.Exists(imagePath))
        {
            Console.WriteLine($"Error: File not found at {imagePath}");
            return;
        }

        try
        {
            // 1. Prepare Payload
            byte[] imageBytes = await File.ReadAllBytesAsync(imagePath);
            string base64Image = Convert.ToBase64String(imageBytes);
            var payload = new { img = base64Image };

            // 2. Setup Request
            client.DefaultRequestHeaders.Clear();
            client.DefaultRequestHeaders.Add("x-api-key", ApiKey); // Required Header

            // 3. Send POST Request
            Console.WriteLine($"Scanning passport at {ApiEndpoint}...");
            HttpResponseMessage response = await client.PostAsJsonAsync(ApiEndpoint, payload);

            // 4. Handle Response
            string responseBody = await response.Content.ReadAsStringAsync();

            if (!response.IsSuccessStatusCode)
            {
                Console.WriteLine($"API Error ({response.StatusCode}): {responseBody}");
                return;
            }

            // 5. Deserialize to Object
            var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
            var result = JsonSerializer.Deserialize<ApiResponse>(responseBody, options);

            if (result?.Success == true && result.Data != null)
            {
                var data = result.Data;
                Console.WriteLine("✅ Extraction Successful!");
                
                // Identity Data
                Console.WriteLine($"Passport #: {data.PassportNumber}");
                Console.WriteLine($"Name:       {data.GivenNames} {data.Surname}");
                Console.WriteLine($"Nation:     {data.Nationality} ({data.CountryCode})");

                // Visual Zone Data (Unique to StructOCR)
                Console.WriteLine($"Birth Place:{data.PlaceOfBirth}");
                Console.WriteLine($"Issued At:  {data.PlaceOfIssue}");
                
                // Dates
                Console.WriteLine($"DOB:        {data.DateOfBirth} ({data.Sex})");
                Console.WriteLine($"Expiry:     {data.DateOfExpiry}");
            }
            else
            {
                Console.WriteLine($"Extraction Failed: {result?.Error}");
            }
        }
        catch (Exception e)
        {
            Console.WriteLine($"Unexpected Error: {e.Message}");
        }
    }
}

// --- Data Models matching the Schema ---
public class ApiResponse
{
    public bool Success { get; set; }
    public PassportData Data { get; set; }
    public string Error { get; set; }
}

public class PassportData
{
    [JsonPropertyName("passport_number")]
    public string PassportNumber { get; set; }
    
    public string Surname { get; set; }
    
    [JsonPropertyName("given_names")]
    public string GivenNames { get; set; }
    
    public string Nationality { get; set; }
    
    [JsonPropertyName("country_code")]
    public string CountryCode { get; set; }
    
    [JsonPropertyName("date_of_birth")]
    public string DateOfBirth { get; set; }
    
    public string Sex { get; set; }
    
    [JsonPropertyName("date_of_expiry")]
    public string DateOfExpiry { get; set; }

    // VIZ Fields (Visual Inspection Zone)
    [JsonPropertyName("place_of_birth")]
    public string PlaceOfBirth { get; set; }
    
    [JsonPropertyName("place_of_issue")]
    public string PlaceOfIssue { get; set; }
}

Technical Specs

  • Latency: < 4s (Average)
  • Uptime: 99.9% SLA
  • Security: AES-256 Encryption & SOC2 Compliant
  • Input: JPG, PNG, WebP (Base64 Encoded)
  • Max File Size: 4.5MB
  • Output: JSON (Structured Data)

Key Features

  • Visual Extraction (VIZ): Parses non-MRZ data fields like Place of Birth and Issuing Authority.
  • Global Support: Optimized for 195+ countries, handling complex backgrounds and holograms.
  • Date Normalization: Returns all dates (Birth, Issue, Expiry) in a standardized YYYY-MM-DD format.

Sample JSON Output

StructOCR returns a normalized JSON object, regardless of the input image angle or quality.

{
  "success": true,
  "data": {
    "type": "passport",
    "country_code": "USA",
    "nationality": "UNITED STATES",
    "passport_number": "E12345678",
    "surname": "DOE",
    "given_names": "JOHN",
    "sex": "M",
    "date_of_birth": "1990-01-01",
    "place_of_birth": "NEW YORK, USA",
    "date_of_issue": "2020-01-01",
    "date_of_expiry": "2030-01-01",
    "place_of_issue": "PASSPORT AGENCY"
  }
}

Frequently Asked Questions

How does StructOCR compare to AWS Textract or Google Vision?

Generic OCR services like AWS Textract or Google Vision are powerful but return raw lines of text. They do not understand the specific structure of an ICAO 9303 passport MRZ. Developers are still required to write and maintain complex parsers and validation logic. StructOCR is a specialized model that performs extraction, parsing, and validation in one step, returning a structured JSON object with clearly defined fields.

Do you store the uploaded images?

No. All images are processed in-memory and are permanently deleted immediately after the OCR process completes. We do not store any personally identifiable information (PII) from your requests.

How do you handle blurry or low-quality images?

Our API includes an automatic image enhancement engine that applies de-blurring and sharpening filters before the OCR process begins. For best results, we recommend images with a minimum resolution of 300 DPI.

You May Also Like

Related tutorials, platform guides, and comparisons

Country Tutorial

Sweden Passport OCR with Python SDK

Use the official StructOCR Python SDK and FastAPI to extract structured MRZ and VIZ data from Sweden passports with a server-side integration.

Python · Passport
Country Tutorial

Hungary Passport OCR with Python SDK

Use the official StructOCR Python SDK and FastAPI to extract structured MRZ and VIZ data from Hungary passports with a server-side integration.

Python · Passport
Country Tutorial

Portugal Passport OCR with Node.js SDK

Use the official StructOCR Node.js SDK with TypeScript and Express to extract structured MRZ and VIZ data from Portugal passports.

Node.js · Passport
Country Tutorial

Pakistan Passport OCR with Python SDK

Use the official StructOCR Python SDK and FastAPI to extract structured MRZ and VIZ data from Pakistan passports with a server-side integration.

Python · Passport
Country Tutorial

Brazil Passport OCR with Node.js SDK

Use the official StructOCR Node.js SDK with TypeScript and Express to extract structured MRZ and VIZ data from Brazil passports.

Node.js · Passport
Country Tutorial

Portugal Passport OCR with Python SDK

Use the official StructOCR Python SDK and FastAPI to extract structured MRZ and VIZ data from Portugal passports with a server-side integration.

Python · Passport
Country Tutorial

Chile Passport OCR with Python SDK

Use the official StructOCR Python SDK and FastAPI to extract structured MRZ and VIZ data from Chile passports with a server-side integration.

Python · Passport
Country Tutorial

Bangladesh Passport OCR with Python SDK

Use the official StructOCR Python SDK and FastAPI to extract structured MRZ and VIZ data from Bangladesh passports with a server-side integration.

Python · Passport
Country Tutorial

Belgium Passport OCR with Python SDK

Use the official StructOCR Python SDK and FastAPI to extract structured MRZ and VIZ data from Belgium passports with a server-side integration.

Python · Passport
Country Tutorial

Belgium Passport OCR with Node.js SDK

Use the official StructOCR Node.js SDK with TypeScript and Express to extract structured MRZ and VIZ data from Belgium passports.

Node.js · Passport

Technical Comparisons & Integrations

Explore platform integrations and competitive analysis

From tutorial to production in 5 minutes.

You've seen the code. Now get your API key, grab your 200 free credits, and see it work with your own images. No credit card required.

Instant Access Cancel Anytime 99.9% Uptime