ZIP archive
| Full name | ZIP archive |
|---|---|
| Extensions | .zip, .zipx (WinZip, newer methods); also the container of .docx, .xlsx, .pptx, .odt, .epub, .jar, .apk, .cbz, .xps |
| MIME type | application/zip |
| Type | archive, per-file compression (usually DEFLATE) |
| Starts with | 50 4B 03 04 (PK\x03\x04); an empty archive is 50 4B 05 06 |
| Specification | APPNOTE.TXT (PKWARE) |
| Also standardized as | ISO/IEC 21320-1 (a restricted profile: stored or DEFLATE only, no encryption) |
| Maintained by | PKWARE |
| License | open; the spec is free to implement. PKWARE "strong encryption" is patented and rarely supported |
ZIP packs many files and folders into one file. Each file is compressed on its own, usually with DEFLATE, and an index at the end of the archive (the central directory) lists every file and where it starts. This index lets a program list the contents and extract a single file without reading the whole archive.
Every desktop OS opens ZIP files without extra software. ZIP is also the container for many other formats: Office documents (DOCX, XLSX, PPTX), OpenDocument, EPUB books, Java JAR files, Android APK, comic books (CBZ), XPS, 3MF and NuGet packages are all ZIP files with a defined set of files inside.
When to use ZIP#
- Use to send a set of files to anyone: Windows, macOS, Linux, iOS and Android open ZIP with built-in tools.
- Use when you need random access: listing contents or extracting one file is fast, even in large archives.
- Use as the container for your own document or package format (like DOCX, EPUB or JAR do).
- Avoid when you need the smallest size: per-file DEFLATE can’t use redundancy between files. 7z or tar + xz or zstd are often 20-50% smaller.
- Avoid for backups that must keep Unix permissions, owners, symlinks and hard links exactly: tar preserves them better.
- Avoid ZipCrypto (“traditional” password protection): it’s broken. Use AES-256 encryption (WinZip AES) or encrypt the whole file with another tool.
File structure#
A ZIP file is a sequence of file entries followed by the central directory and the end of central directory record (EOCD). All integers are little-endian.
[local file header 1][file data 1][data descriptor 1 (optional)]
[local file header 2][file data 2][data descriptor 2 (optional)]
...
[central directory header 1]
[central directory header 2]
...
[ZIP64 end of central directory record + locator (only if needed)]
[end of central directory record]
A reader starts at the end: it searches backwards for the EOCD signature 50 4B 05 06 (the EOCD can be followed by a comment of up to 65,535 bytes), reads the offset of the central directory, then reads the central directory to get the list of files. Data in front of the first local header is allowed, which is how self-extracting .exe archives work.
Each file appears twice: in a local file header right before its data, and in a central directory header. The central directory is authoritative; tools that read the archive as a stream (from a pipe or network) only see local headers.
Signatures#
| Bytes | Record |
|---|---|
50 4B 03 04 |
local file header |
50 4B 01 02 |
central directory file header |
50 4B 05 06 |
end of central directory record |
50 4B 06 06 |
ZIP64 end of central directory record |
50 4B 06 07 |
ZIP64 end of central directory locator |
50 4B 07 08 |
data descriptor (the signature is optional); also marks the start of a split archive |
Local file header#
| Offset | Size | Field |
|---|---|---|
| 0 | 4 | signature 50 4B 03 04 |
| 4 | 2 | version needed to extract (20 = 2.0 for DEFLATE, 45 = 4.5 for ZIP64) |
| 6 | 2 | general purpose bit flags |
| 8 | 2 | compression method |
| 10 | 2 | last modified time (MS-DOS format) |
| 12 | 2 | last modified date (MS-DOS format) |
| 14 | 4 | CRC-32 of the uncompressed data |
| 18 | 4 | compressed size |
| 22 | 4 | uncompressed size |
| 26 | 2 | file name length (n) |
| 28 | 2 | extra field length (m) |
| 30 | n | file name |
| 30+n | m | extra field |
File names use / as the separator. A name ending in / is a directory entry.
Important flag bits:
| Bit | Meaning |
|---|---|
| 0 | the entry is encrypted |
| 3 | CRC and sizes are 0 here and stored in a data descriptor after the data (used when writing to a stream whose size isn’t known in advance) |
| 11 | file name and comment are UTF-8 (without it, names are officially IBM code page 437, but many tools wrote the local code page) |
Central directory file header#
The central directory header repeats the local header fields and adds: version made by (the high byte is the host OS: 0 = MS-DOS/Windows, 3 = Unix, 19 = macOS), a file comment, the disk number, internal attributes, external attributes (MS-DOS attributes in the low byte, Unix mode st_mode in the high 16 bits when made on Unix) and the offset of the local header from the start of the archive.
End of central directory record (EOCD)#
| Offset | Size | Field |
|---|---|---|
| 0 | 4 | signature 50 4B 05 06 |
| 4 | 2 | number of this disk |
| 6 | 2 | disk where the central directory starts |
| 8 | 2 | number of central directory records on this disk |
| 10 | 2 | total number of central directory records |
| 12 | 4 | size of the central directory |
| 16 | 4 | offset of the start of the central directory |
| 20 | 2 | comment length |
| 22 | n | archive comment |
An empty ZIP file is just this 22-byte record: 50 4B 05 06 followed by 18 zero bytes.
ZIP64#
The classic fields limit an archive to 65,535 entries and 4 GiB (232-1 bytes) per file, per archive and per offset. ZIP64 removes the limits: a field that doesn’t fit is set to FFFFFFFF (or FFFF) and the real 64-bit value goes into the ZIP64 extra field (header ID 0x0001). The archive then also has a ZIP64 EOCD record and locator before the regular EOCD. Every current tool reads ZIP64; old tools (Windows XP Explorer, Java before 7) don’t.
Compression methods#
| ID | Method | Support |
|---|---|---|
| 0 | stored (no compression) | everywhere |
| 8 | DEFLATE | everywhere; the default |
| 9 | Deflate64 | 7-Zip, Windows Explorer (read), WinZip |
| 12 | bzip2 | 7-Zip, Info-ZIP, libzip, Python |
| 14 | LZMA | 7-Zip, libzip, Python |
| 93 | Zstandard | WinZip, recent 7-Zip (read), libzip, Python 3.14+ |
| 95 | XZ | 7-Zip, WinZip, libzip |
| 98 | PPMd | 7-Zip, WinZip |
| 99 | marker for WinZip AES encryption; the real method is in the 0x9901 extra field |
7-Zip, WinZip, libzip, minizip-ng |
Use stored or DEFLATE when the receiver may use built-in OS tools. WinZip uses .zipx for archives with newer methods.
Common extra fields#
| Header ID | Content |
|---|---|
0x0001 |
ZIP64 sizes and offsets |
0x000A |
NTFS timestamps (modified, accessed, created, 100 ns precision) |
0x5455 |
extended timestamp: Unix time in seconds (Info-ZIP “UT”) |
0x7875 |
Unix UID and GID (Info-ZIP “ux”) |
0x7075 |
Info-ZIP Unicode path (UTF-8 name for archives without flag bit 11) |
0x9901 |
WinZip AES encryption: strength and the real compression method |
Timestamps#
The header time and date use the MS-DOS format: local time without a time zone, 2-second resolution, years 1980 to 2107. Precise and UTC times are only in extra fields (0x5455, 0x000A).
Hex example#
A ZIP file with one stored file hi.txt containing hi\n:
50 4B 03 04 local file header
0A 00 version needed 1.0
00 00 flags
00 00 method 0 (stored)
xx xx xx xx time, date
xx xx xx xx CRC-32
03 00 00 00 03 00 00 00 compressed size 3, uncompressed size 3
06 00 00 00 name length 6, extra length 0
68 69 2E 74 78 74 "hi.txt"
68 69 0A file data "hi\n"
50 4B 01 02 ... central directory header for hi.txt (52 bytes)
50 4B 05 06 end of central directory
00 00 00 00 disk numbers
01 00 01 00 1 entry on this disk, 1 entry total
34 00 00 00 central directory size 52
27 00 00 00 central directory offset 39
00 00 comment length 0
Encryption#
- ZipCrypto (traditional PKWARE encryption, flag bit 0): supported everywhere, including Windows Explorer, but broken. With 12 bytes of known plaintext, bkcrack recovers the keys. File names stay visible.
- WinZip AES (AE-1 / AE-2, method 99 + extra field
0x9901): AES-128/192/256 in CTR mode with HMAC-SHA1. Supported by 7-Zip, WinZip, WinRAR, PeaZip, Bandizip, libzip, minizip-ng, zip4j and the Rust zip crate. Windows Explorer and macOS Archive Utility can’t open it. File names stay visible. - PKWARE strong encryption (SES): patented, supported only by PKWARE products and a few others.
To hide file names too, put the ZIP inside another encrypted container, or use 7z with header encryption.
Security when extracting#
- Zip Slip: entry names like
../../etc/passwdor absolute paths write outside the target folder. Check every name before you create a file; most libraries have a “safe name” function (e.g.enclosed_namein Rust, path checks in .NETExtractToDirectory). - Zip bombs: a small archive can expand to petabytes, e.g. with overlapping entries. Limit total uncompressed size and entry count, and don’t trust the sizes in headers.
- Mismatched headers: the local header and central directory can disagree. Stream readers and index readers then see different files, which has been used to bypass scanners.
- Symlinks: Unix ZIPs can contain symlink entries; extracting a symlink and then a file “through” it escapes the target folder.
Specifications and documentation#
- APPNOTE.TXT: the official .ZIP File Format Specification from PKWARE (version 6.3.10); plain text copy
- ISO/IEC 21320-1:2015: Document Container File, the restricted ZIP profile used by ODF, EPUB and OOXML
- Info-ZIP extra field list: third-party extra fields
- WinZip AES encryption: the AE-1 / AE-2 specification
- Zip Slip vulnerability: path traversal on extraction
- ZIP on Wikipedia
Software that opens ZIP files#
| Software | Windows | macOS | Linux | Web | Can | Notes |
|---|---|---|---|---|---|---|
| SumatraPDF | ✓ | view | free, open source; shows images inside ZIP archives as pages, like a comic book | |||
| Windows File Explorer | ✓ | view, create | built into Windows; no AES encryption | |||
| macOS Archive Utility | ✓ | view, create | built into macOS: double-click to extract, Finder Compress to create | |||
| 7-Zip | ✓ | ✓ | view, edit, create, convert | free, open source; AES-256, ZIP64, all common methods | ||
| PeaZip | ✓ | ✓ | ✓ | view, edit, create, convert | free, open source | |
| NanaZip | ✓ | view, edit, create | free, open source 7-Zip fork with Windows 11 context menu | |||
| WinRAR | ✓ | view, edit, create, convert | commercial (trial) | |||
| WinZip | ✓ | ✓ | view, edit, create, convert | commercial; created .zipx | ||
| Bandizip | ✓ | ✓ | view, edit, create | free with ads, paid edition | ||
| The Unarchiver | ✓ | view | free | |||
| Keka | ✓ | view, create | free (paid in the Mac App Store) | |||
| Info-ZIP zip / unzip | ✓ | ✓ | ✓ | create | command line, open source; preinstalled on macOS and most Linux distros | |
| bsdtar (libarchive) | ✓ | ✓ | ✓ | view, create, convert | command line; built into Windows 10+ and macOS as tar | |
| Ark | ✓ | view, edit, create | KDE, open source | |||
| File Roller | ✓ | view, edit, create | GNOME, open source | |||
| ezyZip | ✓ | view, create, convert | free, runs in the browser |
Libraries#
Open-source libraries that read and write ZIP archives. See all ZIP libraries for a comparison.
| C/C++ | libarchive, libzip, miniz, minizip-ng |
|---|---|
| C# | SharpCompress, SharpZipLib, System.IO.Compression |
| Java | Commons Compress, java.util.zip, zip4j |
| Go | archive/zip |
| Python | zipfile |
| Ruby | rubyzip |
| Rust | zip |
| PHP | ZipArchive |
Related formats#
- 7z: better compression (LZMA2, solid archives), encrypted file names, less built-in OS support
- RAR: proprietary, solid compression and recovery records; only WinRAR creates it
- tar: Unix archive without compression, usually combined with gzip (the same DEFLATE as ZIP), xz or zstd
- CBZ (comic books), EPUB (e-books), XPS, DOCX, XLSX, JAR and APK: formats that are ZIP files inside