ByteScope

ZIP file format

A ZIP archive — also the container format underlying docx/xlsx/pptx, jar, apk and epub.

MIME type
application/zip
Extensions
.zip
Category
Archives & compression

Magic-number signature

0x00000000504B0304PK··'PK' local-file header

About the ZIP format

ZIP is the most widely used general archive format and, crucially, the container behind a whole family of formats (Office documents, Java JARs, Android APKs, EPUB books). A local file entry begins with 'PK' followed by 03 04.

Header layout, byte by byte

OffsetLengthFieldMeaning
04Local file header signature50 4B 03 04 — 'PK' after Phil Katz, then 3 and 4. Each stored file begins with one of these, so a multi-file archive contains many of them; only the one at offset 0 is at a fixed position.
42Version needed to extractMinimum reader version times ten: 10 means stored entries only, 20 means deflate and is the value you will see almost everywhere, 45 means ZIP64, 63 means AES or LZMA. Little-endian, like every number in a ZIP.
62General purpose bit flagBit 0 marks the entry encrypted. Bit 3 says the CRC and both sizes are zero here and follow the data instead, which is why streamed ZIPs show zeroes in a hex dump. Bit 11 declares the file name UTF-8.
82Compression method0 is stored, meaning the bytes that follow are the file itself; 8 is deflate. 12 bzip2, 14 LZMA, 93 Zstandard and 99 AES exist but far fewer readers accept them.
102Last modified timeMS-DOS packed time: 5 bits of hours, 6 of minutes, 5 of seconds counted in twos. Two-second resolution and no time zone at all, which is why extracted files so often carry a timestamp an hour off.
122Last modified dateMS-DOS packed date: 7 bits of year counted from 1980, 4 of month, 5 of day. Nothing before 1980 can be represented, so archived-from-tape files land on 1980-01-01.
144CRC-32CRC-32 of the uncompressed data. This is the value an extractor compares against after inflating, and the one behind every 'CRC failed' message on a damaged entry.
184Compressed sizeHow many bytes of compressed data follow the header and the variable-length fields. FF FF FF FF means the real value lives in a ZIP64 extra field instead.
224Uncompressed sizeThe original size, with the same ZIP64 escape hatch. Both size fields read zero whenever general purpose bit 3 is set, because they have been moved after the data.
262File name lengthByte length of the name that follows — call it n. Names are stored with forward slashes and never a leading slash, so an entry that begins with one is a path-traversal attempt.
282Extra field lengthByte length of the extra-field block — call it m. It carries ZIP64 sizes, Unix permissions, high-precision timestamps and, on macOS-written archives, a great deal of alignment padding.
30variableFile namen bytes of path, and the single most useful thing in the whole header: it is what separates a docx from an apk from an epub, none of which differ by a single byte before this point.
-224End of central directory signature50 4B 05 06. The fixed part of the EOCD record is 22 bytes, so with an empty archive comment it starts exactly 22 bytes from the end. A comment pushes it further back and readers then have to scan backwards for it.
-64Offset of the central directoryWhere the central directory begins, counted from the start of the file, under the same empty-comment caveat. Readers start here rather than at offset 0 — which is why an archive with a perfectly healthy first header can still refuse to open.

Telling it apart from its neighbours

Easily confused withHow to tell
EPUBThe strictest test in the family, because EPUB's OCF container spec pins the bytes down: the first entry must be named 'mimetype', stored uncompressed, with no extra field. So an EPUB reads 50 4B 03 04 at offset 0, method 0 at offset 8, name length 8 at 26, extra length 0 at 28, 'mimetype' at 30 and the literal string application/epub+zip at offset 38. A plain ZIP will not match all six.
Word document (docx)Byte-identical through the local header; the difference is entirely in the names the central directory lists. An OOXML package must contain [Content_Types].xml at the archive root, and Word writes it as the first entry, so offset 30 usually reads that name. Then word/document.xml means docx, xl/workbook.xml means xlsx and ppt/presentation.xml means pptx.
Android APKAlso a ZIP with no distinguishing header bytes. An APK holds AndroidManifest.xml and at least one classes.dex at the archive root, and that manifest is Android binary XML rather than text, so its data begins 03 00 08 00. APKs signed with scheme v2 or later also carry the 16-byte marker 'APK Sig Block 42' between the last entry and the central directory.
Java JARA JAR is a ZIP whose central directory lists META-INF/MANIFEST.MF. Java's own JarInputStream only finds the manifest when it is the first or second entry, so every build tool writes it up front; a .jar with the manifest buried late still opens as a ZIP but loads as though it had none.
GZIPConstantly confused because both are 'compressed', yet there is nothing to confuse at byte level: gzip is 1F 8B and holds one stream with no directory whatsoever. A .tar.gz cannot be listed without decompressing the whole thing, while a ZIP can be listed from its last few hundred bytes.

