Reference
QR code error correction levels
Every code reserves part of itself for repair data. Four levels are available, they cost capacity in exchange for damage tolerance, and picking the wrong one is why codes fail on textured surfaces or behind a logo.
Updated
Part of every QR code is not your data. It is redundancy — extra symbols computed from your data so that a scanner can rebuild the original when some of the pattern is unreadable. The specification offers four amounts of it, and the one you pick decides both how much damage the code survives and how many characters fit before the grid grows.
The four levels
- L (Low) — recovers up to 7% of codewords, and costs roughly 7% of capacity
- M (Medium) — recovers up to 15%, and costs roughly 25% of capacity
- Q (Quartile) — recovers up to 25%, and costs roughly 40% of capacity
- H (High) — recovers up to 30%, and costs roughly 55% of capacity
Read those percentages carefully, because the two figures measure different things. The recovery figure counts codewords — eight-module blocks — not area, and it is a ceiling on what the mathematics can fix, not a guarantee about any particular smudge. The cost figure is the share of a given version’s payload space consumed by the correction data. Level H is not “twice as good as M”; it roughly halves what you can encode.
Why the cost is not linear
The correction data is added in fixed-size blocks tied to the version, so as data grows the encoder is forced up to the next version, which adds four modules to each side and enlarges the whole grid. A payload that fits comfortably in a 37-module code at level M can require a 45-module code at level H. Every extra row makes each individual module smaller at the same printed size, which is a resolution problem — and resolution problems are the actual cause of most failed scans, not damage.
That is the trap. Raising the level to make a code more robust makes it physically harder to resolve. The robustness only pays off if something is going to damage the code; the resolution cost is paid on every single scan.
Choosing by where the code will live
The useful question is not “how safe do I want to be” but “what specifically is going to interfere with this code”.
Screens and digital documents — level L or M. Nothing will damage a code displayed on a monitor or embedded in a PDF that people view rather than print. Every module is crisp, and the scan distance is short. Use the capacity for a smaller, faster-resolving grid instead.
Paper handled indoors — level M. Menus, business cards, flyers, packaging inserts. Some wear, some finger grease, controlled lighting, short scan distance. M covers all of it.
Anything with a logo in the middle — level Q or H, and test the result. This is the one case where the higher levels earn their cost. See the overlay question above for how much you can actually cover.
Outdoor signage, vehicle livery, window vinyl — level Q or H depending on distance, and increase the printed size to compensate for the extra modules. Sun fading, rain, road grime and partial occlusion all take modules out.
Textiles, curved bottles, laser marking on metal — level H. Fabric weave distorts the grid, curvature compresses one axis, and laser marking on metal produces inconsistent contrast. This is the environment the high levels were designed for.
The interaction with payload type
Some payloads are dense before you touch the level. A vCard carrying a name, title, organisation, two phone numbers, an email and a postal address is often several hundred bytes, which lands it in a large version at level M already. Adding H on top can push it past what a business card sized print can resolve — the code technically encodes, and then nobody can scan it. Trimming fields is a better answer than raising the level.
Wi-Fi credentials sit at the other extreme. Even a long passphrase produces a short payload, so a Wi-Fi code has room for level Q or H without the grid growing beyond what a table tent can carry. If the code will be laminated and handled by hundreds of people, spend the capacity.
Payment payloads deserve their own caution. A misread digit in a UPI or bank transfer string does not usually produce a silent error, because the checksum in the payload catches it — but it does produce a failed payment at a counter with a queue behind it. Level Q is a reasonable floor for anything stuck to a counter.
Testing, not arithmetic
The percentages give you a starting point; they do not tell you whether your specific code works. The only reliable check is physical. Print at final size on the final material, then scan from the distance people will actually stand at, with a cheap phone rather than your own, under the lighting the code will live in. If you are covering part of the code with a logo, scan it after the logo is applied — not the clean version from the design file.
A code that scans in five attempts out of five from arm’s length is fine. One that needs a second attempt is already marginal, and marginal codes get worse as ink fades and surfaces scuff. Drop the payload length, raise the size, or lower the ambition on the logo, in that order.