Privacy-first, local-only barcode scanning SDK for Web, Node.js, React, iOS, and Android.
Live demo: qr-decoder-theta.vercel.app
Choose the package for your runtime. Browser, Node, and React packages already include their required Scanly workspace dependencies.
npm install @scanly/browser
npm install @scanly/node
npm install @scanly/reactAdvanced engine composition can use @scanly/core directly:
npm install @scanly/core- iOS: v2.0.0 ships a Swift Package Manager source package under
native/ios. Because the manifest is not at the repository root, check out tagv2.0.0and addnative/iosas a local package. See the iOS guide. - Android: download
scanly-sdk-2.0.0.aarfrom the v2.0.0 GitHub Release. Maven Central is not a v2.0.0 distribution channel. See the Android guide.
import { BrowserCaptureSession } from "@scanly/browser";
const scanner = new BrowserCaptureSession();
scanner.initialize();
scanner.start();
const outcome = await scanner.scanFile(file);
if (outcome.ok) console.log(outcome.results);
await scanner.dispose();Camera access uses BrowserCameraSource, requires HTTPS or localhost, and remains subject to browser permission and hardware capability.
import { createNodeCaptureRouter, loadNormalizedFrameFromPath } from "@scanly/node";
const router = createNodeCaptureRouter({ formats: ["qr_code", "data_matrix"] });
const frame = await loadNormalizedFrameFromPath("label.png");
const outcome = await router.scan(frame);
if (outcome.ok) console.log(outcome.results);
await router.dispose();"use client";
import { useScanly } from "@scanly/react";
export function Scanner() {
const { outcome, scanning, scanFile } = useScanly();
return <>
<input type="file" accept="image/*" onChange={(event) => {
const file = event.currentTarget.files?.[0];
if (file) void scanFile(file);
}} />
<output>{scanning ? "Scanning…" : outcome?.ok ? outcome.primary.rawText : ""}</output>
</>;
}import ScanlySDK
let decoder = try ScanlyDecoder()
let results = try decoder.decode(pixelBuffer, options: ScanlyOptions(
formats: [.qrCode, .dataMatrix],
maxResults: 8
))val decoder = ScanlyDecoder()
val session = ScanlyScannerSession(
decoder,
ScanlyOptions(formats = setOf(ScanlyBarcodeFormat.QR_CODE), maxResults = 8),
)
session.onResults = { outcome -> outcome.onSuccess(::renderResults) }- QR Code Model 2
- Data Matrix ECC 200
- PDF417
- Code 128
- EAN-13 and EAN-8
- UPC-A and UPC-E
The default scenario remains QR-only for compatibility. Select additional formats explicitly. The JavaScript jsQR and ZXing-JS adapters are QR-only; the default Browser and Node composition lazily loads the ZXing-C++ WASM engine for the full public format set. See symbology support.
- Image upload and realtime camera scanning
- Multiple-code results, tracking, and batch identity
- Bounded industrial recovery for difficult symbols
- Browser Worker execution and lazy, self-hosted ZXing-C++ WASM
- Framework-independent routing and engine registration
- Native iOS and Android wrappers over the shared C++ decode core
Industrial recovery is not an industrial, warehouse, or DPM certification. The dpm-experimental profile is opt-in.
Scanly decodes locally and remains offline-capable after code and WASM assets are loaded. The SDK does not upload images or payloads and contains no analytics, remote logging, account, or cloud-decoder service. Host applications remain responsible for their own telemetry, storage, and privacy disclosures.
v2.0.0 is the published Stable software line. Automated browser, Node, simulator, emulator, API/ABI, security, package, and artifact checks are verified. Automated coverage is not physical-device qualification.
Physical Web iOS/Android, Native iOS/Android, 30-minute and 60-minute camera soaks, and the complete hardware matrix remain POST_RELEASE_VALIDATION_PENDING under Issue #13. No all-device-verified claim is made.
Known limitations include hardware-dependent camera capabilities, difficult or occluded symbols, experimental DPM recovery, unsupported Android armeabi-v7a, no Maven Central or CocoaPods distribution for v2.0.0, and the pending physical-device matrix.
maincontains the current v2.0.0 Stable line.developis the integration branch for post-v2 maintenance and the next patch/minor line.- Feature and fix branches start from
develop. - Historical release branches and immutable RC/Stable tags preserve qualification ancestry;
release/sdk-v2-v2.0.0is not a development base.
Detailed Alpha, Beta, and RC development evidence is preserved in development history and under release/.
- Documentation index
- SDK usage
- Public API
- Worker and WASM deployment
- Platform compatibility
- Migration from v1
- Security policy
Published v2.0.0 artifacts, tags, and historical qualification evidence are immutable. Later documentation and maintenance changes do not replace those bytes.
See CONTRIBUTING.md, SECURITY.md, and the maintenance policy.
