GZIP file format
Gzip-compressed data, typically wrapping a single file or a tarball.
- MIME type
- application/gzip
- Extensions
- .gz
- Category
- Archives & compression
Magic-number signature
| 0x00000000 | 1F8B | ·· | gzip magic |
About the GZIP format
Gzip compresses a single stream with DEFLATE and is the backbone of HTTP compression and the ubiquitous .tar.gz. Files start with the two magic bytes 1F 8B. The format is deliberately tiny — a ten-byte fixed header, a few optional fields, the deflate stream, and an eight-byte trailer — and deliberately streamable: nothing in it needs to be known before compression starts, and nothing at the end needs seeking back to fix up. That is also its limit. There is no directory, no per-file structure and no way to reach the middle of the data without decompressing everything before it.
Header layout, byte by byte
| Offset | Length | Field | Meaning |
|---|---|---|---|
| 0 | 2 | Magic ID1 ID2 | 1F 8B. Neither byte is printable ASCII, which was intentional: a gzip stream must not look like text to a mail gateway or a terminal that might try to be helpful with it. |
| 2 | 1 | Compression method (CM) | 8, meaning deflate. Values 0 through 7 are reserved and none has ever been assigned, so in practice any byte other than 08 here means the file is not gzip or the header is damaged. |
| 3 | 1 | Flags (FLG) | Bit 0 FTEXT (the content is probably text), bit 1 FHCRC (a two-byte header CRC follows), bit 2 FEXTRA, bit 3 FNAME (a NUL-terminated original file name follows), bit 4 FCOMMENT. A file compressed by the command-line tool normally reads 08, because it stores the name. |
| 4 | 4 | Modification time (MTIME) | Little-endian Unix seconds of the original file, or 0 when unavailable. It is why gzipping the same input twice produces different bytes, and why reproducible builds pass a flag to zero it. |
| 8 | 1 | Extra flags (XFL) | With deflate, 2 means the slowest and best compression was used and 4 means the fastest; 0 otherwise. It is advisory only — no decompressor does anything with it. |
| 9 | 1 | Operating system (OS) | The filesystem the original came from: 0 FAT, 3 Unix, 11 NTFS, 255 unknown. It leaks where a file was built, which is another field reproducible builds normalise. |
| 10 | variable | Optional fields, then the deflate stream | Whichever flag bits were set, in a fixed order: extra field (a two-byte length then that many bytes), original file name, comment, header CRC-16. A file storing the name 'payload.bin' spends offsets 10 to 21 on it, and deflate begins at 22. |
| -8 | 4 | CRC-32 of the uncompressed data | Little-endian, computed over the original bytes rather than the compressed ones. This is what `gzip -t` checks and what a truncated file can never satisfy. |
| -4 | 4 | ISIZE | Little-endian original size modulo 2^32. A 200000-byte input ends 40 0D 03 00. Being 32-bit, it silently wraps above four gigabytes, which is why `gzip -l` reports nonsense for very large files and why it must never be trusted as an allocation size. |
Telling it apart from its neighbours
| Easily confused with | How to tell |
|---|---|
| zlib | The pair that actually catches people out, because both wrap the same deflate stream. A zlib stream has a two-byte header instead of ten — in practice 78 01, 78 9C or 78 DA — and ends with an Adler-32 rather than a CRC-32. There is no magic number, no name and no length, so a zlib blob renamed .gz opens nowhere and a gzip fed to a zlib decoder fails immediately. |
| raw deflate | Raw deflate as defined by RFC 1951 has no header and no trailer at all — it starts straight into the first block's three bits. It is what a ZIP entry stores and what HTTP's `Content-Encoding: deflate` ambiguously meant, and it is the reason so many HTTP clients try zlib first and fall back to raw. |
| TAR | A .tar.gz and a gzip of one ordinary file are the same format; only the content differs. Decompress and look at offset 257 of the result — a tar has 'ustar' there, inside the first 512-byte member header. Cheaper still, the FNAME field at offset 10 usually admits it by ending in .tar. |
| ZIP | 1F 8B against 50 4B 03 04, and structurally further apart than the shared word 'compressed' suggests: a ZIP has a central directory at the end and can list and extract one entry without touching the rest, whereas a gzip stream must be read from the beginning to reach anything. |
| BZIP2 | 'BZh' plus a digit against 1F 8B. Both are single-stream Unix compressors used the same way and named almost interchangeably in build scripts, so the extension is often wrong; the first two bytes never are. |
How these files break
- Truncated download. The eight-byte trailer is gone, so the decompressor emits everything it can decode and then reports an unexpected end of file. The recovered bytes are normally sound — the failure is that nothing can confirm it, because both the length and the checksum lived in the missing tail.
- A flipped bit inside the deflate stream. The output length is right and the CRC-32 at offset -8 does not match, which is precisely the case `gzip -t` exists to name. Depending on where the bit landed, decompression may also fail outright with an invalid distance or code-length error rather than reaching the checksum at all.
- Text-mode transfer. Line-ending translation rewrites 0D 0A to 0A inside compressed data, and the ten-byte header survives untouched, so the file still identifies as gzip and still reports its original name before failing partway through the stream.
- Multi-member archives read as one. Concatenating gzip files is legal and a conforming decompressor emits all of them joined, but a hand-rolled parser that reads the first ISIZE and stops silently drops everything after the first member. Parallel compressors produce exactly this shape.
- ISIZE trusted as a size. Above four gigabytes it wraps, so a program that allocates a buffer from it under-allocates by a whole multiple of 4 GiB. It is a header field describing the data, not a promise, and it is not covered by any checksum.
Where the format stands today
Gzip is the most-executed compression format in the world and shows no sign of moving. Every HTTP stack still negotiates it, .tar.gz is the default source-release shape on Unix, log rotation writes it, and every language ships a decoder in its standard library — so it remains the safe answer whenever the reader is unknown. On ratio it lost long ago: bzip2, xz and Zstandard all beat it, and on the web Brotli beats it for static text while Zstandard beats it on speed at similar ratios. What keeps gzip first choice is universality plus streaming: it needs no seeking, no temporary file and no knowledge of the input length, so it works in a pipe, in a socket and in a firmware image. It is the wrong choice whenever you need to reach one file inside a collection, because there is no index — that is what ZIP is for.
Open GZIP 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 GZIP — compare their leading bytes.