The Tiniest GIF Ever
Yesterday I was base64-encoding an image so I could send it to CouchDB to test some code I’m working on for a client. It reminded me of something I did a while back to set cookies on a remote server.
Basically, a small PHP script was put on the remote server which took a couple of GET parameters and set some cookies based on their values. The script then output a 1×1 transparent GIF. A PHP script on the local server generated an IMG tag which linked to this image and set the parameters based on the COOKIES on the local server.
This process also had to happen in the reverse direction, so I had to send the script to developers on the other side. I wanted to keep it as simple as possible, so I put the actual image contents in the PHP file as a base64 encoded string. I used the GIMP to generate the smallest transparent GIF I could manage so there wouldn’t be too huge of a nasty string in the file. I came up with something like the following:
<?php setcookie('foo', $_GET['foo']); header('Content-Type: image/gif'); echo base64_decode('R0lGODlhAQABAIABAP///wAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='); ?>
Remembering this got me to wondering, how small could you make a GIF? The file generated by the GIMP was only 43 bytes, but it seemed to be that you should be able to make a file which is representing a single pixel a bit smaller than that.
So, with equal parts of determination and derangement, I set about finding out.
Though of somewhat dubious usefulness, I managed to generate a perfectly valid GIF of only 26 bytes in length, which has the potential to display completely differently in various different software.
Read on to see how I found my way to this point.
Starting point: the GIF89a specification
The file generated by the GIMP, as I said, was 43 bytes long. You can find it here: tinytrans.gif
To understand what was taking up all those bytes, I read through the GIF89a Spec. The file tinytrans.gif above consists of the following sections:
Header, 6 bytes: Consists of the bytes “GIF” and the version number, which is usually “89a”.
Logical Screen Descriptor, 7 bytes: Without going into too much detail, this section of the file indicates the following:
- The file is 1×1 pixels in size
- There is a global color table
- There are 2 colors in the global color table, the second one should be used as the background color
Global Color Table, 6 bytes: Consists of 3 bytes per color, a byte for red, green, and blue, respectively. In our file, the first color is white an the second color is black.
Graphic Control Extension, 8 bytes: Used to indicate that the second color in the color table should be treated as transparent (can also be used for animation parameters, but isn’t in this file)
Image Descriptor, 10 bytes: A GIF file can actually contain multiple “images” within it, which keeps you from having to specify image data for parts of the image which have the same color as the background color. Each image block has a position and size within the overall image size. In the above file, the position is 0,0 and the size is 1×1.
Image Data, 5 bytes: One LZW-encoded block of image data. It takes 5 bytes to represent the single pixel the image has in it. The compression algorithm wasn’t designed to compress a single byte very well.
GIF Trailer, 1 byte: A single byte with a hex value of 3B (“;” in ASCII) indicates the end of the GIF.
Making a smaller GIF
Based on the required structures for a transparent GIF, it turns out that 43 bytes is pretty close to as small as you can get.
But, I managed to figure out one trick to make it a bit smaller. It’s mentioned in the standard that it is optional to have a global color table. Of course, it’s undefined as to what happens when you make a GIF without a color table at all (there are also optional local color tables per image block).
When you have a color table index defined as transparent, however, GIF decoders don’t seem to care that there isn’t actually a color table.
So I changed the logical screen descriptor to indicate there was no global color table and removed the table itself, saving a total of six bytes, bringing the file size down to a mere 37 bytes.
Here it is in all its glory: handtinytrans.gif
Interestingly enough, Wordpress gave me a lovely list of error messages of GD complaining that this isn’t a valid GIF file, despite the fact that Firefox and the GIMP both open and display (is it “displayed” when it’s transparent?) the file just fine.
So there you go, the tiniest transparent GIF possible (if you can make one smaller, let me know).
But of course, there’s room still for the tiniest GIF ever.
Even smaller, no longer transparent
To make it even smaller, I looked to the biggest remaining “optional” block in the image, the graphic control extension. If you don’t need transparency, this block is no longer needed, and that’s another 8 bytes you can take away.
Sadly, I wanted a whilte image, and I couldn’t get it to come out white without adding the global color table back in, so I only managed to trim 2 bytes off of the file.
Still, 35 bytes is indeed smaller: handtinywhite.gif
The tiniest possible GIF
If I remove the constraint of having the image be white (or any color I choose), I can make it even smaller, though admittedly this becomes much less useful.
I removed both the global image table and the graphic control extension, and then no matter what color the pixel originally was, it comes out black. From there, I took it a step further, because the standard never says you have to actually set any pixels in the image, I removed the LZW encoded image data. I left the required lzw code-size header and block terminator, because without those Firefox and the GIMP both complained it wasn’t a valid GIF, and then I had it.
The tiniest GIF ever, 26 bytes: handtinyblack.gif
Despite the fact that this is called “handtinyblack.gif”, black is just the color that the GIMP chooses to display when there’s no global color table. It’s stated in the spec “If no color table is available at all, the decoder is free to use a system color table or a table of its own.”
This means that any GIF decoder is free to pick whatever color it wants for this image. Opening this image in Firefox at various different times, it has show up as shades of blue, green and brown, as well as transparent if set as a background image.

