How a Scratched QR Code Still Scans
Scratch a corner off a printed QR code and your phone usually still reads it, first try. That is not the camera guessing at torn pixels — the code was built with more data than it strictly needs, in a precise mathematical sense, so that losing some of it still leaves enough to pin down the original exactly. The five figures below show the actual arithmetic behind that, not just the marketing phrase "error correction."
A QR code is bytes, not a picture
The black-and-white squares — modules — aren't pixels of a picture. Each one is a single bit, and a scanner reads them off in groups of 8 to make bytes, called codewords. Three of the four corners hold fixed finder patterns (the bullseye squares) so the scanner can find and orient the code at all; a thin timing pattern of alternating dark and light modules runs between them so it can count modules precisely. Everything else is one long stream of message bytes, written into the grid in a fixed zigzag: up two columns, down two columns, hopping over the timing strip.
Because the message is just a stream of bytes at fixed positions, a scratch doesn't need to be "understood" visually at all — the decoder only needs to know which of those 25 bytes it can trust and which it can't.
Redundancy is just extra equations
Here is the trick that makes lost bytes recoverable. Encode a short message as the coefficients of a low-degree polynomial — for QR this happens with bytes and a finite-field version of the arithmetic, but the idea is identical over ordinary numbers. A degree-3 curve needs exactly 4 points to pin it down uniquely. QR codes deliberately compute and store more points than that: the curve below is evaluated at 8 positions, not 4, using a rule called Reed–Solomon coding. The 4 extra values are pure redundancy — and as long as any 4 of the 8 survive, the exact original curve, and so the exact original message, can be solved for again.
Notice reconstruction is all-or-nothing at the threshold, not a gradual blur. That is the real shape of the guarantee QR codes give you: below the redundancy budget, exact recovery; above it, failure.
Knowing what's broken is worth more than not knowing
Damage comes in two kinds, and they don't cost the same. A erasure is damage the decoder can see — a scratch, a torn corner, a module it knows is unreadable — so it knows exactly which byte to leave out of the equations. An error is damage the decoder can't see — glare, a smudge, a printing defect that still looks like a plausible but wrong value — so it doesn't know which byte is lying to it. For a code with r redundant codewords, Reed–Solomon can fix any mix of e erasures and f errors as long as 2f + e ≤ r: an unknown error costs twice as much budget as a known one, because the decoder has to spend some of the redundancy just finding it before it can fix it.
That is also why a decoder benefits from knowing a scratch happened at all: a scanner that can tell "this patch of the image is unreadable" and mark those bytes as erasures gets twice the mileage out of the same redundancy as one that has to treat every byte as possibly-wrong.
Four levels of armor
You choose how much redundancy to spend when the code is generated. QR defines four error-correction levels — L, M, Q and H — that trade data capacity for scratch tolerance. Their published, standard recovery capacities are roughly L 7%, M 15%, Q 25% and H 30% of the symbol's codewords. A code printed at level H can lose nearly a third of its bytes and still decode; the same damage on a level-L code fails.
Higher levels aren't free: their extra redundancy codewords take up space that would otherwise hold message bytes, so a level-H code carrying the same text needs a physically bigger (or denser) symbol than a level-L one. Designers pick H mainly when the code is likely to get dirty, printed small, or have a logo stamped over the middle.
Why one big scratch usually isn't fatal
There is a last, easy-to-miss piece. A real QR symbol doesn't run its redundancy math over the whole message as one block — for anything past the smallest sizes, it's split into several separate Reed–Solomon blocks, each corrected independently. If a scratch happened to land entirely inside one block, that block alone could easily exceed its own budget and fail, even while the others were untouched. So QR interleaves the blocks: instead of writing block 1 in full, then block 2, then block 3, it writes one codeword from each block in rotation. A scratch that is contiguous on the printed page ends up spread thin across every block once you look at which block each damaged byte actually belonged to.
That's the real reason a single ugly scratch across a printed QR code so often still works: it isn't one big wound to one block, it's a handful of forgivable nicks spread across several, each well inside its own budget.
What redundancy can't fix
Everything above only helps once the scanner has already found the code. If a scratch wipes out a finder pattern, cuts through the timing strip, or eats the quiet white margin around the edge, the camera may never lock onto the symbol's geometry at all — and no amount of Reed–Solomon redundancy fixes a problem that happens before decoding even starts. In practice that's exactly why scratches on the data area are so often survivable while damage to a corner bullseye is not: the two failures live in completely different parts of the pipeline.