File types · Explainer

The XZ file (.xz, .txz)

An XZ file is a single file compressed with LZMA2, the format behind most .tar.xz software downloads on Linux. This guide explains what's inside one, how it compares with gzip, bzip2, Zstandard and ZIP in our own tests, what the 2024 XZ Utils backdoor was, and has free sample XZ files to download for testing.

At a glance

Full name
XZ compressed file (from XZ Utils)
Extensions
.xz; for tar archives .tar.xz or .txz
MIME type
application/x-xz (in wide use, not registered with IANA)
Kind
Binary, lossless compression of one file (not an archive)
Standard
The .xz File Format specification from the Tukaani Project (1.0.0 in 2009; 1.2.1 in 2024)
First released
2009, by Lasse Collin, as the successor to LZMA Utils
Compression
LZMA2 (LZ77-style matching with a large dictionary, then range coding); optional filters for executables
Integrity check
CRC64 by default; CRC32, SHA-256 or none on request
Opens with
xz and unxz on Linux, tar -xf for .tar.xz on macOS, 7-Zip on Windows; .tar.xz in recent Windows 11 File Explorer
Magic number
FD 37 7A 58 5A 00 (ý7zXZ + zero byte); ends with 59 5A (YZ)

The basics

What is an XZ file?

An XZ file is one file compressed with the xz program from XZ Utils. Like gzip and bzip2, xz compresses a single file and doesn't do folders. A folder is first bundled with tar, giving a .tar.xz or .txz file, which is the most common way you'll meet the format.

xz uses LZMA2, a refined version of the LZMA method from 7-Zip, wrapped in a container that adds checksums, an index and room for extra filters. It compresses noticeably better than gzip and decompresses far faster than bzip2, at the cost of slow compression. That suits software distribution: compressed once, downloaded and unpacked many times. The GNU project, many Linux distributions' source and package archives, and the Linux kernel's own downloads have used .tar.xz.

Older relatives you might meet: .lzma files are raw LZMA from the earlier LZMA Utils, without the checks or index, and 7z archives use the same LZMA and LZMA2 compression inside a different, multi-file archive format.

Anatomy

What's inside an XZ file

An XZ file is a stream: a header, one or more blocks of compressed data, an index listing the blocks, and a footer. Almost every part has its own CRC32, and every part is padded to a multiple of 4 bytes. Here is all of sample-text.txt.xz, 1,184 bytes; variable-length numbers use 7 bits per byte.

sample-text.txt.xz (hex)
offset  bytes                          part
0       FD 37 7A 58 5A 00              stream header magic
6       00 04                          stream flags: check = CRC64
8       E6 D6 B4 46                    CRC32 of the flags
12      02                             block header size: (2+1) × 4 = 12
13      00                             block flags: 1 filter, no sizes
14      21 01 16                       filter LZMA2, 1 property byte: 8 MiB
17      00 00 00                       header padding
20      74 2F E5 A3                    CRC32 of the block header
24      E0 0A AC 04 5D 5D 00 1C …      LZMA2 data, 1,125 bytes
1149    00 00 00                       block padding to a multiple of 4
1152    97 AA 75 FE 48 E1 E8 CC        CRC64 of the original data
1160    00 01                          index: indicator, 1 record
1162    F9 08 · AD 15                  block size 1,145; original 2,733
1166    00 00 · 8E 77 54 64            padding; CRC32 of the index
1172    B1 C4 67 FB                    stream footer: CRC32
1176    02 00 00 00                    backward size: index is 12 bytes
1180    00 04 · 59 5A                  flags again; footer magic "YZ"
1184                                   end of file
  1. 1FD 37 7A 58 5A 00

    Stream header magic

    FD keeps it from being mistaken for the older .lzma format, and the zero byte at the end keeps it from looking like text.

  2. 200 04

    Stream flags

    The second byte names the integrity check: 01 CRC32, 04 CRC64 (the default), 0A SHA-256, 00 none. In sample-sha256.xz it's 0A.

  3. 302 00

    Block header

    Its size in units of 4 bytes, then flags: one filter, and no compressed or uncompressed size stored. Single-threaded xz leaves the sizes out; multi-threaded xz writes them so blocks can be decompressed in parallel.

  4. 421 01 16

    The filter chain

    Filter 0x21 is LZMA2, with one property byte: 0x16 means an 8 MiB dictionary, the size preset -6 uses. A chain can hold up to four filters, for example a BCJ filter for x86 code before LZMA2.

  5. 5E0 0A AC 04 5D

    LZMA2 chunk header

    E0 starts a compressed chunk and resets the dictionary and settings, 0A AC and 04 5D give the chunk's sizes minus one (2,733 and 1,118 bytes), and 5D packs the LZMA parameters lc=3, lp=0, pb=2.

  6. 697 AA 75 FE 48 E1 E8 CC

    The check

    A CRC64 of the original 2,733 bytes, after the block. A decoder compares it after decompressing the block.

  7. 700 01 F9 08 AD 15

    The index

    One record per block: its size in the file (1,145) and its original size (2,733). Tools read it from the end of the file to list sizes instantly, and to jump straight to a block.

  8. 802 00 00 00 · 59 5A

    Stream footer

    The index's size, so a reader starting from the end can find it, the flags again, and YZ, the header magic's letters reversed.

