How QR Codes Actually Work: A Practical Guide
What the squares mean, what error correction costs in millimetres, why upper case makes a smaller code, and the reasons a printed QR fails to scan.
QR codes went from novelty to infrastructure without anyone having to learn how they work, which is fine until one of yours comes back from the printer and does not scan.
Most of the reasons are structural and all of them are visible before you commit to print.
What the squares are
- Three large squares at the corners are the finder patterns. They tell a scanner that this is a QR code and which way up it is.
- Dashed lines between them are the timing patterns, which give the scanner the grid pitch.
- Small squares elsewhere in the grid are alignment patterns, which correct for perspective and warp.
- Everything else is modules: the data, plus its error correction.
The alignment patterns are worth being precise about, because most descriptions get this wrong. Version 1 does not have one. Versions 2 through 6 have a single alignment square near the lower right, and larger versions have several, spread across the grid. So "a small square in the fourth corner" describes a mid-sized code rather than QR codes in general.
Versions run from 1 at 21 by 21 modules up to 40 at 177 by 177, four modules wider each step.
The four encoding modes
A QR code does not encode bytes the same way regardless of content.
| Mode | Alphabet | Bits per character |
|---|---|---|
| Numeric | 0-9 | 3.33, as 10 bits per 3 digits |
| Alphanumeric | 0-9 A-Z and $ % * + - . / : and space | 5.5, as 11 bits per 2 characters |
| Byte | any 8-bit byte, usually UTF-8 | 8 |
| Kanji | JIS X 0208 | 13 |
Generators pick the cheapest mode the content allows. "12345" fits Numeric at 17 bits. "HELLO WORLD" fits Alphanumeric at 61 bits. "hello world" falls to Byte at 88 bits, because lower case is not in the alphanumeric alphabet.
That last one has a practical consequence people rarely exploit.
Shouting your URL drops it a whole version. HTTPS://EXAMPLE.COM encodes as version 1, 21 by 21; https://example.com needs version 2, 25 by 25. Same nineteen characters.
This is safe because schemes and host names are case-insensitive2. It stops being safe at the first slash: HTTPS://EXAMPLE.COM/PRICING and /pricing are different paths on most servers, so uppercase the scheme and host and leave the rest alone.
What error correction actually costs
Every QR code carries redundancy so it survives dirt, damage and a logo dropped in the middle. There are four levels, and Denso Wave puts level M at 15 percent recovery and level Q at about 25 percent3, with L lower and H higher.
The interesting question is not what they recover but what they cost.
For an 89-character URL, going from L to H moves you from a 37-module grid to a 53-module one. At a practical 0.4 mm per module that is 18.0 mm of printed width against 24.4 mm, once you include the quiet zone. About a third wider, for four times the damage tolerance, which is nearly always the better trade on anything that goes to print.
The centre-logo trick lives on the same budget. The logo destroys modules and the error correction rebuilds them, so a logo covering more area than the level recovers will not scan. Keep it under about a fifth of the code area and use level H, or put the branding underneath the code where it costs nothing.
Why it does not scan
It was printed too small. Work from the module, not the overall size. Roughly 0.4 mm per module is a sane floor for a phone camera, and Denso Wave's own sizing method is cell size times modules, plus the margin1. A 41-module code needs 41 plus 8 modules of width, so about 19.6 mm. Business cards and wine labels are where this goes wrong, because a code that reads under a desk lamp fails at arm's length in a restaurant.
The quiet zone was cropped. The specification requires a blank margin four modules wide on every side1. Designers trim it to make the code fit a layout, and a code flush against a border or an image is measurably harder to acquire.
Contrast is too low. Black on white is the reference. Dark blue on light blue usually works and fails first in bad light. Inverted codes, light modules on a dark ground, are handled by most current scanners and not all of them, so test before printing ten thousand.
The surface is glossy or curved. Glare defeats the camera, and a bottle or a curved magnet distorts the grid past what the alignment patterns can correct. For curved surfaces, a physically smaller code at level H beats a larger code at level L.
Making codes that survive
- Level M as a minimum for anything printed. L is for screens.
- Keep the URL short, on a domain you own. Fewer characters means fewer modules means a smaller minimum size.
- Use a redirector you control, so the destination can change without a reprint. The sticker is permanent, the URL is not.
- Load the destination from a phone on mobile data before the file goes out. Not from the laptop that still has the staging host in
/etc/hosts. - Test on both iOS and Android, at the distance and in the light the reader will actually have.
Our QR Code Generator exposes the error correction level and size directly and runs in the page, so the URLs you encode are not uploaded anywhere.
The specialised formats
Wi-Fi, as WIFI:S:<ssid>;T:<auth>;P:<password>;;, which a phone camera offers to join directly. Genuinely the best way to hand out a guest password, and our Wi-Fi QR Code Generator writes it for you.
vCard, for contact details at an event. Scanners show the data before adding it, so whoever scans sees exactly what you encoded.
mailto: and SMSTO:, which prefill a recipient and a body. Useful on a support sticker where you want incoming messages to arrive in a predictable shape.
Bulk, for asset tags and tickets: the Bulk QR Code Generator takes a list and produces them at consistent size and error correction.
To check a batch actually points where you think, the QR Code Reader decodes from an image in the browser, which beats scanning a hundred stickers by hand.
A QR code is a link, with all that implies
Nothing in a QR code is encrypted or hidden. Whatever you encode is readable by anyone who scans it, and a link is a credential whenever the destination treats it as one. A menu code pointing at a shared document with link-based editing is handing out edit access to everyone who sits down.
From the other side: your phone shows the decoded target in a banner and waits for a tap. That banner is the only moment you get to notice that the sticker over the parking meter's real code leads somewhere nobody recognises. Scanning is safe. Tapping without reading is where the money goes.
Design them as if they will outlive the campaign, because printed ones do.
Sources
Every number in this article traces to a source below. Where a claim could not be sourced, it was cut rather than softened.
- Primary sourceDenso Wave
That a QR code requires a four-module wide margin on all sides of the symbol, and the method for calculating the physical size of a printed symbol from the cell size plus that margin.
- Primary sourceIETF
That schemes are case-insensitive and that the host subcomponent of the authority is case-insensitive, which is what makes the uppercase encoding trick safe for the scheme and host but not for the path.
- Primary sourceDenso Wave
The existence of the four error correction levels L, M, Q and H, and the stated recovery figures of 15 percent for level M and about 25 percent for level Q.
Topics
- QR Code
- Encoding
- Error Correction
- Printing
Tools mentioned in this article
- QR Code Generator - Generate QR codes for URLs, text, email, phone and WiFi.
- QR Code Reader - Scan and decode QR codes from any image online - upload a photo, screenshot or saved picture and read the QR contents instantly in your browser.
- WiFi QR Code Generator - Generate a QR code for your WiFi network so guests can connect by scanning.
- Bulk QR Code Generator - Generate multiple QR codes at once from a list of URLs or text.
Get new tools by email
New tools and the occasional deep-dive, about once a month. No spam, no sharing your address, unsubscribe in one click.