How QR Codes Work
A QR (Quick Response) code is a 2D barcode that encodes data as a matrix of black and white squares. Developed by Denso Wave in 1994, it supports multiple encoding modes:
- Numeric (0–9) — most compact, 7,089 chars max
- Alphanumeric (0–9, A–Z, space, $%*+-./: ) — 4,296 chars max
- Byte (any binary, typically UTF-8) — 2,953 bytes max
- Kanji — 1,817 characters max
Error correction (L/M/Q/H) allows QR codes to remain readable even when 7–30% of the code is damaged or obscured — important when adding a logo to the center.
What Can a QR Code Encode?
- URL:
https://example.com - vCard / contact:
BEGIN:VCARD FN:Jane Doe TEL:+1234567890 END:VCARD - Email:
mailto:jane@example.com?subject=Hello - SMS:
sms:+1234567890?body=Hello - WiFi credentials:
WIFI:T:WPA;S:NetworkName;P:password;; - Bitcoin:
bitcoin:1A1zP1eP5QGefi2DMPTfTL5SLmv7Divf?amount=0.001 - Plain text: Any UTF-8 string
Generate QR Codes in JavaScript (No Server)
// Using the qrcode library
import QRCode from "qrcode";
// To data URL (for img src)
const dataUrl = await QRCode.toDataURL("https://example.com", {
width: 300,
margin: 2,
color: { dark: "#000000", light: "#ffffff" },
errorCorrectionLevel: "M",
});
document.querySelector("img").src = dataUrl;
// To canvas element
await QRCode.toCanvas(document.getElementById("canvas"), "https://example.com");
// To SVG string
const svg = await QRCode.toString("https://example.com", { type: "svg" });
Error Correction Levels
- L (Low): 7% recovery — smallest QR code, best for clean, undamaged environments
- M (Medium): 15% recovery — good general default Q (Quartile): 25% recovery — use when adding a center logo
- H (High): 30% recovery — maximum recovery, largest code; use for logos or physically printed codes likely to get damaged
Adding a Logo to the Center
async function qrWithLogo(text, logoUrl) {
const canvas = document.createElement("canvas");
await QRCode.toCanvas(canvas, text, { width: 300, errorCorrectionLevel: "H" });
const ctx = canvas.getContext("2d");
const logo = new Image();
logo.src = logoUrl;
await new Promise(r => (logo.onload = r));
// Center logo at 20% of QR size
const logoSize = canvas.width * 0.2;
const x = (canvas.width - logoSize) / 2;
const y = (canvas.height - logoSize) / 2;
ctx.drawImage(logo, x, y, logoSize, logoSize);
return canvas.toDataURL("image/png");
}
Use error correction level H when adding a logo — the logo covers the center, and H provides enough redundancy to recover that data.
Reliable Scanning: Best Practices
- Minimum size: Print QR codes at least 2cm × 2cm (0.8in). On digital screens, at least 200×200px.
- Quiet zone: Leave at least 4 modules of white space around the code.
- Contrast: Black on white is most reliable. Dark on light works; light on dark (inverted) has inconsistent support — most modern scanners handle it, but avoid for print.
- Shorten URLs: Shorter data = simpler QR code = more reliable scanning. Use a URL shortener for long URLs.
- Test before printing: Always scan your final QR code with multiple devices before mass printing.
QR Code Tracking with UTM Parameters
// Track QR code scans in Google Analytics
const url = new URL("https://example.com/landing");
url.searchParams.set("utm_source", "print");
url.searchParams.set("utm_medium", "qr");
url.searchParams.set("utm_campaign", "business-card-2024");
// This URL in the QR code reports as a separate traffic source
url.toString()
// https://example.com/landing?utm_source=print&utm_medium=qr&utm_campaign=business-card-2024
Generate QR Codes Instantly
Use ToolsVito's QR Code Generator to create a QR code for any URL or text, customize colors, and download as PNG — all in your browser.