Inside a QR Code: Versions, Modules, and Encoding Modes
A QR code (ISO/IEC 18004) comes in 40 sizes called versions. Version 1 is a 21×21 grid of modules (the black/white squares); each version adds 4 modules per side, up to version 40 at 177×177. More data means a higher version, smaller modules at the same print size, and a harder scan. The three large squares are finder patterns, the smaller ones are alignment patterns, and the alternating lines between finders are timing patterns — none of these carry your data, and none may be obscured.
Capacity depends on the encoding mode, chosen automatically per segment. Numeric mode packs 3 digits into 10 bits; alphanumeric mode packs 2 characters into 11 bits but only supports a 45-character set (digits, UPPERCASE A–Z, space, and $ % * + - . / :); byte mode spends a full 8 bits per byte, with UTF-8 as the de facto text encoding; kanji mode packs Shift-JIS characters in 13 bits. At version 40 with the lowest error correction the ceilings are 7,089 numeric digits, 4,296 alphanumeric characters, or 2,953 bytes.
Two practical consequences. First, lowercase letters force byte mode — an uppercase URL like HTTPS://EXAMPLE.COM/ABC can encode in alphanumeric mode and produce a visibly sparser code than its lowercase twin (the scheme and host are case-insensitive; the path usually is not, so only uppercase what you control). Second, a typical short URL of 30–50 characters lands around version 2–4 (25×25 to 33×33), which is the sweet spot for reliable scanning from a poster.
Alphanumeric capacity by version and EC level:
Version 1 (21×21): L 25 / M 20 / Q 16 / H 10
Version 5 (37×37): L 154 / M 122 / Q 87 / H 64
Version 10 (57×57): L 395 / M 311 / Q 221 / H 174
Version 40 (177×177): L 4296 / M 3391 / Q 2420 / H 1852
Same 60-char URL: EC L -> version 3, EC H -> version 5
(more correction = physically denser code)
HTTPS://SDK.IS/QR -> alphanumeric mode (sparser)
https://sdk.is/qr -> byte mode (denser, same length)
Error Correction: What L, M, Q, H Really Trade Away
QR codes protect their payload with Reed-Solomon error correction — the same family of codes used on CDs and in deep-space telemetry. The four levels state how many codewords can be destroyed and still recovered: L about 7%, M about 15%, Q about 25%, H about 30%. The cost is capacity: the correction bytes live in the same grid, so the same URL at level H needs roughly twice the modules of level L, pushing the code up one or two versions.
The percentages describe codewords, not printed area, and recovery also depends on where the damage lands. Reed-Solomon handles scattered errors well, but a stripe of glare or a fold across the code can take out interleaved blocks faster than the headline number suggests. And the function patterns — finders, timing, format information — are not covered by error correction at all: a sticker over one corner finder kills the scan regardless of level.
Logo overlays work by deliberately spending the error budget: the decoder treats the covered modules as damage and reconstructs them. If you overlay a logo, use level H and keep the logo under roughly 10% of the code area, centered, away from the three finders. That leaves real-world margin for scuffs and glare on top of the logo's cost. The pragmatic defaults: M for screens and clean print, Q for menus and things people touch, H only when you overlay branding or print on surfaces that will wear — and remember every step up makes the code physically denser.
Level Recoverable codewords Overhead Typical use
L ~7% lowest controlled screens
M ~15% default posters, docs
Q ~25% higher menus, packaging
H ~30% ~2x vs L logo overlay, harsh env
NOT protected by any level:
- the 3 corner finder patterns
- timing patterns / format info
- a missing quiet zone around the code
Print Physics: Quiet Zone, Contrast, and the Distance Rule
Most QR failures in the wild are physical, not digital. The spec requires a quiet zone — an empty border at least 4 modules wide on all sides. Designers crop it constantly because it looks like wasted space; scanners then cannot isolate the symbol from the busy background, and the code fails intermittently in exactly the way that never reproduces on your desk.
Size follows a simple field rule: minimum code width is roughly the scanning distance divided by 10. A code scanned from 10 cm (a business card) works at 1 cm; a poster read from 3 meters needs a 30 cm code. Combine that with module count: at a fixed print width, a version 10 code has 57 modules per side, so each module is one-third the size of a version 2 module — high-version codes need disproportionately more print area. For print resolution, keep each module at or above about 4 printer dots; below roughly 0.4 mm modules on office printers, ink spread starts merging modules.
Contrast is the other silent killer. Decoders binarize the image, so you need dark modules on a light background with strong luminance difference — dark navy on white is fine, yellow on white is not. Inverted codes (light modules on dark) violate the spec; iOS and many Android scanners read some of them anyway, but plenty of scanner apps and embedded readers do not — never ship one without testing. Glossy lamination adds specular glare that can blank out entire regions, and curved surfaces (bottles, mugs) distort geometry: keep codes on the flattest area available, and always test with both an iPhone and an Android camera before printing a thousand copies.
Field rules of thumb:
min code width ≈ scan distance / 10
business card (10 cm) -> 1 cm
shelf label (50 cm) -> 5 cm
poster (3 m) -> 30 cm
quiet zone >= 4 modules, all four sides
module size >= 0.4 mm on office printers (>= 4 dots)
contrast dark-on-light; inverted codes fail many readers
surfaces flat > gently curved; avoid gloss + direct light
Payload Formats Worth Knowing: Wi-Fi, vCard, otpauth, and Dynamic QR
A QR code encodes bytes; what a phone does with them is a convention keyed off the prefix. URLs open the browser. A WIFI: string joins a network: WIFI:T:WPA;S:MyNetwork;P:secret;; — where T is the auth type (WPA covers WPA2/WPA3 personal, use nopass for open networks), S the SSID, P the password, and an optional H:true flags a hidden SSID. The characters backslash, semicolon, comma, colon, and double quote must be escaped with a backslash inside values; an unescaped semicolon in a Wi-Fi password is the classic reason a Wi-Fi QR 'sometimes' fails.
Contact data has two conventions: vCard (BEGIN:VCARD ... END:VCARD) is verbose but understood everywhere and survives multiline addresses; MeCard (MECARD:N:...;TEL:...;;) is a compact NTT DoCoMo format that produces a much smaller code but supports fewer fields. TOTP secrets for two-factor setup travel as otpauth://totp/Issuer:account?secret=BASE32&issuer=Issuer — treat that QR as the secret itself: whoever scans it can generate your codes forever. Other useful prefixes: tel:, mailto:, sms:, and geo:37.5665,126.9780.
The static-versus-dynamic distinction is a product decision, not a format. A static code embeds the final URL: nothing to maintain, works forever, but unchangeable once printed. A 'dynamic' code just encodes a short redirect URL you control, buying you editability after printing, scan analytics, and shorter payloads (hence sparser codes) — at the price of a dependency: if the redirect service dies or the subscription lapses, every printed code dies with it. For anything long-lived on paper, prefer a redirect domain you own over a third-party shortener.
Security and Privacy: Quishing, Secrets, and Where Your Data Goes
A QR code is not encrypted, not signed, and not verifiable by eye. Those three absences define its threat model.
Quishing — phishing via QR — exploits the fact that humans cannot read the payload before scanning. The standard attack is a sticker with a malicious code pasted over a legitimate one on a parking meter, restaurant table, or invoice. Payment-fraud variants redirect to lookalike checkout pages. Defenses are mundane but effective: print the human-readable URL next to the code so people can compare what the scanner previews, use a branded domain rather than a generic shortener (a preview showing pay.yourbrand.com is checkable; a random short code is not), and physically inspect long-lived public codes for tampering. Modern phone cameras show the destination domain before opening — train users to actually read it.
Do not put secrets in QR codes displayed or printed where cameras reach. A Wi-Fi QR contains the password in plaintext; anyone who photographs the poster has it. An otpauth QR is the 2FA seed itself. Event tickets and boarding passes encode enough to clone or cancel a booking — the people who post them on social media learn this the hard way.
Finally, know where generation happens. Some web generators (including this page) build the image by calling a server-side API, which means the payload leaves your machine; others render entirely in the browser via a JavaScript library or offline tools like the qrencode CLI. For URLs to a public website it makes no difference. For Wi-Fi credentials, TOTP seeds, or anything internal, generate offline — the qrencode command or a local library gives you the same PNG without the network round trip.
# offline generation — payload never leaves the machine
qrencode -o wifi.png -l H 'WIFI:T:WPA;S:BackOffice;P:secret;;'
# checklist for public, long-lived codes
[ ] human-readable URL printed next to the code
[ ] branded domain (pay.yourbrand.com), not a generic shortener
[ ] HTTPS destination — camera previews show the domain
[ ] periodic physical check for sticker-over-sticker tampering
[ ] no secrets in the payload (Wi-Fi passwords ARE plaintext)
Last updated:
About this tool
A QR code generator turns any URL, contact card, Wi-Fi credential, or short text into a square barcode that any phone camera can read instantly. QR codes are everywhere — restaurant menus, event check-ins, two-factor auth setup, payment links — because they bridge the physical and digital worlds without requiring an app install.
How to use
Type or paste the content you want to encode (URL, text, contact info, etc.).
Adjust the size slider to balance scanability and the space you have available.
Click Generate to render the QR code in the preview panel.
Test by scanning with your phone camera before publishing.
Download the PNG and embed it on a poster, menu, slide deck, or web page.
Common use cases
Linking a printed menu directly to an online ordering page.
Sharing event Wi-Fi credentials so guests join without typing.
Generating a QR for a TOTP secret during 2FA setup.
Producing a vCard QR for business cards or conference badges.
Driving in-person traffic to a feedback survey or product page.
Adding a QR shortcut to a documentation page in slide decks.
Frequently asked questions
Q. How much data can a QR code hold?
A. Up to ~4,296 alphanumeric characters at the highest density. In practice keep it short: shorter URLs scan faster from a distance and tolerate more damage.
Q. What error correction level should I use?
A. Level M (15%) is a good default. Level H (30%) is recommended if you plan to overlay a logo or print on a surface that may scuff.
Q. Can I track scans?
A. A QR encodes a fixed string. To track scans, point it at a short URL or analytics-aware redirect that you control.
Q. Why do some QR codes have rounded dots?
A. Cosmetic. The QR spec only requires square modules; many generators offer styled variants but very stylised codes can fail on older scanners.