Skip to content
UseQR

Developers & agents

Why you should verify that a QR code decodes

Rendering a QR code proves nothing about whether it scans. Styling, colour, logos and print all consume error-correction budget invisibly. The only reliable check is to rasterise the final output and read it back with a real decoder.

The gap most generators leave

Producing a QR code is two steps: compute the module matrix, then draw it. Almost every generator does both and stops.

But the thing that determines whether it scans is the drawn output, not the matrix. Between matrix and reality sit: module shape, colour, gradient, logo coverage, quiet zone, background transparency, rasterisation, scaling, ink spread, laminate, lighting and camera angle. Each consumes some of the error-correction budget, and none of them are visible to the code that computed the matrix.

What decode-verify means

  1. Render the code exactly as it will ship, including every styling choice.
  2. Rasterise it to a bitmap.
  3. Run a real decoder — ZXing — over the bitmap.
  4. Compare the decoded string against the input.

If step 4 fails, the code does not ship.

UseQR does this in the browser before you download, and in CI across the full permutation matrix of module styles, eye styles, gradients, logo coverages and error-correction levels. A permutation that fails is a build failure rather than a customer complaint.

What it catches

  • A logo that has crept past the error-correction budget.
  • A brand colour whose luminance contrast is too low.
  • A module style so organic that adjacent modules merge and the timing pattern breaks.
  • A quiet zone reduced below four modules.
  • A transparent background that renders as an inverted code.
  • An encoder bug in an unusual payload.

What it does not catch

Decoding a clean digital raster is necessary, not sufficient. It does not model:

  • Ink spread on uncoated stock.
  • Specular reflection from gloss laminate.
  • A camera at 40° in a dim room.
  • Motion blur.
  • Fading after two years outdoors.

For those, print a proof at final size on final stock and scan it from the real distance. Our validator additionally scores contrast and simulates degradation, and compare shows the same code under several print conditions side by side.

In your own pipeline

If you generate codes programmatically, add a decode assertion to your tests:

from pyzbar.pyzbar import decode
from PIL import Image

assert decode(Image.open(out))[0].data.decode() == expected

Or call the API's verify endpoint. Either way, treat "it renders" as an unproven claim.

FAQ

Isn't a generated QR code guaranteed to work?

No. The matrix may be correct while the rendered output is not — styling, colour, logos and scaling all degrade the drawn result without changing the matrix.

How do I know if my styled QR code still scans?

Rasterise the final output and decode it with a real decoder. UseQR does this automatically before download, and the verify endpoint does it on demand.

Does decode-verify guarantee the printed code will work?

No. It proves the digital artwork is readable, which is necessary but not sufficient. Ink spread, glare and camera angle still require a physical proof.

Should I add QR verification to my CI?

Yes, if you generate codes programmatically. A one-line decode assertion catches encoder regressions and styling changes that would otherwise reach production.