Skip to content
Android APK Inspector

APK Inspector: read any Android build without installing it

Drop an .apk to read its manifest, permissions, and native libraries — plus a full security analysis. Entirely in your browser.

On-device parsing No upload required

Client-side only

Parsed with JSZip in your browser — nothing is uploaded, logged, or stored on a server.

Inspect + analyze

Manifest, permissions, components, native libs — plus a one-click Android security analysis.

Security scan

Dangerous permissions, exported components, manifest hardening, signing, and a DEX secret scan.

Frequently asked questions

What is inside an APK file?

An APK is a zip archive with a fixed layout: AndroidManifest.xml at the root, stored as binary AXML rather than text; one or more classes.dex files holding the compiled bytecode; resources.arsc, the compiled resource table; res/ and assets/; native libraries under lib/ grouped by CPU ABI; and the v1 signing metadata in META-INF/. Because that layout is fixed, a browser can read all of it without installing the app.

Is my APK uploaded to a server?

No — the file is opened with a JavaScript zip reader inside the page, so it never leaves your machine; nothing is uploaded, logged or stored. The practical ceiling is 250 MB per file; a larger APK is refused rather than crashing the tab.

Can this tool tell me whether an APK uses signature scheme v2 or v3?

No — the v2 and v3 signatures live in the APK Signing Block, between the last file entry and the zip central directory, a region nothing in the zip structure points at, so a tool built on a zip reader (this one) cannot see it, and the panel says so rather than guessing. Only the v1 (JAR) signature in META-INF/ can be detected here, and its absence does not mean the APK is unsigned. To check every scheme, run apksigner verify -v --print-certs app.apk from the Android SDK build-tools.

What target SDK version does Google Play require?

From 31 August 2026, new apps and app updates submitted to Google Play must target Android 16 (API level 36) or higher, with lower floors for Wear OS, Android Automotive, Android TV and Android XR. Apps already published must target at least Android 15 (API level 35) to stay available to new users on devices running a newer Android version than the app targets, and developers can request an extension to 1 November 2026. The inspector reads targetSdkVersion straight from the manifest, so you can check a build before uploading it.

What is the difference between versionCode and versionName?

versionCode is an integer Android uses to decide which build is newer; it has to increase with every release you distribute, and users never see it. versionName is the human-readable string, such as 3.2.1, that appears in the app's settings entry and store listing. The inspector shows both, which is the quickest way to confirm a tester is running the build you think they are.

Why won't my APK install on a tester's phone?

The three usual causes are all visible here. If minSdkVersion is higher than the device's Android version, the install is rejected outright. If the APK ships native libraries for only one ABI and the device uses another, it will not install either. And Android will not accept a sideloaded package until the tester has allowed their browser to install unknown apps. Checking minSdk and the ABI list before you send the link saves a round trip.

Can I inspect an .aab (Android App Bundle) here?

Not here — an .aab stores its manifest as protobuf in a different layout, so this analyser stops when it cannot find an AndroidManifest.xml. Use the AAB inspector at /aab-inspector/ instead, which reads that format and also estimates what a device downloads once Play splits the bundle. If you specifically want to inspect the APK a bundle produces, convert it first with bundletool build-apks --mode=universal and open the universal APK from the .apks archive here.

betadrop · apk-inspector files never leave your browser

What is inside an .apk file?

An .apk is a zip archive with a fixed internal layout, which is why a build you have never installed can still be read in full. Rename one to .zip and the same entries turn up every time: AndroidManifest.xml at the root, compiled bytecode in classes.dex, the resource table in resources.arsc, drawables and layouts under res/, raw files under assets/, native libraries under lib/, and signing metadata in META-INF/.

The manifest is the part that trips people up. It is not XML text: the build tools compile it into AXML, a binary format with a string pool and typed attribute values, so opening AndroidManifest.xml in an editor shows control characters and a scattering of readable strings. Getting it back means walking the binary chunk structure rather than reading text, and that is most of what this page does: it decodes the AXML in the browser and rebuilds a readable manifest from it.

EntryWhat it holdsWhat the inspector does with it
AndroidManifest.xmlPackage name, version, SDK levels, permissions, components, security flags — in binary AXMLDecoded and shown as readable XML
classes*.dexCompiled bytecode; a second and third file mean the app is multidexCounted and sized; printable strings scanned for secrets
resources.arscCompiled resource table mapping numeric IDs to valuesWalked to resolve the launcher icon
res/, assets/Drawables, layouts and raw bundled filesSize breakdown and file explorer
lib/<abi>/Native .so libraries, one directory per CPU architectureABI list and library names
META-INF/MANIFEST.MF, a .SF file and a .RSA/.DSA/.EC certificate — the v1 signaturev1 (JAR) signature detection only — see below

