Skip to content

As empty as a QR code
can get and still scan

A normal QR code is about half black. This one gets that down to a tenth, without breaking the spec.

Same URL, same scanners

48%An ordinary QR code. Close to half of the data area is black.
13%Barely QR. The middle is hollow, and it points at the same URL.

Not adding blank space. Emptying space that was already wasted.

The grey wash marks the modules we are free to paint. It is close to 70 percent of the code. Only the red dots carry actual meaning.
Leave room to spare
Pick a version larger than your URL needs and you get leftover codewords. The spec tells you to fill them with fixed junk bytes, and that junk is a big part of why QR codes look so dense.
Undo the mask on purpose
The last encoding step XORs a lattice over the data area. XOR of two equal values is zero, so if you pre-load each padding bit with the mask value for that position, the two cancel and the module comes out white.
The reader never looks
Decoders stop at the terminator and ignore everything after it. Whatever sits in the leftover space, the result is identical. That makes it our canvas.

Read the full method and the measurements

How empty it gets is decided by the error correction level

Error correction bytes are computed by the algorithm, so we cannot touch them and they stay black. Raising the level grows that untouchable area and shrinks the blank space.

Share of black modules by error level and version
LevelV2V5V10Good for
L27%15%12%Sharing on screens
M34%21%21%Sensible default
Q38%32%29%Cards and stickers
Hn/a40%34%Print and outdoors

Measured by encoding the same URL with each setting and counting black modules in the data area. An ordinary QR code sits around 47% at every setting.

Questions people ask

Does this break the spec?
Only the contents of the padding differ. The mask number is recorded exactly as the spec requires and Reed-Solomon is computed normally, so decoders treat it as an ordinary QR code. Strict spec mode fills the padding by the book as well.
Will every scanner read it?
Every code is decoded by a real decoder in your browser before you download it, and the result is shown to you. That said, phone cameras and messaging apps each ship their own decoder. Test on real devices before using one somewhere that matters.
Why do some settings scan unreliably?
A large white area gives the binarizer nothing to calibrate against. In dim light or a shaky photo, specks appear where there were none, and if the error correction bytes cannot absorb them the read fails. Raise the error level or drop one version.
Is what I type stored anywhere?
No. Encoding, rendering and verification all happen in your browser, and the text is never sent to a server. There is no link shortener either, so nothing redirects in the middle.
It says my URL is too long
Versions up to 10 are supported. At error level L that is 271 characters for a normal URL, or 395 if you use only uppercase letters and digits, because that mode packs two characters into 11 bits. If you can uppercase the path, your code gets a size or two smaller.