Requirements
The Headless API lets you control HideMyAndroid entirely from ADB or any automation tool — no app UI needed. It is a Premium feature.
- Premium account — the Headless API is Premium-only.
- App version 1.2.8 or newer.
- Root + LSPosed — the same setup HideMyAndroid already needs. See the installation guide.
- ADB connected to your device (
adb deviceslists it). - Internet on the device — needed only when you enable a proxy (it is tested live).
⚠️ Make sure the app has already been granted the VPN permission before using headless mode.
Authentication
Open Settings → Developer → Headless API in the app and turn on Enable. A key is generated automatically — tap Copy. Every request sends this key as the token parameter.
Keep it private — anyone with the key and ADB access can control your profiles. Regenerate issues a new key (the old one stops working); logging out erases it.
Throughout this reference, replace <your_access_token> with your key and <profile_id> with the id returned by profile.create.
Making requests
Two transports, chosen by whether a value contains a colon :
| Transport | Use for | Command |
|---|---|---|
content call | Reads, and values without : (name, gmails, package names) | adb shell content call |
am broadcast | JSON objects (hookFlags, proxy, deviceMock, sim) — they contain : | adb shell am broadcast |
content call splits each --extra on the colon, so it cannot carry JSON — that is why JSON values go through the broadcast instead.
Responses. Success is ok=true (content call) or result=0 (broadcast); failures add error_code and error_message. See Error codes. Every method also takes token. Click any operation below to expand its parameters, request, and response.
Status
READ status Check the API is ready content call
Parameters
No parameters.
Request
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method status --extra token:s:<your_access_token> Response ok=true
Bundle[{data={"premium":true,"featureEnabled":true,"freshnessOk":true,"activeProfileId":"a1b2c3d4-...","version":"1.2.8"}, ok=true}] Fields: premium, featureEnabled, freshnessOk (license confirmed online recently), activeProfileId (or null), version.
Profiles
READ profile.list List all profiles content call
Parameters
No parameters.
Request
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.list --extra token:s:<your_access_token> Response ok=true
Bundle[{data=[{"id":"a1b2...","name":"Demo","isActive":true,"createdAt":1717000000000,"updatedAt":1717000500000}], ok=true}] READ profile.get Read one profile in full content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | The profile id. |
Request
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.get --extra token:s:<your_access_token> --extra id:s:<profile_id> Response ok=true
Bundle[{data={"id":"a1b2...","name":"Demo","isActive":false,"hookFlags":{"hook_wifi":true,...},"proxy":{"enabled":false,...},"deviceMock":{"enabled":false,...},"sim":{"enabled":false,"simCards":[]},"gmails":[],"targetApps":["com.whatsapp"]}, ok=true}] CREATE profile.create Create a profile (returns its id) content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
name | string | required | A label for the profile. |
Request
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.create --extra token:s:<your_access_token> --extra name:s:Demo Response ok=true
Bundle[{data={"id":"a1b2c3d4-..."}, ok=true}] Copy this id in as <profile_id> for later calls.
UPDATE profile.update Change a profile's settings content call / broadcast
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | The profile id. |
name | string | optional | New profile label (content call). |
gmails | string[] | optional | Virtual @gmail.com accounts (content call). |
hookFlags | object | optional | Spoofing on/off switches (broadcast). |
proxy | object | optional | Proxy config (broadcast). |
deviceMock | object | optional | Device model spoof (broadcast). |
sim | object | optional | SIM / carrier spoof (broadcast). |
Request
content call — plain values
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.update --extra token:s:<your_access_token> --extra id:s:<profile_id> --extra name:s:"My Profile" broadcast — JSON configs
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e hookFlags '{"hook_wifi":false,"hook_nearby_bluetooth":false}' Response ok=true
Both forms return the full updated profile. See Configuration for every JSON field.
⚠️ hookFlags replaces the whole set — any flag you omit reverts to its default (ON). To change a few and keep the rest, run profile.get first, edit the full map, then send it all back.
DELETE profile.delete Delete a profile permanently content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | The profile id. |
Request
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.delete --extra token:s:<your_access_token> --extra id:s:<profile_id> Response ok=true
Bundle[{data={}, ok=true}] Activation
A profile only spoofs once active. Activating force-stops the target apps so they restart with the new identity.
ACTION profile.setActive Activate a profile — start spoofing content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | The profile id. |
Request
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.setActive --extra token:s:<your_access_token> --extra id:s:<profile_id> Response ok=true
Bundle[{data={"id":"a1b2...","isActive":true}, ok=true}] ACTION profile.deactivate Deactivate the active profile — stop spoofing content call
Parameters
No parameters.
Request
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.deactivate --extra token:s:<your_access_token> Response ok=true
Bundle[{data={}, ok=true}] No id needed — it deactivates whichever profile is active.
Target apps
Target apps are the apps a profile spoofs.
READ profile.getApps List a profile's target apps content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | The profile id. |
Request
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.getApps --extra token:s:<your_access_token> --extra id:s:<profile_id> Response ok=true
Bundle[{data=[{"packageName":"com.whatsapp"}], ok=true}] CREATE profile.addApp Add a target app to a profile content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | The profile id. |
packageName | string | required | The app's package name. |
Request
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.addApp --extra token:s:<your_access_token> --extra id:s:<profile_id> --extra packageName:s:com.whatsapp Response ok=true · updated app list
Bundle[{data=[{"packageName":"com.whatsapp"}], ok=true}] ⚠️ Adding the same package twice returns BAD_REQUEST.
DELETE profile.removeApp Remove a target app from a profile content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | The profile id. |
packageName | string | required | The app to remove. |
Request
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.removeApp --extra token:s:<your_access_token> --extra id:s:<profile_id> --extra packageName:s:com.whatsapp Response ok=true · updated app list
Bundle[{data=[], ok=true}] Configuration
These are the values you send with profile.update. Defaults when a profile is created:
| Setting | Default | To use it… |
|---|---|---|
| hookFlags (all 20) | ✅ ON | Already on. Send false only for the ones to turn off. |
| proxy | ❌ OFF | Include "enabled":true |
| deviceMock | ❌ OFF | Include "enabled":true |
| sim | ❌ OFF | Include "enabled":true |
| gmails | empty | Send the addresses (virtual accounts on by default) |
⚠️ A config with
enabled:falseis stored but inert — values are saved so you can flip it on later, but nothing is spoofed untilenabled:true. Geo spoofing (hook_geo_*) needs a proxy that isenabled:trueand passes the live test.
hookFlags
Default: all ON. A map of "flag": true|false. An update replaces the whole map — anything you leave out goes back to ON.
| Flag | What it does |
|---|---|
hook_hide_dev_opts | Hide Developer Options |
hook_hide_vpn | Hide VPN |
hook_hide_airplane_mode | Hide airplane mode |
hook_hide_proxy | Hide the system proxy setting |
hook_hide_root | Hide root |
hook_hide_lsposed | Hide LSPosed |
hook_spoof_installer | Spoof the install source |
hook_package_info | Spoof package info / signatures |
hook_lan_scan_block | Block LAN scanning |
hook_identifiers_partly | Spoof Android ID (basic) |
hook_identifiers_fully | Spoof all IDs (IMEI, serial, AAID, MediaDRM, AppSetID, boot_id…) |
hook_wifi | Spoof Wi-Fi name/address (SSID/BSSID) |
hook_nearby_wifi | Spoof nearby Wi-Fi scan results |
hook_nearby_bluetooth | Spoof nearby Bluetooth devices |
hook_realistic_sensor | Use realistic sensor data |
hook_sensor_accelerometer | Spoof the accelerometer (needs hook_realistic_sensor) |
hook_virtual_accounts | Enable virtual Google accounts (gmails need this ON) |
hook_geo_gps | Spoof GPS location (needs a proxy with geo) |
hook_geo_locale | Spoof language/region (needs a proxy with geo) |
hook_geo_timezone | Spoof timezone (needs a proxy with geo) |
proxy
Default: OFF. With enabled:true, the app connects through it for real, reads its location, and fills country/lat/long/timezone for the hook_geo_* flags. The live test takes up to ~8s; a proxy that fails returns PROXY_INVALID and is not saved.
| Field | Type | Default | Meaning / constraints |
|---|---|---|---|
host | string | "" | Proxy IP / hostname |
port | int | 0 | Port — valid 1–65535 |
protocol | string | HTTP | HTTP, SOCKS4, or SOCKS5 |
username | string | "" | Auth (optional) |
password | string | "" | Auth (optional) |
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e proxy '{"enabled":true,"host":"10.0.0.1","port":1080,"protocol":"SOCKS5"}' deviceMock
Default: OFF. Pretends the device is a different model. Set "enabled":true plus any of these fields — all optional strings (default empty), each mapping to an Android Build property:
| Field | Maps to | Example |
|---|---|---|
manufacturer | Build.MANUFACTURER | Samsung |
brand | Build.BRAND | samsung |
model | Build.MODEL | SM-S918B |
device | Build.DEVICE (codename) | dm3q |
product | Build.PRODUCT | dm3qxxx |
board | Build.BOARD | kalama |
hardware | Build.HARDWARE | qcom |
buildId | Build.ID | UP1A.231005.007 |
buildIncremental | Build.VERSION.INCREMENTAL | S918BXXU3CWK9 |
buildType | Build.TYPE | user |
buildTags | Build.TAGS | release-keys |
buildFingerprint | Build.FINGERPRINT | samsung/dm3qxxx/dm3q:14/UP1A.231005.007/S918BXXU3CWK9:user/release-keys |
deviceName | Displayed device name | Galaxy S23 Ultra |
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e deviceMock '{"enabled":true,"manufacturer":"Samsung","brand":"samsung","model":"SM-S918B","device":"dm3q","product":"dm3qxxx","board":"kalama","hardware":"qcom","buildId":"UP1A.231005.007","buildIncremental":"S918BXXU3CWK9","buildType":"user","buildTags":"release-keys","buildFingerprint":"samsung/dm3qxxx/dm3q:14/UP1A.231005.007/S918BXXU3CWK9:user/release-keys","deviceName":"Galaxy S23 Ultra"}' sim
Default: OFF. Spoofs the SIM/carrier. Set "enabled":true and provide up to two cards in simCards. Each card:
| Field | Type | Default | Meaning / constraints |
|---|---|---|---|
slotIndex | int | 0 | SIM slot — only 0 or 1 |
carrierName | string | "" | Carrier name (e.g. AT&T) |
countryIso | string | "" | ISO country code (e.g. us) — lowercased automatically |
mcc | string | "" | Mobile Country Code (e.g. 310) |
mnc | string | "" | Mobile Network Code (e.g. 410) |
operatorCode | string | "" | Operator code = mcc + mnc (e.g. 310410) |
phoneNumber | string | "" | Phone number |
iccid | string | "" | SIM serial number (ICCID) |
imsi | string | "" | IMSI |
networkType | string | "" | Network type — only: LTE, NR 5G, WCDMA, GSM |
networkType accepts only these values:
| Value | Network tier |
|---|---|
NR 5G | 5G |
LTE | 4G |
WCDMA | 3G |
GSM | 2G |
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e sim '{"enabled":true,"simCards":[{"slotIndex":0,"carrierName":"AT&T","countryIso":"us","mcc":"310","mnc":"410","operatorCode":"310410","networkType":"LTE"},{"slotIndex":1,"carrierName":"T-Mobile","countryIso":"us","mcc":"310","mnc":"260","operatorCode":"310260","networkType":"NR 5G"}]}' gmails
Default: empty. A list of virtual Google accounts — only @gmail.com addresses are accepted. The list replaces the previous one; [] clears it. No : inside, so content call works:
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.update --extra token:s:<your_access_token> --extra id:s:<profile_id> --extra 'gmails:s:["[email protected]","[email protected]"]' Full example
A complete setup from scratch:
# 1. create a profile — copy the returned id into <profile_id> below
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.create --extra token:s:<your_access_token> --extra name:s:Demo
# 2. add a target app
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.addApp --extra token:s:<your_access_token> --extra id:s:<profile_id> --extra packageName:s:com.whatsapp
# 3. add the virtual Gmail accounts
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.update --extra token:s:<your_access_token> --extra id:s:<profile_id> --extra 'gmails:s:["[email protected]","[email protected]"]'
# 4. enable + set the device mock
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e deviceMock '{"enabled":true,"manufacturer":"Samsung","brand":"samsung","model":"SM-S918B","device":"dm3q","product":"dm3qxxx","board":"kalama","hardware":"qcom","buildId":"UP1A.231005.007","buildIncremental":"S918BXXU3CWK9","buildType":"user","buildTags":"release-keys","buildFingerprint":"samsung/dm3qxxx/dm3q:14/UP1A.231005.007/S918BXXU3CWK9:user/release-keys","deviceName":"Galaxy S23 Ultra"}'
# 5. enable + set the SIM mock (two cards, full fields)
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e sim '{"enabled":true,"simCards":[{"slotIndex":0,"carrierName":"AT&T","countryIso":"us","mcc":"310","mnc":"410","operatorCode":"310410","networkType":"LTE","phoneNumber":"+12025550123","iccid":"8901410123456789012","imsi":"310410123456789"},{"slotIndex":1,"carrierName":"T-Mobile","countryIso":"us","mcc":"310","mnc":"260","operatorCode":"310260","networkType":"NR 5G","phoneNumber":"+12025550456","iccid":"8901260987654321098","imsi":"310260987654321"}]}'
# 6. enable + set the proxy (tested live, ~8s)
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e proxy '{"enabled":true,"host":"10.0.0.1","port":1080,"protocol":"SOCKS5"}'
# 7. activate (restarts the target app)
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.setActive --extra token:s:<your_access_token> --extra id:s:<profile_id>
# 8. verify
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.get --extra token:s:<your_access_token> --extra id:s:<profile_id> Error codes
On failure you get ok=false with one of these error_code values (broadcasts return result=1):
| Code | Meaning | Fix |
|---|---|---|
UNAUTHORIZED | Token missing or wrong | Use your current key; regenerate if unsure |
FEATURE_DISABLED | Headless API is off | Enable it in Settings → Developer → Headless API |
BAD_REQUEST | Bad parameter or JSON | Check required fields, valid JSON, gmail-only, no duplicate app |
NOT_FOUND | That profile id doesn't exist | Confirm the id with profile.list |
PROXY_INVALID | Proxy failed the live test | Check host/port/protocol/auth and the device's internet; it was not saved |
LICENSE_EXPIRED | Premium expired | Renew Premium |
LICENSE_STALE | License not checked online recently | Open the app once to re-validate (at least every 24h for non-stop use) |
INTERNAL | Internal error (I/O or root) | Retry; check that root/LSPosed are working |
Tips & troubleshooting
- A broadcast does nothing? Make sure you included
-p com.wowsoftware.hidemyandroid— Android blocks broadcasts without it. - A value got cut off after a
:? That value has a colon, socontent calltruncated it. Send it via theHEADLESS_UPDATEbroadcast instead. - JSON broadcast not applying (often on Windows)? Across a desktop shell and the device shell, the quotes in
am broadcastJSON (hookFlags,proxy,deviceMock,sim) are easily stripped, soammisreads the value (you may see it land as adat=…data URI) and nothing changes. The reliable fix is to keep the JSON off the command line — put the whole workflow in a.shfile (single quotes keep every JSON intact), then push and run it on the device. The script runs on the device, so it can even capture the new profile id and reuse it:bashthen push it to the device and run it:# setup.sh — the full example as one runnable script (runs on the device) URI=content://com.wowsoftware.hidemyandroid.headless PKG=com.wowsoftware.hidemyandroid K=<your_access_token> # 1. create a profile and capture its id ID=$(content call --uri $URI --method profile.create --extra token:s:$K --extra name:s:Demo | grep -o '"id":"[^"]*"' | head -n1 | sed 's/.*"id":"//;s/"//') echo "profile id: $ID" # 2. add a target app content call --uri $URI --method profile.addApp --extra token:s:$K --extra id:s:$ID --extra packageName:s:com.facebook.katana # 3. add the virtual Gmail accounts content call --uri $URI --method profile.update --extra token:s:$K --extra id:s:$ID --extra 'gmails:s:["[email protected]","[email protected]"]' # 4. enable + set the device mock am broadcast -a $PKG.HEADLESS_UPDATE -p $PKG -e token $K -e id $ID -e deviceMock '{"enabled":true,"manufacturer":"Samsung","brand":"samsung","model":"SM-S918B","device":"dm3q","product":"dm3qxxx","board":"kalama","hardware":"qcom","buildId":"UP1A.231005.007","buildIncremental":"S918BXXU3CWK9","buildType":"user","buildTags":"release-keys","buildFingerprint":"samsung/dm3qxxx/dm3q:14/UP1A.231005.007/S918BXXU3CWK9:user/release-keys","deviceName":"Galaxy S23 Ultra"}' # 5. enable + set the SIM mock (two cards) am broadcast -a $PKG.HEADLESS_UPDATE -p $PKG -e token $K -e id $ID -e sim '{"enabled":true,"simCards":[{"slotIndex":0,"carrierName":"AT&T","countryIso":"us","mcc":"310","mnc":"410","operatorCode":"310410","networkType":"LTE","phoneNumber":"+12025550123","iccid":"8901410123456789012","imsi":"310410123456789"},{"slotIndex":1,"carrierName":"T-Mobile","countryIso":"us","mcc":"310","mnc":"260","operatorCode":"310260","networkType":"NR 5G","phoneNumber":"+12025550456","iccid":"8901260987654321098","imsi":"310260987654321"}]}' # 6. enable + set the proxy (tested live, ~8s) am broadcast -a $PKG.HEADLESS_UPDATE -p $PKG -e token $K -e id $ID -e proxy '{"enabled":true,"host":"10.0.0.1","port":1080,"protocol":"SOCKS5"}' # 7. activate (restarts the target app) content call --uri $URI --method profile.setActive --extra token:s:$K --extra id:s:$ID # 8. verify content call --uri $URI --method profile.get --extra token:s:$K --extra id:s:$IDbashPlainadb push setup.sh /data/local/tmp/setup.sh adb shell sh /data/local/tmp/setup.shcontent callcommands (no JSON) can be typed directly without a script. In Git Bash, prefix theadblines withMSYS_NO_PATHCONV=1so the on-device path isn't rewritten. - Changes didn't appear? The target app must restart — activating a profile does this for you.
PROXY_INVALIDfor a proxy you trust? The device needs internet for the test, capped at ~8s, so a slow proxy can time out.