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

@scanid-africa/mrz-scanner

v1.0.20

Published

MRZ scanner for React Native (Expo) and React web — powered by ScanID Africa API

Downloads

1,847

Readme

@scanid-africa/mrz-scanner

Scanner MRZ automatique pour React Native (Expo) et React web. Détecte et parse les zones MRZ de passeports, cartes d'identité.

| Plateforme | Mode | Réseau requis | | ------------ | ------------- | ------------- | | React Native | 100% local | ❌ hors ligne | | React web | Via API cloud | ✅ requis |


Installation

npm install @scanid-africa/mrz-scanner

Dépendances React Native

npx expo install expo-camera expo-image-manipulator expo-mlkit-ocr expo-audio mrz-fast mrz

⚠️ Dev build obligatoire — ces modules natifs ne fonctionnent pas dans Expo Go.

npx expo run:ios
# ou
npx expo run:android

Dépendances React web

Aucune dépendance supplémentaire — getUserMedia est natif au navigateur.


Usage React Native

Le scanner s'ouvre dans un Modal plein écran. Le scan démarre automatiquement dès que la caméra est prête — aucun bouton requis.

import { useState } from 'react';
import { Modal } from 'react-native';
import { MrzScannerNative, type MrzResult } from '@scanid-africa/mrz-scanner';

export function DocumentScanScreen() {
  const [showScanner, setShowScanner] = useState(false);

  function handleSuccess(result: MrzResult) {
    setShowScanner(false);
    console.log(result.fields.surname); // "DIOP"
    console.log(result.fields.givenNames); // "MBAYE JACQUES"
    console.log(result.fields.documentNumber); // "XXXXXXXXX"
    console.log(result.documentType); // "TD3_PASSPORT"
  }

  return (
    <Modal visible={showScanner} animationType="slide" statusBarTranslucent>
      <MrzScannerNative
        onSuccess={handleSuccess}
        onError={(err) => console.error(err.message)}
        onClose={() => setShowScanner(false)}
      />
    </Modal>
  );
}

Usage React web

import { MrzScannerWeb, type MrzResult } from '@scanid-africa/mrz-scanner';

export function ScanPage() {
  return (
    <MrzScannerWeb
      api={{ mode: 'cloud', apiKey: 'sk_live_...', region: 'west-africa' }}
      onSuccess={(result: MrzResult) => console.log(result.fields)}
      width="100%"
      height="480px"
    />
  );
}

Next.js — import dynamique obligatoire

getUserMedia n'est pas disponible côté serveur. Utilise dynamic() avec ssr: false :

import dynamic from 'next/dynamic';

const MrzScannerWeb = dynamic(
  () => import('@scanid-africa/mrz-scanner').then((m) => m.MrzScannerWeb),
  { ssr: false },
);

Props

MrzScannerNative

| Prop | Type | Défaut | Description | | -------------- | ----------------------------- | ------------------------------------- | -------------------------------------------------------------------------------------- | | onSuccess | (result: MrzResult) => void | requis | Appelé dès qu'une MRZ valide est détectée | | onError | (error: Error) => void | — | Appelé après maxAttempts échecs | | onClose | () => void | — | Bouton ✕ pour fermer le scanner | | hint | string | "Alignez la zone MRZ dans le cadre" | Texte affiché sous le cadre | | frameColor | string | "#c8ff00" | Couleur du cadre de scan | | successColor | string | "#34d399" | Couleur du cadre lors du succès | | successSound | boolean \| any | true | Son au succès — true (bundlé), false (désactivé), require('./beep.mp3') (custom) |

MrzScannerWeb

| Prop | Type | Défaut | Description | | ---------------- | ----------------------------- | --------- | ----------------------------------------- | | api | ApiConfig | requis | Configuration de connexion à l'API | | onSuccess | (result: MrzResult) => void | requis | Appelé dès qu'une MRZ valide est détectée | | onError | (error: Error) => void | — | Appelé après maxAttempts échecs | | onClose | () => void | — | Bouton ✕ pour fermer le scanner | | maxAttempts | number | 10 | Nombre de tentatives avant abandon | | scanIntervalMs | number | 1500 | Intervalle entre deux captures (ms) | | width | string \| number | "100%" | Largeur du composant | | height | string \| number | "480px" | Hauteur du composant | | className | string | — | Classe CSS additionnelle |


