QuaggaJS is a popular open-source barcode scanner written in JavaScript that locates and decodes various 1D barcode symbologies in the user’s camera stream.
While the original project is no longer maintained, it lives on as Quagga2, which is what we’ll be using in our tutorial.
Since Quagga is a JavaScript-only library, it is easy to integrate into any website or web app. In this tutorial, we’ll show you how to set up the barcode scanner in a single HTML file.
Step 1: Setting up the HTML file
Let’s start by creating the basic structure of the HTML document:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>QuaggaJS</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
</head>
<body>
</body>
</html>
💡 The line <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
ensures that the page fits the device’s resolution and that users cannot zoom into it.
The first thing we’ll put into the body is a div
into which we’ll later render the camera stream:
<body>
<div id="camera"></div>
</body>
Step 2: Configuring Quagga
Next, we’ll add Quagga itself. We’re including the quagga.min.js
script from jsDelivr, but you can of course also host the script on your own web server.
<body>
<div id="camera"></div>
// new
<script src="https://cdn.jsdelivr.net/npm/@ericblade/quagga2/dist/quagga.min.js"></script>
</body>
Now, we need to configure QuaggaJS. First, we have to specify the DOM element where the video stream will be displayed. Next, we also need to specify the barcode decoders we want to use.
To accomplish the first part, we create a config object, which we will call quaggaConf
. We use document.querySelector to select the div
we created above as the target where the video stream will be displayed.
<script>
const quaggaConf = {
inputStream: {
target: document.querySelector("#camera")
}
}
</script>
Now we specify which barcode symbologies our QuaggaJS app will read (to optimize performance, it’s recommended to only include those you expect to scan). In this tutorial, we’ll be sticking to the common barcode type Code 128. You can find a list of all supported symbologies in the Quagga2 GitHub repository.
<script>
const quaggaConf = {
inputStream: {
target: document.querySelector("#camera"),
},
// new
decoder: {
readers: ['code_128_reader']
},
}
</script>
The next step is to prepare the initialization function. We provide our Quagga configuration and an error handler. If the initialization is successful, Quagga.start()
will begin the barcode scanning process.
We have also added a function to display an alert with the barcode result when a barcode is detected and read.
<script>
const quaggaConf = {
inputStream: {
target: document.querySelector("#camera"),
},
decoder: {
readers: ['code_128_reader']
},
}
// new
Quagga.init(quaggaConf, function (err) {
if (err) {
return console.log(err);
}
Quagga.start();
});
Quagga.onDetected(function (result) {
alert("Detected barcode: " + result.codeResult.code);
});
</script>
Step 3: Configuring the video stream
Now we’ll add LiveStream
as the input stream type, since we want to process and display the live video as captured by the user’s camera. Other possible values for the stream type are described in the Quagga docs.
We’ll also have to define the constraints for the video stream. To do that, we need to specify the width, height, aspect ratio, and camera for the input stream.
💡 A lower resolution will result in faster scanning speeds at the cost of accuracy.
<script>
const quaggaConf = {
inputStream: {
target: document.querySelector("#camera"),
// new
type: "LiveStream",
constraints: {
width: { min: 640 },
height: { min: 480 },
facingMode: "environment",
aspectRatio: { min: 1, max: 2 }
}
},
decoder: {
readers: ['code_128_reader']
},
}
Quagga.init(quaggaConf, function (err) {
if (err) {
return console.log(err);
}
Quagga.start();
});
Quagga.onDetected(function (result) {
alert("Detected barcode: " + result.codeResult.code);
});
</script>
Next, we add some styling to display the video in the resolution we requested from the camera to ensure it fits the screen.
<head>
<meta charset="utf-8"/>
<title>QuaggaJS</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
// new
<style>
#camera video{
width:100%;
max-width: 640px;
}
</style>
</head>
Lastly, we’re going to apply a style
attribute to our camera div
to make it take up the entire width of the body.
<body>
<div id="camera" style="width:100%"></div>
</body>
And we’re done! 🎉
The final result looks like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>QuaggaJS</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"/>
<style>
#camera video{
width:100%;
max-width: 640px;
}
</style>
</head>
<body>
<div id="camera" style="width:100%"></div>
<script src="https://cdn.jsdelivr.net/npm/@ericblade/quagga2/dist/quagga.min.js"></script>
<script>
const quaggaConf = {
inputStream: {
target: document.querySelector("#camera"),
type: "LiveStream",
constraints: {
width: { min: 640 },
height: { min: 480 },
facingMode: "environment",
aspectRatio: { min: 1, max: 2 }
}
},
decoder: {
readers: ['code_128_reader']
},
}
Quagga.init(quaggaConf, function (err) {
if (err) {
return console.log(err);
}
Quagga.start();
});
Quagga.onDetected(function (result) {
alert("Detected barcode: " + result.codeResult.code);
});
</script>
</body>
</html>
Try scanning a Code 128 to see if everything works as intended.
![Code 128 barcode example](https://scanbot.io/wp-content/uploads/2024/03/quaggajs-code128-example.png)
Drawbacks of using QuaggaJS
As impressive as this JavaScript-based barcode scanner implementation is, QuaggaJS does have its disadvantages.
The biggest drawback is that it only supports 1D barcodes. Two-dimensional symbologies like QR Code, Data Matrix, and Aztec encode much more data while taking up less space, which makes them a valuable alternative to their one-dimensional counterparts.
As useful as it is to have a barcode scanner written in JavaScript, the performance of the detection algorithm would also benefit from an implementation in WebAssembly. Especially on low-end devices, this could result in increased scanning speeds.
Quagga’s feature set is also not on par with that of professional solutions. Enterprise-grade barcode scanner software often includes dedicated modules for scanning many barcodes simultaneously or in rapid succession, as well as UI elements, all of which this open-source solution lacks.
If you plan to use Quagga in production, you should also keep in mind that you will depend entirely on the open-source community for its maintenance and for support. If you run into a problem, you might have to find a solution on your own.
Conclusion
QuaggaJS is a useful free barcode scanning solution with high compatibility, thanks to it being written in JavaScript.
However, Quagga’s speed, accuracy, and UX features can’t hold a candle to proprietary offerings. For companies that heavily rely on barcode scanning in their business processes, we recommend using an enterprise-grade solution instead.
We developed the Scanbot 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.
You can try it out using our demo app – just scan the barcode with your phone:
![](https://scanbot.io/wp-content/uploads/2023/06/DemoApp_Biz_Barcode_Web.jpg)
You can also take a look at our integration guides for JavaScript and React.js for implementations similar to this one. 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