TL;DR: QR codes encode text data (URLs, WiFi passwords, contact info, etc.) into a scannable black-and-white grid. Keep your data short for easier scanning, use high contrast colors, leave a quiet zone margin, and always test before printing. You can generate them for free right in your browser.
QR codes are everywhere these days. Restaurant menus, product packaging, business cards, concert tickets, payment terminals — even gravestones (seriously). Those little black-and-white squares encode data that any smartphone can read in a fraction of a second.
Despite looking like they were designed by a confused robot, QR codes are actually pretty clever. Let me break down how they work, what you can put in them, and how to make ones that scan perfectly every time.
QR stands for "Quick Response," which is ironic because I have spent an unreasonable amount of time holding my phone at various angles trying to scan a poorly printed one at a restaurant.
How QR Codes Actually Work
QR codes were invented by Denso Wave in 1994 to track automotive parts. They encode data in a grid of black and white squares called "modules." Here is what is inside that pattern:
- Finder patterns: Those three big squares in the corners. They help your phone's camera locate and orient the code instantly, even at an angle.
- Alignment patterns: Smaller squares that correct for perspective distortion (like when you scan at an angle).
- Timing patterns: Alternating black/white lines that define the grid spacing.
- Data + error correction: The actual encoded information, plus backup bits for resilience.
Error Correction: The Built-in Safety Net
This is the cool part. QR codes use Reed-Solomon error correction, meaning they can still scan even if part of the code is damaged, dirty, or covered up:
- L (Low): Recovers up to 7% damage
- M (Medium): 15% — the default for most generators
- Q (Quartile): 25%
- H (High): 30% — this is how you can slap a logo in the center and it still works
Using "H" error correction lets you place a small logo in the center of your QR code without breaking it. The logo covers some data modules, but the error correction fills in the gaps. Pretty neat engineering for 1994.
What Can You Put in a QR Code?
URLs (The Most Common Use)
Just encode the full URL. Shorter URLs create smaller, easier-to-scan codes:
https://codetoolspro.com
WiFi Credentials (The Real Hero)
This is my favorite QR code use case. Create one for your home WiFi, print it, and stick it on the fridge. Guests scan it and they are connected. No more spelling out your password:
WIFI:T:WPA;S:MyNetworkName;P:MyPassword;;
// Real example:
WIFI:T:WPA;S:CoffeeShop_5G;P:Welcome2024;H:false;;
The format: T: = security type (WPA, WEP, or nopass), S: = network name, P: = password, H: = hidden network (true/false).
Email, Phone, SMS
mailto:hello@example.com?subject=Hi&body=Hello%20there
tel:+1234567890
sms:+1234567890?body=Hello%20from%20QR
Contact Card (vCard)
BEGIN:VCARD
VERSION:3.0
FN:John Doe
ORG:Acme Corp
TEL:+1234567890
EMAIL:john@example.com
URL:https://johndoe.com
END:VCARD
Calendar Event
BEGIN:VEVENT
SUMMARY:Team Meeting
DTSTART:20260401T100000
DTEND:20260401T110000
LOCATION:Conference Room B
END:VEVENT
Generating QR Codes with JavaScript
Want to generate them in your own projects? Here is how with the qrcode library:
import QRCode from 'qrcode';
// Generate as a data URL for an img tag
const dataUrl = await QRCode.toDataURL('https://example.com', {
width: 300,
margin: 2,
color: { dark: '#000000', light: '#ffffff' },
errorCorrectionLevel: 'M'
});
document.getElementById('qr-img').src = dataUrl;
// Or generate as SVG (scalable, smaller file)
const svgString = await QRCode.toString('https://example.com', {
type: 'svg',
width: 300,
margin: 2
});
Best Practices for QR Codes That Actually Work
Size and Distance
The rule of thumb for minimum QR code size:
Minimum size = Scanning distance / 10
Business card (30 cm scan) → at least 3 cm
Poster (3 meters scan) → at least 30 cm
Contrast and Colors
Dark modules on a light background, with at least 4:1 contrast ratio. Black on white is the most reliable. If you use brand colors, make sure the "dark" color is genuinely dark and the "light" one is genuinely light.
Avoid: light gray on white, colored-on-colored with low contrast, or inverted codes (white on black). Some older phone cameras really struggle with these.
Quiet Zone
QR codes need a blank margin (called a "quiet zone") around them — at least 4 modules wide. Do not crop the code right to the edge of the pattern. It is like the code needs personal space to function properly.
Always Test!
Before printing 10,000 flyers with your QR code, scan it with multiple phones:
- iPhone camera app
- Android camera app
- At least one third-party scanner app
- At the actual scanning distance and lighting conditions
Static vs. Dynamic QR Codes
Static codes bake the data directly into the pattern. Once printed, you cannot change where they point. Dynamic codes encode a short redirect URL instead — you can update the destination without reprinting. Dynamic codes need a server for the redirect, but they are a lifesaver for marketing materials and product packaging.
Common Mistakes to Avoid
- Too much data. Keep it under 300 characters when possible. Long vCards or paragraphs create super dense codes that are hard to scan.
- Printing too small. What scans fine on screen might fail on a tiny business card.
- No fallback. Always show the URL or info near the QR code for people who cannot or prefer not to scan.
- Linking to non-mobile-friendly pages. QR codes are scanned on phones. Your destination MUST work on mobile.
A QR code that does not scan is like a door with no handle. It looks like it should work, but you just end up frustrated and confused.
QR codes are a free, simple, and surprisingly powerful way to bridge the physical and digital worlds. Get the basics right — good contrast, proper size, short data, and always test — and your codes will scan reliably every time.
Try It Yourself
Generate QR codes for URLs, WiFi credentials, email addresses, and plain text instantly. Download as PNG or SVG.
Open QR Code Generator →