Under the hood

How xz compresses: LZMA2, presets and memory

LZMA2 works like gzip's Deflate in outline: find repeated byte sequences and replace them with references back to an earlier copy. Two things make it compress better:

  • A much larger window. Deflate looks back 32 KB. xz's dictionary is 8 MiB at the default level and 64 MiB at -9, so a repeat far back in a large file still counts.
  • Range coding with adaptive probabilities instead of Huffman codes. It can spend a fraction of a bit on a very predictable symbol, where Huffman needs at least one.
Presets, from the xz manual
PresetDictionaryMemory to compressMemory to decompress
-0256 KiB3 MiB1 MiB
-6 (default)8 MiB94 MiB9 MiB
-964 MiB674 MiB65 MiB

The memory needed to decompress depends on the level used to compress, which matters on small devices. Levels -7 to -9 only help with files bigger than their dictionaries (8, 16 and 32 MiB, says the manual); on our 11.7 MB test, -9 saved 44 bytes over -6. Adding -e (extreme) tries harder at the same level for a slightly smaller file.

Filters prepare data before LZMA2. The BCJ filters (x86, ARM, ARM64, RISC-V and others) turn relative jump addresses in machine code into absolute ones, which repeat more, so executables compress better. The delta filter helps with some audio and image data.

Performance

Blocks, multi-threading and random access

A single-threaded xz writes one big block. With threads (-T0 uses every core), xz splits the input into blocks and compresses them in parallel; each block then stores its sizes in its header. Since XZ Utils 5.4, such files can also be decompressed in parallel, and since 5.6 multi-threaded mode is the default.

  • Smaller blocks compress slightly worse, because each block starts with an empty dictionary. Our sample-multi-block.xz uses 64 KiB blocks to show the structure; the default block size in threaded mode is three times the dictionary, 24 MiB at -6.
  • Random access: thanks to the index, a reader can jump to the block holding a given position without decompressing earlier blocks. Most tools don't offer this, but libraries can.
  • Same input, different bytes: single-threaded and multi-threaded xz produce different files from the same input. Both decompress to the same data, but checksums of the .xz files differ, which surprises people building reproducible packages.

Trade-offs

XZ vs gzip, bzip2, Zstandard and ZIP: size and speed

Our own measurement on our own data: an 11.7 MB tar of a TypeScript web app's source code plus generated CSV, JSON, log and PNG files. One core of a 2.8 GHz Xeon cloud server, best of three runs; gzip 1.12, bzip2 1.0.8, XZ Utils 5.4.5, zstd 1.5.5, Info-ZIP zip 3.0.
Tool and levelOutput sizeCompression speedDecompression speed
gzip -6 (default)20.2%25 MB/s160 MB/s
gzip -919.4%9 MB/s180 MB/s
bzip2 -9 (default)14.7%7 MB/s22 MB/s
xz -6 (default)15.6%1.2 MB/s66 MB/s
xz -915.6%1.2 MB/s73 MB/s
zstd -3 (default)21.4%120 MB/s440 MB/s
zstd -1916.6%0.9 MB/s320 MB/s
ZIP, zip -6 (default)20.7%27 MB/s140 MB/s

Output size is a percentage of the original. ZIP compresses each file separately, so it was measured on the folder, not the tar. Your numbers will differ with other data and hardware, but the pattern is typical:

  • xz made a file about 23% smaller than gzip's default and unpacked about two and a half times slower, but it was by far the slowest to compress at the default level.
  • bzip2 came out slightly smaller than xz on this text-heavy data, but decompressed three times slower.
  • Zstandard at its default level was the fastest at everything, with gzip-like size. At -19 it got close to xz's size and decompressed five times faster than xz. That's why Arch Linux and Fedora switched their packages from xz to Zstandard.
  • gzip and ZIP sit in the middle: quick both ways, larger files, and readable everywhere.

