GIF file format
Graphics Interchange Format — indexed-color raster images and simple animation.
- MIME type
- image/gif
- Extensions
- .gif
- Category
- Images
Magic-number signature
| 0x00000000 | 474946383961 | GIF89a | 'GIF89a' (or 'GIF87a') |
About the GIF format
GIF is limited to a 256-color palette per frame but supports looping animation and one bit of transparency, which is why it survived into the meme era. The header is the ASCII string GIF87a or GIF89a naming the spec version, followed immediately by a seven-byte logical screen descriptor that gives the canvas size and describes the global colour table. After that the file is a stream of blocks, each introduced by a single byte: 2C starts an image, 21 starts an extension, and 3B ends the file. Pixels are compressed with LZW over the palette indices, one variable-width code stream per image, which is why a GIF of a photograph is usually larger than the JPEG it came from.
Header layout, byte by byte
| Offset | Length | Field | Meaning |
|---|---|---|---|
| 0 | 3 | Signature | 47 49 46, the ASCII letters GIF. Fixed for both versions of the format, and the only three bytes a detector can rely on without also deciding which spec revision it will accept. |
| 3 | 3 | Version | Either 38 37 61 for 87a or 38 39 61 for 89a. This is a claim about which block types may appear later in the file, not about the image data, and encoders are supposed to write the lowest version that covers what they actually used. |
| 6 | 2 | Logical screen width | Little-endian 16-bit canvas width in pixels. Note the byte order: GIF predates PNG and stores its numbers the other way round, so 40 00 is 64 and not 16384. The canvas is not necessarily the size of any single frame. |
| 8 | 2 | Logical screen height | Little-endian 16-bit canvas height. Individual frames carry their own position and size later in the file and may be much smaller than this — that is exactly how animated GIFs avoid re-sending the parts of the picture that did not change. |
| 10 | 1 | Packed screen descriptor fields | Bit 7 says a global colour table follows. Bits 6 to 4 are the colour resolution of the source. Bit 3 is the sort flag. Bits 2 to 0 hold N, and the table then contains two to the power N plus one entries — so the common value 6 means 128 colours, and 7 means the full 256. |
| 11 | 1 | Background colour index | An index into the global colour table, used for the area of the canvas no frame has painted. Almost every decoder ignores it and treats uncovered canvas as transparent instead, so a GIF that looks right in one viewer and has a coloured border in another is arguing about this byte. |
| 12 | 1 | Pixel aspect ratio | 0 means no information, which is what essentially every file says. Any other value V means the pixel aspect ratio is V plus 15, divided by 64 — a leftover from displays with non-square pixels. |
| 13 | variable | Global colour table | Present only when bit 7 of the packed byte is set, and then exactly three times two to the power N plus one bytes of RGB triples: 384 bytes for a 128-entry table. Get N wrong and every byte offset in the rest of the file shifts, which is the single most effective way to destroy a GIF with a one-byte edit. |
| -1 | 1 | Trailer | A single 3B byte, the ASCII semicolon, ends the file. Anything after it is ignored, and its absence is the fastest check for a truncated download. |
Telling it apart from its neighbours
| Easily confused with | How to tell |
|---|---|
| GIF87a/GIF89a | Three bytes at offset 3 and nothing else in the header. 89a added the graphic control extension — the block 21 F9 that carries frame delay, disposal method and the transparent colour index — plus application extensions. So a file that animates, or has any transparency at all, must claim 89a; a still opaque image may honestly claim 87a, and encoders like macOS sips still write it. |
| Netscape looping extension | Nothing in the GIF spec makes an animation loop. The behaviour comes from an application extension block reading 21 FF 0B then the eleven ASCII bytes NETSCAPE2.0, followed by a sub-block whose second and third bytes are the little-endian loop count, zero meaning forever. Search for 4E 45 54 53 43 41 50 45 in the first few hundred bytes: if it is missing, the animation plays exactly once no matter what the editor showed. |
| PNG | 89 50 4E 47 against 47 49 46. They overlap on lossless indexed images with transparency, and for that job PNG wins outright: full alpha instead of one transparent index, up to 16 bits per channel instead of a 256-colour palette, and better compression. GIF's only remaining advantage is that it animates without a video element. |
| WebP | An animated WebP does the same job in a fraction of the bytes and is a RIFF file: 52 49 46 46 at offset 0, 57 45 42 50 at offset 8, and a VP8X chunk at offset 12 with the animation flag set. Most chat and social platforms now transcode uploaded GIFs to WebP or MP4 and keep serving them under the same .gif URL. |
How these files break
- Truncation. The header and the palette are intact, so a viewer knows the canvas size and paints as many frames as arrived before stopping. The missing 3B trailer at the end of the file is the confirmation, and a partially received final frame will show as a band of solid colour where the LZW stream ran out.
- A wrong global colour table size. The low three bits of the byte at offset 10 decide how many bytes of palette follow, so a single bad nibble shifts the start of the first block by hundreds of bytes and the file becomes unreadable even though every other byte in it is fine.
- LZW stream desynchronisation. Codes are variable-width and packed across byte boundaries with no alignment, so one flipped bit turns the rest of that frame into diagonal noise. Because each frame has its own stream, the damage stops at the next image block rather than propagating to the end of the animation.
- A lost Netscape application extension. Re-encoding through a tool that does not preserve unknown extension blocks silently drops the loop count, and an animation that ran forever now plays once and freezes. Nothing about the file is invalid, so no tool reports a problem.
- Disposal method rewritten. The three-bit disposal field in each graphic control extension decides whether a frame is cleared before the next one is drawn. A converter that writes the wrong value produces the smearing trail where every frame accumulates on top of the last — a valid file that simply animates wrong.
Where the format stands today
GIF should have been retired a decade ago and is not going anywhere, for one reason: it is the only animated image format that plays inline in every renderer, mail client, chat window and wiki without a video element, a codec licence or a play button. For the short looping clip it stays the lowest-friction option even though animated WebP and a muted MP4 are several times smaller at better quality — which is why most large platforms now accept a .gif upload, transcode it to WebP or H.264 behind the scenes, and keep the extension in the URL. As a still-image format it has no case left at all: 256 colours per frame and a single fully transparent palette index lose to PNG on every axis, and the LZW patent that once made people avoid it expired in 2004. Where it still genuinely earns its place is tiny UI animations, spinners and, unglamorously, the one-pixel tracking image in marketing email, where the file is smaller than the HTTP headers around it.
Open GIF files on this site
Every one of these runs in your browser — the file never leaves your machine.
Related formats
Formats that are easy to confuse with GIF — compare their leading bytes.