How much damage can a QR code take?

A QR Code spends roughly a fifth to a third of its modules on Reed-Solomon parity — the redundancy that lets a scanner repair what a scratch, a glare or a coffee mug destroyed. Build a symbol, damage it on purpose, and watch the repair budget run out. Everything runs in your browser.

  1. Build the symbol.Type a payload, pick an error correction level and a version, and see the data and parity codewords it splits into.
  2. Damage it.Paint on single modules, cover finder or timing patterns, or simulate noise, blur, low contrast and more.
  3. Read it.Decode the result with Dynamsoft Barcode Reader and watch where each level stops recovering.

The symbol

Byte mode. The version grows to fit — up to version 10 here.

Error correction level

Drag on the symbol to damage modules

  • Data codeword
  • Error correction codeword
  • Function pattern
  • Damaged module

Click any module to see which codeword it carries.

Correction capacity at this version

A block repairs up to half of its parity codewords as errors (⌊EC/2⌋ per block).

Damage it

Module damage and capture defects are independent — combine them.
Paint modules

Drag across the symbol. Painted modules flip to a fixed random value, like a real scratch.

Target a pattern

Function patterns carry no parity — a scanner that cannot find or orient the symbol never reaches error correction.

15%

Seeded, so the same percentage always damages the same modules.

40%
0.0% modules damaged No damage yet

Can a reader still read it?

The reader loads on the first decode. Decoding uses the clean render plus your damage — never the structure colours.

Damage Result Time Source Image

Damage the symbol, or run the sweep, to fill this log. Every row keeps the exact image it decoded — download it from the Image column.

How damaged is a QR image?

Someone sent you a code? The demo locates the grid, reads the format information and runs Reed-Solomon decoding to measure how much of the repair budget the image is using — no original file needed.

Drop a QR image here — or paste one from the clipboard

Press Enter or click to browse · PNG, JPG, a screenshot · nothing is uploaded

Or try a generated sample

The report appears here. For an image that still decodes the count is exact — Reed-Solomon knows how many codewords it had to repair — and for one that does not, the budget is what failed.

QR anatomy: what every part is called

Rendered from the symbol above — switch level or version and it redraws. Hover a term to light it up.
How to read these numbers

The symbol is encoded by a QR Code (ISO/IEC 18004) encoder that runs in this page: byte mode, any version up to 10 here, all four error correction levels, and the standard mask search. The module damage you paint or randomize is exact — the demo knows which codeword every module belongs to, so the budget meter counts real corrupted codewords, not an estimate.

The budget model follows the standard: a Reed-Solomon block of e parity codewords repairs up to ⌊e/2⌋ corrupted codewords per block under error decoding (erasure decoding, which a scanner can only use when it knows where the damage is, can do better). Damage to finder, timing, alignment, format or version modules is outside that budget entirely — error correction repairs codewords, not the scaffolding a scanner needs to find the symbol.

The capture defect presets (noise, blur, low contrast, occlusion, crop, shadow, rotation) are rendered onto the same canvas a camera would have produced, and their damage percentage is estimated by sampling each module's centre pixel against its intended value. Decode outcomes apply to Dynamsoft Barcode Reader at default settings on the damaged render; another reader, another resolution or a print-and-scan round trip can shift the boundary, and a successful decode never guarantees reliable scanning on every device.

The How damaged is a QR image? card runs the same story backwards. There is no original to compare against, so the page first locates the symbol — Dynamsoft Barcode Reader's corner points when it decodes, otherwise a finder-pattern locator that finds the 1:1:3:1:1 triplets and fits the grid itself. The reader gets three escalating passes: the default settings, then the modes built for physical damage (BarcodeComplementModes for missing positioning patterns, DeformationResistingModes for a distorted one), then prepared copies of the image — binarized with the pinholes closed, and turned by ±45° — because a label printed with holes in the ink and a code wrapped around a can both defeat the first two. That is also why the page no longer calls a result "unreadable" just because the defaults came back empty; when a prepared copy is what read it, the report says so instead of pretending the page measured it. It then reads the format information for the level and mask, samples every module through that grid, and hands the codeword stream to a Reed-Solomon decoder that reports exactly which codewords it had to repair. When it succeeds the count is exact, because the decoder knows; when it fails the page says so rather than guessing a percentage. When the decode succeeds the page goes one step further: the corrected codewords are a complete reference, so it rebuilds the original matrix and diffs it against what was sampled — a damage percentage on the same scale as the sweep above (damaged modules over the whole symbol). When the decode fails there is no reference to diff against, and the page only states a lower bound: a block that would not decode carries more corrupted codewords than its budget — unless the page still holds the original you generated. Then the differing cells are known by name, and Reed-Solomon switches from error decoding (each repair costs two parity symbols) to erasure decoding (one each): a block of e parity codewords can correct e erasures instead of ⌊e/2⌋ errors, so symbols past the ordinary budget come back. A stranger's image past its budget cannot be rescued this way — without a reference nothing tells the decoder where the damage is. A symbol whose finder patterns, timing patterns or format bits are gone cannot be located or unmasked at all, and for those the page reports that the grid could not be locked — which is the honest answer, and the same reason a scanner in a shop would not read it either.

The rebuilt matrix is what the card's last block draws: a symbol you can download as PNG or SVG. It carries the version, level and mask the image carried, because the damaged modules are restored from the corrected codewords rather than re-encoded from the payload — a repair of this symbol, not a new one. Everything the standard fixes by version is redrawn instead of sampled: finder, separator, timing, alignment, dark module and version information, and both copies of the format field from the level and mask the decode verified. That matters in practice — a rotated or blurred capture misreads the one-module-wide timing patterns first, and copying those errors into the rebuild would hand back a symbol the reader still refuses. Before the download is enabled the page hands the rendered pixels back to Dynamsoft Barcode Reader and requires the same payload, so a rebuild its own reader would not accept is never offered. The limit that remains is upstream: if the finder patterns were too damaged to locate the symbol at all, no grid locks and there is nothing to rebuild.

The SDK downloads its engine and contacts Dynamsoft for license activation; the hosted demo uses the CodePool domain license, and local or self-hosted previews use the SDK trial license. The payload you type and the damaged image never leave the page.