How to Build a Browser-Based QR Code Scanner with JavaScript and HTML5
QR codes1 are everywhere - URLs, payment flows, ticketing, inventory labels, patient wristbands. Building a browser-based QR code scanner means users get instant scanning capability on any device without downloading an app. This guide shows how to build one using the Dynamsoft Barcode Reader JavaScript SDK v11, which runs entirely in-browser via WebAssembly.

The SDK supports 30+ barcode formats including QR Code, Micro QR Code, and QR Code Model 1, with complementation and deformation-resistant algorithms built in for damaged or wrinkled codes.
What you’ll build: A fully functional, camera-powered QR code scanner that runs in any modern browser — no app download required — using Dynamsoft Barcode Reader v11 and fewer than 20 lines of JavaScript.
Key Takeaways
- Dynamsoft Barcode Reader v11 delivers a complete browser-based QR scanning experience via a single
launch()call, with no native app required. - The
barcodeFormatsfilter restricts decoding to QR codes only, measurably improving speed and accuracy in real-time video scenarios. SM_MULTI_UNIQUEscan mode enables continuous multi-code collection with automatic de-duplication, suitable for inventory and batch validation workflows.- The SDK runs entirely via WebAssembly and integrates into WebView, React, Vue, and Angular without modification.
Common Developer Questions
- How do I scan a QR code from a webcam using JavaScript in a browser?
- How do I prevent duplicate QR codes from being scanned multiple times?
- How do I scan only QR codes and ignore other barcode types with Dynamsoft?
Prerequisites
- A modern browser with camera access (Chrome, Edge, Safari, Firefox)
- A 30-day free trial license
Add the SDK to Your Project
CDN (quickest)
<script src="https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader-bundle@11.2.4000/dist/dbr.bundle.js"></script>
npm / yarn (for React, Vue, Angular, etc.)
npm install dynamsoft-barcode-reader-bundle@11.2.4000
# or
yarn add dynamsoft-barcode-reader-bundle@11.2.4000
When using a package manager you must also configure engineResourcePaths so the SDK can locate its .wasm engine files. See the framework samples for ready-made examples.
Scan Your First QR Code in Under 20 Lines
The entire scanner - camera UI, viewfinder, decoding engine - launches with one call. The launch() promise resolves when the user scans a barcode or closes the scanner.
<!DOCTYPE html>
<html>
<head>
<title>QR Code Scanner</title>
<script src="https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader-bundle@11.2.4000/dist/dbr.bundle.js"></script>
</head>
<body>
<button onclick="scan()">Scan QR Code</button>
<script>
async function scan() {
const result = await new Dynamsoft.BarcodeScanner({
license: "YOUR_LICENSE_KEY_HERE",
barcodeFormats: [Dynamsoft.DBR.EnumBarcodeFormat.BF_QR_CODE]
}).launch();
if (result?.barcodeResults?.length) {
alert(result.barcodeResults[0].text);
}
}
</script>
</body>
</html>
The barcodeFormats filter restricts recognition to QR codes only, which improves both speed and accuracy for QR-specific workflows.
Collect Multiple QR Codes Continuously Without Duplicates
For workflows that need to collect several barcodes in sequence - inventory counts, batch ticket validation - use SM_MULTI_UNIQUE mode. The scanner stays open and fires onUniqueBarcodeScanned each time a new unique code is detected. A built-in BarcodeResultView lists results in real time.
<!DOCTYPE html>
<html>
<head>
<title>Multi QR Code Scanner</title>
<script src="https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader-bundle@11.2.4000/dist/dbr.bundle.js"></script>
</head>
<body>
<button onclick="scan()">Start Scanning</button>
<script>
async function scan() {
const result = await new Dynamsoft.BarcodeScanner({
license: "YOUR_LICENSE_KEY_HERE",
barcodeFormats: [Dynamsoft.DBR.EnumBarcodeFormat.BF_QR_CODE],
scanMode: Dynamsoft.EnumScanMode.SM_MULTI_UNIQUE,
onUniqueBarcodeScanned: (item) => {
console.log(`[${item.formatString}] ${item.text}`);
}
}).launch();
// result.barcodeResults contains all unique barcodes collected
console.log("Final results:", result.barcodeResults);
}
</script>
</body>
</html>
By default, a barcode is considered “new” again after 3 seconds (duplicateForgetTime). Adjust this to suit your use case:
const scanner = new Dynamsoft.BarcodeScanner({
license: "YOUR_LICENSE_KEY_HERE",
scanMode: Dynamsoft.EnumScanMode.SM_MULTI_UNIQUE,
duplicateForgetTime: 5000 // ms
});

