What the version number costs you
A QR code is a grid of black and white squares called modules. The grid size is the version: version 1 is 21 by 21, and each step up adds four modules to a side, so version 10 is 57 by 57. The encoder here picks the smallest version that fits your content at the error correction level you chose, then stops at version 10. That is deliberate rather than arbitrary: past that point the modules get dense enough that phone cameras start needing a deliberate, steady, close scan, and the honest answer for a long payload is to host it and encode the URL instead.
Encoding is byte mode with UTF-8, so plain ASCII costs one byte per character and anything outside ASCII costs two to four. Uppercase-only URLs could be packed smaller using alphanumeric mode, but this encoder does not implement that mode, so a shouty URL takes exactly as much room as a lowercase one.
Error correction levels, and what they trade
Reed-Solomon parity is mixed into the code so a damaged or obscured code still decodes. The four levels recover roughly this much of the code:
| Level | Recovers about | Use it when |
|---|---|---|
| L | 7% | Clean screen display, short link, you want the smallest grid |
| M | 15% | Default. Print, signage, anything handled normally |
| Q | 25% | Labels that get scuffed, curved surfaces, outdoor use |
| H | 30% | A logo sits on top of the code, or it will get genuinely abused |
The trade is not free. Higher parity means more codewords for the same payload, which pushes the version up, which makes every module smaller at a fixed print size. An H-level code carrying a long URL can end up harder to scan than an M-level one, because the extra robustness got spent on a denser grid. Raise the level and the printed size together, or you have moved the failure sideways rather than fixed it.
Print size and the quiet zone
The working rule for scan distance is that the code needs to be about a tenth of the distance it is read from. On a business card held at 20 cm, 2 cm is enough. On a poster read from 2 m, you want 20 cm. Denser codes need more than that, because what actually matters is how many camera pixels land on one module, not how many land on the whole code. A version 10 code at 57 modules across needs roughly twice the printed width of a version 4 code to give the camera the same module size.
The white border around the code is the quiet zone, and the spec calls for four modules of it. Cropping it off is the single most common reason a technically valid code will not scan, because the decoder cannot tell where the code ends and the background begins. This generator renders it into the PNG for you. The output width is rounded down so each module is a whole number of pixels, which is why you may get 396 px when you asked for 400 — that rounding is what keeps the module edges crisp instead of blurred by resampling.
Payload formats worth knowing
For a link, include the scheme. https://example.com opens as a link; example.com often gets treated as plain text. Long tracking parameters push the version up fast, so strip what you can or use a short URL. A few other formats decode into actions on most phones: tel:+15550100 for a phone number, mailto:[email protected]?subject=Hello for email, WIFI:T:WPA;S:NetworkName;P:password;; to join a network, and a BEGIN:VCARD block for contact details, though vCards are long enough that they usually blow past version 10.
One thing a generated code cannot do is change later. The URL is baked into the image, so if the destination might move, encode a redirect you control rather than the final address. That is the whole business model of paid QR services, and you can have it for the price of one redirect rule on a domain you already own.
Questions people ask
Why will my printed code not scan?
In rough order of likelihood: the quiet zone got cropped, the code was printed too small for its density, contrast is poor because it was printed on a coloured or glossy stock, or the image was resized with a smoothing filter that blurred the module edges. Test the fix in that order. Print at twice the size and scan again — if that works, the problem was size or resampling, not the encoding. Also check the code is not mirrored, which happens when an image gets flipped in layout software and is invisible to the eye.
Can I put a logo in the middle?
Yes, if you generate at level H and keep the covered area under about 15% of the code. That is what the H level is for. Download the PNG, place the logo in an image editor, and then actually scan the result with two or three different phones before you send it to print. The parity can absorb the loss, but only if you have not also covered a finder pattern or the timing rows.
Are coloured QR codes safe?
They work if the contrast between the dark and light modules is strong and the polarity is correct — dark modules on a light background. Inverting it, so light modules sit on dark, fails on many scanners. Keep the luminance difference large; a mid-blue on white is fine, a mid-blue on light grey is not. Test on real devices rather than trusting an on-screen preview, and never colour the quiet zone.
Does anything I type get sent to a server?
No. The encoder, the Reed-Solomon arithmetic and the canvas rendering all run in the page. The PNG is produced as a data URL by your own browser and the download link points at that data URL rather than at a server. You can verify it by opening the network tab and generating a code, or by disconnecting from the network and reloading the page.