Security

The 2024 XZ Utils backdoor (CVE-2024-3094)

On 29 March 2024, Andres Freund, a PostgreSQL developer at Microsoft, reported that XZ Utils versions 5.6.0 and 5.6.1 contained a deliberately hidden backdoor. It was rated CVSS 10.0, the maximum. He found it because SSH logins on a Debian test machine were using noticeably more CPU than before, and the memory checker Valgrind reported errors.

  • Who: a contributor using the name Jia Tan, who had spent more than two years building trust in the project, with help from other accounts pressing the original maintainer, Lasse Collin, to share control.
  • How it was hidden: the malicious code sat in two binary "test files" in the Git repository. A modified build script, build-to-host.m4, was only in the release tarballs, not in Git, so reading the source on GitHub showed nothing wrong.
  • What it did: when built as a Debian or RPM package on x86-64 Linux with glibc, liblzma was altered to interfere with the OpenSSH server. Some distributions link sshd to libsystemd, which loads liblzma. Someone holding the attacker's private key could then run commands on the server remotely.
  • Who got it: mainly development and rolling releases, such as Debian unstable, Fedora Rawhide and the Fedora 40 beta, openSUSE Tumbleweed and Kali Linux. Stable releases of the major distributions weren't affected. Distributions rolled back to 5.4.x within days, and the project released a clean 5.6.2 in May 2024.

What it means for .xz files

The backdoor was in the XZ Utils software, not in the file format. An .xz file can't carry it, and opening .xz files wasn't how it was triggered. If xz --version says 5.6.0 or 5.6.1, update through your distribution. The wider lesson is about the software supply chain: release tarballs can differ from the public source, and a single overworked maintainer is a target.

Troubleshooting

Common xz problems

  • File format not recognized: the file doesn't start with the xz magic. It may be an old .lzma file (xz --format=lzma -d or unlzma handles those), or something else with the wrong name.
  • Memory usage limit reached: a memory limit is set (with --memlimit or the XZ_DEFAULTS variable) below what the file needs. xz -lvv file.xz shows the memory needed; raise the limit for that file.
  • Unexpected end of input: the file was cut short. With multi-block files, xz -dc still outputs the complete blocks before the break.
  • xz deleted the original. Like gzip, xz replaces its input. Use -k to keep it.
  • Compression is very slow: that's xz at -6 or above. Use -T0 for all cores, a lower level such as -3, or Zstandard if speed matters more than size.
  • A plain .xz won't open on Windows or Mac by double-click: use 7-Zip on Windows. On macOS, tar -xf handles .tar.xz, but a single-file .xz needs xz from Homebrew or an app such as Keka or The Unarchiver.

How to

How to open, create and convert an XZ file

  • Linux: unxz file.xz (or xz -d), xz -k file to compress and keep the original, xzcat and xzless to read without unpacking, xz -l to list sizes and ratio. For tarballs, tar -xf file.tar.xz and tar -cJf archive.tar.xz folder/.
  • macOS: tar -xf file.tar.xz in Terminal works out of the box. For plain .xz files, install XZ Utils with Homebrew (brew install xz).
  • Windows: recent Windows 11 opens .tar.xz and .txz archives in File Explorer. Otherwise use 7-Zip, which reads and writes .xz.
  • Programming: Python's lzma module, liblzma for C, Go and Rust libraries, and Apache Commons Compress with XZ for Java.
  • Convert: xzcat file.tar.xz | gzip > file.tar.gz, or xzcat file.tar.xz | zstd -19 > file.tar.zst. The tar inside stays the same.

Decompression bombs

In our test, 1 GiB of zero bytes compressed to 156,316 bytes with xz -9, a ratio of about 6,900 to one. Code that decompresses uploaded .xz files must cap the output size and the memory it allows (liblzma has a memory limit setting).

Free downloads

Sample XZ files to download

Free sample XZ files for testing decompressors, libraries and upload checks. Each one passes xz -t and decompresses with Python's lzma module. All were made with XZ Utils 5.4.5, a version unaffected by the backdoor.

sample-text.txt.xz · 1.2 KBDownload

Browsers can't show this kind of file in a page. Download it to open it in the app it belongs to.

What's inside sample-text.txt.xz

