A restaurant printed 5,000 menus with a QR code in the lower-right corner. Looked fine on screen. In the wild, half the phones in the room could not scan it. The code sat on a dark photograph with no quiet zone, the finder patterns were half-covered by the brand mark, and the data itself was a 90-character URL pointing at a tracking redirect chain. QR codes are forgiving, but they are not magic. The ISO/IEC 18004 spec defines exactly how they encode data and exactly what a scanner needs to recover it; getting it right is a handful of concrete decisions, not guesswork.

How a QR code encodes data

A QR code is a square grid of modules — black or white squares, not pixels. The spec defines 40 versions, each one a grid of (version × 4) + 17 modules per side. Version 1 is 21×21. Version 40 is 177×177. The version number is not a quality setting; it is the physical size of the matrix, and it is chosen for you by the amount of data you put in and the encoding mode you use.

Encoding modes pack data at different densities. Numeric mode fits three digits into 10 bits. Alphanumeric (uppercase letters, digits, space, and a handful of punctuation) fits two characters into 11 bits. Byte mode fits one byte per 8 bits and is what most URLs end up in. The encoder picks the most efficient mode per segment, so a URL with lowercase paths sits in byte mode and eats capacity fast.

Roughly: version 5 at error-correction level Q holds around 64 bytes of byte-mode data. Version 10 at Q holds around 271. If your URL is 40 characters you can stay on a small, scannable version; if it is 200 characters you are forced into a denser matrix, and dense matrices punish print defects.

Error correction: L, M, Q, H

QR codes use Reed-Solomon error correction, and 18004 defines four levels:

  • L recovers 7% of damaged codewords.
  • M recovers 15%.
  • Q recovers 25%.
  • H recovers 30%.

Higher recovery costs capacity. The same version that holds 271 bytes at Q holds about 395 at L. The temptation is to always pick H so the code survives anything. The tradeoff is that H forces a larger version for the same data, which means smaller modules at the same print size, which means a code that is harder to scan in the first place. You are trading resilience to damage for baseline scannability.

The honest defaults: M for clean digital display, Q for anything printed on paper or packaging where smears and folds happen, H only when you plan to overlay a logo on the code and need the redundancy to cover it. Picking H and then printing tiny is a wash.

Design pitfalls

Most unscannable codes I see fail on one of four things.

Contrast. The spec wants dark-on-light or light-on-dark; it does not care about color, but scanners do. A black-on-white code is what every phone camera is trained on. Yellow on white, blue on black, or a 20% gray background under black modules all drop the scan rate. Brand color belongs in the frame around the code, not in the modules.

Logo occlusion of the finder patterns. Three corners of a QR code carry the large square finder patterns — the nested squares the scanner locks onto first. Cover any of those and the code will not scan at all. Center is the only safe place for a logo, because that area carries data error correction can rebuild. Keep the logo under about 30% of the total area, or you burn through even H-level redundancy.

Missing quiet zone. The spec mandates a 4-module-wide blank margin on every side. That margin is how the scanner finds the edges of the code in a busy image. Designers love to butt the code against other artwork to save space; the result is the second most common scan failure after contrast. Four modules means four of the small squares, not four pixels. On a version 5 code printed at 2cm, that is a real, visible margin.

Inverted colors. Dark background with light foreground looks striking on a poster and breaks a meaningful fraction of scanners, particularly older Android camera apps. If you must invert, test on more than one device, and accept that some users will photograph twice and give up.

Choosing the content

What you put inside the code drives its version more than any design choice. A URL is usually right. A vCard works for contact exchange but is verbose and pushes you up a version or two. WiFi credentials encoded into a WIFI: URI are useful for venue signage. Plain text is fine for short notes but offers no destination control.

Shorten the URL first. A 90-character tracking URL on a print run is a self-inflicted wound. A short path like https://devtidy.com/qr keeps you on version 3 or 4 at M instead of version 7 at Q, and the difference shows up in scan reliability on a smudged table tent.

One digression: the URL should be HTTPS and should not redirect through three hops. Some scanners open the final destination; some show the first hop; some refuse redirects entirely. Send users to the real destination.

Generate and test

Build the code with the QR Code Generator, pick Q for print, keep the URL short, and export at the size you will actually print. Then test the way a real user will: photograph it with a cheap two-year-old Android phone, under restaurant lighting, at the physical distance and angle a customer will use. A flagship iPhone in good light will scan almost anything. That tells you nothing. The cheap phone tells you the truth.

If the scan is flaky, fix it in this order: shorten the URL to drop a version, raise contrast, add the quiet zone. Then re-test on the same bad phone.

FAQ

What error correction level should I use for print?

For paper, packaging, or anything that will get smudged or folded, Q (25% recovery) is the right default. Use H only if a logo will sit on top of the code; the extra redundancy covers the occluded modules. M is fine for clean digital screens, and L is rarely worth the small capacity gain.

How big should the quiet zone be?

Four modules on every side — that is the spec requirement, not a suggestion. On a version 5 code that is four of the small squares, which at a 2cm print width is a couple of millimeters of blank space. Skipping the quiet zone is one of the most common reasons a printed code fails to scan.

Can I put my logo in the middle of the QR code?

Yes, but only in the center, and only if you are using error-correction level H and keeping the logo under about 30% of the code area. Never cover the three corner finder patterns — the scanner locks onto those first, and hiding one of them makes the code unscannable. Build it in the QR Code Generator, then test on a cheap phone at the real print size before you ship.