A QR code is only as good as the scan it earns. Get the size, contrast, quiet zone, and error correction right and it decodes instantly from a phone held at arm's length. Get any one of them wrong and it becomes a dead square that nobody can use. This guide covers exactly what makes a QR code reliable — and how to test it before you commit to print.
How a QR code stores data
A QR code is a two-dimensional grid of black and white squares called modules. The three large squares in the corners are finder patterns that let a scanner locate and orient the code from any angle, while smaller alignment and timing patterns keep the grid readable even when the image is skewed or curved.
Everything else encodes your data — usually a URL — as binary, arranged in a fixed sequence and protected by a mathematical safety net. The more characters you encode, the larger the grid has to be. That grid size is described in versions, from version 1 (21×21 modules) up to version 40 (177×177). A short link stays at a low version with big, easy-to-read modules; a long link forces a higher version packed with tiny modules that a camera struggles to resolve.
Error correction levels explained
QR codes use Reed–Solomon error correction, the same family of math that protects CDs and DVDs. It adds redundant data so a scanner can rebuild the original message even when part of the code is scratched, smudged, or covered. You choose from four levels, each recovering a different fraction of the code:
| Level | Data recovery | Best for |
|---|---|---|
L (Low) | ~7% | Clean digital display, screens, minimal wear expected — keeps the code sparse |
M (Medium) | ~15% | The sensible default for most print and web use |
Q (Quartile) | ~25% | Codes with a small logo, or printed on textured/curved surfaces |
H (High) | ~30% | Logos, harsh environments, packaging that may smudge or wear |
There is a trade-off. Higher correction means more redundant modules, which pushes the code to a higher version and makes it denser. A dense code has smaller modules that are harder to scan at a distance or small size. So don't reach for H by reflex — use M as your baseline and step up only when you add a logo or expect physical damage.
The quiet zone and contrast
Around every QR code sits a mandatory blank margin called the quiet zone. The specification calls for a border of at least 4 modules of empty space on all sides. Without it, the scanner can't tell where the code ends and the surrounding artwork begins, and it simply fails to lock on. Designers crop this margin away constantly — it is one of the single most common reasons a code won't scan.
Contrast is the other make-or-break factor. Scanners read a QR code by distinguishing dark modules from light background, so you need a strong luminance difference between the two. Dark-on-light is what every scanner expects: black (or a dark colour) modules on a white (or very light) background. Coloured codes can work, but only if the dark/light contrast stays high.
The classic failure is an inverted code — light modules on a dark background. Many scanners are built to assume dark-foreground-on-light and will refuse an inverted code even when the contrast is technically fine. If your brand palette pushes you toward a dark background, test relentlessly, and when in doubt keep the code dark-on-light and place your dark styling in the surrounding layout instead.
Size and the 10:1 scan-distance rule
The most reliable sizing guideline is the 10:1 distance-to-size ratio: the minimum width of the code should be about one-tenth of the distance from which it will be scanned.
- Scanned from 30 cm (a product label in hand) → at least 3 cm wide.
- Scanned from 2 m (a table tent or window sticker) → at least 20 cm wide.
- Scanned from 5 m (a poster or billboard) → at least 50 cm wide.
As an absolute floor for print, keep any code at least 2×2 cm (about 0.8 inch). Below that, module size drops under the resolution most phone cameras can reliably resolve, and denser codes need to be even larger. Remember that error correction level and URL length both increase density, so a code that works at 2 cm with a short link and level M may need 3–4 cm once you add a logo and a longer URL.
Keep the URL short and the code sparse
Everything above compounds through one variable you fully control: how much data you encode. A shorter URL means fewer modules, a lower version, larger squares, and a far more forgiving scan.
Compare a long, parameter-laden campaign link with dozens of tracking arguments against a tidy short link. The long one balloons the code into a dense thicket of tiny modules; the short one stays sparse and readable from across a room. Practical ways to keep it light:
- Use a short domain and path rather than a raw deep link stuffed with query parameters.
- Move campaign tracking into a redirect (see dynamic codes below) instead of baking
utm_*parameters into the encoded URL. - Prefer
https://without unnecessary subpaths; avoid encoding session tokens or long IDs. - Skip the
www.if your site resolves without it — every character counts.
Static vs dynamic codes and tracking
This is the decision that most affects what a QR code can do after it's printed.
Static QR codes
A static code encodes the final destination URL directly in the pattern. It works forever without any server, but it has two hard limits: the destination can never be changed once printed, and it cannot report a single scan. If the target page moves or the campaign ends, the code is dead. Static codes suit permanent, unchanging links — a Wi-Fi network, a vCard, a fixed homepage.
Dynamic QR codes
A dynamic code encodes a short redirect URL pointing at a server you control, which then forwards the visitor to the real destination. That indirection unlocks two big advantages:
- Editable destination. Change where the code points at any time — fix a typo, swap a landing page, or repoint an expired campaign — without reprinting anything.
- Scan analytics. Because every scan passes through your redirect, you can measure scan count, timing, rough location, and device type.
As a bonus, the encoded redirect URL is usually short, so dynamic codes stay less dense and more scannable than a static code carrying a long link. The trade-off is a dependency on the redirect service staying online. For any marketing or print run of consequence, dynamic is almost always the right call. If you want that redirect and analytics layer handled for you, a dedicated generator like QR Cheetah builds dynamic codes with editable destinations and scan tracking.
Build a QR code that actually scans
Create dynamic QR codes with editable destinations, logo support, and built-in scan analytics — the right defaults baked in.
Create a QR code with QR Cheetah →Testing before you print
A QR code that scans on your design monitor can still fail in the real world. Physical printing, lighting, and camera variety introduce failures you won't see on screen, so test the actual output:
- Scan with multiple devices. Try several phones across iOS and Android — native cameras behave differently from third-party scanner apps.
- Test at the real distance and size. Print a proof at final dimensions and scan it from where users actually will, not from 10 cm on your desk.
- Vary the lighting. Check bright sun, dim indoor light, and glare on glossy stock. Matte finishes scan more reliably than glossy ones.
- Confirm the destination. Follow the link and verify the page loads, is not a typo, and works on mobile. A perfect code pointing at a dead URL is still a failure.
- Re-test after every design change. Adding a logo, tightening the margin, or recolouring can silently break a code that worked a minute ago.
Common mistakes to avoid
- Too small. The number one failure. Apply the 10:1 rule and never go below the 2 cm print floor.
- Low contrast. Pale modules, busy photo backgrounds, or gradients behind the code all defeat the scanner. Keep it dark-on-light with clear separation.
- No quiet zone. Cropping the 4-module blank margin to fit a layout is a guaranteed scan failure.
- Inverted colours. Light-on-dark codes are refused by many scanners even at good contrast.
- Dead or typo URL. A static code baked with a broken link can't be fixed after printing — verify the destination before committing.
- Over-styling. Rounded modules, heavy gradients, and oversized logos erode readability. Decoration should never come at the cost of a clean scan.
- Skipping the test. Never send a code to print until you've scanned the real proof on real phones in real light.