A UTF-8 text file compressed with xz's defaults: preset -6, LZMA2 with an 8 MiB dictionary, a CRC64 check, one block. The anatomy above walks through every structure in it.

  1. Stream header

    FD 37 7A 58 5A 00, then flags naming CRC64 as the check.

  2. One block

    A 12-byte block header naming LZMA2 with an 8 MiB dictionary, then 1,125 bytes of LZMA2 data.

  3. The check

    CRC64 0xCCE8E148FE75AA97 of the original text, written little-endian after the block.

  4. Index and footer

    12 bytes of index, then a 12-byte footer ending in YZ. xz -lvv sample-text.txt.xz prints all of this.

  5. No name, no date

    XZ stores neither. The output name comes from dropping .xz.

  6. Overhead on small files

    The containers add 59 bytes around the LZMA2 data. On a 2,733-byte text that's noticeable; on a 100 MB file it's nothing.

All sample XZ files

  • Text file, default settings

    sample-text.txt.xz · 1.2 KB (1,184 bytes)

    A UTF-8 text file with accented letters, Greek, Japanese and an emoji, compressed with xz -6 -T1: one stream, one block, CRC64.

    • Basic decompression tests
    • Learning the structure with `xz -lvv`
  • Project folder as .tar.xz

    sample-project.tar.xz · 3.7 KB (3,760 bytes)

    A small project folder (README, CSV, JSON, a PNG and an executable script) in a ustar archive, compressed with xz -6. The same files as the .tar.gz and .tar.bz2 samples.

    • Testing `.tar.xz` extraction
    • Comparing sizes with the .tar.gz and .tar.bz2 versions
  • Six blocks, sizes in headers

    sample-multi-block.xz · 33.4 KB (34,224 bytes)

    A 393,211-byte log of fictional weather readings compressed with two threads and --block-size=65536: six blocks, each with its sizes in the block header, as multi-threaded xz writes them.

    • Testing multi-threaded decompression
    • Index parsing and random access
  • SHA-256 integrity check

    sample-sha256.xz · 684 bytes

    A short text compressed with --check=sha256, so stream flags are 00 0A and each block ends with a 32-byte SHA-256 hash. Decoders aren't required to support this check.

    • Checking a decoder supports every check type
    • Testing what happens when it doesn't

Ways to test with them

  • Check types: sample-sha256.xz uses SHA-256. The specification only requires decoders to support CRC32 and no check, so minimal decoders may refuse this file; they should say so clearly rather than skip the check silently.
  • Threaded decoding: xz -dc -T0 sample-multi-block.xz can use several threads because the block headers store sizes; xz -lvv shows cu under Flags for each block.
  • Integrity: flip a byte in the middle of sample-multi-block.xz. xz -t should name a corrupt block, and the other blocks still decompress.
  • Size comparison: the same project is 3,760 bytes here, 3,997 as .tar.bz2 and 4,273 as .tar.gz.

Free to use for testing, teaching and demos, commercially or not, with no attribution needed. A link back to this page is always appreciated.

Put it online

Have an XZ file? Give it a link.

Drop an .xz or .tar.xz file on 99helpers and it gets its own download link, so you can share a release or a data set without attachment limits. Anyone with the link downloads the file exactly as you uploaded it.

Questions

XZ files, frequently asked

What is an .xz file?

A single file compressed with xz, using LZMA2. If the name ends in .tar.xz or .txz, it's a whole folder: a tar archive compressed with xz.

How do I open an .xz file?

On Linux, unxz file.xz, or tar -xf file.tar.xz for an archive. On Windows, 7-Zip or, for .tar.xz, recent Windows 11 File Explorer. On macOS, tar -xf in Terminal for .tar.xz.

Is xz better than gzip?

It makes smaller files: about 23% smaller than gzip's default in our test. It's much slower to compress and somewhat slower to decompress, so gzip is still the better choice when speed matters.

Is it safe to use xz after the backdoor?

Yes. Only XZ Utils 5.6.0 and 5.6.1 were affected, and distributions removed them within days in March 2024. Check with xz --version. The .xz file format itself was never the problem.

What's the difference between .xz and .7z?

Both can use LZMA2 compression. .xz compresses one file and relies on tar for folders; .7z is a full archive format with folders, encryption and solid compression built in.

What's the difference between .tar.xz and .txz?

None. .txz is the short form. unxz turns either into a .tar file.

Why does xz take so long to compress?

LZMA2 searches a large dictionary for the best matches. On our test machine the default level compressed at about 1.2 MB/s on one core. Use -T0 to use all cores, or a lower level.

Should I use xz or Zstandard?

For the smallest files when you compress once and unpack rarely, xz. For speed, or when files are unpacked often, Zstandard: in our test zstd -19 was within about 7% of xz's size and decompressed about five times faster.

Related formats

Other file types explained

Keep going

Related

Sources

Last reviewed 27 October 2026.