All of it is parsed locally with a JavaScript zip reader. The APK is never uploaded, which matters when the build is unreleased, arrived from a client, or came from somewhere you would rather not send it back out to. The practical ceiling is 250 MB per file; anything larger is refused rather than left to exhaust the tab's memory.

How to open an APK file online

Drop an .apk onto the box at the top of this page, or click it and pick a file. Parsing takes a moment on a large build, then three tabs appear.

  • Details — package name, versionName and versionCode, minSdk and targetSdk with the Android release each maps to, counts of activities, services, broadcast receivers and content providers, every requested permission with the dangerous ones marked, the native ABIs and library names, the DEX file count, a size breakdown by top-level directory, and the compressed download size against the uncompressed total.
  • Security Analysis — static checks over the manifest and file contents: a release build left android:debuggable="true", cleartext HTTP allowed, allowBackup left at its permissive default, components exported without a protecting permission, dangerous runtime permissions, and a secret scan looking for Google API keys, Google App IDs, AWS keys, Slack and Stripe tokens, JWTs and private-key blocks across text resources and strings pulled out of the DEX files. Treat it as triage: a clean report is not a guarantee, and a flag is not automatically exploitable.
  • Explorer — the full file tree with a text and hex viewer, for reading a bundled JSON config or checking what actually ended up in assets/.

One detail worth knowing about the exported-component check: since Android 12 (API level 31) a component that declares an intent filter must set android:exported explicitly, but plenty of older builds leave it out. Where the attribute is missing and an intent filter is present, the inspector counts the component as exported — which is what the platform itself does.

What the permission list tells you, and what it does not

Permissions are the first thing most people look for in a manifest, and the easiest to misread. A <uses-permission> line is a declaration that the app may ask for something. It is not a grant, and it is not evidence the app ever asks.

Android sorts permissions by protection level, and the level decides what happens at install. Normal permissions (INTERNET, VIBRATE, ACCESS_NETWORK_STATE) are granted silently, because the platform judges the risk low enough not to ask. Dangerous permissions cover the things a user would object to: camera, microphone, precise location, contacts, SMS, the call log. Since Android 6.0 (API level 23) those are requested at runtime, one prompt at a time, and can be refused or revoked afterwards from Settings without uninstalling anything. Signature permissions are granted only to apps signed with the same certificate as the app that declared them, which is how a suite of apps from one vendor talks to itself without exposing anything to the rest of the device. The inspector marks the dangerous entries in the list so a long manifest reads at a glance.

The limitation worth internalising is that the manifest in the APK is a merged document. Gradle combines your src/main/AndroidManifest.xml with the manifest of every library the build pulls in, so an analytics SDK, an ads SDK or a crash reporter can contribute a permission that appears nowhere in code you wrote. That is why a permission audit run against the source disagrees with the one a store reviewer runs against the artefact, and why reading the finished APK is the only version of the check that matches what ships. When something unexpected turns up, Android Studio's Merged Manifest view attributes each line back to the module that contributed it.

Two entries deserve a second look wherever they appear. A build that can read both SMS and contacts holds a combination Google Play restricts and reviewers treat as a signal, and REQUEST_INSTALL_PACKAGES lets an app prompt to install other APKs: reasonable in an app store or an updater, and hard to justify anywhere else. Both get their own entry in the Security Analysis tab, so neither has to be spotted by eye in a permission list eighty lines long.

minSdk, targetSdk, and the Google Play deadline

Two SDK numbers sit in every manifest and they answer different questions. minSdkVersion is the floor: the oldest Android release the app will install on. A device below it refuses the package outright, which is the most common reason a tester reports that a beta “won't install”.

targetSdkVersion is a declaration that the app has been tested against a particular platform version. Android reads it to decide which behaviour changes apply: a restriction introduced in a given release takes effect once your target reaches that release, and apps still targeting something older keep the old compatibility behaviour. Raising the number is never a cosmetic bump — it opts the app into whatever the newer platform tightened.

Google Play attaches deadlines to that second number. From 31 August 2026, new apps and app updates must target Android 16 (API level 36) or higher, with lower floors elsewhere: Android 15 (API level 35) for Wear OS and Android Automotive, Android 14 (API level 34) for Android TV and Android XR. An app already published has a separate obligation: it must target at least Android 15 (API level 35) to stay available to new users whose device runs a newer Android version than the app targets. Below that it quietly stops being installable for them, with nothing taken down and no rejection email. Developers who need more time can request an extension to 1 November 2026.

