The short answer
Use M unless you have a specific reason not to. It recovers 15% of the data bytes and keeps the code small enough to scan reliably at normal print sizes.
Go up to Q or H in four situations: you are placing a logo over the centre of the code, the code will get dirty or wet, it is going on a curved or flexible surface, or it is going somewhere you cannot reprint easily. Drop to L only when you are encoding a lot of data in a clean indoor environment and the code is already at its size limit.
The part most guides leave out is that raising the level costs you something real. It is not a free safety margin, and the rest of this article measures exactly what it costs.
What error correction actually does
Error correction lets a scanner rebuild the encoded data when part of the code is unreadable. It is not damage tolerance in a vague sense; it is a mathematical guarantee about how many data bytes can be missing before decoding fails.
QR codes implement this with Reed-Solomon error correction, the same family of codes used on CDs and in deep-space transmission. Redundant bytes are computed from your data and stored alongside it inside the pattern. When a scanner reads a damaged code, it uses those redundant bytes to reconstruct what is missing.
The behaviour is standardised in ISO/IEC 18004, the QR symbology specification, so every compliant scanner handles it identically. A code generated by us decodes the same way as one generated by anyone else. That is worth knowing when a vendor implies their codes are more reliable than the standard allows.
One consequence people find surprising: the redundancy is spread across the whole symbol rather than pooled in one corner. Damage concentrated in a single area is handled well, which is why a logo over the centre works at all.
The four levels
There are exactly four levels, and their recovery rates are fixed by the standard rather than chosen by the generator. Denso Wave, which invented the QR code, publishes the reference table.
| Level | Name | Data bytes recoverable | Typical use |
|---|---|---|---|
| L | Low | 7% | Clean indoor surfaces, large payloads already near the size ceiling |
| M | Medium | 15% | The default for print and screen. Denso Wave notes it is chosen most often |
| Q | Quartile | 25% | Logo overlays, outdoor signage, packaging that gets handled |
| H | High | 30% | Industrial and factory settings, curved surfaces, harsh weather |
Tips
- These percentages describe data bytes, not surface area. A code is not guaranteed to survive 30% of its physical area being destroyed.
- The three position-detection squares in the corners are not covered by error correction in the same way. Damage those and the scanner may never find the code to begin with.
What each level actually costs in size
This is the number the reference pages do not give you, so we measured it. We encoded five realistic payloads at all four levels with the same encoder our generator uses, and recorded the resulting module grid.
A module is one square in the pattern. More modules at the same printed size means each square is physically smaller, and small squares are what scanners struggle with.
| Payload | Characters | L | M | Q | H |
|---|---|---|---|---|---|
| Short link | 26 | 25x25 | 25x25 | 29x29 | 33x33 |
| Type page URL | 31 | 25x25 | 29x29 | 29x29 | 33x33 |
| URL with UTM tags | 90 | 37x37 | 41x41 | 49x49 | 53x53 |
| [WiFi credentials](/qr-codes/wifi) | 47 | 29x29 | 33x33 | 33x33 | 41x41 |
| Short [vCard](/qr-codes/vcard) | 122 | 41x41 | 45x45 | 53x53 | 57x57 |
Tips
- Moving from L to H widened every code by 32% to 43% per side, which is 74% to 105% more modules in total.
- The penalty grows with payload size. A short link barely changes; a vCard jumps from 41x41 to 57x57.
- Measured with the same encoder the EZQR generator uses. Reproduce it yourself with any ISO/IEC 18004-compliant library and you will get the same grid sizes.
How we measured this, and how to check it yourself
We encoded each payload four times, once per error correction level, and recorded the module grid the encoder produced. No rendering, no scaling, no design settings; the grid size is a property of the encoded data and the level, so it is deterministic and anyone can reproduce it.
The encoder is the same ISO/IEC 18004-compliant library behind the EZQR generator. Because the standard fixes how versions and error correction blocks are chosen, a compliant encoder anywhere will return the same grid for the same input. If you run the same five payloads through a different library and get different numbers, one of the two is not compliant.
Two things we deliberately did not do. We did not test scan success rates, because that depends on printer, substrate, lighting, and camera, and any number we published would be a property of our test rig rather than of the code. And we did not average across payload lengths, because the size penalty scales with payload and an average would hide the effect that matters.
What the data supports is narrow and reliable: for a given payload, moving up the error correction scale increases the module count, and the increase is larger for longer payloads. What it does not support is a claim that one level scans better than another in the real world. That depends on the printed size you choose afterwards, which is the subject of the next section.
Tips
- Payloads used: a short link, a type page URL, a UTM-tagged campaign URL, a WPA WiFi credential string, and a six-field vCard.
- Grid sizes are reported as modules per side, before the quiet zone is added. The quiet zone adds four modules on every edge regardless of level.
Why a higher level can scan worse
This is the counterintuitive part, and it is the reason so many printed codes fail in the field. Error correction protects against damage. It does nothing about resolution, and raising it makes the resolution problem worse.
Picture a code printed at one inch square. At level M with a short link, that inch holds a 25x25 grid, so each module is about one millimetre. Switch to H and the same inch now holds 33x33 modules, so each module drops to roughly 0.77 millimetres. The code did not get safer. It got finer, and the camera has less to work with.
The failure mode this produces is specific and common. Someone puts a logo on a code, bumps error correction to H because that is the advice everywhere, keeps the print size the same, and ends up with a code that scans from four inches instead of twelve. It looks fine on screen at 400 pixels and fails on a table tent.
The rule that resolves it: if you raise the error correction level, raise the printed size too. Our size guide covers the scan-distance maths, and the short version is that printed width should be about one tenth of the intended scanning distance.
The logo question
Most people arrive at this topic because they want a logo in the middle of the code, so it deserves a direct answer.
A centred logo works because it covers a contiguous region the error correction can reconstruct. Keep the logo under roughly 20% of the code area and use Q or H. Above that, you are betting on a reconstruction the standard does not promise.
What actually breaks logo codes is rarely the logo size. It is the combination of a large logo, a long destination URL, and a small print size arriving together. Shorten the URL first, because that shrinks the grid more effectively than anything else you can do. A dynamic code encodes a short redirect rather than a long campaign URL with UTM parameters, which is why dynamic codes tolerate logos better than static ones carrying the same destination.
Contrast matters more than either. A logo in a colour close to the background, or a code printed in two mid-tone colours, fails at any error correction level. Our design guide for logos and dark backgrounds covers the contrast floor, and round and circular designs have their own constraints because rounded modules shrink the effective dark area.
Tips
- Test the logo version at final print size, not on screen. Screens are far more forgiving than paper.
- If the logo has to be large, shorten the payload rather than raising error correction. Fewer characters means fewer modules means larger modules.
How to choose, by medium
Match the level to the physical reality of where the code will live, then set the printed size to suit the level you picked.
| Where the code goes | Level | Why |
|---|---|---|
| Business card, flyer, slide deck | M | Clean, handled briefly, scanned close up |
| Restaurant [table tent or menu](/qr-codes/menu) | M | Indoor, short scan distance, gets wiped but not abused |
| Code with a centred logo | Q or H | The logo occludes a contiguous region |
| Product [packaging](/blog/qr-code-packaging-labels-guide) | Q | Handled, scuffed, sometimes curved |
| Outdoor signage and [billboards](/blog/qr-codes-for-billboards-2026) | Q | Weather and distance, and reprints are expensive |
| Industrial labels, warehouse, workshop | H | Dirt, abrasion, chemicals |
| Curved bottles and cylinders | H | Part of the code is always at an angle |
| Large payload already at the size ceiling | L | Only when the environment is clean and controlled |
Mistakes worth avoiding
The pattern behind most of these is treating error correction as a substitute for print quality. It is not; it is insurance against damage after printing.
Tips
- Raising the level without raising the print size. This is the most common error and it makes scanning harder, not easier.
- Using H everywhere by default. It costs modules on every single code for a benefit most of them never need.
- Encoding a long UTM-tagged URL directly into a static code, then trying to fix the resulting density with error correction. Shorten the payload instead.
- Assuming 30% recovery means 30% of the physical code can be destroyed. It refers to data bytes, and the corner position markers are a separate vulnerability.
- Testing only on screen. A code that scans from a monitor at 400 pixels can fail on a printed card at the same nominal size.
- Printing in low contrast and blaming the error correction level when it fails.
Setting the level when you generate
Every code the EZQR generator produces uses a sensible level by default, and the design step lets you raise it when the situation calls for it. Because the choice interacts with size, the practical sequence is to pick the level, generate, then check the result at the size you will actually print.
Export as SVG or PDF for anything going to print. Vector output scales to any dimension without the softening that kills scan reliability at large sizes, and softening is a resolution problem that no error correction level will rescue.
If you are producing many codes at once, set the level once and apply it across the batch with bulk CSV import rather than adjusting each code by hand. For the wider set of pre-print checks, the best practices guide covers contrast, quiet zone, and scan testing.