scanid library
Free, open-source on-device OCR, barcode scanning, and document-edge detection, plus AAMVA driver's-license and ICAO MRZ decoders.
Everything runs on-device (Apple Vision on iOS, ML Kit on Android) — nothing is ever sent to a server, and there's no license fee.
Typical usage:
const capture = PlatformCaptureService();
final payloads = await capture.recognizeBarcodes(imageBytes);
final fields = payloads.map(Aamva.parse).firstWhere(
(f) => f != null,
orElse: () => null,
);
final ocr = await capture.recognize(imageBytes);
final mrz = Mrz.parse(ocr.fullText);
Classes
- Aamva
- Parses the AAMVA payload encoded in the PDF417 barcode on the back of a US/Canada driver license or state ID into structured fields. Like the MRZ, the barcode encodes the data exactly (3-letter element codes, each value newline-terminated) — far more reliable than OCR of the printed front. The barcode bytes come from a scanner (CaptureService.recognizeBarcodes); this just decodes the payload string. Returns null if it isn't an AAMVA payload.
- CaptureService
- On-device OCR, barcode scanning, and document-edge detection. Nothing ever leaves the device — Apple Vision (iOS) / ML Kit (Android) run locally, and the only thing that crosses the platform channel is the image bytes in and recognized data out.
- DocumentRect
-
A detected document's bounding box, normalized to
[0,1]in image space with a top-left origin. Used only as the initial rectangle for a confirm- crop UI — the caller should always let the user adjust/accept it, so a loose detection is fine. - FakeCaptureService
- Deterministic OCR for tests + simulators: returns canned results, either a single fixed result or one built from raw lines. No native dependency.
- Mrz
-
Parses the ICAO 9303 Machine Readable Zone — the
<<<lines at the bottom of a passport — into structured, check-digit-validated fields. The MRZ encodes the data exactly, so this is far more reliable than guessing fields from the visual text (and the check digits catch OCR slips). Handles TD3 (passport, 2×44), TD1 (ID card, 3×30), and TD2 (2×36). parse returns null when no MRZ is found. - OcrBox
-
A recognized text element's bounding box, normalized to
[0,1]in image space with a top-left origin — so it can be overlaid on the displayed image regardless of scale. - OcrLine
- One recognized line of text from on-device OCR, with its position on the image (box) when the platform provides it.
- OcrResult
- The result of recognizing text in an image — all produced on-device.
- PlatformCaptureService
-
Calls the native OCR/barcode/document-detect plugin over a MethodChannel.
The native side (
ScanidPlugin.swift/ScanidPlugin.kt) registersscanid/captureand returns a list of{text, confidence, box}maps forrecognizeText, a list of payload strings forrecognizeBarcodes, and a{left, top, width, height}map or null fordetectDocumentRect.