QR Fixer

How QR error correction works, and what it cannot fix

Every QR code carries spare data so it survives a scratch, a smudge or a bad photograph. That spare capacity is finite and its arithmetic is unforgiving, which is what decides whether a damaged code can be read.

Codewords, blocks and parity

A QR code does not store your link as loose bits. The bits are grouped eight at a time into codewords, and the codewords are grouped into blocks. Each block gets a number of extra codewords computed from its contents, called parity symbols. Those parity symbols carry no message of their own; they exist so the block can be repaired.

A version 6 code at error-correction level M, for example, is four blocks of 43 codewords, and sixteen of every 43 are parity. That is the entire repair budget for that block, and it cannot be borrowed from a neighbour.

An error costs twice what an erasure costs

This is the part that matters, and it is the reason a badly damaged code can sometimes still be read.

Reed-Solomon can repair a corrupt codeword in two situations, at two very different prices:

So sixteen parity symbols will fix eight errors, or sixteen erasures, or any mix along that line. Being able to say where the damage is doubles what can be repaired — which is why a recovery tool works so hard at deciding which modules it could not read confidently. It is not guessing at values; it is spending its budget efficiently.

The arithmetic that decides everything

Put those together and you get a rule that predicts, exactly, whether a block is recoverable.

Take a block with n corrupt codewords and sixteen parity symbols. If k of the corrupt ones are declared erasures, the remaining n − k are unknown errors costing two apiece, so the block decodes when:

2(n − k) + k ≤ 16   →   k ≥ 2n − 16

A block with nine bad codewords needs just two of them correctly identified. One with twelve needs eight. One with seventeen cannot be saved at all, because seventeen unknowns cannot be resolved with sixteen equations, however cleverly you search.

That last case is worth stating plainly, because no amount of computing power changes it. When a recovery attempt fails on a badly damaged photograph, the honest answer is usually not "try harder" — it is that the data is no longer present.

Why blocks are attacked one at a time

Blocks are independent. Reed-Solomon repairs each one on its own and either succeeds or fails with no ambiguity, which makes it a perfect oracle for a single block.

That is a much larger advantage than it sounds. Guessing which codewords are corrupt across a whole symbol means searching a space that grows as k raised to the number of blocks. Doing it a block at a time turns that into the number of blocks multiplied by k — the difference between impossible and about a second of work. A block one or two past the limit gives way after a few hundred combinations; several past, after a few million, which is nothing at a million Reed-Solomon solves a second.

Choosing a level when you make a code

LevelCapacity given to repairUse it when
Labout 7%Clean digital display, code never printed
Mabout 15%The usual default; fine for print
Qabout 25%Stickers, packaging, anything that gets handled
Habout 30%Outdoors, curved surfaces, or a logo over the middle

Higher levels are not free: the same payload needs a physically larger code, or the same size code holds less. But if a code will be photographed off a screen, printed small, or stuck on something that gets scuffed, the extra parity is what makes the difference between a link that survives and one that does not.

If you have a code that will not scan, the recovery tool on this site reads its error-correction level straight out of the symbol and reports how far past the limit each block sits.

More on reading damaged codes