Decoding Barcodes with JavaScript Barcode Detection API

The Barcode Detection API provides web applications with the native ability to detect and decode linear and two-dimensional barcodes directly in the browser using JavaScript. By offloading processing tasks to underlying operating system features, this API enables high-performance, real-time barcode scanning without relying on heavy external third-party JavaScript libraries.

How the API Works

The Barcode Detection API operates via the native BarcodeDetector interface, part of the broader Shape Detection API specification. Instead of executing resource-intensive pixel-parsing algorithms purely within the JavaScript engine, the browser delegates image processing to native platform-level frameworks, such as Google Play Services on Android, Core Image on macOS/iOS, or Windows Media APIs. This architectural approach delivers faster execution times, reduced battery consumption, and smaller web bundle sizes.

Core Steps for Decoding Barcodes

Decoding barcodes with the API involves three primary steps: verifying feature availability and supported formats, initializing the detector, and passing an image source to the detection method.

1. Checking Format Support

Before attempting detection, verify that the browser supports the API and check which barcode types are available:

if ('BarcodeDetector' in window) {
  const supportedFormats = await BarcodeDetector.getSupportedFormats();
  console.log('Supported formats:', supportedFormats);
}

Common supported formats include qr_code, ean_13, ean_8, code_128, code_39, upc_a, and data_matrix.

2. Initializing the Detector

Create an instance of BarcodeDetector, optionally specifying an array of barcode formats to optimize scanning speed:

const barcodeDetector = new BarcodeDetector({
  formats: ['qr_code', 'ean_13', 'code_128']
});

3. Processing Image Sources

The detect() method accepts any standard ImageBitmapSource, such as an HTMLImageElement, HTMLVideoElement, HTMLCanvasElement, Blob, or ImageData. The method runs asynchronously and returns a promise resolving to an array of detected barcode objects:

async function scanSource(imageSource) {
  try {
    const barcodes = await barcodeDetector.detect(imageSource);
    barcodes.forEach(barcode => {
      console.log('Decoded Value:', barcode.rawValue);
      console.log('Format:', barcode.format);
      console.log('Bounding Box:', barcode.boundingBox);
      console.log('Corner Points:', barcode.cornerPoints);
    });
  } catch (error) {
    console.error('Detection failed:', error);
  }
}

Decoded Output Structure

Each item returned in the detection array contains:

Real-Time Video Stream Scanning

For live camera feeds, the detect() method can be called repeatedly inside a requestAnimationFrame() loop or setInterval() timer, passing a live <video> element connected to a MediaStream from navigator.mediaDevices.getUserMedia(). Because the operation is asynchronous, processing frame-by-frame can occur without blocking the main browser UI thread.