NEWSMRZ Scanner is now part of barKoder.What it means for you →

DOCUMENTATION

C API reference

Desktop and server

Documentation / Desktop and server

On this page

The C API in mrzscanner.h is the same in the Linux and Windows libraries (and inside every other package). No function throws; failures are reported as mrz_status.

The licence

int32_t mrz_register_license(const char *key, const char *app_id, const char *device_model, int32_t platform);

platform: 1 iOS, 2 Android, 4 desktop / server, 8 web. Returns 0 on success, -2 invalid key, -3 other app, -4 other device, -5 expired, -6 other platform. The check is offline and process-wide. Without a licence, results come back with masked fields.

A scanner

mrz_scanner *mrz_scanner_create(const char *tessdata_dir, mrz_status *status);
void mrz_scanner_destroy(mrz_scanner *scanner);
void mrz_scanner_reset(mrz_scanner *scanner);

tessdata_dir is the folder with mrz.traineddata; it must be named tessdata. A scanner is not thread-safe: use one per thread. mrz_scanner_reset starts a new camera stream on the same scanner.

Images and frames

typedef struct { const uint8_t *pixels; int32_t width, height, stride, format; } mrz_image;

mrz_status mrz_scan_image(mrz_scanner *s, const mrz_image *image, const mrz_scan_options *options, mrz_result **result);
mrz_status mrz_scan_frame(mrz_scanner *s, const mrz_image *image, const mrz_scan_options *options, mrz_result **result);
  • format: MRZ_PIXEL_RGBA8, BGRA8, RGB8, BGR8 or GRAY8. stride: bytes per row, 0 for packed rows.
  • mrz_scan_image reads a still image (photo, scan) with several passes. The same image and options always give the same result.
  • mrz_scan_frame reads one camera frame. Call it on consecutive frames: a read is returned once the same MRZ came from frame_confirmations frames (default 2).
  • Both return MRZ_OK with a result, or MRZ_NOT_FOUND. Release a result with mrz_result_free.

Options

options may be NULL. Otherwise fill it with mrz_scan_options_init(&options) and change what you need:

Field Default
document_types MRZ_DOC_ALL MRZ_DOC_PASSPORT, MRZ_DOC_ID, MRZ_DOC_VISA (a mask)
roi_x, roi_y, roi_width, roi_height 0, 0, 100, 100 region of interest in percent: only an MRZ inside it is read
upside_down 0 also try the image turned 180 degrees
rotation 0 degrees (0, 90, 180, 270) the image must be turned to be upright, as camera APIs report
frame_confirmations 2 frames that must agree before mrz_scan_frame returns a read; 1: the first read
validate_country_codes 1 issuing state and nationality must be known country codes

Results

const char *mrz_result_text(const mrz_result *r);              /* the MRZ lines, joined by '\n' */
const char *mrz_result_json(const mrz_result *r);              /* the parsed fields */
int32_t mrz_result_check_digits_valid(const mrz_result *r);    /* 1 if every check digit matches */
int32_t mrz_result_corners(const mrz_result *r, int32_t xy[8]);

The strings belong to the result. The corners are in image pixels, top left first, clockwise.

The MRZ as an image

mrz_status mrz_isolate_size(const int32_t corners[8], int32_t height, int32_t *width);
mrz_status mrz_isolate(const mrz_image *image, const int32_t corners[8], int32_t width, int32_t height, uint8_t *out, int32_t stride);

The MRZ alone, straightened and scaled to height pixels, in the pixel format of image.

Following the MRZ on screen

For an overlay at display rate: mrz_scanner_frame_corners gives where the last frame's MRZ is, even before it is read; a mrz_tracker (mrz_tracker_create, mrz_tracker_set, mrz_tracker_track) finds it again in later frames in a few milliseconds. mrz_scanner_document_id changes when a different document comes into view.

Version

mrz_version() returns the core's version, mrz_status_string(status) a status as text.

Updated Oct 24, 2026 ยท Questions? Ask us