@qtrust-id/scanner-web
v1.2.5
Published
Web SDK for the Qtrust on-device QR & barcode scanner — bundles the scanner page, loads it via iframe srcdoc, and bridges results via postMessage. No API key, no server URL.
Maintainers
Readme
@qtrust-id/scanner-web
Web SDK for the Qtrust scanner. Scanning is fully on-device (zxing-wasm) —
there is no host URL and no network. The scanner page ships inside
the package and loads in an iframe via srcdoc; results are bridged to your
page over postMessage. Mirrors the native iOS/Android SDK surface (start /
stop / onResult / onError).
Why iframe
- Camera permission and the scanner UI stay isolated inside the iframe.
- The page is loaded via
srcdoc, so it inherits your page's origin — that is what letsgetUserMedia(camera) work. A sandboxed orblob:iframe would get an opaque origin and the camera would be denied. - One scanner codebase, vendored into the package — no version drift, no CDN.
Install
NPM (bundlers)
npm install @qtrust-id/scanner-webimport { QtrustScanner } from "@qtrust-id/scanner-web";Script tag (no build step)
Modern browsers load the ESM build directly:
<script type="module">
import { QtrustScanner } from "/node_modules/@qtrust-id/scanner-web/src/index.js";
</script>Usage
<div id="scanner" style="width: 100%; height: 480px;"></div>import { QtrustScanner } from "@qtrust-id/scanner-web";
const scanner = new QtrustScanner({
type: "qr", // "qr" | "barcode" | 0 | 1
config: {
skipTutorial: true,
theme: 0, // 0 = DARK, 1 = LIGHT
locale: 0, // 0 = ID, 1 = EN
},
});
scanner.onResult((r) => {
// { data, format, boundingBox }
console.log(r.data, r.format);
});
scanner.onError((msg) => console.error(msg));
scanner.mount("#scanner");
scanner.start();
// later
scanner.stop();
scanner.destroy();API
| Method | Description |
|---|---|
| new QtrustScanner(options) | Create a scanner. No key or URL required. |
| mount(target) | Insert the iframe into a selector or element. Returns the <iframe>. |
| start() | Begin scanning (init handshake is race-safe). |
| stop() | Stop the camera in the iframe. |
| destroy() | Remove iframe + listeners. |
| onResult(cb) | Per-decode result. Returns an unsubscribe fn. |
| onError(cb) | Error message. Returns an unsubscribe fn. |
| onReady(cb) | Scanner initialized + camera ready. |
| onClose(cb) | Scanner closed. |
Options
interface ScannerOptions {
type?: 0 | 1 | "qr" | "barcode";
config?: {
vendorId?: string;
textHintScan?: string;
theme?: 0 | 1; // DARK | LIGHT
locale?: 0 | 1; // ID | EN
skipTutorial?: boolean;
formats?: string; // e.g. "PDF417|QRCode"
};
debug?: boolean; // console diagnostics, off by default
dedupWindowMs?: number; // suppress identical results within N ms (default 1500)
}ScanResult
interface ScanResult {
data: string;
format: string; // "QR_CODE", "EAN_13", …
boundingBox: { x; y; width; height } | null;
}Requirements
- HTTPS (camera access requires a secure context).
localhostis also a secure context for development. - That is the only requirement — no server, no allowlist, no key. See PROTOCOL.md for the internal postMessage bridge.
