How Big Does This QR Code Need to Be: Bytes, Versions, and What Level H Costs

· 5 min read · QR code UTF-8 printing · 简体中文

A QR code’s size is settled by arithmetic before anyone opens a graphics program. Type a string and the grid follows: how many bits that text costs, how much of the symbol is reserved for repair words, and how large a grid therefore has to be to hold what is left. The dial people reach for first — pixels per module — changes none of it. It scales a picture that is already decided.

Whether a printed symbol survives a busy noticeboard is a millimetre figure you can put a ruler against, and it comes out of the same arithmetic. That is the useful form of “will this scan”.

A version is a size, and that is the entire claim

Versions run 1 to 40, and version v is a grid 4v + 17 modules on a side: 21 at version 1, 29 at version 3, 37 at version 5, 177 at version 40. Nothing about the bigger number means more detail. The information is the same pattern of black and white; a larger version spreads it over more ground, which makes the symbol bigger rather than better.

Each version carries a fixed count of codewords - 8-bit words the grid has room for - and version 1 has 26 of them at every level. What the level decides is the split between them: 19 words of data plus 7 of repair at L, 9 plus 17 at H. So a version and a level are two independent dials. The grid fixes how much picture you are printing; the level fixes how much of that grid is yours. Two symbols can both be 29 x 29 modules and hold wildly different amounts of text - version 3 at L keeps 55 data words, at H only 26.

What your text costs, in bits

Three modes, three rates. Numeric packs three digits into 10 bits, about 3.3 apiece. Alphanumeric puts a pair of characters from its set of 45 into 11 bits, so 5.5 each. Byte mode spends a flat 8 bits per UTF-8 byte. On top of the payload every mode pays a header: four bits for the mode indicator, then a character count whose width depends on the version - 8 bits in byte mode up to version 9, then 16, and numeric and alphanumeric widen again past version 26.

https://vixyun.top/tools/qr-code-generator/ is 43 characters, every one of them a single byte, and it still lands in byte mode because the alphanumeric set contains no lower case. 4 + 8 + 344 = 356 bits.

Shout the same string in capitals and it prices as alphanumeric: 21 pairs at 11 bits plus one leftover character at 6, so 237 payload bits, 250 all in. At level L that buys a version 2 symbol, 25 x 25, where the same characters in lower case need version 3 and 29 x 29. Folding a URL’s case to buy that back would break the link, of course, and a generator that did it quietly would hand you a picture that reads back as something you never typed. The cheaper mode is worth having when the content really is upper case: a tracking number, a booking reference, a part code stamped on a moulding.

Chinese pays the byte rate at three bytes per han character. 你好,欢迎光临。 is 8 characters, 24 bytes, 192 payload bits, 204 all in - one han costs about seven times what one digit costs. The specification has a kanji mode that packs those characters into 13 bits each, and the published capacity tables quote it: version 1 at level L holds 10 kanji characters where the byte route holds five. That mode is for a Japanese double-byte set, and it is not implemented in the QR generator, so anything Chinese takes the 24-bit price. Paste the text into the character lookup if you want to see those byte counts for the exact characters you are using rather than the average.

The same URL at four levels

Level Version and grid Room kept for data, against the 356 bits needed Words spent on repair
L 3 - 29 x 29 55 data words = 440 bits 15 of 70 codewords
M 4 - 33 x 33 64 = 512 bits 36 of 100
Q 4 - 33 x 33 48 = 384 bits 52 of 100
H 5 - 37 x 37 46 = 368 bits 88 of 134

Read the middle column as a budget, not a grade. Your text costs 356 bits in all four rows - the level cannot make a URL shorter. What it changes is how many words out of the grid are reserved for repair, and once that reserve starts eating into the 356 the symbol has to grow: version 4 at H keeps just 288 data bits, which is why level H on this string jumps to version 5.

M and Q both land in version 4 even though one offers 512 bits and the other 384, because the block table moves in whole words and whole blocks, not in the size of your text. Which is also why a finished symbol is usually part filler: at M, your 43 characters filled 356 of the 512 bits on offer and the rest got padded out with the two alternating words 0xEC and 0x11. At H there are 12 bits of slack left over and exactly one pad word. The ledger table under the picture lists every one of those steps - header, payload, terminator, zeros to the byte edge, pad words, check words - for whatever you actually typed.

The 7%, 15%, 25%, 30% figures are not what the table above prints

Those four numbers get quoted everywhere as “how much of the code you are allowed to cover up”. They are rough estimates of how much damaged ground a reader can still work through, averaged over the whole symbol. The check-word share is a different quantity, and the table above prints it: 21.4% of codewords are repair at 3-L, 65.7% at 5-H. Same four letters, not the same measurement.

Three consequences follow from that difference.

The estimate is an average, so it says nothing about where the damage lands. Scuffs, coffee rings, stickers and a stapler arrive in clusters, and a decoder reconstructs a contiguous run of destroyed words far worse than the same count scattered across the grid.

Damage also is not evenly expensive. The parts of the symbol that carry none of your text are fixed, named places: the three finder patterns, the two timing tracks, the format area, and from version 7 up the two blocks that write the version number itself. A symbol that has lost a finder corner is unreadable at any level, and a logo placed over the centre of a version 3 code is much worse than the same area of dots spread over the whole grid.

