Skip to main content
Version: v8001

Scan a double-sided document

BlinkID uses automatic scanning mode by default. In this mode, the SDK detects whether a document has a back side with extractable data and, if so, prompts the user to flip the document before completing the session. No special configuration is needed for this to work.

This article covers how to configure and read results for two-sided scanning, and how to control whether the back side is always required.

Default behavior​

With automatic mode, the scanning flow is:

  1. The user scans the front of the document.
  2. The SDK detects if the document has a back side with extractable data.
  3. If it does, the user is prompted to flip the document.
  4. After the back is scanned, the SDK merges data from both sides into a single result.

If the back side has no extractable data, the SDK skips it by default (controlled by secondSideWithNoExtractableDataSkipped, which defaults to true).

Initialize with automatic mode​

Since automatic is the default, no configuration is required for basic double-sided scanning.

import { createBlinkId } from "@microblink/blinkid";

const blinkId = await createBlinkId({
licenseKey: "your-license-key",
// scanningMode defaults to "automatic"
});

blinkId.addOnResultCallback((result) => {
console.log("Result:", result);
void blinkId.destroy();
});

Always scan the back side​

By default, the SDK skips the back side if it contains no extractable data. Set secondSideWithNoExtractableDataSkipped to false to always require a back-side scan, regardless of whether any data can be extracted from it. This setting requires automatic scanning mode.

import { createBlinkId } from "@microblink/blinkid";

const blinkId = await createBlinkId({
licenseKey: "your-license-key",
scanningSettings: {
documentCaptureModule: {
secondSideWithNoExtractableDataSkipped: false,
},
},
});

Read results from both sides​

The top-level result object contains aggregated fields merged from all scanned sides. For side-specific data (images, raw MRZ, VIZ), use subResults.

blinkId.addOnResultCallback((result) => {
// Aggregated fields from both sides
console.log("First name:", result.firstName?.latin?.value);
console.log("Last name:", result.lastName?.latin?.value);
console.log("Date of expiry:", result.dateOfExpiry?.originalString?.latin?.value);

// Side-specific data
const front = result.subResults[0];
const back = result.subResults[1]; // undefined if only one side was scanned

console.log("Front VIZ:", front.viz);
console.log("Back barcode:", back?.barcode);

void blinkId.destroy();
});

Check data consistency between sides​

When both sides are scanned, the result includes a dataMatchResult field that indicates whether data extracted from the front and back sides is consistent.

blinkId.addOnResultCallback((result) => {
const dataMatch = result.dataMatchResult;
if (dataMatch) {
console.log("Data match state:", dataMatch.statePerField);
}
void blinkId.destroy();
});