Reading targetSdk out of the finished artefact, rather than out of the Gradle file you believe produced it, is a fast way to catch a build made from the wrong branch or with a flavour override you had forgotten about.

What a browser can and cannot verify about signing

An APK can carry four signature schemes, and only the first is readable here.

v1 is the original JAR signing: MANIFEST.MF, a .SF file and a .RSA, .DSA or .EC certificate inside META-INF/. Those are ordinary zip entries, so the inspector can report v1 with confidence.

v2 (Android 7.0) and v3 (Android 9, which adds key rotation) are stored in the APK Signing Block — a region inserted between the last file entry and the zip central directory. A zip reader parses the entries and the central directory; nothing in either points at the block wedged between them, so it is invisible to any tool built on one, this page included. The signing panel therefore reads “can't be read in-browser” rather than “not detected”. Those are different claims, and reporting the second as though it were the first is exactly how an inspector ends up telling a correctly signed build that it is vulnerable. v4 (Android 11) is not in the archive at all; it lives in a separate .idsig file alongside it, for incremental installs.

It follows that an empty v1 row is not evidence of an unsigned APK. When minSdkVersion is 24 or higher, build tooling commonly turns v1 signing off, because every device that can run the app understands v2. For a definitive answer, run apksigner verify -v --print-certs app.apk from the Android SDK build-tools: it prints which schemes verified and the certificate digests behind them.

Browser inspector versus the Android SDK command line

Nothing here replaces the SDK tools; it replaces the ten minutes of setup they need when all you have is an APK and a question. Where the browser cannot answer, the equivalent command is worth knowing.

What you want to knowIn this pageCommand-line equivalent
Package name, versionCode, SDK levelsYesaapt2 dump badging app.apk
Permissions and componentsYesapkanalyzer manifest print app.apk
Native ABIs and size breakdownYesapkanalyzer files list app.apk
v1 (JAR) signature presentYesapksigner verify -v app.apk
Signature schemes v2, v3 and v4No — outside the zip structuresapksigner verify -v app.apk
Signing certificate fingerprintNoapksigner verify --print-certs app.apk
Decompiled Java or Kotlin sourceNo — DEX is counted and string-scanned, not decompiledjadx -d out app.apk

Questions an APK inspection answers

Almost nobody opens an APK out of curiosity. These are the situations that send people looking, and the field to look at first.

The build on the device is not the one you think you built
versionCode and versionName come straight out of the shipped manifest, so comparing them against the CI run that was supposed to produce the file settles the argument in seconds. targetSdk is the other useful fingerprint: a value you do not recognise usually means the artefact came off the wrong branch or picked up a flavour override.
A release build went out with debug settings still on
The Security Analysis tab flags android:debuggable="true", cleartext HTTP left permitted, and allowBackup sitting at its permissive default: the three configuration mistakes that survive code review because they live in a manifest nobody reads at release time.
The APK is much heavier than the last release
The size breakdown groups the archive by top-level directory (res/, assets/, lib/), and the compiled bytecode is reported separately as a DEX total, so you can see which of them the weight went into. A universal APK carrying native libraries for all four ABIs is the usual culprit, and splitting per ABI or shipping an app bundle is the usual fix.
The app requests a permission nobody on the team added
Read the permission list off the artefact rather than the source. Gradle merges the manifest of every dependency into the final one, so a permission that appears in no file you wrote can still be in the shipped APK — see the section above on where permissions actually come from.
Someone sent you an APK and you do not know what it is
Package name, versionName, launcher icon, the full permission list and the native ABIs identify a build without installing it or trusting whoever sent it. The Explorer tab goes further and shows what is actually sitting in assets/.
It installs on your phone but not on the tester's
Two fields cover most of these. If minSdkVersion is above the tester's Android version, the package is refused outright. If lib/ contains only one ABI and their device uses another, the install fails too: an arm64-v8a-only build will not run on an armeabi-v7a device.

Once the APK checks out, get it onto a device

Inspecting a build usually happens right before sending it to someone. BetaDrop's APK upload page turns a build into an install link and QR code, which a tester opens on their Android device: no Play Store listing, no review queue and no account for the tester, who only has to allow their browser to install unknown apps. The iOS equivalent is sharing a signed IPA over the air.

For iOS builds, the IPA inspector does the same job on the other side of the fence: Info.plist, bundle identifier, minimum iOS version, frameworks and the embedded provisioning profile. If you are chasing an identifier for an app that is already published rather than one on your disk, the App Store bundle ID lookup reads it from Apple's public metadata.