What's inside a QR code: structure, capacity, and error correction
How a QR code stores data, what the finder patterns and quiet zone are for, why error-correction level changes how much you can encode, and the practical limits worth knowing before you generate one.
A QR code looks like random black-and-white noise, but every part of it is structured — the three big corner squares, the timing lines, the quiet margin, and the data area all have jobs. Most of the time you just want a working code, but a few of those parts directly affect whether your code scans reliably, how much it can hold, and how small you can print it. Knowing what the pieces do turns "it sometimes doesn't scan" from a mystery into a checklist.
The fixed patterns
Before any of your data, a QR code carries patterns that let a scanner find and orient it:
- Finder patterns — the three large nested squares in the corners. A scanner detects these first; their fixed ratio is how it locates the code and works out rotation, even when the image is at an angle.
- Alignment patterns — smaller squares (in all but the tiniest codes) that correct for distortion when the code is on a curved or tilted surface.
- Timing patterns — the dotted lines running between finders that tell the scanner the grid size of each module.
- Quiet zone — the blank margin around the whole code, recommended at four modules wide. It's not decoration: without it, scanners can fail to isolate the code from surrounding content. Crowding a QR code right up against other graphics is the most common reason a printed one won't scan.
Everything else — the speckled interior — is your encoded data plus its error-correction bytes.
Versions and capacity
QR codes come in versions 1 through 40, where the version is just the grid size: version 1 is 21×21 modules, and each step up adds 4 modules per side. A bigger grid holds more data. Capacity also depends on what you encode, because QR has dedicated modes:
- Numeric — digits only, densest.
- Alphanumeric — digits, uppercase letters, and a few symbols.
- Byte — arbitrary bytes, which is what URLs and mixed-case text use, and the least dense.
The headline maximum — thousands of characters — assumes numeric mode at the largest version with minimal error correction. A real-world URL in byte mode hits practical limits far sooner, which is why long links produce dense, hard-to-scan codes. The fix is usually to shorten the URL, not to enlarge the code.
Error correction is a real trade-off
This is the setting people generate without understanding, and it matters. QR codes use Reed-Solomon error correction, which adds redundant bytes so a code still reads when part of it is dirty, damaged, or covered. There are four levels:
| Level | Recovers up to | Cost |
|---|---|---|
| L (Low) | ~7% | most data capacity |
| M (Medium) | ~15% | balanced default |
| Q (Quartile) | ~25% | less capacity |
| H (High) | ~30% | least capacity |
Higher levels are what make those QR codes with a logo in the middle work — the logo covers data, and the error correction reconstructs it. But redundancy costs capacity: at level H, nearly a third of the code is correction bytes, so the same data needs a larger, denser grid. Level M is the sensible default; bump to Q or H only when you expect damage or want to overlay a logo, and accept the larger code that results.
Practical limits worth knowing
A few things no QR code can do, despite common assumptions:
- A QR code is not encrypted or private. It's an open encoding — anyone with a scanner reads exactly what's in it. Don't put secrets in one expecting the format to protect them.
- It's static. The data is fixed at generation time. "Dynamic" QR codes that you can edit later don't change the code — they encode a short redirect URL that you repoint, which means they depend on a third-party service staying alive.
- Contrast and size are not optional. Dark-on-light with the quiet zone intact, printed large enough that each module survives the capture resolution. Inverted colors and tight margins are the usual culprits behind a code that scans on one phone but not another.
If the content is a URL, remember the code just stores the text verbatim, so the encoding rules for the link itself still apply — spaces and special characters should be handled as in percent-encoding before they go in. To generate one with the mode and error-correction level set explicitly, our QR code generator builds it in the browser so the data never leaves your machine.