# Decode a QR code by hand

> To decode a QR code by hand, orient the symbol using its three finder patterns, read the 15-bit format information (XOR with 101010000010010), apply the named mask to the data region, read modules in zig-zag order, de-interleave the codewords, verify with Reed–Solomon, then parse mode indicators to recover the text.

Source: https://useqr.app/docs/spec/decode-a-qr-code-by-hand · Last reviewed 2026-08-21 · UseQR is free forever, MIT licensed, no signup.

---

## What you need

A printed or on-screen code, graph paper, and patience. Pick a small symbol — a version 1
(21 × 21) or version 2 (25 × 25) code — because the work grows with the square of the side.
This page is the reverse of [encoding "hello world" by hand](/docs/spec/encode-hello-world-by-hand);
doing both once teaches you more about QR than any amount of reading.

Copy the symbol onto graph paper as a grid of dark and light cells. The side length tells you
the version: **modules per side = 17 + 4 × version**, so 21 means version 1, 25 means
version 2, and so on.

## Step 1 — orient and read the format information

The three [finder patterns](/docs/spec/finder-patterns) belong at top-left, top-right and
bottom-left. If the empty corner is anywhere but bottom-right, rotate (or un-mirror) your copy.

The 15-bit [format information](/docs/spec/format-information) runs along the edges of the
top-left finder. Read it, then XOR with the fixed masking constant **101010000010010**
(0x5412) — the spec applies this so the format field is never all zeros. The first two
resulting bits give the error correction level, the next three name the mask:

| EC bits | Level |
|---|---|
| 01 | L |
| 00 | M |
| 11 | Q |
| 10 | H |

The remaining 10 bits are BCH error correction over the field itself. A second, identical
copy sits split beside the other two finders — read it if the first is damaged.

## Step 2 — remove the mask

Every data module was XORed with a [mask pattern](/docs/spec/mask-patterns-0-to-7) at encode
time. Apply the same pattern again to undo it: for mask 0, flip every module where
(row + column) mod 2 = 0; each of the eight masks has a similar coordinate formula. Only
data and error-correction modules are masked — leave finders, timing patterns, alignment
patterns and the format information untouched.

## Step 3 — read the zig-zag

Data is stored in two-module-wide columns, starting at the bottom-right corner, running
upward, then down the next pair, alternating. Within each pair read right cell then left
cell. Skip every function-pattern module and skip column 6 entirely (the vertical timing
pattern) — the walk simply steps over it. Dark = 1, light = 0. Group the bits into 8-bit
[codewords](/glossary/codeword).

## Step 4 — de-interleave and check Reed–Solomon

For version 1 there is a single block, so the codewords are already in order. Larger
versions [interleave](/glossary/interleaving) codewords from multiple blocks — codeword 1 of
block 1, codeword 1 of block 2, and so on — and you must deal them back out using the block
table for your version and level.

A full [Reed–Solomon](/docs/spec/reed-solomon-error-correction) check means computing
syndromes over GF(256): all zeros confirms an undamaged code. By hand, most people
(reasonably) assume a cleanly printed code is intact and move on.

## Step 5 — parse the bit stream

Now read the data codewords as a [bit stream](/docs/spec/qr-code-bit-stream-walkthrough):

| First 4 bits | Meaning |
|---|---|
| 0001 | Numeric mode |
| 0010 | Alphanumeric mode |
| 0100 | Byte mode |
| 1000 | Kanji mode |
| 0000 | Terminator — stop |

After the mode indicator comes a character count (8 bits for byte mode at versions 1–9),
then the data itself — in byte mode, each 8 bits is one character. Decode until you hit the
terminator; everything after it is padding (the alternating bytes 11101100 and 00010001).

If you want to check your work, point [/scan](/scan) at the code, or feed the payload to
[/validate](/validate) and compare.

## FAQ

### How do I know which mask a QR code used?
Read the 15 format bits beside the top-left finder pattern, XOR them with 101010000010010, and take bits three to five of the result. They name one of the eight mask patterns, each defined by a simple coordinate formula.

### Can you really decode a QR code without a computer?
Yes, for small versions. A version 1 code holds at most 152 data bits, and every step — unmasking, the zig-zag read, mode parsing — is pencil-and-paper arithmetic. Verifying the Reed–Solomon codewords by hand is the only genuinely tedious part.

### Why do the bits I read look like random noise?
You probably forgot to remove the mask. Raw modules are XORed with a mask pattern precisely so they look balanced and noise-like; undo the mask named in the format information before reading the zig-zag.

### What order are QR code bits stored in?
In two-module-wide columns starting from the bottom-right corner, running alternately up and down, right cell before left cell, skipping all function patterns and the vertical timing column. Bits group into 8-bit codewords, most significant bit first.

## Try it

- https://useqr.app/scan
- https://useqr.app/validate
- https://useqr.app/text
