npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-native-doc-scanner

v0.1.1

Published

Real-time AI document scanner for React Native — VisionCamera + ONNX Runtime document detection, OpenCV quality analysis, and PaddleOCR (RapidOCR/ONNX) field extraction for passports, driving licences, and ID cards.

Readme


What this is

A React Native identity-document scanning SDK for iOS and Android. It watches the camera stream, finds the document, decides whether the frame is actually good enough, fires the shutter itself, corrects perspective, and reads the fields — all natively, on the device.

The point of the SDK is the part between "a rectangle is visible" and "capture": glare, motion, sharpness, framing and skew are each measured per frame and gated, so you get one usable image instead of a roll of near-misses.

Frames never leave the phone. Detection, quality analysis and OCR all run locally; only structured results cross back into JavaScript.

npm i react-native-doc-scanner

📦 Live on npm: react-native-doc-scanner


Capture pipeline


The app

| Screen | What it does | | --- | --- | | Guided capture | Live quad tracking with document-type confidence. The shutter fires on its own once every gate passes — the user just holds still. | | Extraction result | Perspective-corrected crop, parsed fields, raw MRZ, and a confidence score you can threshold on. | | Diagnostics | Raw per-frame metrics and every individual guidance gate, so a rejected frame is always traceable to a specific check. |


Quick start

Drop-in screen:

import { DocumentScannerScreen, DocumentType } from 'react-native-doc-scanner';

export function PassportScanner() {
  return (
    <DocumentScannerScreen
      documentType={DocumentType.PASSPORT}
      onCaptured={(result) => console.log(result.data)}
      onCancel={() => console.log('Scanner cancelled')}
    />
  );
}

Or bring your own UI and reuse the engine:

import {
  useDocumentScanner,
  ScannerOverlay,
  GuidanceBanner,
  DocumentType,
} from 'react-native-doc-scanner';

function CustomScanner() {
  const { guidance, quad, frameSize, captureStage } = useDocumentScanner({
    documentType: DocumentType.DRIVING_LICENCE,
    onCaptured: (result) => console.log(result.data),
  });

  return (
    <>
      <ScannerOverlay
        width={390}
        height={844}
        quad={quad}
        frameWidth={frameSize.width}
        frameHeight={frameSize.height}
        isValid={guidance.isValid}
        captureStage={captureStage}
      />
      <GuidanceBanner
        code={guidance.code}
        message={guidance.message}
        isValid={guidance.isValid}
      />
    </>
  );
}

Result shape:

interface DocumentResult {
  documentType: string;
  confidence: number;

  name?: string;
  documentNumber?: string;
  dateOfBirth?: string;
  expiryDate?: string;
  nationality?: string;
  address?: string;

  mrz?: string;

  fields?: Record<string, { value: string; confidence: number }>;
}

Installation

npm i react-native-doc-scanner
# or: pnpm add react-native-doc-scanner

Peer dependencies:

pnpm add \
  react-native-vision-camera \
  react-native-vision-camera-worklets \
  react-native-nitro-modules \
  react-native-reanimated \
  react-native-mmkv \
  react-native-gesture-handler \
  @shopify/react-native-skia

| Peer dependency | Minimum | | --- | --- | | react-native-vision-camera | 5.0.0 | | react-native-vision-camera-worklets | 5.0.0 | | react-native-nitro-modules | 0.35.0 | | react-native-reanimated | 3.10.0 | | react-native-mmkv | 4.0.0 | | react-native-gesture-handler | 2.14.0 | | @shopify/react-native-skia | 1.5.0 |

zustand ships as a direct dependency — you don't install it yourself.

Then:

cd ios && pod install

VisionCamera 5 / Nitro required. This SDK targets the Nitro architecture and does not support the legacy v3/v4 frame-processor-plugin API.

Requirements

React Native — New Architecture (Fabric + TurboModules), JSI, Nitro Modules.

iOS — 15+, Xcode 15+, Swift, ONNX Runtime, OpenCV.

<key>NSCameraUsageDescription</key>
<string>We use the camera to scan identity documents.</string>

Android — API 24+, Kotlin, CameraX/VisionCamera, ONNX Runtime, OpenCV.

<uses-permission android:name="android.permission.CAMERA" />

Auto capture

The SDK does not capture because a quadrilateral appeared. Capture requires every gate to pass, and to keep passing across a stable-frame window:

Document detected
   → correct framing        → correct size
   → valid perspective      → low motion
   → sharp                  → acceptable exposure
   → low glare              → stable tracking
   → temporal confidence accumulated
      → CAPTURE

Single-frame decisions produce false positives, so confidence is smoothed over time and fused before the shutter fires. Thresholds can be regenerated from labelled replay sessions:

npm run generate:thresholds

The same detection and quality signals drive the on-screen guidance:

Move closer          Hold still            Reduce glare
Move farther away    Improve lighting      Turn the document
Center the document  Keep it in frame      Capturing…

Architecture

                     React Native Application
                              │
                              ▼
                    DocumentScannerScreen
                              │
                              ▼
                     useDocumentScanner()
                              │
                              ▼
                    VisionCamera Frame
                              │
                              ▼
                     JSI / Nitro Module
                 ┌────────────┴────────────┐
                 ▼                         ▼
          Frame Scheduler             Camera Engine
                 │
                 ▼
          Document Engine
        ┌────────┼─────────┐
        ▼        ▼         ▼
     Detect   Track     Quality
        └────────┼─────────┘
                 ▼
          Decision Engine
                 ▼
             Auto Capture
                 ▼
        Perspective Correction
                 ▼
           OCR / MRZ / Barcode
                 ▼
        Structured Result Object

Why the hot path is native

