Android APK file format
An Android application package — a ZIP archive of compiled code, resources and a manifest.
- MIME type
- application/vnd.android.package-archive
- Extensions
- .apk
- Category
- Archives & compression
Magic-number signature
| 0x00000000 | 504B0304 | PK·· | 'PK' — it is a ZIP |
Inside the ZIP: an 'AndroidManifest.xml' entry (and usually 'classes.dex').
About the Android APK format
An APK is a ZIP archive with a required inner layout and one unusual extra: a signing block wedged between the last file's data and the ZIP central directory, in space the format leaves unclaimed. That is what makes an APK verifiable as a whole file rather than entry by entry, and it is also why appending anything to an APK, or rebuilding it with an ordinary ZIP tool, silently destroys the v2 and later signatures. Inside, AndroidManifest.xml is stored as Android binary XML rather than text, resources are indexed by resources.arsc, and the code lives in one or more classes.dex files.
Header layout, byte by byte
| Offset | Length | Field | Meaning |
|---|---|---|---|
| 0 | 4 | Local file header signature | 50 4B 03 04 — an APK is a ZIP, byte for byte, and nothing at the front of the file says Android. Each stored entry begins with one of these headers; only the one at offset 0 is at a fixed position. |
| 4 | 2 | Version needed to extract | Minimum reader version times ten: 10 for stored entries, 20 for deflate — the two values that cover essentially every entry in an APK, since Android's runtime does not accept the exotic compression methods a general ZIP allows. |
| 6 | 2 | General purpose bit flag | Bit 11 declares the entry name UTF-8 and is set by modern build tools. Bit 3, which moves the sizes and CRC after the data, must not be set in an APK because the runtime maps entries directly and needs their sizes up front. |
| 8 | 2 | Compression method | 0 stored or 8 deflate. resources.arsc must be stored uncompressed and aligned so the runtime can memory-map it, and native libraries in lib/ are usually stored too, so a hex dump of an APK shows long runs of readable data where a plain ZIP would show compressed noise. |
| 14 | 4 | CRC-32 | CRC-32 of the entry's uncompressed bytes, at offset 14 with the compressed and uncompressed sizes following at 18 and 22. These are the values the installer checks when unpacking, separate from and unrelated to the APK's signature. |
| 26 | 2 | File name length | Length in bytes of the entry name that starts at offset 30. Together with the extra-field length at 28 it fixes where this entry's data begins — and the extra field in an APK is often padding inserted by zipalign to push the next entry onto a 4-byte or 16 KiB boundary. |
| 30 | variable | First entry name | The only place in the header that hints this is Android at all. Which name comes first depends on the build tool, so treat it as a hint rather than a test: what identifies an APK is the presence of AndroidManifest.xml and normally classes.dex somewhere in the central directory. |
| variable | 16 | APK Signing Block magic | The 16 ASCII bytes 'APK Sig Block 42', sitting immediately before the ZIP central directory, preceded by an 8-byte size that repeats the block's own length. Reading the block backwards from the central directory offset is how a verifier finds the v2, v3 and v3.1 signature records. |
| -22 | 4 | End of central directory signature | 50 4B 05 06, 22 bytes from the end when there is no archive comment. Every reader starts here, walks back to the central directory, and only then knows what is in the file — which is why an APK with an intact first entry can still fail to install. |
| -6 | 4 | Offset of the central directory | Where the central directory begins, counted from the start of the file. It is also the anchor for the signing block, so any tool that rewrites the archive and moves this value without re-signing produces an APK the installer rejects. |
Telling it apart from its neighbours
| Easily confused with | How to tell |
|---|---|
| ZIP | There is no byte-level difference at the front — an APK is a ZIP. What identifies it is content: AndroidManifest.xml at the archive root, normally classes.dex, usually resources.arsc, and META-INF holding the v1 signature files. If those entries are absent it is a plain ZIP, whatever the extension says. |
| Java JAR | Both are ZIPs with a META-INF directory, and an APK is historically a JAR. The separator is what else is there: a JAR holds .class entries and META-INF/MANIFEST.MF, an APK holds .dex entries and AndroidManifest.xml, and only an APK carries the 'APK Sig Block 42' magic before the central directory. |
| aab/apks/xapk/apkm | All ZIPs, none of them installable APKs. An .apks bundle from bundletool contains toc.pb plus split APKs; an .xapk contains manifest.json plus APKs and OBB data; an .apkm carries info.json. Each of those markers sits at the archive root, so the first entry names in the central directory are what tells them apart — and the APKs inside are the real packages. |
| AndroidManifest.xml (binary XML) | Worth knowing because people extract it and find gibberish. The manifest inside an APK is not text: it is a chunk-structured binary XML file whose first 16-bit value is the chunk type 0x0003, followed by a 16-bit header size, so a hex dump starts 03 00 08 00. Decoding it needs the string pool and the resource map, not an XML parser. |
How these files break
- Rebuilt with an ordinary ZIP tool. Unpacking an APK and re-zipping it produces a structurally perfect archive whose signing block has been dropped and whose resources.arsc is now compressed and misaligned. The file opens fine in any archive viewer and is refused by the installer, which is the single most common self-inflicted APK failure.
- Anything appended to the file. Some distribution wrappers stuff data after the central directory to carry a channel or referrer id. ZIP tolerates it, but the v2 signature covers the file up to the central directory offset, so the signature check now sees a different file than the one that was signed.
- Truncation. As with any ZIP the end of central directory record goes first, so a partially downloaded APK has every local header intact and no way to list its contents. Recovery means scanning forward for 50 4B 03 04, and an APK reassembled that way will not verify even if every entry is recovered.
- Entries renamed or reordered by a repackaging tool. The signature covers entry names, so renaming even one file, or letting a tool normalise the order and drop the zipalign padding in the extra fields, invalidates v2 and later signatures while leaving a perfectly valid ZIP behind.
Where the format stands today
The APK is the only thing Android installs. App bundles changed how apps are published — a developer uploads an .aab and Google Play generates per-device split APKs from it — but the artefact that lands on a phone is still an APK, and sideloading, enterprise distribution, F-Droid and every alternative store deal in APKs directly. That is why the surrounding zoo of container formats exists: .aab for publishing, .apks, .xapk and .apkm for shipping a set of splits as one download, all of them ZIPs wrapping the real packages. For inspection the format is unusually rewarding: permissions, components, minimum SDK, signing certificates, native architectures and the full class list are all readable from the archive without running anything, which is what an APK analyser does.
Open Android APK 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 Android APK — compare their leading bytes.
| Format | First bytes | Extension |
|---|---|---|
| ZIP | 50 4B 03 04 | .zip |
| Java JAR | 50 4B 03 04 | .jar |
| Android DEX | 64 65 78 0A | .dex |