Command reference
Run goopdl COMMAND --help for the same information in your terminal.
| Command | What it does |
|---|---|
download |
Download an app's APKs |
fast-download |
Download the latest version with a single token |
latest |
Find the newest version Google is rolling out |
inspect-delivery |
Show what a version would deliver, without downloading |
info |
Show app details |
search |
Search Google Play |
list-splits |
List an app's split APKs |
profiles |
List bundled device profiles |
auth login |
Sign in with a Google account and save it |
auth logout |
Remove the saved account and every cached token |
auth clear-cache |
Remove cached tokens and device records, keep the saved account |
auth status |
Show which credentials goopdl uses |
auth token |
Get and cache an anonymous token |
#Common flags
Most commands that talk to Google Play accept these:
| Flag | Short | Description |
|---|---|---|
--arch |
Device type: arm64 (default), armv7, x86, x86_64, or tv. See architectures |
|
--country |
-c |
2-letter country code, such as US or IN |
--proxy |
-p |
Proxy URL, such as socks5://host:1080 or http://host:8080 |
--profile |
Device profile key or name substring, such as D2 or Samsung. See profiles |
|
--dispenser |
-d |
Custom token dispenser URL. See custom dispenser |
--country only sets region headers. To get a region's actual APK variant,
also route traffic through a proxy in that region with --proxy.
#download
Downloads the base APK. Add --splits for split APKs and --extras for OBB
files and Play Asset Delivery packs.
goopdl download com.whatsapp # base APK, latest version
goopdl download com.whatsapp --splits # + split APKs
goopdl download com.whatsapp --splits --extras # + OBB files and asset packs
goopdl download com.whatsapp -o ./apks # custom output directory
goopdl download com.whatsapp -a arm64,armv7 # one download per architecture
goopdl download com.google.android.katniss -a tv # Android TV build
goopdl download com.whatsapp -v 231205015 # exact version code
goopdl download com.instagram.android -v 434.0.0.44.74 # exact version string
goopdl download com.whatsapp --splits -l de,fr,zh-CN # extra language splits
goopdl download com.whatsapp --dm # DEX metadata for faster first launch
goopdl download com.whatsapp -c IN -p socks5://host:1080 # regional variant| Flag | Short | Default | Description |
|---|---|---|---|
--output |
-o |
. |
Output directory |
--arch |
-a |
arm64 |
Device type. Comma-separate several to download each in turn; goopdl stops at the first one that fails |
--version |
-v |
latest | Version code (384009971) or version string (434.0.0.44.74). For a version string, goopdl probes fresh GSF IDs until one sees that version |
--splits / --no-splits |
--no-splits |
Include split APKs | |
--extras / --no-extras |
--no-extras |
Include OBB files and asset packs | |
--locale |
-l |
English | Extra language splits, comma-separated. Needs --splits |
--dm |
off | Download verified DEX metadata (.dm) |
|
--integrity-manifest |
— | Write a verified JSON manifest. See integrity manifest |
Also accepts the common flags.
#Output files
| Type | Name | Example |
|---|---|---|
| Base APK | {package}-{vc}.apk |
com.whatsapp-231205015.apk |
| Split APK | {package}-{vc}-{split}.apk |
com.whatsapp-231205015-config.arm64_v8a.apk |
| OBB (main/patch) | {type}.{vc}.{package}.obb |
main.20925.com.tencent.ig.obb |
| Asset pack | {package}-{vc}-asset.apk |
com.tencent.ig-20925-asset.apk |
{vc} is the version code. After a split download, goopdl prints an
adb install-multiple command listing exactly the APK and .dm files it
downloaded, quoted for your shell (PowerShell on Windows):
adb install-multiple com.whatsapp-231205015.apk com.whatsapp-231205015-config.arm64_v8a.apk#Integrity manifest
--integrity-manifest PATH makes the download fail unless Google sends size
and digest metadata for every requested base and split APK. goopdl:
- Verifies each file against that metadata before moving it into place. It prefers SHA-256 and uses SHA-1 only when SHA-256 is missing.
- Writes the manifest atomically: relative file name, size, algorithm, and Base64url digest for each file.
With several architectures, one manifest lists the files of all of them.
Google sends no digests for OBB files and asset packs, so --extras files are
downloaded unverified and left out of the manifest. The manifest never
contains download URLs, cookies, headers, or tokens.
If a check fails, goopdl prints the reason and exits with code 1.
#Rate limits
Google Play sometimes answers delivery requests with HTTP 429. goopdl retries
the delivery request up to twice with backoff. It does not retry file
downloads. If throttling continues, it exits with code 5. Wait, or switch
account, network, or dispenser.
#fast-download
Downloads the latest version using one token: a valid pooled token for the
--country if one exists, otherwise a single fresh one. Unlike download, it
doesn't fill the 5-token pool or try several device profiles. Use it for
crawlers and other high-volume callers, where hitting the dispenser on every
call gets your IP blocked.
goopdl fast-download com.whatsapp -o ./apks --splits| Flag | Short | Default | Description |
|---|---|---|---|
--output |
-o |
. |
Output directory |
--arch |
-a |
arm64 |
Device type (one only) |
--splits / --no-splits |
--no-splits |
Include split APKs | |
--extras / --no-extras |
--no-extras |
Include OBB files and asset packs | |
--profile |
random | Device profile. Defaults to a random pick from the two newest profiles |
Also accepts --country, --proxy, and --dispenser. --proxy applies only
to Google Play calls; dispenser requests rotate proxy regions on their own.
#latest
Finds the newest version available by asking Google Play through several GSF IDs and keeping the highest version code. Finding the latest version explains why one device isn't enough.
goopdl latest com.instagram.android
goopdl latest com.instagram.android --stable 5
goopdl latest com.instagram.android -s 4 -c US -p socks5://host:1080| Flag | Short | Default | Description |
|---|---|---|---|
--stable |
-s |
3 |
Stop once the highest version code hasn't changed for this many probes in a row |
--profile |
top-ranked | Device profile for every probe. Defaults to the one with the highest SDK and Play Store version |
Also accepts the common flags. --proxy applies to both
dispenser and Google Play calls.
The output is a table with each probe's GSF ID prefix, version name, and version code. The highest version is highlighted and printed last.
#inspect-delivery
Asks Google Play what it would deliver for an exact version code, without downloading any APK. Use it to check that a device profile gets the ABI you want before you start a large download.
goopdl inspect-delivery com.whatsapp --arch armv7 --version 231205015 --json
goopdl inspect-delivery com.whatsapp --version 231205015 -o delivery.json{
"architecture": "armv7",
"package": "com.whatsapp",
"splits": ["base", "config.armeabi_v7a", "config.en"],
"version": {"code": 231205015, "name": "2.23.26.15"}
}| Flag | Short | Default | Description |
|---|---|---|---|
--version |
-v |
required | Exact version code |
--json |
off | Print JSON | |
--output |
-o |
— | Write the JSON to a file instead of stdout |
Also accepts the common flags. The command authenticates and "purchases" the version (see how it works), but downloads nothing.
#info
Shows an app's name, version, developer, rating, download count, and Play Store URL.
goopdl info com.whatsapp
goopdl info com.whatsapp -c IN -p socks5://host:1080
goopdl info com.whatsapp --raw # full decoded protobuf response as JSON| Flag | Short | Default | Description |
|---|---|---|---|
--raw |
-r |
off | Print the full decoded response as JSON |
Also accepts the common flags.
#search
goopdl search "whatsapp"
goopdl search "file manager" --limit 5
goopdl search "whatsapp" --country IN| Flag | Short | Default | Description |
|---|---|---|---|
--limit |
-l |
10 |
Maximum number of results |
Also accepts the common flags.
#list-splits
Lists an app's split APKs (ABI, density, and language configs) without downloading anything.
goopdl list-splits com.whatsappAccepts --arch and --dispenser.
#profiles
Lists the bundled device profiles. Pass a value from the Key column to
--profile in any command.
goopdl profiles # every profile
goopdl profiles --arch arm64 # one architecture--arch accepts arm64, armv7, x86, x86_64, tv, or all (default).
#auth
Manages credentials. Run goopdl auth alone for the list of subcommands.
Authentication explains both auth modes.
#auth login
Signs in to a Google account in a browser and saves it for
Google account mode. Later commands use it
until you run auth logout. GOOPDL_ACCOUNT_EMAIL and GOOPDL_AAS_TOKEN
take precedence over it. The AAS token goes to the
system keyring, or to
account.json if there is none. The last line says which.
goopdl auth login # isolated browser window, recommended
goopdl auth login --manual # your usual browser, paste the oauth_token
goopdl auth login --insecure-storage # keep the token in account.json
TOKEN=$(goopdl auth login --print) # print the AAS token, save nothing| Flag | Default | Description |
|---|---|---|
--print |
off | Print only the AAS token on stdout instead of saving the account. Messages go to stderr |
--manual |
off | Open Google EmbeddedSetup in your usual browser and ask for the email and the oauth_token cookie |
--insecure-storage |
off | Save the token in account.json without trying the system keyring |
Getting an AAS token walks through
both modes. goopdl aastoken still works as a hidden, deprecated alias of
auth login --print; it accepts only --browser and --oauth (same as
--manual).
#auth logout
Deletes the saved account, its token in the system keyring, every cached
token, and the
account-mode device records. If
the keyring entry can't be removed, it warns and deletes the rest anyway. If
GOOPDL_ACCOUNT_EMAIL or GOOPDL_AAS_TOKEN is still set, it warns that
goopdl keeps using them. To keep the account and delete only the cache, use
auth clear-cache.
goopdl auth logout#auth clear-cache
Deletes every cached token and the
account-mode device records.
The saved account stays: it doesn't touch account.json or the system
keyring. Use it when Google stops accepting a registered device: the next
command registers a new one without signing in again. It has no flags.
goopdl auth clear-cache#auth status
Shows the active mode (environment, saved account, or anonymous), the
account email, where the saved token is (system keyring and its backend, or
file), and a summary of the cache. It never prints a token. For a token in
the keyring it checks that the token is there; if not, the mode reads
saved account (unusable) and the reason goes to stderr. With the account
variables set it doesn't open the keyring. Exits 2 if only one of the
account variables is set.
goopdl auth status#auth token
Gets an anonymous token from the dispenser and caches it. With a Google account it signs in to Google instead and caches nothing but the device registration.
goopdl auth token
goopdl auth token --arch armv7
goopdl auth token --country IN
goopdl auth token --profile "Galaxy S25 Ultra"| Flag | Short | Default | Description |
|---|---|---|---|
--country |
-c |
— | Register the device with that country's MCC/MNC, so later calls with the same --country see its catalog without a proxy |
Also accepts the common flags.
#Exit codes
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Other error |
2 |
Invalid input or configuration, such as only one Google account variable set or an unusable saved account |
3 |
Authentication failed: the dispenser rejected every device profile, is down or unreachable, or Google account sign-in failed. download also exits 3 when the token pool is busy |
4 |
Version unavailable (HTTP 404 or confirmed unavailable) |
5 |
Rate limited (HTTP 429): by Google Play after retries in download, fast-download, latest, and inspect-delivery, or by the token dispenser when no valid pool token is left (after a dispenser 429, later token requests in the same command fail at once, without asking it again), or by Google account sign-in |
When the dispenser answers but rejects every profile, goopdl prints
Authentication failed — all profiles rejected (last dispenser response: …)
with the last HTTP status, or no authToken. A dispenser that is down prints
… It may be down; retry later. instead.
If another goopdl process holds the token pool lock for more than 180
seconds, goopdl prints
Token pool is busy (another goopdl process holds the lock); retry later.
and exits with 3 from download, or 1 from latest and
fast-download. Retry once the other process finishes.