How QR Codes Work: Error Correction, Versions, and Designing Codes That Scan
What the patterns in a QR code actually encode, how Reed–Solomon error correction lets codes survive logos and damage, and the practical rules for size, contrast and print.
Reading the anatomy
The three large squares are finder patterns — they let a scanner locate and orient the code from any rotation. The smaller inner squares are alignment patterns for perspective correction; the alternating line between finders is the timing pattern that establishes the module grid. Everything else is data and error-correction codewords, laid out in a zigzag with a mask applied to avoid confusing runs of same-color modules.
Capacity scales with version: version 1 is 21×21 modules, version 40 is 177×177 holding up to ~4,296 alphanumeric characters. More data means a denser grid — and a harder scan from a distance.
Error correction is a design budget
QR codes carry Reed–Solomon error correction at four levels: L recovers ~7% damage, M ~15%, Q ~25%, H ~30%. This redundancy is why a code still scans with a logo punched through its middle — the logo *is* damage, spent from the correction budget. Center logos should cover well under the level’s ceiling (under ~10% of area at level H is comfortable), because real-world scuffs, glare and print defects draw from the same budget.
Rules for codes that actually scan
- Quiet zone: keep a margin of 4 modules of background around the code; crowding it is the most common scan failure.
- Contrast: dark modules on light background, roughly 4.5:1 or better. Inverted (light-on-dark) codes fail in many scanner apps.
- Print size: minimum ~2×2 cm for arm’s-length scans; for posters, scan distance ÷ 10 is a serviceable size rule.
- Shorten the payload: a shorter URL means a lower version, bigger modules, and scans from farther away.
- Test on paper, not just on screen — ink spread and matte lamination change everything.
Static vs dynamic codes
A static code encodes the destination directly: free, permanent, private, but unchangeable once printed. "Dynamic" codes encode a redirect URL whose target you can edit later — at the cost of depending on the redirect service’s uptime, subscription and analytics tracking. For anything long-lived in print, either accept the static trade-off or run the redirect on a domain you control.