<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/rss-style.xsl" type="text/xsl"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	     xmlns:dc="http://purl.org/dc/elements/1.1/"
	   xmlns:atom="http://www.w3.org/2005/Atom"
	     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	  xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
<channel>
	<title>Why are QR Codes with capital letters smaller than QR codes with lower-case letters? &#8211; Terence Eden’s Blog</title>
	<atom:link href="https://shkspr.mobi/blog/2025/02/why-are-qr-codes-with-capital-letters-smaller-than-qr-codes-with-lower-case-letters/feed/" rel="self" type="application/rss+xml" />
	<link>https://shkspr.mobi/blog</link>
	<description>Regular nonsense about tech and its effects 🙃</description>
	<lastBuildDate>Tue, 25 Mar 2025 10:04:40 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://shkspr.mobi/blog/wp-content/uploads/2023/07/cropped-avatar-32x32.jpeg</url>
	<title>Why are QR Codes with capital letters smaller than QR codes with lower-case letters? &#8211; Terence Eden’s Blog</title>
	<link>https://shkspr.mobi/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title><![CDATA[Why are QR Codes with capital letters smaller than QR codes with lower-case letters?]]></title>
		<link>https://shkspr.mobi/blog/2025/02/why-are-qr-codes-with-capital-letters-smaller-than-qr-codes-with-lower-case-letters/</link>
					<comments>https://shkspr.mobi/blog/2025/02/why-are-qr-codes-with-capital-letters-smaller-than-qr-codes-with-lower-case-letters/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sun, 23 Feb 2025 12:34:37 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[qr]]></category>
		<category><![CDATA[QR Codes]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=58337</guid>

					<description><![CDATA[Take a look at these two QR codes. Scan them if you like, I promise there&#039;s nothing dodgy in them.           Left is upper-case HTTPS://EDENT.TEL/ and right is lower-case https://edent.tel/  You can clearly see that the one on the left is a &#34;smaller&#34; QR as it has fewer bits of data in it. Both go to the same URl, the only difference is the casing.  What&#039;s going on?  Your first thought might be th…]]></description>
										<content:encoded><![CDATA[<p>Take a look at these two QR codes. Scan them if you like, I promise there's nothing dodgy in them.</p>

<hr>

<p><img src="https://shkspr.mobi/blog/wp-content/uploads/2025/02/caps.png" alt="QR CODE" width="400" height="400" class="alignnone size-full wp-image-58339" style="max-width:45%;display:inline;">&nbsp;&nbsp;&nbsp;<img src="https://shkspr.mobi/blog/wp-content/uploads/2025/02/lower.png" alt="QR Code." width="400" height="400" class="alignnone size-full wp-image-58338" style="max-width:45%;display:inline;"></p>

<hr>

<p>Left is upper-case <code>HTTPS://EDENT.TEL/</code> and right is lower-case <code>https://edent.tel/</code></p>

<p>You can clearly see that the one on the left is a "smaller" QR as it has fewer bits of data in it. Both go to the same URl, the only difference is the casing.</p>

<p>What's going on?</p>

<p>Your first thought might be that there's a different level of error-correction. QR codes can have increasing levels of redundancy in order to make sure they can be scanned when damaged. But, in this case, they both have <strong>L</strong>ow error correction.</p>

<p>The smaller code is "Type 1" - it is 21px * 21px. The larger is "Type 2" with 25px * 25px.</p>

<p>The <a href="https://www.qrcode.com/en/about/version.html">official specification</a> describes the versions in more details. The smaller code should be able to hold 25 alphanumeric character. But <code>https://edent.tel/</code> is only 18 characters long. So why is it bumped into a larger code?</p>

<p>Using a decoder like <a href="https://zxing.org/">ZXING</a> it is possible to see the raw bytes of each code.</p>

<p>UPPER</p>

<pre><code class="language-_">20 93 1a a6 54 63 dd 28   
35 1b 50 e9 3b dc 00 ec
11 ec 11 
</code></pre>

<p>lower:</p>

<pre><code class="language-_">41 26 87 47 47 07 33 a2   
f2 f6 56 46 56 e7 42 e7
46 56 c2 f0 ec 11 ec 11   
ec 11 ec 11 ec 11 ec 11
ec 11 
</code></pre>

<p>You might have noticed that they both end with the same sequence: <code>ec 11</code> Those are "padding bytes" because the data needs to completely fill the QR code. But - hang on! - not only does the UPPER one safely contain the text, it also has some spare padding?</p>

<p>The answer lies in the first couple of bytes.</p>

<p>Once the raw bytes have been read, a QR scanner needs to know exactly what sort of code it is dealing with.  <a href="https://www.thonky.com/qr-code-tutorial/data-encoding#step-3-add-the-mode-indicator">The first four <em>bits</em> tell it the mode</a>. Let's convert the hex to binary and then split after the first four bits:</p>

<table>
<thead>
<tr>
  <th align="center">Type</th>
  <th align="center">HEX</th>
  <th align="center">BIN</th>
  <th align="center">Split</th>
</tr>
</thead>
<tbody>
<tr>
  <td align="center">UPPER</td>
  <td align="center"><code>20 93</code></td>
  <td align="center"><code>00100000 10010011</code></td>
  <td align="center"><code>0010 000010010011</code></td>
</tr>
<tr>
  <td align="center">lower</td>
  <td align="center"><code>41 26</code></td>
  <td align="center"><code>01000001 00100110</code></td>
  <td align="center"><code>0100 000100100110</code></td>
</tr>
</tbody>
</table>

<p>The UPPER code is <code>0010</code> which indicates it is Alphanumeric - the standard says the next <strong>9</strong> bits show the length of data.</p>

<p>The lower code is <code>0100</code> which indicates it is Byte mode - the standard says the next <strong>8</strong> bits show the length of data.</p>

<table>
<thead>
<tr>
  <th align="center">Type</th>
  <th align="center">HEX</th>
  <th align="center">BIN</th>
  <th align="center">Split</th>
</tr>
</thead>
<tbody>
<tr>
  <td align="center">UPPER</td>
  <td align="center"><code>20 93</code></td>
  <td align="center"><code>00100000 10010011</code></td>
  <td align="center"><code>0010 0000 10010</code></td>
</tr>
<tr>
  <td align="center">lower</td>
  <td align="center"><code>41 26</code></td>
  <td align="center"><code>01000001 00100110</code></td>
  <td align="center"><code>0100  000 10010</code></td>
</tr>
</tbody>
</table>

<p>Look at that! They both have a length of <code>10010</code> which, converted to binary, is 18 - the exact length of the text.</p>

<p>Alphanumeric users 11 bits for every two characters, Byte mode uses (you guessed it!) 8 bits per single character.</p>

<p>But why is the lower-case code pushed into Byte mode? Isn't it using letters and number?</p>

<p>Well, yes. But in order to store data efficiently,  Alphanumeric mode only has <a href="https://www.thonky.com/qr-code-tutorial/alphanumeric-table">a limited subset of characters available</a>. Upper-case letters, and a handful of punctuation symbols: <code>space $ % * + - . / :</code></p>

<p>Luckily, that's enough for a protocol, domain, and path. Sadly, no GET parameters.</p>

<p>So, there you have it. If you want the smallest possible <em>physical</em> size for a QR code which contains a URl, make sure the text is all in capital letters.</p>

<hr>

<p><ins datetime="2025-03-25T10:02:55+00:00">This blog post was exhibited at <a href="https://qrshow.nyc/retrospective.html">QR Show, NYC</a><img src="https://shkspr.mobi/blog/wp-content/uploads/2025/02/image0.jpeg" alt="A print out of the blog post pinned up in an exhibition space." width="360" height="640" class="aligncenter size-full wp-image-59093"></ins></p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=58337&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/02/why-are-qr-codes-with-capital-letters-smaller-than-qr-codes-with-lower-case-letters/feed/</wfw:commentRss>
			<slash:comments>18</slash:comments>
		
		
			</item>
	</channel>
</rss>