March 16th, 2009 at 5:43 am
[...] Bonser a scris un articol interesant despre cum se poate genera un GIF valid de maxim 26 [...]
March 16th, 2009 at 5:53 am
I enjoyed reading your article. Nice hack.
March 16th, 2009 at 2:52 pm
Interesting
March 16th, 2009 at 7:25 pm
Ooo, if browser gives different color each time, it means uninitialized memory, which means stealing potentially sensitive data 768 bytes at a time! (with canvas).
March 16th, 2009 at 7:45 pm
@kL, well, if they’re following the standard, it’s actually pulling the palette from other images that have been loaded in the browser. That’s a suggestion that the standard has in it, though, so who knows where it’s coming from.
Here’s an image I converted to GIF and then removed the color table from:
It seems to just show up black for me.
Ten points to the first person to find the picture hidden within
April 26th, 2009 at 12:28 am
pretty cool read… here is your image :
April 26th, 2009 at 12:29 am
how about just a link: http://xmiles.info/yeah.png
September 24th, 2009 at 8:17 pm
Amazingly, if you use your code and vary bytes 7,8,9,10, you can create a 26 byte image of any size (theoretically up to 65,535 pixels by 65,535 pixels). See http://seconds.com/tiny.gif
September 24th, 2009 at 9:00 pm
Gerry: Oh, I hadn’t even thought about that. Yeah, I didn’t put any image data, so you can define whatever size you want…I’m not sure I can think of much use of such a huge one-color image, but it’s good to know I can do it in just 26 bytes if I want.
September 24th, 2009 at 11:49 pm
I put up another test at seconds.com/pixel.php?x=16&y=255 How would I add color/transparency? Code is: $x=1;$y=1; if($_GET['x']) $x=$_GET['x']; if($_GET['y']) $y=$_GET['y']; Header( “Content-type: image/gif”); printf(“%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c”,71,73,70,56,57,97,$x,0,$y,0,0,255,0,44,0,0,0,0,1,0,1,0,0,2,0,59); //Didn’t use extra byte for x/y ?> How hard would it be to create textured background images of any size/color and stay within 1kB packet size? Seems crazy to have to use all the %c%c%c’s
December 1st, 2009 at 5:47 am
i am wandering what this smallest or tiniest GIF ever looks like… well i guess this is one of the innovations on GIF technology… this is really interesting and must be featured on http://www.wegif.com/ Gif Photo Animation
December 20th, 2009 at 3:57 pm
Pretty interesting, never thought that…hey! what happened to that “Cancer Cure” you were working on??? >->O