Skip to content

Building an HTML5 QR Code & Barcode Scanner in JavaScript

Kevin March 14, 2025 9 mins read
app store

In this tutorial, we’ll use the html5-qrcode library to create a web app for scanning 1D and 2D barcodes with just a few lines of HTML and JavaScript code. This library runs in most desktop and mobile browsers and supports scanning barcodes from a live camera stream as well as image files.

Scanning a QR code with our HTML5 barcode scanner's default configuration

We’ll set up our scanner in three simple steps:

  1. Creating the HTML page
  2. Using JavaScript to initialize and configure the scanner
  3. Linking the JavaScript file to the HTML page

Let’s get started!

Step 1: Create the HTML page

In your project folder, create an index.html file with the usual boilerplate.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTML5 Barcode Scanner</title>
</head>
<body>
</body>
</html>

Step 2: Use JavaScript to initialize and configure the scanner

Next, create a script.js file in the same folder. To set up our scanner, we can copy and paste a code snippet that the library’s developer has provided in a gist on GitHub:

function docReady(fn) {
    // see if DOM is already available
    if (document.readyState === "complete" || document.readyState === "interactive") {
        // call on next available tick
        setTimeout(fn, 1);
    } else {
        document.addEventListener("DOMContentLoaded", fn);
    }
} 

docReady(function() {
    var resultContainer = document.getElementById('qr-reader-results');
    var lastResult, countResults = 0;

    var html5QrcodeScanner = new Html5QrcodeScanner(
        "qr-reader", { fps: 10, qrbox: 250 });

    function onScanSuccess(decodedText, decodedResult) {
        if (decodedText !== lastResult) {
            ++countResults;
            lastResult = decodedText;
            console.log(`Scan result = ${decodedText}`, decodedResult);

            resultContainer.innerHTML += `<div>[${countResults}] - ${decodedText}</div>`;

            // Optional: To close the QR code scannign after the result is found
            html5QrcodeScanner.clear();
        }
    }

    // Optional callback for error, can be ignored.
    function onScanError(qrCodeError) {
        // This callback would be called in case of qr code scan error or setup error.
        // You can avoid this callback completely, as it can be very verbose in nature.
    }

    html5QrcodeScanner.render(onScanSuccess, onScanError);
});

Back in index.html, we need to include our script.js as well as the html5-qrcode library itself. In this tutorial, we’ll use a CDN, but you can also use npm install or similar methods to include the library in your project.

We also need to add two <div> elements. One for the QR code scanner and one for displaying the scan result.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTML5 Barcode Scanner</title>
</head>
<body>
    <div id="qr-reader" style="width:600px"></div>
    <div id="qr-reader-results"></div>
    <script src="https://unpkg.com/html5-qrcode"></script>
    <script src="script.js"></script>
</body>
</html>

Since smartphone cameras are much better suited for scanning barcodes than laptop or desktop webcams, let’s also make sure our scanner looks good on mobile by including some simple CSS in our index.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>HTML5 Barcode Scanner</title>
    <style>
        #qr-reader {
            width: 100%;
            max-width: 600px;
            margin: auto;
        }
        @media (max-width: 600px) {
            #qr-reader {
                width: 100%;
            }
        }
    </style>
</head>
<body>
    <div id="qr-reader"></div>
    <div id="qr-reader-results"></div>
    <script src="https://unpkg.com/html5-qrcode"></script>
    <script src="script.js"></script>
</body>
</html>

To test your project on your phone, you have a few options. One option is to use a service like ngrok, which creates a tunnel to one of their SSL-certified domains. Their Quick Start guide will help you get up and running quickly.

Now let’s test our app by scanning a barcode!

Scanning a QR code with our HTML5 barcode scanner's default configuration

Optional: Implement additional features

The html5-qrcode library offers some further customization options. Let’s say you want to build a PDF417 scanner that also works in poor lighting conditions. By passing a config object as an argument to the Html5QrcodeScanner constructor in script.js, you can …

  • adapt the aspect ratio of the viewfinder to the more horizontal format of a PDF417 barcode,
  • restrict scanning to PDF417 barcodes to avoid false positives,
  • enable a button that turns on the device’s flashlight if it has one.
// define the config object
let config = {
    fps: 10,
    qrbox: {width: 300, height: 100},
    formatsToSupport: [Html5QrcodeSupportedFormats.PDF_417],
    showTorchButtonIfSupported: true,
};

// existing code

    // pass the config object to the Html5QrcodeScanner constructor
    var html5QrcodeScanner = new Html5QrcodeScanner(
        "qr-reader", config);

// existing code
Scanning a PDF417 barcode with our customized HTML5 barcode scanner

Disadvantages of using html5-qrcode for scanning barcodes

The html5-qrcode library is easy to integrate and offers a preconfigured UI, which makes it a good choice for quick prototyping or personal projects.

