Wouldn't it have been much more sensible to have a lowercase version of alphanumerics in the QR code standard? Almost all URLs are lowercase, and even if the have capitalised parts, in most cases they're case-insensitive.
> Alphanumeric data, in the context of QR codes, comes from the following alphabet of 44 characters:
> 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-.:
This is wrong: alphanumeric has 45 characters, not 44. It’s missing the second last character, /.
(The slash is important because it makes alphanumeric-mode URLs possible: you can write HTTPS://EXAMPLE.COM/PATH which will be parsed to https://example.com/PATH. No query string or fragment due to no ?&=#, and your server must accept the uppercase path, either serving it or redirecting to the lowercase and then serving that.)
An alphabet size of 45 is the largest that will fit into 5½ bits per character (log₂ 45 ≈ 5.49).
FWIW, the path segment itself is case-sensitive and it comed down to the webserver (and then mostly the filesystem) whether it wants to treat the path case-sensitive or not. There's no guarantee in HTTP that /PATH will serve a path located at /path.
A major frustration in my life is that LinkedIn QR codes will not support all caps. It’s not even a profile capitalization issue; the app will refuse to scan the code if the “/in/“ is capitalized. The resulting size difference is quite noticeable particularly in small format.
I am amazed at how much there is to know about QR codes, particularly if you want them to look pretty.
I want the super succinct QR code and I believe that to be optimal. However, I keep seeing massively complicated QR codes, as if going from 8 bit to 64 bit, and I assume these work well. Given the amount of megapixels in any camera made this century and the prevalence of over complicated URLs in QR form, I am not sure if minimised QR codes have any benefit whatsoever. By minimised, I mean 29 x 29.
On the QR topic, I don't understand how logos in the middle work. You are losing pixels and checks with the logo in the middle which is fine until you make the logo too big.
Also related, imagine you wanted a HN QR code with 'Hacker News' written in the middle. This would work as a box in the middle but would be hard to read. So you can make a line across the middle rather than a box in the middle. This will break the QR code but not if you rotate the QR code 90 degrees first.
Maybe my best option to fully understand the quirks is to start with the QR spec and then to make my own QR codes.
It's not just that. It's the resolution of the display device too. It's brightness and whether that is causing bloom. If it's printed small, users may instinctively put the camera too close and it won't be able to focus. People have shaky hands and the image will have motion blur. Glare is a persistent problem with bikeshare apps, where the app turns on your phone's flashlight while scanning for nighttime use, but the QR code is glossy. Codes get scratched up, and the smaller the blocks are, the more they are degraded.
There really are tons of ways QR codes degrade no matter how many megapixels you have, and smaller codes are always going to be more resistant given the same overall physical size.
This tool [1] let me figure that out couple of years ago. And on the printable pages of the sites I own, for instance [2], I use a all caps domain and identifiers so that all my QR Codes are tiny (e.g: `HTTPS://ABC.DE/ABCD/42`, with up to 10 chars in the path).
In the 2010s I had a startup generating a bunch of QR Codes. We generated URLs with a BASE32 variant plus upper case domain and scheme so we could stay within the 5.5 bits per character encoding. I kept trying to explain this feature to people, but it was an uphill battle. To this day I still use upper case w/ URLs JUST-IN-CASE I want to put them in a QR Code.
One minor annoyance I have is the ``git`` command line tools (at least the ones distributed w/ Debian) are case sensitive w/ URLs, so if you try the command:
git clone HTTPS://GIT.BI6.US/TQT
you'll get an error, but
git clone https://GIT.BI6.US/TQT
does what you might expect it to do. This is a very minor nit since no git tool I know directly consumes QR codes and if you made one, you could lower case the protocol section yourself. It's just that all day I'm using URLs that are intentionally upper-cased and the one time I need to lower-case a portion of it, I always forget.
I should probably publish the BASE32 variant we used. Mostly just removed the I's O's and a few other letters that could easily be confused with digits or with other letters.
You don't need to make the whole payload uppercase to benefit from this aspect of QR code, as a single QR code can use multiple different encoding schemes. It is sufficient that a large consecutive portion of your payload is limited to those alphanumeric characters.
This was something that I paid close attention to when designing a QR code to be hand-carved into a set of coasters. To minimize the amount of detail carving required, I wanted to use the smallest QR code at 21x21 (version 1) tiles.
With ascii encoding, this would limit me to 17 characters, but the alphanumeric encoding allowed up to 25 characters. Since DNS is case-insensitive, this let me carve a slightly longer URL. The only downside was that it required making a custom redirect on my own website, since I couldn’t find any url shorteners that would use all caps.
To this day, it is the most effort I’ve put into rick-rolling somebody.
I invested quite a bit of effort into designing URLs for the PartsBox ID Anything™ system so that they fit well into optimized QR codes. Uppercasing was one of the tricks, and it makes quite a difference indeed. This is important when you want small and yet easily readable/scannable QR codes.
Later it turned out that when printing labels, you hand your data off to the printer to produce the QR code anyway, and printers do not try very hard to find an optimal encoding.
Just this week, I was writing a script to generate a UUID, make a QR code of it, and print both on a label. I uppercased the UUID to hopefully make the label more human readable after scratching and scuffing, and noticed the QR code got smaller.
(self promo-ish) The above blog article was one of the pieces shown at the QR Show that I helped co-organize earlier this year at the Recurse Center. I'm definitely tempted to have another one in 2026!
20 comments
[ 4.4 ms ] story [ 30.4 ms ] threadI tested this with the following example: https://imgur.com/a/hTsvV3Z
> 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-.:
This is wrong: alphanumeric has 45 characters, not 44. It’s missing the second last character, /.
(The slash is important because it makes alphanumeric-mode URLs possible: you can write HTTPS://EXAMPLE.COM/PATH which will be parsed to https://example.com/PATH. No query string or fragment due to no ?&=#, and your server must accept the uppercase path, either serving it or redirecting to the lowercase and then serving that.)
An alphabet size of 45 is the largest that will fit into 5½ bits per character (log₂ 45 ≈ 5.49).
FWIW, the path segment itself is case-sensitive and it comed down to the webserver (and then mostly the filesystem) whether it wants to treat the path case-sensitive or not. There's no guarantee in HTTP that /PATH will serve a path located at /path.
I want the super succinct QR code and I believe that to be optimal. However, I keep seeing massively complicated QR codes, as if going from 8 bit to 64 bit, and I assume these work well. Given the amount of megapixels in any camera made this century and the prevalence of over complicated URLs in QR form, I am not sure if minimised QR codes have any benefit whatsoever. By minimised, I mean 29 x 29.
On the QR topic, I don't understand how logos in the middle work. You are losing pixels and checks with the logo in the middle which is fine until you make the logo too big.
Also related, imagine you wanted a HN QR code with 'Hacker News' written in the middle. This would work as a box in the middle but would be hard to read. So you can make a line across the middle rather than a box in the middle. This will break the QR code but not if you rotate the QR code 90 degrees first.
Maybe my best option to fully understand the quirks is to start with the QR spec and then to make my own QR codes.
It's not just that. It's the resolution of the display device too. It's brightness and whether that is causing bloom. If it's printed small, users may instinctively put the camera too close and it won't be able to focus. People have shaky hands and the image will have motion blur. Glare is a persistent problem with bikeshare apps, where the app turns on your phone's flashlight while scanning for nighttime use, but the QR code is glossy. Codes get scratched up, and the smaller the blocks are, the more they are degraded.
There really are tons of ways QR codes degrade no matter how many megapixels you have, and smaller codes are always going to be more resistant given the same overall physical size.
[1]: https://www.nayuki.io/page/creating-a-qr-code-step-by-step [2]: https://www.brainzilla.com/logic/zebra/pdf/blood-donation.pd...
One minor annoyance I have is the ``git`` command line tools (at least the ones distributed w/ Debian) are case sensitive w/ URLs, so if you try the command:
you'll get an error, but does what you might expect it to do. This is a very minor nit since no git tool I know directly consumes QR codes and if you made one, you could lower case the protocol section yourself. It's just that all day I'm using URLs that are intentionally upper-cased and the one time I need to lower-case a portion of it, I always forget.I should probably publish the BASE32 variant we used. Mostly just removed the I's O's and a few other letters that could easily be confused with digits or with other letters.
With ascii encoding, this would limit me to 17 characters, but the alphanumeric encoding allowed up to 25 characters. Since DNS is case-insensitive, this let me carve a slightly longer URL. The only downside was that it required making a custom redirect on my own website, since I couldn’t find any url shorteners that would use all caps.
To this day, it is the most effort I’ve put into rick-rolling somebody.
Later it turned out that when printing labels, you hand your data off to the printer to produce the QR code anyway, and printers do not try very hard to find an optimal encoding.
Now I know why.
https://shkspr.mobi/blog/2025/02/why-are-qr-codes-with-capit...
Past discussion: https://news.ycombinator.com/item?id=43149077
(self promo-ish) The above blog article was one of the pieces shown at the QR Show that I helped co-organize earlier this year at the Recurse Center. I'm definitely tempted to have another one in 2026!
The whole lists of pieces is here: https://qrshow.nyc/retrospective.html