Each block is a block header, the compressed data, 0 to 3 zero bytes of block padding to a multiple of 4, and the check named in the stream flags. Blocks are independent, so they can be compressed and decompressed in parallel. Variable-length integers are described on the stream page.
Block header
| Field | Size | Description |
|---|---|---|
| Block header size | 1 | 01 to FF; the header is (value + 1) × 4 bytes, 8 to 1,024. A 00 here is the index indicator instead. |
| Block flags | 1 | Bits 0 and 1: number of filters − 1 (1 to 4 filters). Bits 2 to 5: reserved, 0. Bit 6 (40): compressed size present. Bit 7 (80): uncompressed size present. |
| Compressed size | varint | Only with bit 6: size of the compressed data, without padding or check. Not 0. |
| Uncompressed size | varint | Only with bit 7. |
| Filter flags | repeated | For each filter, in order of encoding: filter ID (varint), size of properties (varint), properties. |
| Header padding | … | Zero bytes up to the header size less 4. |
| CRC32 | 4 | CRC-32 of the header up to here. |
A typical header from xz is 02 00 21 01 16 00 00 00 and a
CRC: size byte 2 (12 bytes), flags 0 (one filter, no sizes), filter
21 (LZMA2) with 1 byte of properties, 16 (an 8 MiB
dictionary), then padding.
Filter IDs
| ID | Filter | Properties | Where |
|---|---|---|---|
21 | LZMA2 | 1 byte: dictionary size | Last only |
03 | Delta | 1 byte: distance − 1 (1 to 256) | Not last |
04 | x86 (BCJ) | 0 or 4 bytes: start offset | Not last |
05 | PowerPC, big-endian | 0 or 4 bytes | Not last |
06 | IA-64 (Itanium) | 0 or 4 bytes | Not last |
07 | ARM, little-endian instructions | 0 or 4 bytes | Not last |
08 | ARM Thumb | 0 or 4 bytes | Not last |
09 | SPARC | 0 or 4 bytes | Not last |
0A | ARM64 | 0 or 4 bytes | Not last |
0B | RISC-V | 0 or 4 bytes | Not last |
Plain LZMA (the .lzma method) is not allowed; only LZMA2. The branch filters convert relative jump and call addresses in machine code to absolute ones so that they compress better; the optional 4-byte start offset (little-endian) must be a multiple of the filter’s alignment: x86 1, PowerPC 4, IA-64 16, ARM 4, ARM Thumb 2, SPARC 4, ARM64 4 (4,096 works best), RISC-V 2. Delta subtracts the byte distance bytes earlier, for samples and tables.
Filter chain rules
- At most four filters, so at most three that are not last.
- At most two of the non-last filters may change the size of the data, and they must not expand it much (about 2n bytes in must give at least n out).
- The last filter’s output is aligned to 4 bytes from the start of the stream.
Custom filter IDs
A developer can ask the maintainer for an ID range, or make one: bits 0 to 15 the
filter, bits 16 to 55 a random 40-bit developer ID, bits 56 to 62 the prefix
3F, which always encodes in 9 bytes. IDs of 262 and above are
for internal use and never appear in files. The ranges 300 to
4FF, 20000 to 7FFFF and 2000000 to
7FFFFFF are reserved because 7z uses those method IDs.
LZMA2 properties
One byte. Bits 0 to 5 encode the dictionary size; bits 6 and 7 are reserved, 0.
For values 0 to 39 the size is (2 | (b & 1)) << (b / 2 + 11):
0 is 4 KiB, 1 is 6 KiB, 2 is 8 KiB, and so on up to 39, 3 GiB. 40 means
4 GiB − 1. Above 40 is an error. For example, 16 (22) is 8 MiB.
LZMA2 chunks
The xz specification gives
only the filter ID and the property byte above; the chunks below follow the LZMA
SDK’s decoder, C/Lzma2Dec.c,
whose header comment lays them out. Both were read 2026-11-12. LZMA2 data is a
series of chunks, each starting with a control byte.
| Control | Chunk |
|---|---|
00 | End of the LZMA2 data. |
01 | Uncompressed chunk, and reset the dictionary; the next LZMA chunk must then reset the state and set new properties. Then 2 bytes, big-endian: size − 1 (up to 64 KiB). Then the bytes. |
02 | Uncompressed chunk, no reset. |
03 to 7F | Invalid. |
80 to FF | LZMA chunk. Bits 0 to 4 are bits 16 to 20 of (uncompressed size − 1); then 2 bytes big-endian complete it (up to 2 MiB). Then 2 bytes big-endian: compressed size − 1 (up to 64 KiB). Then, for resets 2 and 3, a properties byte (pb × 5 + lp) × 9 + lc with lc + lp ≤ 4. Then the LZMA data. |
Bits 5 and 6 of an LZMA chunk’s control byte say what to reset first:
| Value | Reset |
|---|---|
0 (80) | Nothing: continue the previous chunk’s state. |
1 (A0) | The LZMA state. |
2 (C0) | The state, with new properties. |
3 (E0) | The state, new properties and the dictionary. The first chunk must reset the dictionary. |
Every chunk header gives its packed size, so chunks can be stepped over without decoding them.