MRZ Scanner
A highly customizable, on-device Machine Readable Zone (MRZ) hardware scanner for Flutter, powered by Google ML Kit.
This package provides both a ready-to-use full-screen passport scanner, and highly decoupled widget building blocks so you can design your own custom scanning UI.
Features
- On-Device OCR: Fast text recognition powered by Google ML Kit without making network calls.
- Accurate Parsing: Automatically finds and parses standard 2-line TD3 MRZ codes (like passports) even with image distortion or extra text.
- Ready-to-Use UI: Includes a fully functional
PassportScannerPagefor a quick integration. - Highly Customizable: Decoupled
MrzScannerlogic controller and customizableMrzScannerOverlaywidget. Let's you design literally whatever UI you want on top of the camera stream.
Setup
Since this package uses the device camera, you need to configure permissions for both iOS and Android.
iOS Configuration
Add the following keys to your ios/Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>This app needs access to the camera to scan passport MRZ elements.</string>
Android Configuration
Ensure your android/app/build.gradle has a minimum SDK version of at least 21.
Usage
1. The Quick Start (Ready-to-use UI)
For a drop-in solution, use PassportScannerPage:
import 'package:mrz_sc/mrz_sc.dart';
void startScan(BuildContext context) async {
final MrzData? result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const PassportScannerPage(
alignPassportText: 'Align passport MRZ within the box',
passportDetectedText: 'Passport Detected!',
processingErrorText: 'Processing Error',
),
),
);
if (result != null) {
print('Scanned Document: ${result.documentNumber}');
print('First Name: ${result.givenNames}');
}
}
2. Custom Layouts
If you want to build your own custom interface (e.g., adding specific buttons, different overlay shapes, or embedding it as a smaller widget inside another page instead of fullscreen), compose the MrzScanner component yourself:
import 'package:mrz_sc/mrz_sc.dart';
class MyCustomScanner extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MrzScanner(
onSuccess: (mrzData) {
Navigator.pop(context, mrzData);
},
onError: (exception) {
print(exception);
},
builder: (context, isDetecting) {
return Stack(
children: [
// Adds the dimmed background and cutout box
MrzScannerOverlay(
borderColor: isDetecting ? Colors.yellow : Colors.white,
),
// Your custom UI here
Positioned(
bottom: 50,
child: Text('Scanning...'),
)
]
);
},
);
}
}