card_passbook_scanner
Live camera OCR for payment cards and Indian bank passbooks using Google ML Kit on-device text recognition, with manual parsers (no third-party parsing libraries).
Screenshots
| Card mode | Passbook mode |
|---|---|
![]() |
![]() |
Features
- Card: live scan until Luhn-valid PAN + expiry are read; masked PAN in the UI.
- Passbook: live scan until account number + IFSC are read.
- Manual
parseCard/parsePassbook, Luhn check, IFSC validation, account scoring. parsePassbookWithMetadata()for JSON export with confidence scores.- Riverpod MVVM; drop-in
CardPassbookScannerPage.
Supported platforms
| Platform | Supported |
|---|---|
| Android | Yes (API 21+, compileSdk 36+) |
| iOS | Yes (camera permission required) |
| Web | No |
| Desktop | No |
Installation
Add the package to your app:
dependencies:
card_passbook_scanner: ^1.0.0
Then run:
flutter pub get
Wrap your app with ProviderScope (Riverpod is required for the built-in scanner page).
Platform setup
Android
- Set
compileSdkto 36 or higher inandroid/app/build.gradle(required bycamera). - Add the ML Kit OCR model flag in
android/app/src/main/AndroidManifest.xmlinside<application>:
<meta-data
android:name="com.google.mlkit.vision.DEPENDENCIES"
android:value="ocr" />
- Release builds: if R8/ProGuard strips optional ML Kit script classes, add rules like the example app:
-dontwarn com.google.mlkit.vision.text.chinese.**
-dontwarn com.google.mlkit.vision.text.devanagari.**
-dontwarn com.google.mlkit.vision.text.japanese.**
-dontwarn com.google.mlkit.vision.text.korean.**
iOS
Add a camera usage description in ios/Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>Camera access is required to scan cards and passbooks.</string>
User guide — how to use the scanner
1. Add the scanner to your app
import 'package:card_passbook_scanner/card_passbook_scanner.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
runApp(
const ProviderScope(
child: MaterialApp(
home: CardPassbookScannerPage(),
),
),
);
}
Or navigate to it from any route:
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (_) => const CardPassbookScannerPage(),
),
);
2. Choose scan mode
On the home screen, use the Card / Passbook toggle at the top:
- Card — for debit/credit cards. The scan completes when a valid card number (Luhn check) and expiry date are detected.
- Passbook — for Indian bank passbooks. The scan completes when account number and IFSC code are detected.
3. Start a live scan
- Tap Live camera scan.
- Allow camera permission when prompted.
- Align the document inside the green on-screen frame.
- Hold the phone steady in good lighting. The app reads frames continuously (about every 450 ms) until required fields are found.
- When successful, the live view closes and you return to the results screen with a captured preview image.
4. Read the results
Card mode shows:
| Field | Description |
|---|---|
| Card number | Masked as XXXX XXXX XXXX 1234 (last four digits only) |
| Expiry date | MM/YY when found near Valid Thru / Good Thru / EXP. labels |
| Card holder name | Best-effort from OCR lines |
Passbook mode shows:
| Field | Description |
|---|---|
| Account holder | Name line from passbook OCR |
| Account number | Scored from keyword lines (Account No, A/C No, etc.) |
| IFSC code | Validated against AAAA0XXXXXX format |
5. Scan again or switch mode
- Tap the refresh icon (top right) to clear results and start over.
- Switch Card / Passbook before scanning — mode change clears previous results.
Tips for better OCR
- Use bright, even lighting; avoid glare on embossed card numbers.
- Fill the frame with the card or passbook text you care about.
- For cards, include the Valid Thru / Expiry line in view.
- For passbooks, include both the account number line and IFSC line.
- If scan fails, tap refresh and try a slightly different angle or distance.
Developer usage
Drop-in scanner page
Use CardPassbookScannerPage when you want the full UI (mode toggle, live camera, results).
Parsers only (bring your own OCR)
If you already have ML Kit or another OCR source, call the parsers on raw text:
import 'package:card_passbook_scanner/card_passbook_scanner.dart';
final card = parseCard(mlKitRawText);
print(card.maskedCardNumber);
print(card.hasCardNumberAndExpiry); // true when live scan would stop
final passbook = parsePassbookWithMetadata(mlKitRawText);
print(passbook.toStructuredJson()); // fields + confidence map
Custom UI with package view models
import 'package:card_passbook_scanner/card_passbook_scanner.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
// scannerViewModelProvider + ScanMode for your own layout
final state = ref.watch(scannerViewModelProvider);
ref.read(scannerViewModelProvider.notifier).setMode(ScanMode.passbook);
Example app
Run the bundled example on a physical device (camera required):
cd example
flutter pub get
flutter run
Build a release APK from the example:
cd example
flutter build apk
Tests
flutter test
Assumptions
- Card numbers: 13–19 digits and must pass Luhn validation.
- Expiry:
MM/YY,MM-YY, or near labels (Valid Thru, Good Thru, Expiry Date, split EXP./DATE). - OCR digit cleanup: common misreads (O→0, I/L→1, S→5, etc.).
- IFSC:
^[A-Z]{4}0[A-Z0-9]{6}$. - Account numbers: scored by keywords; phone/date-like lines are penalized.
Limitations
- No backend — all OCR and parsing run on-device.
- Camera only — no gallery upload in the built-in UI.
- OCR quality depends on lighting, focus, and document condition.
- Passbook layouts vary by bank; scoring heuristics may need tuning for unusual formats.
License
MIT — see LICENSE.
Libraries
- card_passbook_scanner
- Live camera OCR for payment cards and Indian bank passbooks (ML Kit + manual parsers).