Supported QR Code Variants
Beyond standard QR codes, the SDK also recognises Micro QR Code and QR Code Model 1 without any extra configuration.

Customize the Scanner Behavior and UI
Restrict Decoding to a Scan Region
To speed up decoding and guide the user, you can restrict recognition to a rectangular region of the camera frame. Set the scan region via the BarcodeScannerConfig using a custom template file (templateFilePath), or rely on the built-in viewfinder to give users a visual alignment guide.

Filter by Barcode Format to Improve Speed
Pass any combination of EnumBarcodeFormat values to barcodeFormats:
const scanner = new Dynamsoft.BarcodeScanner({
license: "YOUR_LICENSE_KEY_HERE",
barcodeFormats: [
Dynamsoft.DBR.EnumBarcodeFormat.BF_QR_CODE,
Dynamsoft.DBR.EnumBarcodeFormat.BF_CODE_128
]
});
Limiting formats is one of the most effective ways to improve scan speed in real-time video scenarios.
Decode Damaged or Deformed QR Codes with a Custom Template
For damaged, incomplete, or heavily deformed QR codes (plastic bags, wrinkled paper), provide a custom template JSON via templateFilePath:
const scanner = new Dynamsoft.BarcodeScanner({
license: "YOUR_LICENSE_KEY_HERE",
templateFilePath: "path/to/DBR-PresetTemplates.json"
});
The template file lets you enable algorithms such as BarcodeComplementModes (for incomplete codes) and DeformationResistingModes (for wrinkled/curved codes). Start from the dist/DBR-PresetTemplates.json file included in the SDK package and add the parameters you need.

Replace the Default UI with Your Own
The scanner’s built-in UI is defined in dist/ui/barcode-scanner.ui.xml. Copy and edit this file, then point the scanner to your custom version:
const scanner = new Dynamsoft.BarcodeScanner({
license: "YOUR_LICENSE_KEY_HERE",
uiPath: "path/to/my-barcode-scanner.ui.xml?v=1"
});
You can show or hide individual controls (flash button, camera-switch button, upload-image button, close button) via BarcodeScannerConfig properties without modifying the XML.
Use the Scanner Inside a WebView App
Because the scanner is pure HTML5/JavaScript, it runs in WebView components on Android and iOS without modification.
Integrate with React, Vue, or Angular
For React, Vue, and Angular projects, install via npm and configure engineResourcePaths to point the SDK to its WASM assets:
import { BarcodeScanner, EnumScanMode } from "dynamsoft-barcode-reader-bundle";
const config = {
license: "YOUR_LICENSE_KEY_HERE",
engineResourcePaths: {
rootDirectory: "https://cdn.jsdelivr.net/npm/"
},
uiPath: "https://cdn.jsdelivr.net/npm/dynamsoft-barcode-reader-bundle@11.2.4000/dist/ui/barcode-scanner.ui.xml",
container: ".barcode-scanner-view"
};
const scanner = new BarcodeScanner(config);
scanner.launch().then(result => console.log(result));
See the official framework samples for complete Angular, React, and Vue starters.
Common Issues & Edge Cases
- Camera permission denied: On iOS Safari and some Android browsers, camera access requires the page to be served over HTTPS. Localhost is an exception; all production deployments must use TLS or scanning will silently fail.
- WASM fails to load from CDN in restricted networks: Corporate firewalls or offline environments may block jsdelivr.net. Host the
dist/folder yourself and setengineResourcePaths.rootDirectoryto your own origin to avoid this. - Duplicate scans in multi-mode: If the same physical label appears in two consecutive frames,
SM_MULTI_UNIQUEwill suppress the duplicate untilduplicateForgetTimeelapses. For kiosk use cases where the same code is intentionally re-scanned, setduplicateForgetTime: 0.
Further Reading
- Customize the BarcodeScanner
- BarcodeScanner API Reference
- Official samples and demos
- Foundational APIs - for fully custom decoding pipelines without the built-in UI
Source Code
References
-
https://en.wikipedia.org/wiki/QR_code ↩