Configuration API (web)

Self-hosted — votre propre instance

api={{ mode: 'selfhosted', apiUrl: 'https://your-api.com' }}

Cloud ScanID Africa

api={{
  mode: 'cloud',
  apiKey: 'sk_live_...',
  region: 'west-africa' // 'west-africa' | 'north-africa' | 'auto'
}}

Son de succès

Par défaut, un bip est joué lors d'un scan réussi (bundlé dans le SDK, aucun fichier requis).

// Son par défaut (bundlé)
<MrzScannerNative onSuccess={handleSuccess} />

// Son custom
<MrzScannerNative
  onSuccess={handleSuccess}
  successSound={require('./assets/sounds/beep.mp3')}
/>

// Son désactivé
<MrzScannerNative onSuccess={handleSuccess} successSound={false} />

Compatible expo-audio (nouveau) et expo-av (ancien) — détection automatique.


Type MrzResult

interface MrzResult {
  documentType: 'TD1_ID' | 'TD2' | 'TD3_PASSPORT' | 'DL';
  documentLabel: string; // "Passeport" | "Carte d'identité " | …
  corrected: boolean; // true si une correction OCR a été appliquée
  fields: {
    surname: string | null;
    givenNames: string | null;
    nationality: string | null;
    issuingState: string | null;
    dateOfBirth: string | null; // YYMMDD
    sex: 'male' | 'female' | 'unspecified' | null;
    expirationDate: string | null; // YYMMDD
    documentNumber: string | null;
    personalNumber: string | null;
  };
}

Documents supportés

| Type | Document | Lignes | Parser | | ------------ | ---------------- | ------------ | ------------------------- | | TD3_PASSPORT | Passeport | 2 × 44 chars | mrz-fast (correction OCR) | | TD1_ID | Carte d'identité | 3 × 30 chars | mrz |


Flow technique

React Native — 100% local

expo-camera → takePictureAsync()
  ↓
expo-image-manipulator → crop 50% bas (zone MRZ)
  ↓
expo-mlkit-ocr → OCR local (Apple Vision / Google MLKit)
  ↓
mrz-mapper → extrait les lignes MRZ depuis les blocs OCR
  ↓
mrz-fast / mrz → parse + validation des checksums ICAO
  ↓
onSuccess(MrzResult)

Le crop sur les 50% bas de l'image réduit le bruit OCR et accélère la détection. La gestion des blocs OCR individuels (en plus du texte global) permet de gérer les images en mode paysage sur Android.

React web — via API

getUserMedia → flux caméra
  ↓
canvas → capture frame + crop 50% bas
  ↓
fetch POST /mrz/scan (multipart/form-data)
  ↓
onSuccess(MrzResult)

Configuration metro.config (si usage en local)

Si tu testes le SDK en local avec file:../mrz-scanner-sdk, ajoute dans metro.config.cjs :

const { getDefaultConfig } = require('expo/metro-config');
const path = require('path');

const sdkPath = path.resolve(__dirname, '../mrz-scanner-sdk');
const config = getDefaultConfig(__dirname);

config.watchFolders = [sdkPath];

config.resolver.extraNodeModules = {
  react: path.resolve(__dirname, 'node_modules/react'),
  'react-native': path.resolve(__dirname, 'node_modules/react-native'),
  'expo-camera': path.resolve(__dirname, 'node_modules/expo-camera'),
  'expo-mlkit-ocr': path.resolve(__dirname, 'node_modules/expo-mlkit-ocr'),
  'expo-image-manipulator': path.resolve(
    __dirname,
    'node_modules/expo-image-manipulator',
  ),
  'expo-haptics': path.resolve(__dirname, 'node_modules/expo-haptics'),
  'expo-audio': path.resolve(__dirname, 'node_modules/expo-audio'),
};

config.resolver.unstable_enableSymlinks = true;
module.exports = config;

Utilise l'extension .cjs si ton projet a "type": "module" dans package.json.



Licence

MIT © ScanID Africa