Fast, native React Native document scanner for iOS and Android using Apple VisionKit (iOS) and Google ML Kit (Android). Features automatic document detection, edge/perspective correction, multi‑page scanning, configurable image quality, optional Base64, and support for the React Native New Architecture on ios and android.
| iOS Demo | Android Demo |
|---|---|
![]() |
![]() |
| FileNest AI - Docs Organizer | MyGarage - CarDocs & History |
|---|---|
![]() |
![]() |
Keywords: React Native document scanner, VisionKit document scanner, ML Kit document scanner, scan documents React Native, edge detection, perspective correction, multi‑page scanner
npm install @dariyd/react-native-document-scanner
or with yarn:
yarn add @dariyd/react-native-document-scanner
npm install https://github.com/dariyd/react-native-document-scanner.git
or
yarn add https://github.com/dariyd/react-native-document-scanner.git
cd ios && pod install
No additional steps required. The ML Kit dependency will be automatically included.
Add the NSCameraUsageDescription key to your Info.plist:
<key>NSCameraUsageDescription</key>
<string>We need access to your camera to scan documents</string>
Add camera permission to your AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
The module automatically requests camera permission when launching the scanner.
This module requires React Native 0.77.3 or higher and supports the new architecture on iOS, while using the stable old architecture on Android.
iOS: Full support for Fabric and TurboModules - automatically detected and enabled when you enable new architecture in your project.
Android: Uses the stable bridge implementation for maximum compatibility. New architecture support is planned for a future release.
✅ iOS: Fully supported - Set RCT_NEW_ARCH_ENABLED=1 in your Podfile or build settings
✅ Android: Fully supported - Keep newArchEnabled=true in your gradle.properties
The iOS implementation will automatically use Fabric/TurboModules when enabled, while Android will continue to use the stable bridge implementation.
import { launchScanner } from 'react-native-document-scanner';
// Basic usage
const result = await launchScanner();
// With options
const result = await launchScanner({
quality: 0.8,
includeBase64: false,
});
// With EXIF metadata
const result = await launchScanner({
quality: 0.8,
includeExif: true,
});
console.log('EXIF:', result.images[0].exif);
// With EXIF + GPS location
const result = await launchScanner({
quality: 0.8,
includeExif: true,
includeLocationExif: true,
});
console.log('GPS:', result.images[0].exif?.GPSLatitude, result.images[0].exif?.GPSLongitude);
// With callback (optional)
launchScanner({ quality: 0.9 }, (result) => {
if (result.didCancel) {
console.log('User cancelled');
} else if (result.error) {
console.log('Error:', result.errorMessage);
} else {
console.log('Scanned images:', result.images);
}
});
import {launchScanner} from 'react-native-document-scanner';
launchScanner()Launch scanner to scan documents.
See Options for further information on options.
The callback will be called with a response object, refer to The Response Object.
| Option | iOS | Android | Description |
|---|---|---|---|
| quality | ✅ | ✅ | Number between 0 and 1 for image quality (default: 1). Lower values reduce file size |
| includeBase64 | ✅ | ✅ | If true, creates base64 string of the image (Avoid using on large image files due to performance) |
| includeExif | ✅ | ✅ | If true, embeds EXIF metadata (timestamps, device info, dimensions) in the image file and returns it in the response (default: false) |
| includeLocationExif | ✅ | ✅ | If true, also embeds GPS coordinates in EXIF. Requires location permission — see Location Permission Setup (default: false) |
| key | iOS | Android | Description |
|---|---|---|---|
| didCancel | ✅ | ✅ | true if the user cancelled the process |
| error | ✅ | ✅ | true if error happens |
| errorMessage | ✅ | ✅ | Description of the error, use it for debug purpose only |
| images | ✅ | ✅ | Array of the selected media, refer to Image Object |
| key | iOS | Android | Description |
|---|---|---|---|
| base64 | ✅ | ✅ | The base64 string of the image (if includeBase64 is true) |
| uri | ✅ | ✅ | The file uri in app specific cache storage |
| width | ✅ | ✅ | Image width in pixels |
| height | ✅ | ✅ | Image height in pixels |
| fileSize | ✅ | ✅ | The file size in bytes |
| type | ✅ | ✅ | The file MIME type (e.g., "image/jpeg") |
| fileName | ✅ | ✅ | The file name |
| exif | ✅ | ✅ | EXIF metadata object (if includeExif is true). See EXIF Object |
When includeExif is true, each image includes an exif object with the following fields:
| key | iOS | Android | Description |
|---|---|---|---|
| DateTimeOriginal | ✅ | ✅ | Scan timestamp (format: yyyy:MM:dd HH:mm:ss) |
| DateTimeDigitized | ✅ | ✅ | Scan timestamp (format: yyyy:MM:dd HH:mm:ss) |
| PixelXDimension | ✅ | ✅ | Image width in pixels |
| PixelYDimension | ✅ | ✅ | Image height in pixels |
| ColorSpace | ✅ | ✅ | Color space (1 = sRGB) |
| Make | ✅ | ✅ | Device manufacturer |
| Model | ✅ | ✅ | Device model |
| Software | ✅ | ✅ | App name |
| GPSLatitude | ✅ | ✅ | Latitude (only if includeLocationExif is true and permission granted) |
| GPSLongitude | ✅ | ✅ | Longitude (only if includeLocationExif is true and permission granted) |
| GPSAltitude | ✅ | ✅ | Altitude in meters |
| GPSHorizontalAccuracy | ✅ | ✅ | GPS accuracy in meters |
| GPSDateTimeUTC | ✅ | ✅ | GPS fix timestamp in UTC |
When using includeLocationExif: true, the package automatically requests location permission. However, you must add the required permission keys to your app:
Add to your Info.plist:
<key>NSLocationWhenInUseUsageDescription</key>
<string>Your location will be embedded in scanned documents for record-keeping.</string>
No additional setup required. The package declares ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions in its own manifest, which will be merged automatically.
includeLocationExif: true — it has no effect otherwiseWhile both platforms provide similar functionality, there are some minor differences:
If you encounter issues with ML Kit on Android, ensure that:
1. Google Play Services is installed on the device/emulator
2. Your compileSdkVersion is 35 or higher
3. Your targetSdkVersion is 35 (required by Google Play Store)
4. Your minSdkVersion is 21 or higher
Ensure you've added the NSCameraUsageDescription key to your Info.plist.
Check the example/ directory for a complete example app demonstrating the scanner.
MIT
$ claude mcp add react-native-document-scanner \
-- python -m otcore.mcp_server <graph>