The short answer
A QR code works by turning your data into a grid of black and white squares that a phone camera can read in a single snapshot. The camera finds the code, works out which way is up, reads the bits, fixes any errors, and performs the action the data asks for. The whole chain runs offline in a fraction of a second.
Under the hood there is a fixed pipeline: choose an encoding mode, pack the data into bits, add Reed-Solomon error correction, apply a mask pattern so no large block of same-color squares confuses the scanner, then lay everything into the grid. Our what is a QR code guide covers the basics; this page goes one level deeper into the mechanism.
The finder patterns locate and orient the code
The three big squares in the corners are finder patterns. Their fixed 1:1:3:1:1 ratio of dark-light-dark is something almost no ordinary image contains, so a scanner can search the whole camera frame for that ratio and instantly know there is a QR code here and which way is up.
Because there are three finders and not one, the scanner can read the code from any angle and correct for rotation or skew. A smaller fourth square, the alignment pattern, helps the reader rescan a code that is tilted or curved. This any-angle reading is the Quick Response part of the name, and it is the key difference from a one-dimensional barcode, covered in our QR code vs barcode guide.
The data grid and modules
The rest of the code is a grid of modules — the small squares. The grid size depends on the version: version 1 is 21x21 modules and version 40 is 177x177, growing by four modules per side per version. More data means a bigger, denser grid.
Timing patterns (alternating dark and light rows and columns) run between the finders so the scanner can work out the module size and count. Format information next to the finders records the error-correction level and the mask used. Once the scanner knows the grid, it walks the data modules along a fixed zig-zag path, reading off the bits.
Reed-Solomon error correction
The bits are not just your data. A chunk of Reed-Solomon redundancy is added so the code still scans when part of it is damaged, dirty, or covered by a logo. Four levels (L, M, Q, H) trade capacity for resilience, from about 7% recovery up to about 30%.
This is why a QR code can survive a scratch, a smudge, or a centered logo and still decode. It is also why adding a logo is safe at level H. Our QR error correction guide goes deeper on choosing the right level for your use case.
Masking prevents confusing patterns
A raw data grid can easily contain a long run of the same color, which a scanner can mistake for a finder pattern or simply fail to read. To prevent that, the encoder chooses one of eight mask patterns and XORs the data modules with it, breaking up big blocks of one color.
The format information records which mask was used so the decoder can undo it. The encoder actually tries all eight masks and picks the one that scores best on rules rewarding an even spread of dark and light modules, which is why two QR codes for the same text can look quite different.
The parts of a QR code at a glance
A finished QR code is built from several named regions, each with a job. The table below lists them and what each one does.
| Part of the QR code | What it does | Why it matters |
|---|---|---|
| Finder patterns (3 corners) | Fixed-ratio squares the scanner searches for | Lets any camera locate the code and read it at any angle |
| Alignment pattern | Small offset square in the lower right | Lets the reader rescan a code that is tilted or curved |
| Timing patterns | Alternating dark/light rows and columns | Tell the scanner the module size and the grid count |
| Format information | Bits stored next to the finders | Record the error-correction level and the mask used |
| Data + Reed-Solomon modules | The encoded payload plus redundancy | Hold the message and let it survive damage |
| Mask pattern | XOR applied to the data modules | Breaks up long runs of one color that confuse readers |
| Quiet zone | Blank margin around the whole code | Separates the code from the background so it can be found |
From data to scan in one pass
Encoding follows a fixed order: pick the mode (numeric, alphanumeric, byte, or kanji), pad the data to the right length for the version and error-correction level, split it into blocks, add Reed-Solomon bytes to each block, interleave the blocks, apply the chosen mask, and place everything into the grid along with the format and version info.
The decoder runs the same steps in reverse: find the finders, read the format, undo the mask, de-interleave the blocks, correct errors with Reed-Solomon, unpack the mode and data, and hand the result to the phone. Because the whole thing is self-contained, a static code works forever with no server. Keep yours readable with our QR best practices, choose the right payload with our QR types guide, and see how the format got started in our QR code history guide.
Frequently asked questions
How does a QR code work step by step?
The scanner finds the three corner squares to locate and orient the code, reads the format info for the error-correction level and mask, walks the data modules, undoes the mask, uses Reed-Solomon to fix any errors, and unpacks the original text, which the phone then acts on.
Why are there three big squares in a QR code?
Those are the finder patterns. Their fixed dark-light-dark ratio lets any camera detect the code in a full frame and work out which way is up, which is why QR codes scan from any angle instead of needing a straight line like a barcode.
How does a QR code store data?
As a grid of black and white modules. The data is converted to bits, packed into the grid along a zig-zag path with Reed-Solomon redundancy added, and a mask is applied so the pattern stays easy to read. The grid size grows with the amount of data.
Can a damaged QR code still scan?
Yes, up to a point. Reed-Solomon error correction adds redundant data so the code recovers even when part is scratched, dirty, or covered by a logo. Level H tolerates the most damage, around 30%, while level L tolerates only about 7%.