The square below is a real, scannable QR code, built from scratch in your browser by the few hundred lines of JavaScript behind this page. Point your phone at it. Every dot is a module. The whole grid comes in 40 fixed sizes called versions: version 1 is 21×21 modules, version 40 is 177×177. Every section on this page works off whatever you type here.
The error-correction level decides how much of the code can be destroyed and still read: roughly 7%, 15%, 25% or 30% of it. More protection means more modules, so the code grows. Notice that HELLO WORLD in level H needs a bigger version than in level L.
In a small QR code, a big chunk of the modules carry no data at all. They are navigation aids: things a camera needs to find the code, orient it, measure it and read its settings, before it can read a single bit of yours. Hover (or tap) the legend to light up each part.
Before anything is drawn, the message becomes bits with a small header. The first 4 bits announce the mode. Digits only? Numeric mode squeezes 3 digits into 10 bits. Uppercase letters, digits and a few symbols? Alphanumeric mode packs 2 characters into 11 bits. Anything else falls back to byte mode, 8 bits per byte of UTF-8. Then comes a character count, then the data itself.
After the data: a 4-bit terminator of zeros, a few zeros to reach a whole byte, and if the version still has room, filler bytes 11101100 and 00010001 alternating until it's full. Those two pad bytes are probably the most photographed bytes on Earth.
Here is the trick behind Reed–Solomon error correction, the same family of codes that guards CDs, hard drives and the photos from Voyager. Suppose your message is three numbers. Instead of sending the three numbers, treat them as the coefficients of a parabola and send seven points on the curve. Any three points pin down a parabola, so the receiver has four to spare. If a couple of points get corrupted they simply won't fit a curve with the others. The majority still agree.
QR codes do exactly this, with two twists. The arithmetic happens in a finite field of 256 elements, so every value stays a single byte and nothing ever rounds off. And instead of "points", each unit is a byte called a codeword. A block with n error-correction codewords can repair ⌊n/2⌋ corrupted codewords anywhere in the block, without being told which ones.
Long messages are split into several blocks, each with its own error-correction codewords. Then the blocks are interleaved: the first byte of every block, then the second byte of every block, and so on. A coffee stain that wipes out one contiguous patch of the code is spread thinly across all the blocks instead of killing one outright.
Top: each row is one block, its data codewords first (solid) then its error-correction codewords (outlined), each block in its own colour. Bottom: the order they are actually written into the grid. Same colours, shuffled.
Paint over the code. Every stroke is decoded live by the Reed–Solomon machinery described above, running right here. Watch how long it holds out, and where it gives up.
Three things to notice. A blob in the middle is cheap. Interleaving spreads it across every block, and each block absorbs its share. That's why logos in the centre of QR codes work at all. Scattered noise is expensive. Flipping a single module corrupts an entire 8-bit codeword, so 40 random dots can cost 40 codewords while a 40-module blob costs far fewer. The map is sacred. Error correction protects the message, not the finder patterns.
Codewords are written into the grid two columns at a time, starting at the bottom-right corner. The pair of columns is filled upward, right module then left module, row by row. At the top the snake turns and fills the next pair downward. It skips the vertical timing pattern in column 6 and flows around every finder, alignment and format area it meets. The most significant bit of each byte goes first.
Shown before masking, so the modules you see are the raw bits of the codewords. Blue-tinted modules belong to data codewords, coral ones to error-correction codewords. Grey ones are function patterns the snake has to avoid.
Raw data is lumpy. It can produce big empty patches, long stripes, or worst of all an accidental 1:1:3:1:1 pattern that looks like a finder and sends the scanner hunting in the wrong place. So the encoder XORs the data region with one of eight mask patterns, scores each result with four penalty rules, and keeps the one with the lowest score. The scanner reads which mask was used from the format bits and XORs it right back off.
Rule 1: any run of 5 or more same-coloured modules in a row or column, 3 points plus 1 per extra module. Rule 2: every 2×2 block of one colour, 3 points. Rule 3: a 1:1:3:1:1 finder-like pattern with 4 light modules on either side, 40 points each. Rule 4: 10 points for every 5% the overall dark ratio strays from 50%.
Before it can unmask anything, the scanner needs to know two things: which error-correction level and which mask. That's 2 + 3 = 5 bits of format information. They matter so much that they get their own miniature error-correcting code, a 10-bit BCH checksum that can fix 3 wrong bits out of 15, and the whole 15-bit word is written twice, in two different places, so a smudge can't take out both copies. Finally it's XORed with a fixed pattern so that the format bits are never all zero.
A camera frame is just pixels. The scanner walks along every row of the image looking for a run of dark, light, dark, light, dark in the ratio 1 : 1 : 3 : 1 : 1. That ratio is the whole reason the finder patterns look the way they do: any straight line through the centre of a finder, at any angle, crosses it in exactly that ratio. Drag the angle.
Three finders give the scanner three corners and the orientation: the corner without a bullseye is bottom-right, so a code can be read upside down or sideways. The timing patterns between the finders give the module pitch, so it can count rows and columns. The alignment patterns pin down the grid in the middle of larger codes, so a code wrapped around a bottle or photographed at a slant can be un-warped. And the four-module white margin around the code, the quiet zone, is what stops the scanner from mistaking the surrounding page for more code.
Then it's the whole pipeline in reverse: read the format bits, undo the mask, follow the snake to collect codewords, un-interleave them into blocks, run Reed–Solomon over each block to repair whatever the camera got wrong, parse the mode and count, and hand you the text. All in the time it takes a menu to open.
A header that says how to read the bits. Reed–Solomon codewords so the bits survive the real world. A snake to lay them out, a mask to keep them from fooling the camera, fifteen carefully guarded bits to say which mask, and three bullseyes so a camera can find any of it in a messy photograph.
QR codes were invented in 1994 by Masahiro Hara at Denso Wave, a Toyota subsidiary, to track car parts on a factory floor. The design was released for anyone to use, royalty-free. Thirty years later, the very same zig-zag reads your restaurant menu.