Everything developers need to know about QR codes — how they work, generating them in JavaScript, customizing design, and reading them with a camera.
QR codes are everywhere — from restaurant menus to payment apps to event tickets. As a developer, you need to know how to generate them dynamically, customize their appearance, and handle scanning in the browser. This guide covers it all.
A QR (Quick Response) code is a 2D matrix barcode that encodes data as a pattern of black and white squares. The spec (ISO/IEC 18004) supports four data types:
QR codes include error correction using Reed-Solomon coding. There are four levels:
| Level | Recovery | Use case |
|---|---|---|
| L (Low) | 7% | Clean environments |
| M (Medium) | 15% | Most applications |
| Q (Quartile) | 25% | Industrial/print |
| H (High) | 30% | Logo overlay on QR |
Higher error correction → larger QR code. Use level M for most cases, level H if you want to overlay a logo.
The most popular library is qrcode:
npm install qrcode
import QRCode from 'qrcode';
// Render to a canvas element
await QRCode.toCanvas(canvasElement, 'https://heolab.com', {
width: 300,
margin: 2,
errorCorrectionLevel: 'M',
color: {
dark: '#000000',
light: '#ffffff',
},
});
<img> tags)const dataUrl = await QRCode.toDataURL('https://heolab.com', {
width: 300,
margin: 2,
});
// Use in React
return <img src={dataUrl} alt="QR Code" />;
const svgString = await QRCode.toString('https://heolab.com', {
type: 'svg',
width: 300,
});
// SVG can be scaled infinitely — great for print
Logos work because of error correction. Use level H, then overlay a logo covering up to 30% of the QR area:
async function generateQRWithLogo(url, logoSrc) {
const canvas = document.createElement('canvas');
await QRCode.toCanvas(canvas, url, {
width: 300,
errorCorrectionLevel: 'H',
});
const ctx = canvas.getContext('2d');
const logo = new Image();
logo.src = logoSrc;
await new Promise(resolve => logo.onload = resolve);
const logoSize = 60; // ~20% of 300px
const x = (300 - logoSize) / 2;
const y = (300 - logoSize) / 2;
// White background behind logo
ctx.fillStyle = 'white';
ctx.fillRect(x - 4, y - 4, logoSize + 8, logoSize + 8);
ctx.drawImage(logo, x, y, logoSize, logoSize);
return canvas.toDataURL();
}
The jsQR library reads QR codes from image data:
npm install jsqr
import jsQR from 'jsqr';
async function scanFromCamera() {
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
const video = document.querySelector('video');
video.srcObject = stream;
await video.play();
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
function tick() {
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
ctx.drawImage(video, 0, 0);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const code = jsQR(imageData.data, imageData.width, imageData.height);
if (code) {
console.log('Scanned:', code.data);
stream.getTracks().forEach(t => t.stop()); // stop camera
} else {
requestAnimationFrame(tick);
}
}
requestAnimationFrame(tick);
}
Use HeoLab's QR Code Generator to create, customize, and download QR codes for any URL, text, or contact info — no signup required.