QRForge

How QR Scanning Works

6 min readUpdated September 2026
A close-up of a camera lens

Scanning a QR code feels effortless: you point, and the link appears. Underneath, the decoder runs the encoding process in reverse — finding the code in a messy photo, correcting its geometry, reading the modules and repairing any damage. QRForge's built-in reader does exactly this in your browser, and knowing the steps helps you produce codes that scan on the first try.

Finding and squaring the code

The decoder first converts the image to black and white and hunts for the three finder patterns — the nested squares in the corners. Their fixed 1:1:3:1:1 ratio of dark to light is rare in ordinary scenes, which makes them easy to spot at any angle. Once located, they define the code's position, size and rotation, so the reader can mathematically flatten a photo taken from the side back into a straight-on grid.

That first conversion deserves more credit than it gets. A decoder rarely uses one brightness threshold for the whole frame, because one side of a poster is usually lit more strongly than the other. Instead it divides the image into small tiles and computes a threshold for each, which is what lets a code read under a lamp that illuminates only half of it. The step that most often defeats this is glare: a specular highlight on laminate, a glossy menu or a phone screen carries no local detail to threshold, so that patch of the code simply vanishes.

Building the sampling grid

Three corners are enough to orient a code but not to read it accurately. The decoder still has to know where the centre of every module falls, and a photo taken at an angle or of a slightly curved surface does not map onto a perfect square. So it computes a perspective transform from the finder patterns, refines it using the alignment patterns — every code from version 2 upward carries at least one, and a version 40 code carries 46 — and confirms the module pitch against the timing patterns, the alternating dark-and-light line running between the finders.

Only then does it sample. Each module is read at its centre point rather than averaged across its whole area, because an average taken over a blurred boundary is exactly what pushes a marginal module to the wrong side of the threshold. The result is a matrix of ones and zeros. The format information is read first to recover the error-correction level and the mask number, the mask is XOR-ed away, the codewords are put back into their original order, and only then does Reed–Solomon get to work.

Reading and repairing the data

With the grid aligned, the decoder samples each module as a one or a zero, undoes the mask pattern that kept the code visually balanced, and reassembles the raw bits. Then the error-correction stage does its work: using the redundant Reed–Solomon bytes, it detects and repairs modules that were scratched, blurred or hidden. This is why a code with a coffee stain or a small logo still reads — the maths fills in what the camera could not see.

Finally the bytes are interpreted according to the mode indicator — as a URL, plain text, a Wi-Fi string and so on — and handed to the operating system, which decides what to offer you. The whole pipeline runs in a fraction of a second.

Why scans fail in practice

Almost every failure traces back to one of four things. The modules are too small for the distance — the working rule is that a code's width should be roughly a tenth of the distance it is read from, so a 2 cm code wants an arm's length and a code read across a 20 m hall needs to be about 2 m wide. The contrast is too low, usually a pale brand colour on white or a dark code sitting on a dark photograph. The quiet zone is missing, so the decoder cannot tell where the grid ends. Or the image is blurred, whether by movement or because a phone camera cannot focus that close.

A few more are worth knowing. Inverted codes — light modules on a dark field — are read by many modern scanners but not all, and the standard itself assumes dark on light. Codes printed across a fold, a seam or a bottle's curve break the perspective model faster than the alignment patterns can rescue them. And a code displayed on one screen and scanned from another can produce moiré that confuses the sampling grid; raising the display's brightness and holding it steady usually settles it.

Decoding an image with QRForge

You do not always scan with a live camera. QRForge's reader tab lets you upload or drag in a screenshot or photo, then decodes it locally with the jsQR library — no upload, no server. It is the quickest way to read a code someone sent you, or to confirm that a code you just generated actually contains what you intended before you commit it to print.

A few habits make local decoding more reliable. Crop tightly but keep the quiet zone inside the frame; a screenshot of a whole web page gives the decoder a great many irrelevant edges to search through. Use the original file rather than a photograph of a screen whenever you have it. And if a code refuses to decode, enlarging the image rarely helps — the detail lost to blur is already gone — whereas re-exporting the source at a higher resolution usually does.

The takeaway

A scanner locates the finder patterns, squares up the grid, reads the modules and uses error correction to repair damage. Use the reader tab to decode any image locally and verify your codes before printing.

Related tool
QRForge · Reader

Open the tool and try it now