The GIF file header
Every GIF file starts with six bytes: three signature letters and three version characters. It is the simplest block in the format and the only one without an identifying byte.
Structure
| Bytes | Length | Contents |
|---|---|---|
| 0-2 | 3 | signature: 47 49 46 = "GIF" |
| 3-5 | 3 | version: 38 37 61 = "87a" or 38 39 61 = "89a" |
In the example file (see the introduction):
47 49 46 38 39 61 → "GIF89a"
87a or 89a
GIF89a added extension blocks (byte 21) and two new meanings for existing fields. A file with no extensions is practically identical in both versions.
| Feature | 87a | 89a |
|---|---|---|
| images, palettes, LZW, interlacing | yes | yes |
| transparency, delay, frame disposal | no | yes ($F9) |
| comments | no | yes ($FE) |
| plain text | no | yes ($01) |
| application data, animation loop | no | yes ($FF) |
| palette sort flag, pixel aspect | reserved fields | yes |
The specification recommends writing "87a" if the file uses nothing from 89a, and "89a" otherwise. In practice nearly all software always writes "89a", and every modern decoder reads both versions the same way.
Detecting the format
A file's first bytes (its magic numbers) identify the format without looking at the file name extension:
| Format | First bytes |
|---|---|
| GIF | 47 49 46 38 ("GIF8") |
| PNG | 89 50 4E 47 0D 0A 1A 0A |
| JPEG | FF D8 FF |
| WebP | 52 49 46 46 ("RIFF"), then "WEBP" from byte 8 |
const isGif = (b) => b[0] === 0x47 && b[1] === 0x49 && b[2] === 0x46 && b[3] === 0x38;
The logical screen descriptor begins right after the header.