International Passport OCR

Automatically extracts data from passports

Many onboarding processes in mobile or web apps require extracting some data from ID documents. Using Mindee's passport API, you can automatically extract data from passports to offer your users the best onboarding experience. The API extracts:

  • Birth date
  • Birth place
  • Country
  • Expiry date
  • Gender
  • Given names
  • Id number
  • Issuance date
  • Mrz1 (Passport's machine-readable zone line 1)
  • Mrz2 (Passport's machine-readable zone line 2)
  • Surname

Set up the API

📘

Before making any API calls, you need to have created your API key.

  1. You'll need to get a picture of a passport. You can use this fake one below.

sample fake passport

  1. Access your Passport API by clicking on the International Passport card in the APIs Store.


  1. From the left navigation, go to documentation > API reference, you'll find sample code in popular languages and command line.
    passport api sample code in the api reference section
from mindee import Client, PredictResponse, product

# Init a new client
mindee_client = Client(api_key="my-api-key-here")

# Load a file from disk
input_doc = mindee_client.source_from_path("/path/to/the/file.ext")

# Load a file from disk and parse it.
# The endpoint name must be specified since it cannot be determined from the class.
result: PredictResponse = mindee_client.parse(product.PassportV1, input_doc)

# Print a summary of the API result
print(result.document)

# Print the document-level summary
# print(result.document.inference.prediction)
const mindee = require("mindee");
// for TS or modules:
// import * as mindee from "mindee";

// Init a new client
const mindeeClient = new mindee.Client({ apiKey: "my-api-key-here" });

// Load a file from disk
const inputSource = mindeeClient.docFromPath("/path/to/the/file.ext");

// Parse the file
const apiResponse = mindeeClient.parse(
  mindee.product.PassportV1,
  inputSource
);

// Handle the response Promise
apiResponse.then((resp) => {
  // print a string summary
  console.log(resp.document.toString());
});
using Mindee;
using Mindee.Input;
using Mindee.Product.Passport;

string apiKey = "my-api-key-here";
string filePath = "/path/to/the/file.ext";

// Construct a new client
MindeeClient mindeeClient = new MindeeClient(apiKey);

// Load an input source as a path string
// Other input types can be used, as mentioned in the docs
var inputSource = new LocalInputSource(filePath);

// Call the API and parse the input
var response = await mindeeClient
    .ParseAsync<PassportV1>(inputSource);

// Print a summary of all the predictions
System.Console.WriteLine(response.Document.ToString());

// Print only the document-level predictions
// System.Console.WriteLine(response.Document.Inference.Prediction.ToString());
require 'mindee'

# Init a new client
mindee_client = Mindee::Client.new(api_key: 'my-api-key-here')

# Load a file from disk
input_source = mindee_client.source_from_path('/path/to/the/file.ext')

# Parse the file
result = mindee_client.parse(
  input_source,
  Mindee::Product::Passport::PassportV1
)

# Print a full summary of the parsed data in RST format
puts result.document

# Print the document-level parsed data
# puts result.document.inference.prediction
import com.mindee.MindeeClient;
import com.mindee.input.LocalInputSource;
import com.mindee.parsing.common.PredictResponse;
import com.mindee.product.passport.PassportV1;
import java.io.File;
import java.io.IOException;

public class SimpleMindeeClient {

  public static void main(String[] args) throws IOException {
    String apiKey = "my-api-key-here";
    String filePath = "/path/to/the/file.ext";

    // Init a new client
    MindeeClient mindeeClient = new MindeeClient(apiKey);

    // Load a file from disk
    LocalInputSource inputSource = new LocalInputSource(filePath);

    // Parse the file
    PredictResponse<PassportV1> response = mindeeClient.parse(
        PassportV1.class,
        inputSource
    );

    // Print a summary of the response
    System.out.println(response.toString());

    // Print a summary of the predictions
//  System.out.println(response.getDocument().toString());

    // Print the document-level predictions
//    System.out.println(response.getDocument().getInference().getPrediction().toString());

    // Print the page-level predictions
//    response.getDocument().getInference().getPages().forEach(
//        page -> System.out.println(page.toString())
//    );
  }

}
<form onsubmit="mindeeSubmit(event)" >
  <input type="file" id="my-file-input" name="file" />
  <input type="submit" />
</form>

<script type="text/javascript">
const mindeeSubmit = (evt) => {
  evt.preventDefault()
  let myFileInput = document.getElementById('my-file-input');
  let myFile = myFileInput.files[0]
  if (!myFile) { return }
  let data = new FormData();
  data.append("document", myFile, myFile.name);

  let xhr = new XMLHttpRequest();

  xhr.addEventListener("readystatechange", function () {
    if (this.readyState === 4) {
      console.log(this.responseText);
    }
  });

  xhr.open("POST", "https://api.mindee.net/v1/products/mindee/passport/v1/predict");
  xhr.setRequestHeader("Authorization", "Token my-api-key-here");
  xhr.send(data);
}
</script>
curl -X POST \
  https://api.mindee.net/v1/products/mindee/passport/v1/predict \
  -H 'Authorization: Token my-api-key-here' \
  -F document=@/path/to/your/file.png
<?php

use Mindee\Client;
use Mindee\Product\Passport\PassportV1;

// Init a new client
$mindeeClient = new Client("my-api-key-here");

// Load a file from disk
$inputSource = $mindeeClient->sourceFromPath("/path/to/the/file.ext");

// Parse the file
$apiResponse = $mindeeClient->parse(PassportV1::class, $inputSource);

echo $apiResponse->document;
  • Replace my-api-key-here with your new API key, or use the "select an API key" feature and it will be filled automatically.
  • Copy and paste the sample code of your desired choice in your application, code environment, terminal etc.
  • Replace /path/to/your/file/png with the path to your passport.

❗️

Always remember to replace your API key!

  1. Run your code. You will receive a JSON response with the passport details.

API Response

Below is the full sample JSON response you get when you call the API. Since the response is quite verbose, we will walk through the fields section by section.

{
  "api_request": {
    "error": {},
    "resources": [
      "document"
    ],
    "status": "success",
    "status_code": 201,
    "url": "https://api.mindee.net/v1/products/mindee/passport/v1/predict"
  },
  "document": {
    "id": "c2651887-85f0-4890-88a1-55d1acbe1263",
    "name": "sample_passport.jpg",
    "n_pages": 1,
    "is_rotation_applied": true,
    "inference": {
      "started_at": "2021-05-06T16:37:28",
      "finished_at": "2021-05-06T16:37:29",
      "processing_time": 0.56,
      "pages": [
        {
          "id": 0,
          "orientation": {"value": 0},
          "prediction": { .. },
          "extras": {}
        }
      ],
      "prediction": { .. },
      "extras": {}
    }
  }
}

You can find the prediction within the prediction key found in two locations:

  • In document > inference > prediction for document-level predictions: it contains the different fields extracted at the document level, meaning that for multi-pages PDFs, we reconstruct a single passport object using all the pages.
  • In document > inference > pages[ ] > prediction for page-level predictions: it gives the prediction for each page independently. With images, there is only one element on this array, but with PDFs, you can find the extracted data for each PDF page.

Each predicted field may contain one or several values:

  • a confidence score
  • a polygon highlighting the information location
  • a page_id where the information was found (document level only)
{
 "prediction": {
   "birth_date": {
     "confidence": 1,
     "page_id": 0,
     "polygon": [[0.342, 0.689], [0.569, 0.689], [0.569, 0.713], [0.342, 0.713]],
     "value": "1995-05-20"
    },
    "birth_place": {
      "confidence": 0.89,
      "page_id": 0,
      "polygon": [[0.442, 0.725], [0.555, 0.725], [0.555, 0.743], [0.442, 0.743]],
      "value": "CAMTETH"
    },
    "country": {
      "confidence": 1,
      "page_id": 0,
      "polygon": [[0.509, 0.548], [0.558, 0.548], [0.558, 0.567], [0.509, 0.567]],
      "value": "GBR"
    },
    "expiry_date": {
      "confidence": 1,
      "page_id": 0,
      "polygon": [[0.34, 0.797], [0.575, 0.797], [0.575, 0.82], [0.34, 0.82]],
      "value": "2017-04-22"
    },
    "gender": {
      "confidence": 1,
      "page_id": 0,
      "polygon": [[0.054, 0.92], [0.927, 0.92], [0.927, 0.944], [0.054, 0.944]],
      "value": "M"
    },
    "given_names": {
      "confidence": 0.99,
      "page_id": 0,
      "polygon": [[0.342, 0.617], [0.435, 0.617], [0.435, 0.638], [0.342, 0.638]],
      "value": "HENERT"
    },
    "id_number": {
      "confidence": 1,
      "page_id": 0,
      "polygon": [[0.723, 0.548], [0.899, 0.548], [0.899, 0.568], [0.723, 0.568]],
      "value": "707797979"
    },
    "issuance_date": {
      "confidence": 1,
      "page_id": 0,
      "polygon": [[0.34, 0.763], [0.564, 0.763], [0.564, 0.785], [0.34, 0.785]],
      "value": "2012-04-22"
    },
    "mrz1": {
      "confidence": 0.99,
      "page_id": 0,
      "polygon": [[0.056, 0.883], [0.926, 0.883], [0.926, 0.911], [0.056, 0.911]],
      "value": "P<GBRPUDARSAN<<HENERT<<<<<<<<<<<<<<<<<<<<<<<"
    },
    "mrz2": {
      "confidence": 1,
      "page_id": 0,
      "polygon": [[0.054, 0.92], [0.927, 0.92], [0.927, 0.944], [0.054, 0.944]],
      "value": "7077979792GBR9505209M1704224<<<<<<<<<<<<<<00"
    },
    "orientation": {
      "confidence": 0.99,
      "degrees": 0
    },
    "surname": {
      "confidence": 0.99,
      "page_id": 0,
      "polygon": [[0.34, 0.581], [0.472, 0.581], [0.472, 0.603], [0.34, 0.603]],
      "value": "PUDARSAN"
    }
  }
 }

Additional Attributes

Depending on the field type specified, additional attributes can be extracted from the passport object. Using the above passport example, the following are the basic fields that can be extracted.

Birth Informations

  • birth_date: In the JSON response below, we have the value of the holder's birth date in ISO format(yyyy-mm-dd).
{
  "birth_date": {
    "confidence": 1,
    "page_id": 0,
    "polygon": [[0.341, 0.689], [0.571, 0.689], [0.571, 0.689], [0.341, 0..714]],
    "value": "1995-05-20"
  }
}
  • birth_place: In the JSON response below, we have the value of the holder's birth place.
{
  "birth_date": {
    "confidence": 0.9,
    "page_id": 0,
    "polygon": [[0.441, 0.724], [0.556, 0.724], [0.556, 0.744], [0.441, 0.744]],
    "value": "CAMTETH"
  }
}

Country

  • country: In the JSON response below, we have the value of the passport's country in ISO 3166-1 alpha-3 code format (three-letter country codes).
{
  "country": {
    "confidence": 1,
    "page_id": 0,
    "polygon": [[0.508, 0.547], [0.559, 0.547], [0.559, 0.568], [0.508, 0.568]],
    "value": "GBR"
  }
}

Date

  • expiry_date: In the JSON response below, we have the value of the passport's expiry date in ISO format(yyyy-mm-dd).
{
  "expiry_date": {
    "confidence": 1,
    "page_id": 0,
    "polygon": [[0.34, 0.796], [0.576, 0.796], [0.576, 0.82], [0.34, 0.82]],
    "value": "2017-04-22"
  }
}
  • issuance_date: In the JSON response below, we have the value of the passport's date of issuance in ISO format(yyyy-mm-dd).
{
  "issuance_date": {
    "confidence": 1,
    "page_id": 0,
    "polygon": [[0.341, 0.763], [0.565, 0.763], [0.565, 0.788], [0.34, 0.788]],
    "value": "2012-04-23"
  }
}

Gender

  • gender: In the JSON response below, we have the value of the holder's gender.
{
  "gender": {
    "confidence": 1,
    "page_id": 0,
    "polygon": [[0.054, 0.919], [0.928, 0.919], [0.928, 0.945], [0.054, 0.095]],
    "value": "M"
  }
}

ID Number

  • id_number: In the JSON response below, the value ID number is the passport's number.
{
  "id_number": {
    "confidence": 1,
    "page_id": 0,
    "polygon": [[0.723, 0.547], [0.899, 0.547], [0.899, 0.569], [0.723, 0.569]],
    "value": "707797979"
  }
}

Machine Readable Zone

  • mrz1: In the JSON response below, we have the value of the passport's machine-readable zone line 1.
{
  "mrz1": {
    "confidence": 1,
    "page_id": 0,
    "polygon": [[0.055, 0.882], [0.926, 0.882], [0.926, 0.911], [0.055, 0.911]],
    "value": "P<GBRPUDARSAN<<HENERT<<<<<<<<<<<<<<<<<<<<<<<"
  }
}
  • mrz2: In the JSON response below, we have the value of the passport's machine-readable zone line 2.
{
  "mrz2": {
    "confidence": 1,
    "page_id": 0,
    "polygon": [[0.54, 0.919], [0.928, 0.919], [0.928, 0.945], [0.054, 0.945]],
    "value": "7077979792GBR9505209M1704224<<<<<<<<<<<<<<00"
  }
}

Names

  • given_names: In the JSON response below, we have the value of the holder's given names.
{
  "given_names": {
    "confidence": 0.99,
    "page_id": 0,
    "polygon": [[0.341, 0.617], [0.435, 0.617], [0.341, 0.638], [0.341, 0.638]],
    "value": "HENERT"
  }
}
  • surname: In the JSON response below, we have the value of the holder's surname.
{
  "surname": {
    "confidence": 0.99,
    "page_id": 0,
    "polygon": [[0.34, 0.581], [0.473, 0.581], [0.473, 0.604], [0.34, 0.604]],
    "value": "PUDARSAN"
  }
}

Orientation

  • orientation: The orientation field is only available at the page level as it describes whether the page image should be rotated to be upright. The rotation value is also conveniently available in the JSON response at:
    document > inference > pages [ ] > orientation > value.
    If the page requires rotation for correct display, the orientation field gives a prediction among these 3 possible outputs:
    • 0 degree: the page is already upright
    • 90 degrees: the page must be rotated clockwise to be upright
    • 270 degrees: the page must be rotated counterclockwise to be upright
{
  "orientation": {
    "confidence": 0.99,
    "degrees": 0
  }
}

📘

All polygon fields across the JSON response are already rotated accordingly!

 

Questions?
Slack Logo Icon  Join our Slack