An .xz file is one or more streams, each followed by optional stream padding. A stream is a 12-byte header, any number of blocks, an index and a 12-byte footer. This page follows The .xz File Format version 1.2.1 (2024-04-08). Fixed-size numbers are little-endian.
Variable-length integers
Sizes and counts are stored 7 bits per byte, lowest bits first; every byte but the
last has bit 7 (80) set. Values are limited to 63 bits, so at most 9
bytes. 0 to 127 take one byte. A final byte of 00 after a continuation
byte (a longer form than needed) is rejected. Example: 300 is AC 02.
Stream header
| Offset | Size | Name | Description |
|---|---|---|---|
0 | 6 | Header magic | FD 37 7A 58 5A 00 (FD, 7zXZ, 00). |
6 | 2 | Stream flags | First byte 00. Second byte: bits 0 to 3 the check type; bits 4 to 7 reserved, must be 0. |
8 | 4 | CRC32 | CRC-32 of the stream flags. |
Check types
Each block ends with a check of its uncompressed data, of the type the stream flags name. Decoders must support none and CRC32; the others are optional, and an unsupported one gives a warning or an error.
| ID | Size | Check |
|---|---|---|
0 | 0 | None |
1 | 4 | CRC32 |
2, 3 | 4 | Reserved |
4 | 8 | CRC64 |
5, 6 | 8 | Reserved |
7 to 9 | 16 | Reserved |
A | 32 | SHA-256 |
B, C | 32 | Reserved |
D to F | 64 | Reserved |
The sizes of the reserved types are fixed so that a decoder can skip a check it
does not know. CRC32 is the usual ZIP CRC (polynomial EDB88320); CRC64 is
the ECMA-182 polynomial in reflected form (C96C5795D7870F42), starting at
all ones and inverted at the end. xz uses CRC64 by default.
Index
After the last block. It lists every block, so a reader can find any block without decompressing the others.
| Field | Size | Description |
|---|---|---|
| Index indicator | 1 | 00. It sits where the next block header’s size byte would be, and a block header size is never 0, so the reader knows the blocks have ended. |
| Number of records | varint | Number of blocks. |
| Unpadded size | varint | Per block: block header, compressed data and check, without the block padding. At least 5. |
| Uncompressed size | varint | Per block. |
| Index padding | 0 to 3 | Zero bytes up to a multiple of 4. |
| CRC32 | 4 | CRC-32 of the index up to here. |
The index is at most 16 GiB. A block’s position is the sum of the earlier blocks’ unpadded sizes, each rounded up to a multiple of 4, after the 12-byte header.
Stream padding and limits
Streams can be joined one after another, as when two .xz files are concatenated. Between and after them may be stream padding: zero bytes, a multiple of 4 in number. Every part of the format is a multiple of 4 bytes, so a valid .xz file’s size always is too. A stream, and its uncompressed data, must be smaller than 8 EiB.
The specification lists what is an error (stop) and what may be a warning: bad magic, set reserved bits, any CRC mismatch, flags that differ between header and footer, a wrong backward size, non-zero padding, wrong sizes in a block header or the index, and a wrong check are all errors.
Example
The header and footer of a stream with CRC64 checks and an 8-byte index:
FD 37 7A 58 5A 00 header magic
00 04 stream flags: check 4, CRC64
E6 D6 B4 46 CRC32 of 00 04
… blocks, then the index
xx xx xx xx CRC32 of the next 6 bytes
01 00 00 00 backward size: (1 + 1) × 4 = 8
00 04 stream flags again
59 5A "YZ"