How QR Codes Work

A visual, layer-by-layer breakdown — from the very first pattern to the encoded data itself.

1Layer One

Position Detection Patterns

Before any data can be decoded the scanner must first find and orient the code. These compulsory elements are the foundation of every QR code.

v1 (21×21)
Finder
Timing
Data area

The Three Corner Anchors

Every QR code starts with three identical markers — one each in the top-left, top-right, and bottom-left corners. Each has a 7×7 black outer ring, white middle ring, and solid 3×3 black centre — a ratio that never appears in ordinary data.

The Timing Patterns along row 6 and column 6 alternate black/white, letting the decoder count rows and columns precisely. Drag the slider to see alignment patterns appear from version 2 onward.

💡 Why only three corners?

The missing bottom-right marker acts as a rotation cue — a scanner determines orientation just from which corner lacks a marker.

2Layer Two

Format Information

15 bits wrapped around the top-left finder — and duplicated across the other two corners — tell the scanner how to decode everything else.

Copy 1 (TL finder)
Copy 2 (TR + BL)

Three Parts, 15 Bits

EC level (2 bits)
Mask (3 bits)
BCH check (10 bits)
Bit 14 (MSB) → Bit 0 (LSB)

EC Level (2 bits) — sacrifices capacity for recovery redundancy.

Mask (3 bits) — which XOR pattern was applied to the data area.

BCH check (10 bits) — BCH(15,5) error correction on the 5 data bits, then XOR'd with 101010000010010 to prevent all-zero sequences.

💡 Two identical copies

If an entire corner is torn off, the other copy is used. BCH covers bit errors within one copy; the duplicate survives total corner loss.

3Layer Three

Mask Patterns

After placing data, one of 8 XOR patterns is applied to every data module. Where the formula is true, the module flips. Structural modules are never masked. The encoder scores all 8 and picks the lowest-penalty result.

4Playground

Interactive QR Structure

All structural layers combined. Each element type is colour-coded. The mask is actually applied to the data. Toggle blank data to see the mask pattern directly.

Finder
Separator
Timing
Alignment
Format info
Dark module
Data
5Layer Four

Data Encoding

Before any bits reach the grid, raw data is packaged into a specific bitstream. Here is how it is structured.

Bitstream Structure

ENC0100
LEN00001100
DATA bytes…01001000 01100101 …
PAD0000…

ENC — Mode Indicator (4 bits) — tells the decoder which encoding scheme was used:

BitsModeCharactersEfficiency
0001Numeric0–9 only3 digits / 10 bits
0010Alphanumeric0–9, A–Z, $%*+–./:2 chars / 11 bits
0100ByteAny binary / text1 byte / 8 bits
1000KanjiShift-JIS1 char / 13 bits

LEN — character count. Width varies by version and mode (for byte mode: 8 bits in versions 1–9, 16 bits in versions 10–40).

DATA — in byte mode each character is its ISO 8859-1 byte value, identical to ASCII for characters below 128. Modern encoders use UTF-8 with an ECI header for non-Latin text.

After data: a 0000 terminator, byte-boundary padding zeros, then alternating 11101100 / 00010001 padding bytes to fill remaining capacity. The block is then Reed-Solomon encoded — that is the next layer.

💡 Why not always use Byte mode?

A URL with only digits and uppercase letters uses Alphanumeric mode (~30% more capacity), giving a less dense, easier-to-scan code.

6Interactive

Encode Text

Type any short text and see it converted to bytes, then watch each byte's bits placed onto the QR code grid in the zigzag order the spec defines.

7Layer Five

Reed-Solomon Error Correction

That grey area from §6 — now explained. RS adds check bytes so a scanner can reconstruct data even when part of the code is torn, dirty, or obscured.

The core idea

Imagine fitting a curve through a set of points. If you know the curve has a certain shape, a handful of damaged points can be reconstructed from the undamaged ones. RS does exactly this — for bytes instead of geometric points.

Step 1 — treat the data as a polynomial. Each data codeword becomes a coefficient: D(x) = d₀x^(n-1) + d₁x^(n-2) + … + d_(n-1).

Step 2 — divide by the generator polynomial G(x) = (x−α⁰)(x−α¹)···(x−α^(ec-1)), where α is a primitive element of GF(256). The remainder R(x) = D(x) mod G(x) gives the EC codewords.

Step 3 — append the remainder. The final block is D(x)·x^ec + R(x), which is exactly divisible by G(x). That divisibility lets the scanner detect and fix errors.

🔢 GF(256) — the only hard part

All arithmetic runs in GF(256): a "Galois Field" of 256 elements (every byte). Addition = XOR. Multiplication uses precomputed exp/log tables built from the primitive polynomial x⁸+x⁴+x³+x²+1. Once gfMul(a,b) works, the rest is polynomial long division — about 20 lines of code.

💡 Data is split into blocks first

For larger QR versions the data codewords are split into 2–4 groups (blocks) and each block gets its own independent RS computation. The resulting data and EC codewords are then interleaved — a burst of damage that hits several consecutive modules only destroys one codeword per block, keeping errors correctable.