Skip to the content.

Using Quagga2 in Node.js

This tutorial covers server-side barcode scanning with Quagga2 in Node.js.

Installation

npm install @ericblade/quagga2

Basic Usage

const Quagga = require('@ericblade/quagga2').default;

Quagga.decodeSingle({
  src: './barcode.jpg',
  decoder: {
    readers: ['code_128_reader', 'ean_reader']
  }
}, function(result) {
  if (result && result.codeResult) {
    console.log('Barcode:', result.codeResult.code);
    console.log('Format:', result.codeResult.format);
  } else {
    console.log('No barcode found');
  }
});

With Promises

Wrap in a Promise for async/await:

const Quagga = require('@ericblade/quagga2').default;

function decodeBarcode(imagePath, readers = ['code_128_reader']) {
  return new Promise((resolve, reject) => {
    Quagga.decodeSingle({
      src: imagePath,
      decoder: { readers }
    }, (result) => {
      if (result && result.codeResult) {
        resolve(result.codeResult);
      } else {
        resolve(null);
      }
    });
  });
}

// Usage
async function main() {
  const result = await decodeBarcode('./barcode.jpg');
  if (result) {
    console.log(`Found ${result.format}: ${result.code}`);
  }
}

main();

Express API Example

const express = require('express');
const multer = require('multer');
const Quagga = require('@ericblade/quagga2').default;

const app = express();
const upload = multer({ dest: 'uploads/' });

app.post('/scan', upload.single('image'), (req, res) => {
  if (!req.file) {
    return res.status(400).json({ error: 'No image provided' });
  }

  Quagga.decodeSingle({
    src: req.file.path,
    decoder: {
      readers: ['code_128_reader', 'ean_reader', 'upc_reader']
    }
  }, (result) => {
    if (result && result.codeResult) {
      res.json({
        code: result.codeResult.code,
        format: result.codeResult.format
      });
    } else {
      res.json({ code: null, error: 'No barcode found' });
    }
  });
});

app.listen(3000, () => {
  console.log('Barcode API running on port 3000');
});

Batch Processing

Process multiple images:

const Quagga = require('@ericblade/quagga2').default;
const fs = require('fs');
const path = require('path');

async function decodeImage(imagePath) {
  return new Promise((resolve) => {
    Quagga.decodeSingle({
      src: imagePath,
      decoder: { readers: ['code_128_reader', 'ean_reader'] }
    }, (result) => {
      resolve({
        file: path.basename(imagePath),
        code: result?.codeResult?.code || null,
        format: result?.codeResult?.format || null
      });
    });
  });
}

async function processDirectory(dir) {
  const files = fs.readdirSync(dir)
    .filter(f => /\.(jpg|jpeg|png)$/i.test(f));
  
  const results = [];
  for (const file of files) {
    const result = await decodeImage(path.join(dir, file));
    results.push(result);
    console.log(`${result.file}: ${result.code || 'No barcode'}`);
  }
  
  return results;
}

processDirectory('./images');

Configuration Tips

Image Size

Control processing resolution:

Quagga.decodeSingle({
  src: './large-image.jpg',
  inputStream: {
    size: 1280  // Scale to max 1280px
  },
  decoder: { readers: ['ean_reader'] }
}, callback);

Locator Settings

For difficult images:

Quagga.decodeSingle({
  src: './image.jpg',
  locate: true,
  locator: {
    patchSize: 'small',
    halfSample: false
  },
  decoder: { readers: ['code_128_reader'] }
}, callback);

← Back to Tutorials