QR codes that actually scan: error correction, capacity and print size
A QR code either scans instantly or it frustrates everyone who tries. The difference is rarely the generator. It is usually one of four things: too much data, too little contrast, no quiet zone, or printed too small for the distance.
Versions, not sizes
A QR code's size is described by its version, from 1 to 40. Version 1 is a 21 by 21 grid of modules, and each version adds 4 modules per side, so version 40 is 177 by 177.
The generator picks the smallest version that fits your data at the error correction level you chose. You do not usually set it directly. What you control is the amount of data and the error correction level, and both change the version, which changes how dense the printed code is.
Density is the thing that matters physically. A version 3 code has chunky modules that a phone camera resolves at arm's length. A version 20 code holding the same physical width has modules four times smaller, and now the camera has to be close, the print has to be crisp and the lighting has to be decent.
Shorter data is not a nice to have. It is the single biggest lever on whether the code scans.
Error correction levels
QR uses Reed-Solomon error correction, and there are four levels:
| Level | Recovers up to | Cost |
|---|---|---|
| L | 7% of the code | Smallest, least robust |
| M | 15% | The usual default |
| Q | 25% | Noticeably larger |
| H | 30% | Largest |
Higher levels do not add safety for free. The correction data occupies the same grid, so going from L to H on the same content can push the code up several versions, which makes every module smaller at a fixed print width. Beyond a point you have traded away more legibility than you gained in damage tolerance.
The useful rule: use M for anything on a screen or on clean print. Use Q or H only when the code will be damaged, curved, partially covered or printed on something that scuffs, such as a product label, a sticker on a machine, or a code on fabric. Use L essentially never, since the saving is small and the margin is thin.
Encoding modes change everything
QR has several encoding modes with very different efficiencies:
| Mode | Characters | Bits per character |
|---|---|---|
| Numeric | 0 to 9 | 3.33 |
| Alphanumeric | 0 to 9, A to Z uppercase, space, $%*+-./: | 5.5 |
| Byte | Any, usually UTF-8 | 8 or more |
| Kanji | Shift JIS | 13 |
Alphanumeric mode is the one worth knowing about, because it is restricted to uppercase and it is 30% denser than byte mode. A URL written in lowercase falls into byte mode. The same URL in uppercase can use alphanumeric mode and produce a smaller, more scannable code.
This is safe for the scheme and the host, which are case insensitive, and unsafe for the path and query on most servers, which are not. So HTTPS://EXAMPLE.COM is fine, and HTTPS://EXAMPLE.COM/MyPage is a different resource from /mypage unless your server says otherwise. In practice this means the trick pays off best for short domain only codes, which is a good argument for pointing QR codes at a short redirect URL rather than a deep link.
For rough calibration: about 25 characters of URL sits comfortably around version 2 or 3 at level M. Around 100 characters pushes toward version 6 or 7. A URL with a long tracking query string can easily double the version, which is why campaign parameters deserve scrutiny before they go into a printed code. The URL parser makes it easy to see exactly which parameters are riding along.
The quiet zone
A QR code needs an empty margin of at least 4 modules on all sides. This is part of the specification, not a design preference. The decoder uses the contrast between the quiet zone and the finder patterns to locate the code in the camera frame.
Codes that fail to scan against a patterned background, or when butted up against other artwork, are usually quiet zone failures. Micro QR reduces the requirement to 2 modules, but standard QR needs 4, and more does not hurt.
The margin must be the same colour as the light modules. A white code on a dark background with a dark margin has no quiet zone at all.
Contrast and inversion
Dark modules on a light background. Some decoders handle inverted codes, many do not, and the specification assumes the standard polarity.
Contrast should be high and the foreground should be genuinely dark. Mid tone brand colours on white are the common failure: a code in a light grey or a pastel may look fine on a designer's calibrated monitor and fail on a phone camera in a dim room. If you must colour a code, keep the dark modules dark and leave the background white.
Avoid gradients across the modules, and avoid printing on anything glossy or reflective. A laminated menu under a ceiling light is a well known bad case.
Logos in the middle
Placing a logo over the centre works because of error correction. The covered modules are treated as damage, and Reed-Solomon reconstructs them.
Two rules keep it reliable. Stay well inside the budget: at level H you have 30% to spend, and covering more than about 15% of the code area leaves nothing for real world damage, smudges and camera noise. And keep the logo central. The three large finder patterns in the corners and the alignment patterns are used to locate and orient the code before any error correction happens, so covering any part of them breaks the scan outright regardless of level.
Raising to level H specifically to fit a logo is the one case where the higher level is clearly worth the extra version.
How big to print it
The common rule of thumb is that the code's width should be about one tenth of the intended scan distance.
| Scan distance | Minimum code width |
|---|---|
| 30 cm, a printed page | 3 cm |
| 1 m, a table tent | 10 cm |
| 3 m, a poster | 30 cm |
| 10 m, a billboard | 1 m |
That is a minimum, and it assumes a low version code and good contrast. Add margin for a denser code, for print that may be imperfect, and for users with older phones. There is no downside to a code being larger than necessary.
For print, keep each module at least 0.5 mm, and prefer vector output such as SVG or EPS so the modules stay crisp at any size. Bitmap output scaled up in a layout program produces soft edges that confuse decoders. Watch for ink spread on absorbent stock, which thickens dark modules and closes the gaps between them.
Test before you commit
Generating a code and checking it looks right is not a test. Print it at final size, on the final material, and scan it with several phones, including at least one older Android device, from the distance a real user will stand at, under the lighting the code will actually live in.
The QR code generator runs entirely in the browser, so the content of your code, which may be a private URL or a WiFi password, is never sent anywhere. Generate, download at the size you need, and test the artefact rather than the screen.
Related reading: generate QR codes in your browser covers the tool and the common content formats, and parse a URL into its parts covers trimming the URL you are about to encode.