How these files break

  • Truncated at the tail. Every local header survives, so a hex dump looks perfectly healthy from offset 0, and yet nothing will open the file — readers start from the EOCD at the end and it is gone. Recovery means scanning forward for 50 4B 03 04 and rebuilding the directory from the local headers.
  • Prepended bytes. Self-extracting stubs are legal and common, but an HTML error page saved under a .zip name does the same thing: the central directory's offsets are now measured from the wrong base. Some readers auto-correct by computing the shift, others report every entry as corrupt.
  • Text-mode transfer. The same line-ending translation that ruins PNGs turns 0D 0A into 0A inside compressed data. The header still parses and the entry names still list correctly, so the failure surfaces only as a CRC mismatch at extraction time.
  • The 4 GiB and 65535-entry walls. A writer that never emits ZIP64 wraps the 32-bit size fields and the 16-bit entry count modulo their range. The archive stays well-formed and the numbers are simply wrong: an entry claiming 300 MB that extracts to 4.3 GB is this bug.
  • Mojibake in file names. Before bit 11 of the general purpose flag existed, names were written in the creator's local code page. A Windows-made archive full of Japanese file names lists as garbage on Linux even though not one byte of the file is damaged.

Where the format stands today

ZIP stopped being merely an archive format a long time ago and became a container format, which is why it is not going anywhere. Every OOXML document, every EPUB, every JAR, APK, XPI and ODF file is a ZIP with a required inner layout. As a plain archiver it has been beaten on compression ratio by 7z, xz and Zstandard for two decades, and tar.gz won on Unix because it preserves permissions and symlinks that ZIP represents only awkwardly through extra fields. What keeps ZIP first choice is random access: because the directory sits at the end rather than being interleaved, a reader can list an archive and pull one file out of it without touching the rest. That is exactly what an Android runtime or a word processor needs, and exactly what a compressed tarball cannot do.

Open ZIP 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 ZIP — compare their leading bytes.

FormatFirst bytesExtension
GZIP1F 8B.gz
Word document (docx)50 4B 03 04.docx
Android APK50 4B 03 04.apk
Java JAR50 4B 03 04.jar
EPUB50 4B 03 04.epub
7-Zip37 7A BC AF 27 1C.7z

Frequently asked questions

What is a magic number in a file?

The first few bytes of a file, which identify its format regardless of what the name says. A PNG always starts with 89 50 4E 47; a ZIP with 50 4B 03 04. Operating systems, browsers and the file command all read these bytes rather than trusting the extension, which is why renaming a file does not change what it actually is.

How do I check a file's magic number myself?

On macOS or Linux, xxd -l 16 yourfile prints the first 16 bytes; on Windows, Format-Hex -Path yourfile -Count 16 in PowerShell. Or drop the file into the File Type Identifier on this site, which reads the bytes locally and names the format for you — nothing is uploaded.

Why do two formats share the same magic number?

Because one is built on the other. Every docx, xlsx, pptx, apk, jar and epub begins with the ZIP signature, since all of them are ZIP archives underneath; telling them apart means looking at the entries inside. Java class files and macOS universal binaries both start with CA FE BA BE and are distinguished by the field that follows.

Can a file have no magic number at all?

Yes. Text-based formats — XML, HTML, JSON, SVG, CSV — have no fixed byte signature, so they are recognized structurally instead: a leading <?xml declaration, a <svg element, or a { followed by a quoted key. That detection is a good guess rather than a certainty, which is why this reference marks those formats as probe-detected.

Does a matching magic number mean the file is safe?

No. It tells you what the format is, not whether the contents are harmless — a genuine PDF or docx can still carry a malicious payload. Identifying the true type is a useful first check, especially when the extension disagrees with the bytes, but it is not a malware scan.

Have a file that might be in the ZIP format? Identify it with the File Type Identifier — it reads the magic number locally, nothing is uploaded. Or browse all formats.