
July 17, 2026
Testing QR Code Error Correction: How Much Damage Can QR Codes Survive?
By Said Ouarrak · Founder
You have almost certainly seen a claim like "a QR code can lose 30% of its surface and still scan." It sounds reassuring right up until the moment a printed code stops working and nobody can tell you why. The short version of what our tests confirmed: the 30% number describes what the Reed-Solomon error-correction math can theoretically rebuild, and it has almost nothing to do with what survives in the real world. In this guide we separate the spec from the practice with reproducible measurements, show you which parts of a QR code fail first, and give you a repeatable 5-step testing routine so you can verify your own codes before you print them.
If you are new to how these four settings work, read what each error-correction level means first, then come back to the damage numbers here.
What the specification actually promises
The QR code standard, ISO/IEC 18004, defines four error-correction levels. Each one adds redundancy to the data codewords so a decoder can rebuild the payload from a partially damaged code:
| Level | Spec-level erasure recovery |
|---|---|
| L | 7% of codewords |
| M | 15% of codewords |
| Q | 25% of codewords |
| H | 30% of codewords |
Two caveats are hiding in that table.
First, the percentage applies to data codewords available for reconstruction, not to 7–30% of the square you see. The finder patterns (the three large squares), the timing lines, the format information blocks, and the alignment pattern are not protected by the same recovery mechanism.
Second, erasure tolerance assumes the damaged symbols are known and spread across the interleaved blocks. Real damage is never that tidy: a sticker, a teardrop of coffee, or a crease wipes out a contiguous region, and a single destroyed structural feature can stop the scanner before Reed-Solomon ever gets a chance to work.
That gap between theory and reality is exactly what we set out to measure instead of repeating a marketing number.
How we measured it (and how you can repeat it)
To keep the result honest and reproducible, the entire experiment is a committed script in this site's repository at scripts/qr-damage-experiment.js. It uses the exact QR encoder this site ships (qrcode v1.5.4) and an independent open-source decoder (jsqr v1.4.0), with a fixed random seed. Every number below can be regenerated with:
node scripts/qr-damage-experiment.js --seed 20260717 --trials 24
The payload is a real destination URL (https://www.qrgenerators.dev/), 29 characters. That matters, because payload length changes the module grid:
| Level | Grid (modules) | ISO version |
|---|---|---|
| L | 25×25 | 2 |
| M | 29×29 | 3 |
| Q | 29×29 | 3 |
| H | 33×33 | 4 |
For each level we generated the code, applied a damage model to the raw module grid, rendered the result to a high-resolution bitmap with a proper quiet zone, and attempted an actual decode. Each cell represents 24 independent trials. "OK" means the payload decoded byte-for-byte.
We ran four damage models that map to real-world failure modes:
- Center logo — a solid black square exactly centered (the way most people drop their brand mark in).
- Inner scribble — a square blotch in the inner area of the code (pen, marker, coffee).
- Corner smudge — a square in the bottom-right region (the corner without a finder pattern).
- Random marks — a scatter of individual modules turned black (dust, scratches, print defects).
What we measured — level by level
Center logo
| Damage area | L | M | Q | H |
|---|---|---|---|---|
| 5% | 0% | 100% | 100% | 100% |
| 10% | 0% | 0% | 100% | 100% |
| 15% | 0% | 0% | 0% | 100% |
| 20% | 0% | 0% | 0% | 0% |
The pattern is clear: a centered logo is survivable, but only if you pick the right level. Level L died at even 5%, M managed 5%, Q managed 10%, and H was still decoding at 15% of the code covered. That is the strongest, most practical argument for choosing level H whenever you intend to place a logo, because the logo sits in the center of the grid where the data lives.
Inner scribble
| Damage area | L | M | Q | H |
|---|---|---|---|---|
| 5% | 4% | 42% | 54% | 75% |
| 10% | 0% | 17% | 33% | 42% |
| 15% | 0% | 0% | 8% | 42% |
| 20% | 0% | 0% | 0% | 4% |
Marking over the face of a code is the most common real-world accident, and the numbers show why the spec table is optimistic. Where ISO/IEC 18004 says M tolerates 15% and H tolerates 30%, our measurements only reached meaningful success around 5–10% at M and 10–15% at H — roughly a third to one half of the theoretical figure, and only when the blotch happened to avoid the alignment pattern.
There is also a visible ordering effect: when the random inner position happened to land on the alignment structure, even a large level-H code failed. Recovery is not simply proportional to the area covered; it depends on which modules the damage touches.
Corner smudge (bottom-right)
| Damage area | L | M | Q | H |
|---|---|---|---|---|
| 5% | 0% | 0% | 0% | 100% |
| 8% | 0% | 0% | 0% | 0% |
This row is the least intuitive and the most valuable. The bottom-right corner has no finder pattern, so people assume it is a safe place to let damage occur. It is not. Larger grids carry a single alignment pattern in that corner, and a smudge large enough to cover it defeated every level — including H, which the spec says can recover 30%. Note the 5% / 8% difference: at 5% the smudge footprint on the largest grid (33×33) still missed the alignment module, and H decoded everything; at 8% it swallowed the alignment pattern and H collapsed to 0%. A few modules of position decided the outcome.
Random marks
| Damage area | L | M | Q | H |
|---|---|---|---|---|
| 5% | 0% | 0% | 0% | 0% |
| 10% | 0% | 0% | 0% | 0% |
This is the result that most directly refutes the "remove any 30%" folklore. Randomly scattered marks almost inevitably touch a finder, a timing line, or the format information within the first few percent, and the moment they do, no level of error correction saves you. Detection fails before reconstruction can start.
The practical summary of all four tables: structure beats redundancy. Keep the three finder patterns, the timing lines, and — once the grid is large enough to have one — the bottom-right alignment pattern pristine, and the EC level only then begins to help.
A 5-step testing routine for your own codes
The mistake most people make is repeating the theoretical percentages instead of testing the actual code that will go on the flyer, the label, or the box. This is the routine we used, generalised so you can apply it to your design without any tooling beyond what this site already gives you.
Step 1 — Fix the scan scenario first. Decide the physical size, the material, the viewing distance, and the lighting before generating anything, because those variables determine which error-correction level is even worth testing. A business card read at arm's length under office light is a completely different problem from a drink menu stamped with condensation. Write the scenario down: this decision anchors every later choice, and it is the step almost everyone skips. If you are unsure about the physical dimensions, our QR code sizing guide shows how distance sets the minimum print size.
Step 2 — Generate the code at the candidate level. Use the QR code generator on this site with error-correction set to H as your default candidate. If the final code is larger than a giant sticker and there is zero risk of damage or a logo, dropping to M is reasonable; start at H and only move down if the extra modules break your layout. Export at the exact size and resolution you will use in production — a 300 DPI PNG or an SVG — so the pattern you test is the pattern you print.
Step 3 — Recreate realistic damage, not random noise. Rather than "removing 30%," damage the code the way it will actually be damaged: place your logo over the center, smear ink across the face, cover the bottom-right corner, run a crease through the middle. Our four models map to those four situations, and each one produces a different failure threshold. This is the step where you discover which single point of failure your particular layout is exposing.
Step 4 — Scan to decode, and record the result. Scan with at least two decoders: your phone's camera for the real-world check, and a software decoder (like the one in the reference experiment) for a repeatable, byte-exact verification. Repeat each condition the same number of times, at the same distance and angle, and record pass/fail rather than "it feels fine." A code that works 1 time out of 24 is not a working code.
Step 5 — Adjust and re-test before you ever print. If a 10% center logo killed the decode at level M, re-generate at H and re-run the same test. Our measurements show the ordering behaves predictably — H gives you roughly a 10% headroom over M for centered damage — so you can set expectations before spending print money. Stop only when the code survives its own worst-case scenario, not the best case.
Decision table: which level to start with
| Scenario | Typical level | Why |
|---|---|---|
| Temporary screen or email code, no logo, controlled conditions | L | Smallest, densest grid; nothing to protect against |
| General print: flyers, labels, posters | M | Balance of density and resistance |
| Logo placed in the code | Q–H | Any center damage demands the strongest protection |
| Outdoor, dirty, curved, or folded materials | H | Maximum rebuild margin for unpredictable damage |
Troubleshooting: why a code stopped scanning
The code prints, but nothing scans even when clean. This is almost never error correction. Check the printed size against the scan distance (use the 10:1 rule from our sizing guide), confirm a quiet zone of at least 4 modules on every side, and verify contrast — grey-on-white inks and glossy gloss coats are frequent killers before any damage is involved.
It worked in Photoshop/Inkscape but not on paper. You tested a screen-rendered image and then printed it smaller or lower resolution than intended. Re-export at the true final size at 300 DPI minimum (or use SVG) and re-test the printed version at the real distance.
A finder pattern is damaged and nothing on earth will fix it. A sticker, label, or fold that obscures any of the three corner squares destroys detection. There is no EC level high enough to compensate; move the obstacle or reprint. This matches the random-marks result exactly.
The bottom-right corner was covered and level H still failed. As measured above, the alignment pattern lives there on larger grids. If your design or your packaging overlaps that corner, change the position, shrink the payload to drop to a smaller grid, or both.
A crease or fold crosses the code. Thin bands across a code routinely kill the timing patterns on one side. Either move the code away from the fold line or accept that creased artifacts need a new print rather than a better level.
FAQ
Can a QR code really survive 30% damage? Only in the Reed-Solomon sense — 30% of its data codewords, arranged as recoverable erasures. Our measurements show realistic localised damage (logo, scribble, corner smudge) survives roughly a third to a half of that, and random marks stop failing-fast far earlier.
Which error-correction level should I use for a logo? Level H. In our centered-logo test H was the only level still decoding with 15% of the code covered; Q gave up at 15%, M at 10%, and L at 5%.
Why did my level H code fail after a tiny smudge? Because the smudge touched a structural feature. The error-correction explanation covers why finders, timing, format, and alignment modules behave differently from data modules — damage there is not recoverable.
Is the bottom-right really the most fragile spot? For larger grids, yes. It holds the single alignment pattern, and our 8% corner test collapsed even level H to 0%. The safest corner is the one your design never touches; the realistic answer is to keep the whole 4-module quiet zone clear and test your actual layout.
Do phone cameras give the same results as the software decoder? Close enough for pass/fail on the same layout, but phone scanning adds distance, angle, and lighting variables. Use software decoding for the byte-exact threshold and the phone for the final real-world confirmation.
Make your code survive reality
The spec numbers are a useful ceiling, not a floor. Our measured tables are the ground truth for this specific payload and these damage shapes: put your logo in the centre only with level Q or H, treat the bottom-right alignment pattern as fragile once your grid grows, and never trust "30%" to cover a random scratch. Generate a test code on this site, run it through the routine above, and you will know exactly how your artwork behaves before it ever reaches the printer.
Create a test QR code now — set the error-correction level to H, drop your logo in, and scan the result at every distance in your use case.