Docovue
Privacy-first document scanning and OCR plugin for Flutter with smart auto-capture and anti-spoofing detection. Supports 12+ document types with 100% on-device processing β no cloud, no network calls, no data leaks.
β¨ Features
π― Smart Auto-Capture
- Automatic document detection with edge recognition
- Live bounding box with color-coded feedback (White β Orange β Green)
- Hands-free capture β detects document and captures automatically
- Front & back camera support with seamless switching
π‘οΈ Anti-Spoofing / Liveness Detection
- Prevents fraud β detects photos of photos, screen displays, photocopies
- Blur detection β ensures sharp, focused images
- Texture analysis β verifies physical document properties
- Reflection detection β identifies screen glare patterns
π Supported Documents
| Document Type | Extraction | Output Fields |
|---|---|---|
| Indian Documents | ||
| Aadhaar Card | βββββ Full | Number, Name, DOB |
| PAN Card | βββββ Full | Number, Name, DOB |
| Voter ID | ββββ Good | ID Number, Name, Age |
| Driving License | ββββ Good | License No, Name, DOB |
| Global Documents | ||
| Passport | βββ Generic | Number, Name, DOB |
| National ID | βββ Generic | Top 3 fields |
| Financial | ||
| Credit/Debit Cards | βββββ Full | Masked Number, Expiry, Name |
| Invoices | βββ Generic | Invoice No, Amount, Date |
| Receipts | βββ Generic | Receipt No, Amount, Date |
| Healthcare | ||
| Insurance Cards | βββ Generic | Policy No, Name, Validity |
| Lab Reports | βββ Generic | Patient, Report No, Date |
π Privacy & Compliance
- β 100% On-Device β All OCR runs locally (ML Kit on Android, Vision on iOS)
- β Zero Network Calls β No data sent to cloud services
- β No Data Storage β Plugin doesn't cache or persist data
- β GDPR Ready β Built-in consent dialogs
- β HIPAA Compatible β Suitable for healthcare apps (with proper implementation)
- β PCI-DSS Friendly β Masks sensitive card data
π Quick Start
Installation
Add to your pubspec.yaml:
dependencies:
docovue: ^1.0.0
Run:
flutter pub get
Platform Setup
Android
Add to android/app/build.gradle:
android {
compileSdkVersion 34
defaultConfig {
minSdkVersion 21 // ML Kit requires API 21+
}
}
dependencies {
implementation 'com.google.mlkit:text-recognition:16.0.0'
}
Add to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
iOS
Add to ios/Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>This app needs camera access to scan documents</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs photo library access to import documents</string>
Minimum iOS version: 11.0
π Usage
Basic Example β Auto-Capture Scanner
import 'package:flutter/material.dart';
import 'package:docovue/docovue.dart';
class DocumentScannerPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Scan Document')),
body: DocovueScannerWidget(
allowedTypes: const {
DocovueDocumentType.aadhaar,
DocovueDocumentType.pan,
DocovueDocumentType.creditCard,
},
config: const DocovueScannerConfig(
autoCapture: true, // Enable smart auto-capture
verifyOriginal: true, // Enable anti-spoofing
confidenceThreshold: 0.70,
),
onResult: (result) {
result.when(
success: (document) {
// Get top 3 extracted fields
final summary = document.toSummary(maxFields: 3);
print('Extracted: $summary');
Navigator.pop(context, document);
},
unclear: (rawText, confidence) {
print('Unclear (${(confidence * 100).toFixed(0)}%): $rawText');
},
error: (error) {
print('Error: ${error.message}');
},
);
},
),
);
}
}
Scan from File (Gallery/Existing Image)
import 'package:image_picker/image_picker.dart';
import 'package:docovue/docovue.dart';
Future<void> scanFromGallery() async {
// Pick image
final picker = ImagePicker();
final image = await picker.pickImage(source: ImageSource.gallery);
if (image == null) return;
// Scan document
final result = await DocovueScanner.scanDocumentFromFile(
imagePath: image.path,
allowedTypes: const {
DocovueDocumentType.aadhaar,
DocovueDocumentType.passport,
},
config: const DocovueScannerConfig(
verifyOriginal: false, // Skip liveness for gallery images
confidenceThreshold: 0.75,
),
);
result.when(
success: (document) {
final fields = document.toSummary(maxFields: 3);
print('Success: $fields');
},
unclear: (rawText, confidence) {
print('Could not classify document');
},
error: (error) {
print('Scan error: ${error.message}');
},
);
}
Configuration Options
// High-security mode (recommended for financial/ID documents)
DocovueScannerConfig.highSecurity()
// β’ verifyOriginal: true (anti-spoofing enabled)
// β’ confidenceThreshold: 0.90
// β’ maskSensitiveDataInLogs: true
// Healthcare mode (PHI/HIPAA)
DocovueScannerConfig.healthcare()
// β’ verifyOriginal: true
// β’ confidenceThreshold: 0.85
// Financial mode (PCI-DSS)
DocovueScannerConfig.financial()
// β’ verifyOriginal: true (fraud prevention)
// β’ confidenceThreshold: 0.95
// Development mode
DocovueScannerConfig.development()
// β’ verifyOriginal: false
// β’ debugMode: true
// Custom configuration
const DocovueScannerConfig(
autoCapture: true, // Smart auto-capture
verifyOriginal: true, // Anti-spoofing
confidenceThreshold: 0.70, // 70% minimum confidence
showConsentDialog: true, // GDPR consent
maskSensitiveDataInLogs: true, // Privacy protection
debugMode: false, // Debug logs
)
π¨ UI Components
Auto-Capture Flow
1. User opens scanner
ββ WHITE bounding box: "Position document"
2. Document detected
ββ ORANGE bounding box: "Hold steady... 1/4"
ββ Progress counter: 2/4 β 3/4 β 4/4
3. Document stable
ββ GREEN bounding box: "Capturing!"
ββ Auto-captures (2 seconds total)
4. Liveness check (if enabled)
ββ "Verifying authenticity..."
ββ β
Original β Continue to OCR
ββ β Fake β "Original ID Required" error
5. OCR Processing
ββ Extracts text using ML Kit
ββ Classifies document type
ββ Extracts structured fields
6. Result
ββ SUCCESS: Returns top 3 fields
ββ UNCLEAR: Shows tips + raw OCR text
ββ ERROR: Shows error message
Camera Controls
- π Camera Switch: Toggle between front/back camera
- βͺ AUTO Indicator: Shows progress (1/4, 2/4, 3/4, 4/4)
- π‘ Flash: Toggle flash/torch (back camera only)
π§ Advanced Usage
Extract Specific Document Fields
result.when(
success: (document) {
document.map(
aadhaar: (aadhaar) {
print('Aadhaar: ${aadhaar.maskedAadhaarNumber}');
print('Name: ${aadhaar.name}');
print('DOB: ${aadhaar.dateOfBirth}');
},
pan: (pan) {
print('PAN: ${pan.maskedPanNumber}');
print('Name: ${pan.name}');
},
card: (card) {
print('Card: ${card.maskedCardNumber}');
print('Expiry: ${card.expiryDate}');
print('Holder: ${card.cardHolderName}');
},
passport: (passport) => handlePassport(passport),
generic: (generic) {
// Generic extraction for other document types
print('Fields: ${generic.detectedFields}');
},
);
},
);
Validation Utilities
import 'package:docovue/docovue.dart';
// Validate extracted data
bool isValidAadhaar = isValidAadhaar('123456789012');
bool isValidPAN = isValidPan('ABCDE1234F');
bool isValidCard = isValidCardNumber('4111111111111111');
// Mask sensitive data
String masked = maskCardNumber('4111111111111111');
// Output: "**** **** **** 1111"
String maskedAadhaar = maskAadhaarNumber('123456789012');
// Output: "XXXX-XXXX-9012"
π‘οΈ Security Best Practices
Data Handling
// β
DO: Use masked data in logs
print('Card scanned: ${document.maskedCardNumber}');
// β DON'T: Log full sensitive data
print('Card: ${document.fullCardNumber}'); // Bad!
// β
DO: Enable data masking in production
DocovueScannerConfig(
maskSensitiveDataInLogs: true, // Always true in production
)
// β
DO: Enable anti-spoofing for ID/financial docs
DocovueScannerConfig(
verifyOriginal: true, // Prevents photo-of-photo attacks
)
Compliance
GDPR β Show consent dialog:
DocovueScannerConfig(
showConsentDialog: true,
consentDialogTitle: 'Document Processing',
consentDialogMessage: 'We process your document locally...',
)
HIPAA β Use healthcare mode:
DocovueScannerConfig.healthcare()
PCI-DSS β Never store full card numbers:
// β
Store masked version only
final safeData = card.toPciCompliantJson(); // Excludes full PAN
π Performance
- OCR Speed: 1-3 seconds per document
- Auto-Capture: 2 seconds from detection to capture
- Memory: ~50-100 MB during processing
- Battery: Minimal impact (camera + ML Kit)
π Troubleshooting
"Unclear Document" Issues
Causes:
- Poor lighting (too dark/bright)
- Document too far/close
- Blurry image (camera not focused)
- Low contrast document
Solutions:
// Lower confidence threshold
DocovueScannerConfig(
confidenceThreshold: 0.60, // Default: 0.70
)
// Enable debug mode to see raw OCR text
DocovueScannerConfig(
debugMode: true,
)
Auto-Capture Not Triggering
Check:
- Lighting is adequate
- Document fills 50-70% of bounding box
- Holding device steady for 2 seconds
autoCapture: truein config
Liveness Detection Too Strict
// Disable for testing
DocovueScannerConfig(
verifyOriginal: false,
)
// Or use in specific scenarios only
verifyOriginal: documentType == DocovueDocumentType.creditCard,
πΊοΈ Roadmap
iOS implementation (currently Android-optimized)Enhanced MRZ parsing for passportsBatch document scanningCustom document type trainingImproved low-light performance
π License
MIT License - see LICENSE file for details.
π Support
Contact
- Developer: Praveen
- Email: praveenvenkat042k@gmail.com
- Portfolio: praveen-dev.space
- Issues: GitHub Issues
Contributing
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Commit your changes
- Push to the branch
- Open a Pull Request
β οΈ Disclaimer
Docovue is not a legally certified KYC solution. OCR accuracy is best-effort. Always:
- Validate extracted data before use
- Implement proper error handling
- Follow compliance requirements for your jurisdiction
- Use human review for critical workflows
Made with β€οΈ for privacy-conscious developers
Privacy-first document scanning and OCR plugin for Flutter. Supports Aadhaar, PAN, passports, credit cards, and more with 100% on-device processing.
π Privacy & Compliance First
Docovue is designed from the ground up for privacy and compliance:
- π« No Network Calls: All OCR and processing happens on-device
- π No Data Storage: Plugin doesn't persist any document data
- π± No Analytics: Zero telemetry or tracking
- π‘οΈ Compliance Ready: Built for PHI/HIPAA, GDPR, and PCI-DSS environments
β¨ Features
Supported Documents
| Document Type | India | Global | Extraction Quality | Output Fields |
|---|---|---|---|---|
| Government & Identity | ||||
| Aadhaar Card | β | - | βββββ Full | Number, Name, DOB |
| PAN Card | β | - | βββββ Full | Number, Name, DOB |
| Voter ID | β | - | ββββ Good | ID Number, Name, Age |
| Driving License | β | β | ββββ Good | License No, Name, DOB |
| Passport | β | β | βββ Generic | Number, Name, DOB |
| National ID | - | β | βββ Generic | Top 3 detected fields |
| Financial | ||||
| Credit Cards | β | β | βββββ Full | Number, Expiry, Name |
| Debit Cards | β | β | βββββ Full | Number, Expiry, Name |
| Invoices | β | β | βββ Generic | Invoice No, Amount, Date |
| Receipts | β | β | βββ Generic | Receipt No, Amount, Date |
| Healthcare | ||||
| Insurance Cards | β | β | βββ Generic | Policy No, Name, Validity |
| Lab Reports | β | β | βββ Generic | Patient, Report No, Date |
Legend:
βββββ Full Support: Dedicated extraction with high-confidence field-level validation
ββββ Good Support: Returns as Generic with strong pattern matching
βββ Generic Support: Returns top 3 detected fields from OCR text
Key Features
- π― High-Level API: Simple one-line document scanning
- π§ Low-Level API: Advanced OCR and classification control
- π± Live Camera Widget: Auto-capture with bounding box guides
- π‘οΈ Anti-Spoofing: Liveness detection to verify physical documents
- π Smart Output: Returns only top 3 most important fields
- β Smart Validation: Luhn, Verhoeff, and format validation
- π¨ Form Binding: Auto-populate form controllers
- π Multi-Language: Support for English, Hindi, and more
- β‘ Fast Processing: Optimized on-device OCR
π Quick Start
Installation
Add to your pubspec.yaml:
dependencies:
docovue: ^1.0.0
Basic Usage
import 'package:docovue/docovue.dart';
// Simple document scanning
final result = await DocovueScanner.scanDocument(
context: context,
allowedTypes: const {
DocovueDocumentType.aadhaar,
DocovueDocumentType.pan,
DocovueDocumentType.creditCard,
},
config: const DocovueScannerConfig(
showConsentDialog: true,
maskSensitiveDataInLogs: true,
),
);
// Handle results
result.when(
success: (document) {
document.map(
aadhaar: (aadhaar) {
print('Aadhaar: ${aadhaar.maskedAadhaarNumber}');
print('Name: ${aadhaar.name}');
// Auto-populate form
aadhaar.bindToForm(
nameController: nameController,
aadhaarController: aadhaarController,
dobController: dobController,
);
},
pan: (pan) => handlePanCard(pan),
card: (card) => handleCreditCard(card),
passport: (passport) => handlePassport(passport),
generic: (generic) => handleGenericDocument(generic),
);
},
unclear: (rawText, confidence) {
// Show manual review UI
showManualReview(rawText, confidence);
},
error: (error) {
// Handle error
showError(error.message);
},
);
Using the Scanner Widget
// Live camera scanner with auto-capture and liveness detection
DocovueScannerWidget(
allowedTypes: const {
DocovueDocumentType.aadhaar,
DocovueDocumentType.pan,
DocovueDocumentType.creditCard,
},
config: const DocovueScannerConfig(
verifyOriginal: true, // Enable anti-spoofing
autoCapture: true, // Enable auto-capture
confidenceThreshold: 0.85,
),
onResult: (result) {
result.when(
success: (document) {
// Get only top 3 fields
final summary = document.toSummary(maxFields: 3);
print(summary); // {"number": "XXXX-1234", "name": "John", "dob": "01/01/1990"}
},
unclear: (rawText, confidence) => handleUnclear(),
error: (error) => handleError(error),
);
},
)
Scan from File (Gallery/Existing Image)
// Process an existing image file
final result = await DocovueScanner.scanDocumentFromFile(
imagePath: '/path/to/image.jpg',
allowedTypes: const {
DocovueDocumentType.aadhaar,
DocovueDocumentType.passport,
DocovueDocumentType.invoice,
},
config: const DocovueScannerConfig(
verifyOriginal: false, // Skip liveness check for gallery images
confidenceThreshold: 0.75,
),
);
result.when(
success: (document) {
// Returns only top 3 most important fields
final topFields = document.toSummary(maxFields: 3);
print('Extracted: $topFields');
},
unclear: (rawText, confidence) {
print('Could not classify document (${(confidence * 100).toFixed(0)}% confidence)');
},
error: (error) {
print('Scan error: ${error.message}');
},
);
π Usage
Configuration Options
// High-security configuration (recommended for production)
DocovueScannerConfig.highSecurity()
// β
verifyOriginal: true (liveness detection enabled)
// β
confidenceThreshold: 0.90
// β
maskSensitiveDataInLogs: true
// Healthcare/PHI environments
DocovueScannerConfig.healthcare()
// β
verifyOriginal: true
// β
confidenceThreshold: 0.85
// Financial/PCI environments
DocovueScannerConfig.financial()
// β
verifyOriginal: true (anti-spoofing for card fraud)
// β
confidenceThreshold: 0.95
// Development configuration
DocovueScannerConfig.development()
// β οΈ verifyOriginal: false (for testing)
// β οΈ debugMode: true
// Custom configuration
const DocovueScannerConfig(
showConsentDialog: true,
maskSensitiveDataInLogs: true,
debugMode: false,
autoCapture: true,
verifyOriginal: true, // Enable liveness detection
confidenceThreshold: 0.8,
allowedLanguages: ['en', 'hi'],
captureTimeout: Duration(seconds: 10),
)
Low-Level API
For advanced use cases, you can use the low-level API:
// Extract text from image
final textBlocks = await DocovueScanner.extractTextFromImage(
DocovueImageSource.camera,
);
// Classify document type
final documentType = await DocovueScanner.classifyDocument(textBlocks);
// Extract structured data
final document = await DocovueScanner.extractDocumentData(
documentType,
textBlocks,
);
Validation Utilities
// Validate document numbers
bool isValidAadhaar = isValidAadhaar('123456789012');
bool isValidPAN = isValidPan('ABCDE1234F');
bool isValidCard = isValidCardNumber('4111111111111111');
// Mask sensitive data
String masked = maskCardNumber('4111111111111111'); // **** **** **** 1111
String maskedAadhaar = maskAadhaarNumber('123456789012'); // XXXX-XXXX-9012
π Security & Privacy
What Docovue Does
β
On-Device Processing: All OCR happens locally using ML Kit (Android) and Vision (iOS)
β
No Network Calls: Zero HTTP requests or external API calls
β
No Data Persistence: Plugin doesn't store images or extracted data
β
Configurable Logging: Sensitive data masking in logs
β
Consent Management: Built-in consent dialogs for GDPR compliance
What Docovue Does NOT Do
β No Cloud OCR: No data sent to Google, AWS, or other cloud services
β No Analytics: No crash reporting, usage tracking, or telemetry
β No Background Processing: No data processing when app is backgrounded
β No Caching: No temporary storage of sensitive document data
Your Responsibilities
As the app developer, you are responsible for:
- Data Handling: How you store, process, and transmit extracted data
- User Consent: Obtaining proper consent for document processing
- Compliance: Ensuring your app meets relevant regulations (GDPR, HIPAA, PCI-DSS)
- Security: Implementing proper encryption and access controls for sensitive data
π₯ PHI / HIPAA Considerations
When processing healthcare documents:
// Use healthcare-optimized configuration
final config = DocovueScannerConfig.healthcare();
// Handle PHI data appropriately
result.when(
success: (document) {
// Ensure PHI is handled according to HIPAA requirements
// - Encrypt data at rest and in transit
// - Implement proper access controls
// - Maintain audit logs
// - Follow minimum necessary principle
},
);
Important: Docovue provides the tools for secure document scanning, but HIPAA compliance requires proper implementation throughout your entire application and infrastructure.
π GDPR Considerations
For GDPR compliance:
const config = DocovueScannerConfig(
showConsentDialog: true, // Required for GDPR
consentDialogTitle: 'Document Processing Consent',
consentDialogMessage: 'Your custom GDPR-compliant consent message...',
);
GDPR Rights: Your app must handle user rights including access, rectification, erasure, and data portability for any extracted document data you store.
π³ PCI-DSS & Card Scanning
When scanning payment cards:
// Use financial-optimized configuration
final config = DocovueScannerConfig.financial();
result.when(
success: (document) {
document.map(
card: (card) {
// Use PCI-compliant data handling
final safeData = card.toPciCompliantJson(); // Excludes full PAN
// Never log full card numbers
print('Card: ${card.maskedCardNumber}');
// For PCI compliance:
// - Never store full PAN unless you're PCI-compliant
// - Use tokenization for card storage
// - Implement proper network security
// - Follow PCI-DSS requirements
},
);
},
);
Warning: Card scanning is for UI convenience only. If you store or process card details, you must ensure your backend and application are PCI-DSS compliant.
π οΈ Platform Setup
Android
Add to android/app/build.gradle:
android {
compileSdkVersion 34
defaultConfig {
minSdkVersion 21 // ML Kit requires API 21+
}
}
dependencies {
implementation 'com.google.mlkit:text-recognition:16.0.0'
}
Add to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" android:required="true" />
iOS
Add to ios/Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>This app uses the camera to scan documents for data extraction.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app accesses your photo library to scan documents for data extraction.</string>
Minimum iOS version: 11.0 (required for Vision framework)
π§ͺ Testing
// Unit tests for validators
test('should validate Aadhaar numbers', () {
expect(isValidAadhaar('123456789012'), isTrue);
expect(isValidAadhaar('000000000000'), isFalse);
});
// Integration tests
testWidgets('should scan document successfully', (tester) async {
await tester.pumpWidget(MyApp());
// Simulate document scanning
final result = await DocovueScanner.scanDocument(
context: tester.element(find.byType(MaterialApp)),
allowedTypes: {DocovueDocumentType.aadhaar},
);
expect(result.isSuccess, isTrue);
});
π§ Limitations
- Accuracy: OCR accuracy depends on image quality and document condition
- Languages: Limited language support (primarily English and Hindi)
- Document Variants: May not recognize all regional document variations
- Real-time: Not optimized for real-time video processing
- Offline Only: No cloud-based accuracy improvements
πΊοΈ Roadmap
Version 1.1
Enhanced MRZ parsing for passportsSupport for more Indian regional documentsImproved address parsingBank statement support
Version 1.2
Real-time document detectionCustom document type trainingBatch processing supportEnhanced error recovery
Version 2.0
Video-based scanningDocument authenticity checksAdvanced image preprocessingCustom ML model support
π€ Contributing
We welcome contributions! Please see our Contributing Guide for details.
Development Setup
git clone https://github.com/prawinn04/docovue.git
cd docovue
flutter pub get
cd example
flutter run
π License
This project is licensed under the MIT License - see the LICENSE file for details.
β οΈ Disclaimer
Docovue is not a legally certified KYC solution. Extraction accuracy is best effort and human review is recommended for critical workflows. Always validate extracted data before using it in production systems.
π Support
- π Documentation
- π Issue Tracker
- π¬ Discussions
- π§ Email Support
Made with β€οΈ for privacy-conscious developers
Libraries
- docovue
- Privacy-first document scanning and OCR plugin for Flutter.