And repair words are a share of the data, not a coat of varnish over the picture. That is why raising the level costs you room: nothing is added to the symbol, something is taken away from your text.

Five han characters fit in version 1; six do not

Version 1 at L has 19 data words, which is 152 bits, and a byte-mode header costs 12 of them. So 17 bytes - the capacity table’s own number - and 5 han characters at 15 bytes walk straight in while 6 at 18 bytes do not: the symbol moves to version 2 and the grid goes from 21 x 21 to 25 x 25.

At H the same version keeps 9 words, 72 bits, and byte capacity drops to 7. Two characters fit; three need a bigger box. The four levels at version 1 are 17, 14, 11 and 7 bytes, which is a decent feel for how fast a short Chinese phrase eats versions.

A name badge with 「张伟」 and a company name gets there in one version. A paragraph does not exist as one code - it exists as a URL pointing at a paragraph.

Millimetres fall out of the version

The picture is not just the symbol. A quiet zone of blank ground goes around it - four modules on each side is what the specification asks for - so a 29-module symbol prints as a 37-module picture. At 0.4 mm per module that is 14.8 mm on a side. The same text at H: 37 + 8 = 45 modules, 18 mm.

On a shop door, 3 mm is nothing. On a pen barrel, a lanyard badge, or the corner of a receipt it is the difference between a code and a decoration. Two things to keep straight about that 0.4 mm: it is a rule of thumb about a phone camera at arm’s length, not a figure lifted from the standard, whose own tables work from symbol size and viewing distance; and the lever when you need a smaller print is never the pixel slider. It is shorter text or a lower level. Take the module size down and you have the same geometry with less ink on it, which is exactly what a camera cannot resolve.

On a screen the same arithmetic arrives from the other side. Ask for one pixel per module and the box takes it: a version 2 symbol plus its quiet zone becomes a 33 x 33 pixel picture. The message guarding that range says plainly where the trade stops working - one pixel a module is where reading off a display starts to fail, and 40 is where a version 40 symbol pushes the picture clean off the screen behind it. The drawing itself stops at 4,096 px a side, which is the canvas ceiling browsers enforce rather than a limit invented here.

Exporting matters as much as the grid. A PNG at 8 px per module is a bitmap with real edges; if it goes through a resample or a lossy re-encode on the way to the print shop, those edges are the only thing the scanner was ever reading. The image compressor will show you what each format costs in bytes for the file you just made, which is a quick way to see how badly a low JPEG setting treats a symbol. For print, the SVG export writes the same modules as vector rectangles, so there is no resampling step left to blame.

When a box in a browser is the wrong tool

Long data is the clear one. Encoding stops at 4,000 characters, and the largest symbol in existence holds 2,953 bytes of data at level L - past that a code is a file, and a code you cannot photograph is not worth much. Put the long text behind a URL and encode the URL.

Mixed content is the subtler one. A single mode indicator covers the whole string, so PK-2026-118 张伟 costs byte mode from end to end, while an encoder that segments the string - one alphanumeric run, one numeric run, one byte run - pays each part at its own rate and gets a smaller symbol out of it. Segmentation is a real technique and a real saving; it also makes a claim about your text that a plain generator declines to make on your behalf.

And then the honest limits of the round trip. Once every module is placed, the finished grid is decoded again in the browser and compared with what went in - both copies of the format area lifted and checked against each other, the Reed-Solomon remainder recomputed from what the modules now say, the string reassembled and diffed. That catches misplaced bits, a bad interleave order, an off-by-one in the block split. It does not prove the symbol is legal, because it is one reading of the specification used twice, and a shared misreading round-trips perfectly. The test that matters is a scanner you do not own, on a print you can hold.

What the local route is good for: the text never leaves this device, so a card carrying somebody’s mobile number and home address can be built on a train, and the module grid stays exact rather than being guessed at by a service that also wants your traffic. What it is not good for: an API that has to regenerate ten thousand unique codes overnight, a batch where every symbol needs its own serial, or a design system that wants the same code re-emitted at four print sizes from one source file. Those want a library, a build step, and somebody who owns the versioning.

Do I need level H because I want a logo in the middle? A logo covers modules, and the level decides how the codewords are split - not which parts of the picture are protected. A cover over the finder patterns fails at any level. A shorter string at M beats the same string at H with a sticker on it, because the smaller symbol has more margin per module.

Why did my text jump two versions at once? Two prices move at once: the character count widens past version 9 and again past 26, and the block table’s data words per block change step, not smoothly. A string that nearly fills one version can be forced up two when the count field widens.

Can I read the version off a printed code? Count dark modules along one side of the symbol itself, excluding the blank ground, and solve 4v + 17. Version 7 and above also write its own number twice, in two 18-bit blocks near the top-right and bottom-left corners, so a reader does not have to guess.

Does a bigger module size make scanning easier? Only up to the point where the print resolution stops keeping edges sharp. The geometry, the mask and the repair words are fixed the moment the version is chosen; the rest is how much ink you put on each square.

Support on PayPal