How to Reliably Read QR Codes in Node.js

How to Reliably Read QR Codes in Node.js

Introduction

In today's digital landscape, QR codes are widely used. Thanks to the QR code's efficiency in storing and reading data, you can see QR codes being used in restaurants, public transportation, app downloads, survey forms, and a whole lot of other applications.

Reading QR codes is usually handled by frontend applications via scanners or image uploads, but if you need a way to read QR codes in the backend, then you've come to the right place!

Why I made this blog post

I was figuring out how to read QR codes in Node.js, so I've tried following existing guides from LogRocket and GeeksforGeeks. They both had similar solutions using qrcode-reader.

Upon testing the solution multiple times, I've encountered occasional bugs with qrcode-reader, which made it unsuitable for production workloads.

The qrcode-reader package is no longer maintained and the owner recommended jsqr as an alternative, which is what we're going to use.

QR Code Reader Solution

Now let's walk through the solution for reading QR codes in Node.js. You can follow along or check the sample repository here.

Installing Jimp and jsQR

For the npm packages, we'll be using jimp for the image loader and jsqr for the QR code reader.

npm install jimp jsqr

TypeScript Code (src/app.ts)

The sample QR code src/qr.png is in the sample repository. You can also replace src/qr.png and use any QR code image if you want.

import Jimp from 'jimp';
import jsQR from 'jsqr';

const decodeQR = async (): Promise<string> => {
    try {
        // Load the image with Jimp
        const image = await Jimp.read('src/qr.png');

        // Get the image data
        const imageData = {
            data: new Uint8ClampedArray(image.bitmap.data),
            width: image.bitmap.width,
            height: image.bitmap.height,
        };

        // Use jsQR to decode the QR code
        const decodedQR = jsQR(imageData.data, imageData.width, imageData.height);

        if (!decodedQR) {
            throw new Error('QR code not found in the image.');
        }

        return decodedQR.data;
    } catch (error) {
        console.error('Error decoding QR code:', error);
    }
}

// Test the decodeQR() function
const run = async () => {
    console.log(await decodeQR());
}

run();

Optional: If you need to read base64 string QR codes, replace the Jimp.read() function with this.

const base64 = 'data:image/png;base64,iVBORw0KGgo...' // replace with your base64 string
const qrBuffer = Buffer.from(base64.replace(/^data:image\/[a-z]+;base64,/, ''), 'base64');
const image = await Jimp.read(qrBuffer);

Testing the Code

To test the solution, you can build and start the function, which will retrieve the data from the src/qr.png image file.

npm build (or tsc)
npm start (or node src/app.js)

> qrcode-decoder-nodejs@1.0.0 start
> node src/app.js

Sample QR code data for testing.

As you can see, we decoded the data and received "Sample QR code data for testing.".

Conclusion

To recap, we implemented a QR code reader in Node.js using jimp and jsqr. We also tested the decodeQR() function, which decoded the sample QR image. Also, here's the sample repository with the code shown in this guide if you've missed it.

I hope this helped you with implementing a QR code reader in Node.js. Thank you for reading, and feel free to connect with me on Twitter and LinkedIn.