Parse APK metadata and signature information in Node.js and modern browsers.
This project was developed entirely with AI assistance.
- Parse APK files in browsers with
File/Blob - Parse remote APK URLs with HTTP
Rangerequests - Read:
- app name
- package name
- version code
- version name
- app icon
- signature info for v1 / v2 / v3
- Works in:
- Node.js 18+
- modern browsers
npm install simple-apk-parserParse a local APK File / Blob.
import { parseApkFile } from "simple-apk-parser";
const result = await parseApkFile(file);
console.log(result.packageName);Parse a remote APK by URL.
import { parseApkUrl } from "simple-apk-parser";
const result = await parseApkUrl("https://example.com/app.apk");
console.log(result.packageName);Create a browser parser with optional runtime overrides. This is the recommended way to inject a custom digest() fallback.
import { createBrowserParser } from "simple-apk-parser";
import { sha1 } from "@noble/hashes/sha1";
import { sha256 } from "@noble/hashes/sha256";
const parser = createBrowserParser({
digest(algorithm, data) {
if (algorithm === "SHA-1") return sha1(data);
if (algorithm === "SHA-256") return sha256(data);
throw new Error(`Unsupported digest algorithm: ${algorithm}`);
},
});
const result = await parser.parseApkFile(file);Create a Node.js parser. In most Node.js environments you do not need to pass anything, but the hook remains available for advanced overrides.
import { createNodeParser } from "simple-apk-parser";
const parser = createNodeParser();Advanced API for building a parser from a fully custom runtime.
Node.js low-level entry:
import { createNodeRuntime, createParser } from "simple-apk-parser";
const parser = createParser(createNodeRuntime());Browser low-level entry:
import { createBrowserRuntime, createParser } from "simple-apk-parser";
const parser = createParser(createBrowserRuntime());Type: boolean
Default: true
Controls whether resources.arsc is loaded and resolved.
true: resolves resource references for app name and iconfalse: skipsresources.arsc
When loadResources: false, the parser still reads manifest and signature info, but it usually cannot resolve the final human-readable appName or icon.
const result = await parseApkUrl(url, {
loadResources: false,
});Type: string
Default: system locale
Controls which localized resource variant is preferred when resolving values from resources.arsc.
- defaults to the current runtime locale, such as
en-USorzh-CN - can be set explicitly to make parsing deterministic across environments
const result = await parseApkFile(file, {
locale: "en-US",
});When locale is set, the parser prefers exact language-region matches first, then same-language fallbacks, then non-localized resources.
When you provide digest, the parser calls it as:
await digest(algorithm, data)algorithmis currently"SHA-1"or"SHA-256"datais aUint8Array- the return value may be a
Uint8Array,ArrayBuffer, or a hex string - hex strings may be uppercase or lowercase; the parser normalizes them to lowercase internally
If digest is omitted, the parser falls back to crypto.subtle.digest() when available. If both are provided, digest wins.
Typical result:
{
appName: "Example App",
packageName: "com.example.app",
versionCode: 123,
versionName: "1.2.3",
iconBlob: Blob | null,
signatures: [
{
scheme: "v3",
found: true,
certificate: {
dn: "...",
sha256: "...",
sha1: "...",
md5: "..."
}
},
{
scheme: "v2",
found: true,
certificate: { ... }
},
{
scheme: "v1",
found: false,
certificate: null
}
]
}Signature fields indicate that the parser detected the corresponding signature structure and extracted its certificate information. They are not intended to mean the APK would necessarily pass strict verification by apksigner or jarsigner.
Modern bundlers should pick the browser ESM build automatically through the package browser export condition. For direct <script> usage, the IIFE bundles remain available at dist/simple-apk-parser.iife.js and dist/simple-apk-parser.iife.min.js.
The browser runtime expects these APIs:
fetchBlobTextDecoderTextEncodercrypto.subtleor a customdigest(algorithm, data)implementationDecompressionStreamfor deflate-raw ZIP entries
In browsers, crypto.subtle is usually only available in a secure context such as https:// or http://localhost. If you run the page from an insecure origin and crypto.subtle is missing, you can inject a third-party digest implementation instead.
parseApkUrl depends on HTTP range requests.
The server must support:
Range: bytes=...206 Partial ContentContent-Range
If the server ignores range requests or always returns 200, parsing will fail.
In browsers, parseApkUrl can fail because of:
- CORS
- mixed-content restrictions
- certificate errors
- network failures
- browser or extension policy interference
This library supports normal ZIP32 APKs only.
If a target APK uses ZIP64, parsing fails with:
ZIP64 APK is not supported
This is intentional. In practice, Android APK tooling and installation behavior around ZIP64 is not reliable enough to treat it as a normal supported APK format.
Install dependencies:
npm installBuild:
npm run buildTest:
npm testStart a static server from the repository root:
npx serve .Then open:
The demo imports source modules directly, so the server should be started from the repository root instead of from the demo/ directory.