BZIP2 file format
Bzip2-compressed data, using the Burrows-Wheeler block-sorting algorithm.
- MIME type
- application/x-bzip2
- Extensions
- .bz2
- Category
- Archives & compression
Magic-number signature
| 0x00000000 | 425A68 | BZh | 'BZh' header |
About the BZIP2 format
Bzip2 compresses better than gzip but slower, using a Burrows-Wheeler transform; common for source tarballs on Unix. The header is 'BZh' followed by a block-size digit. After those four bytes the file stops being byte-oriented altogether: blocks, Huffman tables and coded symbols are packed bit by bit with no alignment, which is why only the very first block starts on a byte boundary and why a hex editor can show you the start of a bzip2 file but not the middle of one. The compensation is that each block is independent, so damage is contained and recovery is genuinely possible.
Header layout, byte by byte
| Offset | Length | Field | Meaning |
|---|---|---|---|
| 0 | 2 | 'BZ' magic | 42 5A. Two printable letters, which is unusual for a binary format and is why 'BZh' shows up as readable text in a hex dump. |
| 2 | 1 | Version byte | 'h' (0x68), for Huffman coding. It is the only version the tool has produced since 0.9.0, and the decoder accepts nothing else — so the recognisable three-byte prefix is really magic plus version, not magic alone. |
| 3 | 1 | Block-size digit | An ASCII digit '1' to '9', giving the block size in units of 100 kB — '9' is 0x39 and means 900 kB, which is the default. It sets memory use for compression and, more importantly, for decompression, so it is chosen once by the writer and every reader must honour it. |
| 4 | 6 | First block magic | 31 41 59 26 53 59, the digits of pi as packed decimal. It is byte-aligned only here, at the start of the first block; every later block's copy sits at whatever bit position the previous block happened to end on. |
| 10 | 4 | Block CRC-32 | The checksum of this block's uncompressed contents, again byte-aligned only for the first block. Per-block checksums are what make partial recovery meaningful: a reader can tell exactly which block went bad. |
| 14 | variable | Randomised flag and BWT origin pointer | One deprecated flag bit (always 0 in anything written this century) followed by a 24-bit pointer to the row of the Burrows-Wheeler matrix that reconstructs the original order. From here nothing is byte-aligned: the symbol map, Huffman tables, selectors and coded data are a continuous bit stream. |
| variable | 6 | End-of-stream magic | 17 72 45 38 50 90, the digits of the square root of pi, marking that no further blocks follow. It lands near the end of the file but at a bit offset determined by everything before it, so it is not at a fixed distance from the end. |
| variable | 4 | Combined CRC-32 | A running combination of every block's CRC, immediately after the end-of-stream magic and followed by zero to seven padding bits so the file finishes on a byte boundary. It is the only whole-file integrity value bzip2 has. |
Telling it apart from its neighbours
| Easily confused with | How to tell |
|---|---|
| GZIP | 'BZh' plus a digit against 1F 8B. They are used identically in scripts and their extensions get swapped constantly, but nothing else is shared: gzip is a byte-aligned header over a deflate stream, bzip2 is a four-byte header over a bit stream with its own per-block checksums. |
| 7-Zip | A false positive waiting to happen in the other direction. 7-Zip's own magic starts 37 7A, which reads as '7z', and 7z archives can use bzip2 as an internal method — so a 'BZh' string turns up inside a .7z file. Only offset 0 decides, and a .7z has 37 7A BC AF 27 1C there. |
| ZIP | ZIP compression method 12 is bzip2, so a ZIP entry's data can begin 'BZh' immediately after its local file header and variable-length fields. Searching a file for 'BZh' and concluding you have a .bz2 is wrong whenever offset 0 reads 50 4B 03 04. |
| XZ | The format that replaced it for most source releases. XZ opens FD 37 7A 58 5A 00 and reaches a better ratio; bzip2's remaining advantage is that its blocks are independent, which xz's are not by default. |
| pbzip2/lbzip2 | Parallel compressors emit a concatenation of complete, independent bzip2 streams, so 'BZh' appears repeatedly through the file at byte-aligned positions and the pi block magic appears once per stream. The result is still a legal .bz2 that the ordinary decompressor reads end to end. |
How these files break
- Truncation. Every complete block before the cut is still decodable, because blocks do not depend on one another. That is exactly what bzip2recover exploits: it splits the bit stream at each pi block magic and writes every block out as its own small .bz2, so a damaged archive gives back all but one block's worth of data.
- A flipped bit inside a block. Because the block is Huffman-coded, the damage usually derails decoding long before the end — a data error, not a checksum mismatch. When decoding does reach the end, the per-block CRC at offset 10 catches it and names which block failed.
- Text-mode transfer. Line-ending translation inside the bit stream shifts everything after the damaged byte by eight bits, so decoding fails almost immediately even though the four-byte header is intact and the file still identifies correctly.
- A hand-edited block-size digit. Changing '9' to '1' leaves a file that still looks like bzip2 to every detector and fails at the first block, because the decompressor sizes its buffers from that one byte.
- Concatenated streams truncated mid-way. Parallel-compressed archives are several streams in one file; losing the tail loses only the last stream, and the earlier ones decompress cleanly — which is why a partially downloaded pbzip2 file often yields most of its content.
Where the format stands today
Bzip2's moment was roughly 1999 to 2010, when it was the obvious step up from gzip for source tarballs, and a great deal of the internet's archived software is still .tar.bz2 — which alone guarantees decoders will ship forever. For new work it is squeezed from both sides: xz compresses noticeably smaller at similar or better decompression speed, and Zstandard compresses far faster at gzip-class ratios, so distributions moved away years ago. It also has no upstream momentum; the original implementation was effectively unmaintained for a decade. What still argues for it is the block structure. Blocks are independent, which means compression parallelises trivially with pbzip2 and, uniquely among the common Unix compressors, a damaged archive can be salvaged block by block instead of being written off at the first bad byte.
Open BZIP2 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 BZIP2 — compare their leading bytes.