At 30–60 FPS, pushing every frame through the JS bridge costs memory copies, serialization, GC pressure, scheduling overhead, latency and dropped frames. So the loop stays native — Camera → Frame → ONNX/OpenCV → Tracking → Decision — and only small state objects and guidance codes are propagated to React Native.

Three techniques keep it cheap:

  • ROI-first — detect once on the full frame, then run expensive work only on the document region.
  • Temporal scheduling — tracking runs every frame; the detector runs adaptively at 10–15 FPS.
  • Backpressure — frames arriving while inference is in flight are dropped rather than queued.

Default stack

| Component | Technology | | --- | --- | | Camera | VisionCamera Core / Nitro | | Native bridge | Nitro Modules / JSI | | Document detection | ONNX Runtime | | Image processing | OpenCV | | OCR | RapidOCR / PaddleOCR (ONNX) | | MRZ | OCR + ICAO 9303 parser | | Barcode | Native / CV pipeline | | UI | React Native + Skia | | State | Zustand | | Persistence | MMKV |


Supported documents

Passport · Driving licence · National ID · Residence permit · Visa · Vehicle registration · Insurance card · Proof of address · Custom types.

Document-specific models and parsers can be added without touching the core scanner.


Swappable models

Models are decoupled from application logic, so you can fine-tune, ship regional variants, or benchmark alternatives without changing a line of UI code.

import { ModelManager } from 'react-native-doc-scanner';

ModelManager.register({
  id: 'custom-document-detector-v1',
  label: 'Custom Document Detector',
  license: 'Apache-2.0',
  paths: {
    android: 'models/document_detector.onnx',
    ios: 'models/document_detector.onnx',
  },
});

await ModelManager.activate('custom-document-detector-v1');

Registry: document detector · document classifier · OCR detector · OCR recognizer · MRZ detector · your own.

Verify bundled model files and hashes:

npm run verify:models

Engineering tools

The example app ships with the instrumentation used to develop the pipeline.

Diagnostics — unfiltered per-frame metrics (blurScore, brightness, glareRatio, motionScore, distanceRatio, perspectiveSkew) plus the pass/fail state of every guidance gate.

Record — capture a labelled .idvr session straight from the live camera, tagged with expected outcome (must_capture / must_not_capture) and lighting condition (dim / normal / bright / backlit).

Replay — re-run any recorded session through the current build's pipeline, deterministically. Threshold changes become measurable instead of anecdotal.

npm run replay                                              # run sessions through this build
node --experimental-strip-types bench/replay/run.ts push     # push a session to a device

Benchmarking

Benchmark on real devices, from recorded sessions, across low-end Android, mid-range Android, high-end Android, an older iPhone, a modern iPhone and iPad. Desktop inference numbers are not a proxy for mobile.

Metric                  Result
--------------------------------
Detection latency       XX ms
Tracking latency        XX ms
Quality latency         XX ms
Capture latency         XX ms
Median acquisition      XX ms
P95 acquisition         XX ms
Peak RAM                XX MB
CPU / GPU utilization   XX %
False capture rate      XX %
Successful captures     XX %

Development

pnpm install
pnpm test          # unit tests
pnpm typecheck     # tsc --noEmit
pnpm lint          # eslint src bench
pnpm specs         # regenerate Nitro bindings after editing src/specs/DocScanner.nitro.ts

Run the example app:

pnpm --dir example install
pnpm --dir example android   # or: ios

Project structure

react-native-kyc-sdk/
├── src/            components · hooks · models · ocr · opencv · screens
│                   services · specs · store · types · utils · vision
├── android/        native scanner implementation
├── ios/            native scanner implementation
├── bench/replay/   deterministic session replay
├── tools/          threshold generation
├── scripts/        verify-models.sh
├── docs/           DEVELOPMENT · MODEL_TRAINING · TROUBLESHOOTING · redesign · images
├── example/
└── nitro.json

The native contract lives in src/specs/DocScanner.nitro.ts — that file is the source of truth; run pnpm specs after changing it.

Tests cover

Document geometry · corner ordering · quality scoring · guidance decisions · auto-capture decisions · OCR parsing · MRZ parsing · document classification · model management · scanner state · native integration.


Security

This is a capture and computer-vision component, not a KYC compliance platform. Do not treat OCR output as proof that a document is genuine.

A production identity system still needs: TLS, server-side verification, document authenticity checks, face matching, presentation-attack detection, device integrity and root/jailbreak detection, replay protection, encrypted storage, secure model distribution, tamper detection, audit logging, risk analysis, and whatever your jurisdiction requires.


Roadmap

Shipped — real-time document detection · perspective correction · OpenCV quality analysis · OCR pipeline · MRZ extraction · auto capture · session recording and deterministic replay · diagnostics instrumentation

Next — multi-task document detector · document tracking · advanced temporal confidence · face detection and quality · passive then active liveness · face verification · document authenticity analysis · PDF417 pipeline · Web/WASM · unified C++ vision core · production benchmark suite

See docs/redesign/ for the engineering architecture and milestones.


Model licensing

Model licenses differ from this repository's license. Before shipping, check the terms on model weights, training datasets, OCR models, third-party native libraries, OpenCV components, ONNX Runtime, and any document-specific models. An open-source model does not automatically permit commercial redistribution.

See docs/MODEL_TRAINING.md.


Contributing

pnpm install && pnpm test && pnpm typecheck

Native changes: validate the example app on both Android and iOS. Model changes: include benchmark results and state the model's license.


Disclaimer

react-native-doc-scanner is a developer SDK for document capture, computer vision and OCR. It does not by itself guarantee identity, document authenticity, regulatory compliance or fraud prevention.

Documents shown in this repository are specimen documents containing fictitious data.


License

MIT — see LICENSE. Built by Muhammad Ahmad.