However, it comes with a few drawbacks:

  • Camera issues: Some users have reported issues with the camera not starting on specific platforms.
  • Poor performance: Compared to alternative libraries, html5-qrcode tends to be less performant and can struggle with certain barcode types.
  • Inconsistent results: Scanning results can vary between devices and environments, leading to unreliable performance.
  • Lack of supported symbologies: Under the hood, html5-qrcode uses ZXing.js (another barcode scanning library that is no longer officially supported), which limits the different barcode types it can scan.
  • Difficulties when troubleshooting: Debugging an app that uses html5-qrcode can be challenging due to insufficient documentation and unclear error messages.

For companies that heavily rely on barcode scanning in their business processes, we recommend using an enterprise-grade solution instead.

Building an HTML5 QR Code & Barcode Scanner with the Scanbot SDK

We developed the Scanbot Web Barcode Scanner SDK to help enterprises overcome the hurdles presented by free barcode scanning software. Our goal was to have a developer-friendly solution available for a wide range of platforms that consistently delivers high-quality results – even in challenging circumstances.

Thanks to the Scanbot SDK’s Ready-to-Use UI Components, you can even use an AR overlay to display multiple barcodes’ contents right in the viewfinder.

Scanning a single barcode with our JavaScript barcode scanner
Scanning a single barcode
Scanning multiple barcodes with an AR overlay with our JavaScript barcode scanner
Scanning multiple barcodes with the AR overlay

To accomplish that, you will need to follow the steps below:

  1. Downloading the Web SDK
  2. Creating the HTML page and configuring the Web SDK
  3. Enabling the AR overlay

Let’s dive into more details for each step.

Step 1: Download the Web SDK

First, create a new empty directory for your app and name it, e.g. “barcode-scanner-app”.

Then download the Scanbot SDK package directly from the npm registry.

💡 You can also use npm to download and install the package, but in this tutorial, we’ll do it manually. You can check the latest SDK version in the changelog.

Unzip the downloaded files into barcode-scanner-app. If the unzipped folder is named “package” or similar, rename it to “scanbot-web-sdk” or make sure to later provide the correct directory path in the code.

Your folder structure should look like this:

barcode-scanner-app/
  |- scanbot-web-sdk/
    |- webpack/
    |- bundle/
    |- @types/
    |- index.js
    |- ui.js
    ... (and some other files)

Step 2: Create the HTML page and configure the Web SDK

Create an index.html file in the barcode-scanner-app folder. Then add the following code to the file:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <!-- We prevent the user from zooming on mobile device -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
    <title>My Scanner App</title>
</head>
<body style="margin: 0">
<button id="start-scanning">Start scanning</button>
<pre id="result"></pre>
<script type="module">
    // We import the necessary ScanbotSDK module
    import "./scanbot-web-sdk/bundle/ScanbotSDK.ui2.min.js";
    // When initializing the SDK, we specify the path to the barcode scanner engine
    const sdk = await ScanbotSDK.initialize({
        enginePath: "scanbot-web-sdk/bundle/bin/barcode-scanner/"
    });
    document.getElementById("start-scanning").addEventListener("click", async () => {
        // We create a new default configuration for the barcode scanner
        const config = new ScanbotSDK.UI.Config.BarcodeScannerScreenConfiguration();
        // We create a barcode scanner UI component
        const scanResult = await ScanbotSDK.UI.createBarcodeScanner(config);
        // Once the scanning is done, we display the result
        if (scanResult?.items?.length > 0) {
            document.getElementById("result").innerText =
                `Barcode type: ${scanResult.items[0].barcode.format} \n` +
                `Barcode content: "${scanResult.items[0].barcode.text}" \n`;
        } else {
            document.getElementById("result").innerText = "Scanning aborted by the user";
        }
    });
</script>
</body>
</html>

The code block above:

  • Adds the “Start scanning” button.
  • Imports and initializes the Scanbot SDK.
  • Executes the user interface from the Scanbot SDK when the user clicks the “Start scanning” button.
  • If a barcode is identified, it will present the barcode type and its content to the user.

💡 Without a license key, our SDK only runs for 60 seconds per session. This is more than enough for the purposes of our tutorial, but if you like, you can generate a license key on our website.

Feel free to run the app to see if everything is working so far.

Scanning a single barcode with our JavaScript barcode scanner

Step 3: Enable the AR overlay

The Scanbot SDK lets you display an AR overlay on the screen so users can pick a specific barcode when the scanner recognizes multiple barcodes. All you need to do to enable this feature is to add the following code after defining the config object:

config.useCase.arOverlay.visible = true;
config.useCase.arOverlay.automaticSelectionEnabled = false;

Run your app again to see the AR overlay in action.

Scanning multiple barcodes with an AR overlay with our JavaScript barcode scanner

Conclusion

🎉 That’s it! You now have a fully functional barcode scanning web app using the Scanbot SDK’s RTU UI.

Are you interested in how the scanner implementation works in your favorite JavaScript framework?

We’ve got you covered:

Should you have any questions, feel free to reach out to us on Slack or MS Teams or send us an email via sdksupport@scanbot.io

Happy scanning! 🤳