Prérequis
La Headless API vous permet de piloter HideMyAndroid entièrement depuis ADB ou n’importe quel outil d’automatisation — sans passer par l’interface de l’application. C’est une fonctionnalité Premium.
- Compte Premium — la Headless API est réservée aux comptes Premium.
- Version de l’application 1.2.8 ou ultérieure. Tout ce qui a été ajouté depuis est un champ ou une méthode supplémentaire, donc la 1.2.8 fonctionne toujours — mais les éléments plus récents exigent une version plus récente :
hook_spoof_uptimerequiert la 1.3.4+,geoetprofile.duplicaterequièrent la 1.4.5+, tout le groupe sauvegarde / restauration requiert la 1.5.3+, le générateur SIM & appareil (simCountries,deviceTemplate,sim.countries,device.templates) requiert la 1.5.9+,hook_sensor_gyroscoperequiert la 1.6.3+,hook_sensor_lightrequiert la 1.6.4+, et les quatre flags de cohérence des capteurs (hook_sensor_magnetometer,hook_sensor_fused,hook_sensor_pressure,hook_sensor_roster) requièrent la 1.6.9+. Une version plus ancienne ignore un champ qu’elle ne connaît pas et répond quand mêmeok=true— mais une méthode inconnue se remarque davantage : appeler le groupe sauvegarde / restauration sur une version antérieure à 1.5.3, ousim.countries/device.templatesavant la 1.5.9, renvoieBAD_REQUESTavec l’error_message« Unknown method: … ». Si un réglage semble sans effet, vérifiez laversionen cours d’exécution avec status — une version publiée l’indique fidèlement, tandis qu’une version compilée par vos soins avant l’incrément du numéro de version peut contenir une fonctionnalité tout en affichant encore l’ancien numéro. - Root + LSPosed — la même configuration que celle dont HideMyAndroid a déjà besoin. Consultez le guide d’installation.
- ADB connecté à votre appareil (
adb devicesle liste). - Internet sur l’appareil — nécessaire uniquement lorsque vous activez un proxy (il est testé en direct).
⚠️ L’autorisation VPN n’est nécessaire que pour les profils qui utilisent un proxy. Le mode headless ne peut pas afficher la boîte de dialogue système de consentement VPN ; accordez-la donc une fois depuis l’écran Headless API de l’application. Sans elle, activer un profil avec proxy active tout de même le profil — mais le proxy ne se connectera pas et l’appel renvoie
INTERNALen l’indiquant explicitement.
Authentification
Ouvrez Paramètres → Développeur → Headless API dans l’application et activez Activer. Une clé est générée automatiquement — appuyez sur Copier. Chaque requête envoie cette clé dans le paramètre token.
Gardez-la confidentielle — toute personne disposant de la clé et d’un accès ADB peut contrôler vos profils. Régénérer émet une nouvelle clé (l’ancienne cesse de fonctionner) ; la déconnexion l’efface.
Dans toute cette référence, remplacez <your_access_token> par votre clé et <profile_id> par l’id renvoyé par profile.create.
Envoyer des requêtes
Deux transports, choisis selon qu’une valeur contient ou non un deux-points :
| Transport | À utiliser pour | Commande |
|---|---|---|
content call | Les lectures, et les valeurs sans : (name, gmails, noms de paquets, simCountries, ids deviceTemplate intégrés) | adb shell content call |
am broadcast | Les objets JSON (hookFlags, proxy, deviceMock, sim) et les ids de modèle custom: — ils contiennent : | adb shell am broadcast |
content call découpe chaque --extra au niveau du deux-points, il ne peut donc pas transporter de JSON — c’est pourquoi les valeurs JSON passent plutôt par le broadcast.
Seules trois méthodes existent sous forme de broadcast : HEADLESS_UPDATE (profile.update), HEADLESS_SET_ACTIVE et HEADLESS_DEACTIVATE. Les dix-sept autres — status, toutes les lectures (y compris sim.countries et device.templates), profile.create, profile.duplicate, profile.delete, les appels sur les applications cibles et tout le groupe sauvegarde / restauration — sont uniquement en content call. Inutile de chercher un HEADLESS_CREATE — ou un HEADLESS_BACKUP — : il n’en existe pas.
Le broadcast n’est pas réservé au JSON. HEADLESS_UPDATE transmet exactement neuf extras — name, hookFlags, proxy, geo, deviceMock, sim, gmails, et depuis la 1.5.9 simCountries et deviceTemplate — donc name, gmails et simCountries passent par l’un ou l’autre transport. Le tableau ci-dessus indique lequel est le plus pratique, pas lequel est possible. Tout extra dont le nom ne figure pas dans cette liste de neuf est ignoré sans erreur.
Réponses. Un succès renvoie ok=true (content call) ou result=0 (broadcast) ; un échec ajoute error_code et error_message. Voir Codes d’erreur. Chaque méthode prend également token. Cliquez sur une opération ci-dessous pour afficher ses paramètres, sa requête et sa réponse.
Statut
READ status Vérifier que l’API est prête 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.5.9"}, ok=true}] Champs : premium, featureEnabled, freshnessOk, activeProfileId (ou null), version. freshnessOk vaut true lorsque l’application a effectué une validation de licence en ligne au cours des dernières 24 heures. La vérification elle-même se fait hors ligne — une requête headless n’accède jamais au réseau, elle lit seulement le résultat enregistré, et premium est lu hors ligne lui aussi. Ouvrez l’application au moins une fois par jour pour que freshnessOk reste à true.
💡
statusest la seule méthode qui répond encore lorsque la licence est expirée ou périmée — tout autre appel renvoieLICENSE_EXPIREDouLICENSE_STALEet rien d’autre. C’est donc le moyen de distinguer les deux lorsqu’une requête est refusée : lisezpremiumpour savoir si le Premium a réellement expiré, etfreshnessOkpour savoir s’il suffit d’ouvrir l’application une fois.statusreste soumis àFEATURE_DISABLEDetUNAUTHORIZED; une API désactivée ou un token incorrect se présentent donc ici comme partout ailleurs.
Profils
READ profile.list Lister tous les profils 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 Lire un profil en entier content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | L’id du profil. |
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,...},"geo":{"source":"PROXY",...},"deviceMock":{"enabled":false,...},"sim":{"enabled":false,"simCards":[]},"gmails":[],"targetApps":["com.whatsapp"]}, ok=true}] CREATE profile.create Créer un profil (renvoie son id) content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
name | string | required | Un libellé pour le profil. |
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}] Reprenez cet id comme <profile_id> pour les appels suivants.
CREATE profile.duplicate Cloner un profil avec une nouvelle identité content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | L’id du profil à copier. |
Request
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.duplicate --extra token:s:<your_access_token> --extra id:s:<profile_id> Response ok=true
Bundle[{data={"id":"e5f6a7b8-...","name":"Brave Falcon 42"}, ok=true}] Le nouvel id et le nom généré sont renvoyés tous les deux — profile.create ne renvoie qu’un id, ne vous attendez donc pas à ce que les deux réponses aient la même forme.
⚠️ Le nom est généré pour vous et ne peut pas être choisi dans l’appel. Renommez la copie avec profile.update juste après si vous voulez le vôtre.
Ce que conserve une copie
Clone un profil comme le fait le menu Dupliquer dans l’application — requiert l’application 1.4.5+. Les réglages sont conservés, mais chaque valeur d’identification est régénérée, si bien que la copie possède sa propre empreinte au lieu d’être la jumelle de l’original. Il n’existe pas de forme broadcast : un broadcast « fire-and-forget » ne pourrait pas vous transmettre le nouvel id, ce qui est tout l’intérêt de l’appel.
| Élément | Dans la copie |
|---|---|
Applications cibles, hookFlags, proxy (y compris sa géolocalisation validée), geo, paquets masqués | Conservés à l’identique |
| Chaque identifiant d’appareil, au niveau du profil et pour chaque application du profil | Réémis, de sorte que la copie possède sa propre empreinte au lieu d’être la jumelle de l’original |
deviceMock (s’il est activé) | Tiré au sort sur un autre modèle d’appareil |
sim | Même pays, nouveaux numéros |
| Paquets sauvegardés | Non copiés — les sauvegardes sont indexées par {package}-{profileId}, la copie n’en possède donc aucune et démarre vide |
| Comptes Gmail virtuels | Une nouvelle adresse si hook_virtual_accounts était activé sur la source ; une liste vide sinon |
| Nom | Généré et garanti unique, sous la forme Brave Falcon 42 — vous ne pouvez pas le choisir, c’est pourquoi il vous est renvoyé |
| État actif | Toujours isActive: false — dupliquer n’active jamais |
Pour obtenir un nom de votre choix, dupliquez d’abord, puis renommez dans un second appel :
# 1. duplicate — the new id and its generated name come back together
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.duplicate --extra token:s:<your_access_token> --extra id:s:<source_profile_id>
# 2. rename the copy — profile.duplicate never takes a name of your own
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.update --extra token:s:<your_access_token> --extra id:s:<new_profile_id> --extra name:s:"My Profile" UPDATE profile.update Modifier les réglages d’un profil content call / broadcast
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | L’id du profil. |
name | string | optional | Nouveau libellé du profil (content call). |
gmails | string[] | optional | Comptes @gmail.com virtuels (content call). |
hookFlags | object | optional | Interrupteurs marche/arrêt de l’usurpation (broadcast). |
proxy | object | optional | Configuration du proxy (broadcast). |
geo | object | optional | Source de localisation — proxy ou personnalisée (broadcast). Requiert l’application 1.4.5+. |
deviceMock | object | optional | Usurpation du modèle d’appareil (broadcast). |
sim | object | optional | Usurpation SIM / opérateur (broadcast). |
simCountries | string[] | optional | Générer les cartes SIM à partir de 1 à 2 codes pays au lieu d’écrire sim à la main (l’un ou l’autre transport). Requiert l’application 1.5.9+ — voir Générateur SIM & appareil. |
deviceTemplate | string | optional | Générer deviceMock à partir d’un modèle — random ou un id issu de device.templates (content call ; broadcast pour les ids custom:). Requiert l’application 1.5.9+. |
Request
content call — valeurs simples
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 — configurations JSON
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
Les deux formes renvoient le profil complet mis à jour. Voir Configuration pour chaque champ JSON.
⚠️ hookFlags remplace l’ensemble complet — tout flag omis revient à sa valeur par défaut, qui est ON pour chaque flag sauf hook_spoof_uptime, où elle est OFF. Une mise à jour qui omet hook_spoof_uptime le désactive donc sans prévenir. Pour en modifier quelques-uns et conserver les autres, exécutez d’abord profile.get, modifiez la table complète, puis renvoyez-la en entier.
DELETE profile.delete Supprimer définitivement un profil content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | L’id du profil. |
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}] ⚠️ Supprimer un profil supprime aussi ses sauvegardes de données d’applications sous /sdcard/HideMyAndroid_Backups/ — copiez-les hors de l’appareil au préalable si vous en avez besoin. Et depuis la 1.5.3, profile.delete répond BUSY tant qu’une tâche de sauvegarde / restauration occupe encore le créneau — même une tâche déjà annulée ; réessayez jusqu’à ce que BUSY cesse.
Activation
Un profil n’usurpe qu’une fois actif, et un seul profil est actif à la fois. profile.setActive bascule le profil actif — le profil précédemment actif est désactivé pour vous ; inutile donc d’appeler profile.deactivate au préalable.
⚠️ L’activation efface les données des applications cibles.
profile.setActivene se contente pas de les redémarrer : il force l’arrêt de chaque application cible et efface ses données, afin qu’elle redémarre à neuf et prenne réellement en compte la nouvelle identité. C’est voulu — mais cela signifie que tout ce qui se trouve dans ces applications disparaît, sessions connectées comprises. Dans l’application, la même action vous demande d’abord une confirmation et vous oriente vers la fonction de sauvegarde ; un appel headless n’affiche aucune boîte de dialogue et s’exécute directement, cet avertissement est donc le seul que vous recevrez. En mode headless, le filet de sécurité estbackup.start(1.5.3+) avant de basculer. Et depuis la 1.5.3, tant qu’une tâche de sauvegarde / restauration occupe encore le créneau,profile.setActiveetprofile.deactivaterépondentBUSY— même pour une tâche déjà annulée ; réessayez jusqu’à ce queBUSYcesse.
ACTION profile.setActive Activer un profil — démarrer l’usurpation content call / broadcast
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | L’id du profil. Via le broadcast, il est accepté sous la forme id ou profile_id. |
Request
content call — recommandé
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.setActive --extra token:s:<your_access_token> --extra id:s:<profile_id> broadcast — pour l’automatisation
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_SET_ACTIVE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> Response ok=true
Bundle[{data={"id":"a1b2...","isActive":true}, ok=true}] ACTION profile.deactivate Désactiver le profil actif — arrêter l’usurpation content call / broadcast
Parameters
No parameters.
Request
content call — recommandé
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.deactivate --extra token:s:<your_access_token> broadcast — pour l’automatisation
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_DEACTIVATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> Response ok=true
Bundle[{data={}, ok=true}] Aucun id nécessaire — désactive le profil actif, quel qu’il soit.
content call est la forme à privilégier : il est synchrone et affiche le Bundle renvoyé. Les broadcasts HEADLESS_SET_ACTIVE et HEADLESS_DEACTIVATE font le même travail depuis des outils d’automatisation comme Tasker. Ils répondent sous forme de broadcast ordonné, qui renvoie toujours des données : en cas de succès, am broadcast affiche result=0 avec le JSON du résultat dans data="…", et en cas d’échec result=1 avec data="{"error_code":…,"error_message":…}". Ils ne sont donc pas strictement « fire-and-forget » — analysez data= et vous obtenez la même réponse que content call aurait donnée. HEADLESS_SET_ACTIVE prend l’id du profil sous la forme -e id ou -e profile_id ; HEADLESS_DEACTIVATE n’a besoin d’aucun id. Comme toujours, incluez -p com.wowsoftware.hidemyandroid.
Applications cibles
Les applications cibles sont les applications qu’un profil usurpe.
READ profile.getApps Lister les applications cibles d’un profil content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | L’id du profil. |
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 Ajouter une application cible à un profil content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | L’id du profil. |
packageName | string | required | Le nom de paquet de l’application. |
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}] ⚠️ Ajouter deux fois le même paquet renvoie BAD_REQUEST.
DELETE profile.removeApp Retirer une application cible d’un profil content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | L’id du profil. |
packageName | string | required | L’application à retirer. |
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}] ⚠️ Retirer un paquet absent du profil réussit quand même et ne change rien — ce n’est pas une erreur. C’est volontairement différent de addApp, où ajouter un doublon renvoie BAD_REQUEST.
Sauvegarde et restauration
Nouveau dans la 1.5.3, ce groupe copie les données d’applications d’un profil dans des archives sur l’appareil et les réinjecte plus tard — le même travail que Manage Backups dans l’application, sans l’interface. Les six méthodes sont uniquement en content call (pas de forme broadcast), et les deux appels *.start sont asynchrones : ils vous remettent immédiatement un jobId et poursuivent le travail en arrière-plan — interrogez backup.job pour suivre l’avancement. La sauvegarde d’une seule application peut prendre plusieurs minutes.
⚠️ Une tâche à la fois. Un second
*.startpendant qu’une tâche tourne renvoieBUSY, avec lejobIden cours danserror_message. Les deux appels*.startexigent également que le profil cible soit actif — sinonREQUIRES_ACTIVE_PROFILE, et il n’existe aucun flag pour passer outre. Les quatre autres méthodes fonctionnent sur n’importe quel profil. Et comme partout dans la Headless API, rien ne demande de confirmation — chaque appel s’exécute directement.
ACTION backup.start Lancer une tâche de sauvegarde pour le profil actif content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | L’id du profil — doit être le profil actuellement actif. |
packages | string | optional | Noms de paquets à sauvegarder, séparés par des virgules (sans espaces). Omettez-le pour sauvegarder toutes les applications cibles du profil. Chaque paquet doit appartenir au profil. |
Request
content call — toutes les applications cibles
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method backup.start --extra token:s:<your_access_token> --extra id:s:<profile_id> content call — paquets sélectionnés uniquement
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method backup.start --extra token:s:<your_access_token> --extra id:s:<profile_id> --extra packages:s:com.twitter.android,com.facebook.katana Response ok=true · job accepted
Bundle[{data={"jobId":"f0e1d2c3-...","type":"backup","total":2,"packages":["com.twitter.android","com.facebook.katana"],"foregroundHeld":true}, ok=true}] L’appel rend la main dès que la tâche est acceptée — il n’attend pas la fin de la copie. total indique combien d’applications la tâche va traiter ; interrogez backup.job pour la suivre. Pour ce que foregroundHeld promet (et ne promet pas), voir les remarques ci-dessous.
⚠️ Une sauvegarde ne force jamais l’arrêt de l’application et n’efface jamais ses données. Pour lire un instantané cohérent, elle met brièvement l’application en pause (SIGSTOP) pendant l’archivage de chaque composant, puis la relance (SIGCONT) — l’application continue de tourner et ne perd rien. Sauvegarder un paquet qui possède déjà une sauvegarde remplace l’ancienne archive : une sauvegarde par application et par profil, sans historique.
ACTION restore.start Restaurer les données d’applications sauvegardées dans le profil actif content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | L’id du profil — doit être le profil actuellement actif. Une sauvegarde ne se restaure que dans le profil qui l’a créée. |
packages | string | optional | Noms de paquets à restaurer, séparés par des virgules (sans espaces). Omettez-le pour restaurer toutes les applications qui ont une sauvegarde dans ce profil — celles qui n’en ont pas sont ignorées sans message. Si vous nommez explicitement des paquets, l’appel échoue immédiatement : une seule sauvegarde manquante fait échouer tout l’appel avec NO_BACKUP et rien n’est restauré. |
Request
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method restore.start --extra token:s:<your_access_token> --extra id:s:<profile_id> Response ok=true · job accepted
Bundle[{data={"jobId":"09a8b7c6-...","type":"restore","total":1,"packages":["com.twitter.android"],"foregroundHeld":true}, ok=true}] Même modèle de tâche que backup.start — la réponse est immédiate et le champ type indique "restore". Interrogez backup.job pour la suivre ; il n’existe pas de restore.job distinct.
⚠️ La restauration force l’arrêt de l’application cible (am force-stop) sans la redémarrer, puis extrait l’archive par-dessus /data/data/<pkg> sans vider le répertoire au préalable — les fichiers créés par l’application après la sauvegarde sont conservés. Et les sauvegardes sont indexées par paquet + profil, c’est pourquoi la restauration entre profils n’existe pas — vous ne pouvez pas réinjecter la sauvegarde d’un profil dans un autre.
READ backup.job Suivre la progression et les résultats d’une tâche content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
jobId | string | optional | La tâche à inspecter. Omettez-le pour lire la tâche la plus récente. |
Request
content call — une tâche précise
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method backup.job --extra token:s:<your_access_token> --extra jobId:s:<job_id> content call — la dernière tâche (sans jobId)
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method backup.job --extra token:s:<your_access_token> Response ok=true
# while it runs
Bundle[{data={"jobId":"f0e1d2c3-...","type":"backup","profileId":"a1b2...","state":"RUNNING","total":2,"done":0,"ok":0,"failed":0,"currentPackage":"com.twitter.android","currentComponent":"Internal Data","progress":0.31,"results":[],"error":null,"foregroundHeld":true,"startedAt":1712345678901,"finishedAt":null}, ok=true}]
# when it finishes — note: DONE even though one app failed
Bundle[{data={"jobId":"f0e1d2c3-...","type":"backup","profileId":"a1b2...","state":"DONE","total":2,"done":2,"ok":1,"failed":1,"currentPackage":null,"currentComponent":null,"progress":1.0,"results":[{"packageName":"com.twitter.android","ok":true,"error":null},{"packageName":"com.facebook.katana","ok":false,"error":"tar exited 2"}],"error":null,"foregroundHeld":true,"startedAt":1712345678901,"finishedAt":1712345699999}, ok=true}] Une seule méthode sert les deux types de tâche — type indique "backup" ou "restore". state vaut RUNNING, DONE, FAILED ou CANCELLED ; progress va de 0 à 1 sur l’ensemble de la tâche ; startedAt / finishedAt sont en millisecondes epoch et finishedAt reste null tant que la tâche tourne. DONE signifie que la tâche est allée jusqu’au bout — pas que chaque application a réussi — lisez donc toujours failed et results[] (un {packageName, ok, error} par application). currentComponent est un nom d’étape lisible ("Internal Data", "Device Encrypted Data", "External Data", "Media", "OBB", "Permissions", "SSAID") — volontairement différent des chaînes de components[] dans backup.list. Fonctionne sur n’importe quel profil. Seules les cinq tâches les plus récentes sont conservées — un jobId inconnu ou plus ancien renvoie NOT_FOUND, tout comme une interrogation avant qu’aucune tâche n’ait jamais été lancée.
ACTION backup.cancel Annuler une tâche en cours content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
jobId | string | optional | La tâche à annuler. Omettez-le pour annuler la tâche la plus récente. |
Request
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method backup.cancel --extra token:s:<your_access_token> --extra jobId:s:<job_id> Response ok=true · job snapshot
Renvoie l’instantané de la tâche après annulation — la même forme que celle renvoyée par backup.job.
⚠️ Annuler au milieu d’une application laisse son archive à moitié écrite : l’application n’est pas ajoutée à la liste des sauvegardes et les fichiers restants sont dans un état indéfini. Ne restaurez pas à partir de celle-ci — faites un backup.delete du paquet et sauvegardez-le à nouveau. Par ailleurs, l’instantané passe immédiatement à CANCELLED (avec finishedAt renseigné), mais le tar root sous-jacent ne peut pas être interrompu en cours de fichier et continue de tourner — la tâche peut donc encore occuper le créneau alors que CANCELLED est déjà affiché (voir les remarques ci-dessous).
READ backup.list Lister les sauvegardes stockées d’un profil content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | L’id du profil — n’importe quel profil, pas seulement le profil actif. |
Request
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method backup.list --extra token:s:<your_access_token> --extra id:s:<profile_id> Response ok=true
Bundle[{data=[{"packageName":"com.twitter.android","appName":"X","timestamp":1712345678901,"totalSize":12345678,"components":["INTERNAL_DATA","EXTERNAL_DATA","OBB"]}], ok=true}] Une entrée par application sauvegardée. appName est le nom d’affichage relevé au moment de la sauvegarde (lu dans le metadata.json de l’archive, et non déduit du paquet). timestamp est en millisecondes epoch, totalSize en octets, et components[] utilise des noms d’énumération : INTERNAL_DATA, DEVICE_ENCRYPTED, EXTERNAL_DATA, MEDIA, OBB, PERMISSIONS, SSAID.
DELETE backup.delete Supprimer la sauvegarde d’une application dans un profil content call
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | L’id du profil. |
packageName | string | required | L’application dont la sauvegarde doit être supprimée. |
Request
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method backup.delete --extra token:s:<your_access_token> --extra id:s:<profile_id> --extra packageName:s:com.twitter.android Response ok=true
Bundle[{data={}, ok=true}] Synchrone — aucune tâche n’est créée ; le dossier de sauvegarde est supprimé sur-le-champ. Supprimer une sauvegarde inexistante n’est pas une erreur : l’appel est idempotent et renvoie quand même ok=true avec data={}. NOT_FOUND signifie uniquement que l’id du profil n’existe pas ; un packageName mal formé renvoie BAD_REQUEST.
Comportement des tâches
DONEne signifie pas que chaque application a réussi. Cela signifie seulement que la tâche est allée jusqu’au bout. Une application peut échouer alors que la tâche se termine quand même enDONE— lisez toujoursfailedetresults[].- L’activation attend désormais les tâches. Tant qu’une tâche occupe le créneau,
profile.setActive,profile.deactivateetprofile.deleterépondentBUSY— même pour une tâche que vous avez déjà annulée, car letarroot sous-jacent ne peut pas être arrêté en cours de fichier, et aucun champ de l’instantané n’indique l’état du créneau. Une tâche qui se termine normalement enDONEouFAILEDlibère le créneau presque aussitôt ; après une annulation, ne considérez pasCANCELLEDcomme « créneau libre » — réessayez simplement l’appel jusqu’à ce queBUSYcesse. foregroundHeldest une observation, pas une promesse. Il indique si un service de premier plan protège la tâche contre l’arrêt par le système. Il a été mesuré àtruesur l’API 36, mais mêmetruesignifie seulement que le démarrage du service a été accepté — l’étape de promotion ultérieure peut encore échouer silencieusement sur certains appareils. Pour les tâches longues, gardez l’appareil éveillé plutôt que de vous y fier.- Emplacement des sauvegardes.
/sdcard/HideMyAndroid_Backups/<packageName>-<profileId>/— un dossier par application et par profil, contenant des archives.tar.gz(data.tar.gz,data_ext.tar.gz,media.tar.gz, …) ainsi quemetadata.json, écrites avec letarroot. C’est la clé{package}-{profileId}qui limite la restauration au même profil. Les sauvegardes réalisées en mode headless apparaissent aussi dans l’écran Manage Backups de l’application.
SIM & appareil depuis la base de données intégrée
Nouveau dans la 1.5.9. La section Configuration ci-dessous montre comment écrire à la main un bloc sim ou deviceMock, champ par champ. Ce groupe vous permet de vous en passer : deux clés supplémentaires de profile.update — simCountries et deviceTemplate — font générer le bloc entier par l’application à partir de la même base d’opérateurs et d’appareils que celle utilisée par sa propre interface, et deux méthodes de lecture listent ce qu’elle peut générer. Le résultat est enregistré dans le profil avec enabled:true déjà défini, il n’y a donc rien d’autre à envoyer — relisez-le avec profile.get.
⚠️ Une seule méthode par réglage, par appel.
simetsimCountriesdans la même requête donnentBAD_REQUEST, tout commedeviceMockavecdeviceTemplate. Mélanger entre réglages ne pose aucun problème —simCountriesà côté d’undeviceMockécrit à la main, ou les deux générateurs à la fois, comme dans le premier exemple ci-dessous. L’appel est atomique : tout est validé avant que quoi que ce soit ne soit enregistré, donc un id de modèle incorrect fait échouer toute la requête et lesimCountriesenvoyé avec lui n’est pas appliqué non plus.
READ sim.countries Lister les pays connus du générateur SIM content call
Parameters
No parameters.
Request
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method sim.countries --extra token:s:<your_access_token> Response ok=true
Bundle[{data=[{"code":"AF","country":"Afghanistan"},{"code":"AL","country":"Albania"},...,{"code":"GB","country":"United Kingdom"},...,{"code":"US","country":"United States"},...], ok=true}] Seuls les pays ayant au moins un opérateur dans la base sont listés, triés par nom. code est la valeur ISO 3166-1 alpha-2 en majuscules attendue par simCountries ; country est le nom anglais tel qu’il est stocké ("United Kingdom", "United States").
READ device.templates Lister les modèles d’appareil — intégrés et importés content call
Parameters
No parameters.
Request
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method device.templates --extra token:s:<your_access_token> Response ok=true
Bundle[{data=[{"id":"asus|ASUS_AI2401|AI2401_A","manufacturer":"asus","label":"ROG Phone 8","isCustom":false},...,{"id":"custom:samsung|e3qxeea|SM-S928B","manufacturer":"samsung","label":"Galaxy S24 Ultra","isCustom":true}], ok=true}] Une entrée par modèle. id est ce que prend deviceTemplate — brand|product|model, précédé de custom: pour les modèles que vous avez importés dans l’application (isCustom true) ; label est le nom commercial (ROG Phone 8) ; manufacturer est conservé exactement tel que le fabricant l’écrit (asus, samsung, OnePlus), sans normalisation. Voir la remarque sur le transport ci-dessous pour les ids custom:.
UPDATE profile.update Générer des cartes SIM et/ou un appareil depuis la base content call / broadcast
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string | required | L’id du profil. |
simCountries | string[] | optional | Tableau JSON de 1 à 2 codes ISO alpha-2, par ex. ["US","GB"] — un par emplacement SIM, dans l’ordre. content call ou broadcast. |
deviceTemplate | string | optional | random (ou une chaîne vide) pour un modèle aléatoire, intégré ou importé ; ou un id issu de device.templates. Ids intégrés : content call ou broadcast. Ids custom: : broadcast uniquement. |
Request
broadcast — les deux générateurs en un seul appel (tel que testé)
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e simCountries '["US","GB"]' -e deviceTemplate random content call — simCountries uniquement, emplacement 0 uniquement (les guillemets simples sont obligatoires)
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 'simCountries:s:["US"]' content call — un modèle aléatoire
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 deviceTemplate:s:random content call — un modèle intégré précis (les guillemets simples sont obligatoires : | est un pipe du shell)
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 'deviceTemplate:s:asus|ASUS_AI2401|AI2401_A' broadcast — un modèle importé (custom:)
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e deviceTemplate 'custom:samsung|e3qxeea|SM-S928B' Response ok=true · full updated profile
Renvoie le profil complet mis à jour, comme tout profile.update — les sim.simCards et deviceMock générés figurent directement dans la réponse.
⚠️ Chaque appel tire de nouvelles valeurs : répéter le même simCountries donne de nouveaux numéros, et deviceTemplate random peut tomber sur un appareil différent à chaque fois. N’envoyez que la clé que vous voulez régénérer.
simCountries
- Format. Un tableau JSON de codes ISO 3166-1 alpha-2 —
["US","GB"], insensible à la casse. La position correspond à l’emplacement : le premier code remplit l’emplacement0, le second l’emplacement1. Tout ce qui n’est pas un tableau JSON, un tableau vide, une entrée vide, plus de deux entrées, ou un code quesim.countriesne liste pas renvoieBAD_REQUEST— un troisième code est refusé, jamais ignoré en silence comme l’est une troisième cartesim. - Ce que vous obtenez. Pour chaque emplacement, l’application choisit un opérateur de ce pays dans sa base et remplit chaque champ du bloc
simécrit à la main :carrierName,countryIso,mcc,mnc,operatorCode, unphoneNumbermobile E.164 valide avec l’indicatif du pays (+1…pour les US), uniccidet unimsipréfixés par le MCC+MNC de cet opérateur, et unnetworkTypetiré au hasard parmiLTE,NR 5G,WCDMAetGSM. Elle définit ensuitesim.enabledàtrueet enregistre. - Il remplace tout le bloc SIM. Comme avec
sim, le résultat est normalisé à deux cartes :["US"]remplit l’emplacement0et laisse l’emplacement1vide, quel que soit son contenu précédent.
deviceTemplate
random(ou une chaîne vide) — l’application tire un modèle parmi tous ceux qu’elle connaît, intégrés comme importés. Notez la différence entre vide et absent :-e deviceTemplate ""signifie aléatoire, tandis qu’omettre complètement la clé laisse l’appareil inchangé.- Un id de modèle issu de
device.templates— cet appareil, à chaque fois. Les ids intégrés sont de la formebrand|product|model, par ex.asus|ASUS_AI2401|AI2401_A; les modèles importés dans l’application ont la même forme précédée decustom:, par ex.custom:samsung|e3qxeea|SM-S928B. Un id absent de la liste renvoieBAD_REQUEST. - Ce que vous obtenez. Chaque champ de
deviceMockrempli à partir du modèle,deviceMock.enableddéfini àtrue, et le profil enregistré.
Quel transport
La règle habituelle du deux-points s’applique. sim.countries, device.templates, simCountries et les ids de modèles intégrés ne contiennent pas de :, donc content call les transporte. Entourez la valeur de guillemets simples dès qu’elle contient |, [, ] ou " — c’est le cas de chaque tableau simCountries et de chaque id de modèle. Sans les guillemets, le shell de l’appareil interprète | comme un pipe et échoue avant même que content ne s’exécute (sh: e3qxeea: not found, code de sortie 127). Un id personnalisé commence par custom:, et ce deux-points supplémentaire casse la forme key:type:value de --extra : l’outil content lui-même le rejette avec [ERROR] Binding not well formed et la requête n’atteint jamais l’application — il n’y a aucun BAD_REQUEST à intercepter. Envoyez les ids personnalisés via le broadcast HEADLESS_UPDATE ; rien d’autre ne change dans l’appel.
Configuration
Voici les valeurs que vous envoyez avec profile.update. Valeurs par défaut à la création d’un profil :
| Réglage | Par défaut | Pour l’utiliser… |
|---|---|---|
| hookFlags (all 27) | ✅ ON — sauf hook_spoof_uptime ❌ OFF | Déjà activés. Envoyez false uniquement pour ceux à désactiver — et true pour hook_spoof_uptime, le seul flag désactivé au départ. |
| proxy | ❌ OFF | Incluez "enabled":true |
| geo | PROXY | Envoyez "source":"CUSTOM" avec des coordonnées, countryCode et timezone pour définir une localisation sans proxy |
| deviceMock | ❌ OFF | Incluez "enabled":true — ou envoyez plutôt deviceTemplate et laissez l’application le remplir (1.5.9+) |
| sim | ❌ OFF | Incluez "enabled":true — ou envoyez plutôt simCountries et laissez l’application le remplir (1.5.9+) |
| gmails | empty | Envoyez les adresses (comptes virtuels activés par défaut) |
⚠️ Une configuration avec
enabled:falseest enregistrée mais inactive — les valeurs sont conservées pour que vous puissiez l’activer plus tard, mais rien n’est usurpé tant queenabled:truen’est pas défini.geofait exception : il n’a pas d’interrupteurenabled. Les flagshook_geo_*s’appliquent dès quegeoaboutit à une localisation exploitable — soit viasource: CUSTOM, soit via un proxy enenabled:truequi a réussi son test en direct.
hookFlags
Par défaut : ON pour chaque flag sauf hook_spoof_uptime, qui est OFF. Une table de "flag": true|false. Une mise à jour remplace toute la table, mais uniquement la table que vous envoyez effectivement : une mise à jour qui omet complètement l’extra hookFlags laisse chaque flag exactement tel qu’il était. Dans une table que vous envoyez, chaque flag omis revient à sa propre valeur par défaut : les 26 autres repassent donc à ON tandis que hook_spoof_uptime repasse à OFF, même si vous l’aviez activé. Pour en modifier quelques-uns et conserver les autres, exécutez d’abord profile.get, modifiez la table complète, puis renvoyez-la en entier.
| Flag | Effet |
|---|---|
hook_hide_dev_opts | Masquer les options pour les développeurs |
hook_hide_vpn | Masquer le VPN |
hook_hide_airplane_mode | Masquer le mode avion |
hook_hide_proxy | Masquer le réglage de proxy système |
hook_hide_root | Masquer le root |
hook_hide_lsposed | Masquer LSPosed |
hook_spoof_installer | Usurper la source d’installation |
hook_package_info | Usurper les informations de paquet / signatures |
hook_lan_scan_block | Bloquer l’analyse du réseau local |
hook_identifiers_partly | Usurper les identifiants de base de l’appareil |
hook_identifiers_fully | Usurper l’ensemble complet des identifiants de l’appareil — inclut tout ce que couvre hook_identifiers_partly |
hook_wifi | Usurper les détails du réseau Wi-Fi connecté |
hook_nearby_wifi | Usurper les résultats d’analyse des réseaux Wi-Fi à proximité |
hook_nearby_bluetooth | Usurper les appareils Bluetooth à proximité |
hook_realistic_sensor | Utiliser des données de capteurs réalistes |
hook_sensor_accelerometer | Usurper l’accéléromètre (requiert hook_realistic_sensor) |
hook_sensor_gyroscope | Usurper le gyroscope (requiert hook_realistic_sensor). Requiert l’application 1.6.3+. |
hook_sensor_light | Usurper le capteur de luminosité ambiante (requiert hook_realistic_sensor). Requiert l’application 1.6.4+. Le préréglage d’environnement lumineux (Indoor, On the move, Outdoors, Night / dark) ne peut être choisi que dans l’application ; un profil créé via la Headless API démarre sur Indoor, et une mise à jour headless laisse un choix existant inchangé. À partir de l’application 1.6.9, la mesure suit aussi l’heure locale (nuit, crépuscule, jour ; selon le fuseau horaire du profil lorsque l’usurpation du fuseau horaire est activée) et peut chuter fortement lorsque le capteur de proximité signale un objet proche, par ex. téléphone tenu contre l’oreille. |
hook_sensor_magnetometer | Usurper le magnétomètre (boussole), y compris le capteur non calibré (requiert hook_realistic_sensor). Le champ magnétique est calculé pour les coordonnées usurpées du profil et pivote selon la même orientation de l’appareil que l’accéléromètre et le gyroscope. Sans localisation de profil, un champ plausible propre au profil est utilisé. Appliqué uniquement lorsque hook_sensor_accelerometer est également activé. Requiert l’application 1.6.9+. |
hook_sensor_fused | Usurper les capteurs de fusion : gravité, accélération linéaire, vecteur de rotation, vecteur de rotation de jeu, vecteur de rotation géomagnétique et orientation, tous dérivés du même mouvement simulé (requiert hook_realistic_sensor). La gravité, l’accélération linéaire et le vecteur de rotation de jeu requièrent hook_sensor_accelerometer et hook_sensor_gyroscope activés ; le vecteur de rotation, le vecteur de rotation géomagnétique et l’orientation requièrent en plus hook_sensor_magnetometer. Requiert l’application 1.6.9+. |
hook_sensor_pressure | Usurper le baromètre (requiert hook_realistic_sensor). La pression atmosphérique suit l’altitude de la localisation usurpée du profil (la même altitude que renvoie Location.getAltitude()), plus une lente dérive météorologique. Ne prend effet que si le profil dispose d’une géolocalisation (géolocalisation du proxy ou localisation personnalisée) et que hook_geo_gps est activé. Requiert l’application 1.6.9+. |
hook_sensor_roster | Faire correspondre la liste des capteurs et les métadonnées de chaque capteur (nom, fabricant, plage, résolution, consommation, minDelay) à l’appareil simulé (requiert hook_realistic_sensor). Ne prend effet que lorsque la simulation d’appareil (deviceMock.enabled) est activée. Masque les capteurs que l’appareil simulé n’aurait pas ; n’ajoute jamais de capteurs absents de l’appareil réel. Requiert l’application 1.6.9+. |
hook_spoof_uptime | Usurper la durée de fonctionnement de l’appareil — donne l’impression que l’appareil tourne depuis plus longtemps. Premium, expérimental. Désactivé par défaut — le seul flag dans ce cas. Requiert l’application 1.3.4+. |
hook_virtual_accounts | Activer les comptes Google virtuels (gmails nécessite ce flag sur ON) |
hook_geo_gps | Usurper la position GPS (requiert geo — proxy ou personnalisée) |
hook_geo_locale | Usurper la langue/région (requiert geo — proxy ou personnalisée) |
hook_geo_timezone | Usurper le fuseau horaire (requiert geo — proxy ou personnalisée) |
proxy
Par défaut : OFF. Avec enabled:true, l’application s’y connecte réellement, lit sa localisation et remplit countryCode/lat/lon/timezone. Le test en direct prend jusqu’à ~8 s ; un proxy qui échoue renvoie PROXY_INVALID et n’est pas enregistré. Ces quatre champs sont des sorties — l’application les écrit, donc tout ce que vous y envoyez est écrasé. Pour définir une localisation à la main, utilisez plutôt geo avec source: CUSTOM ; cela ne nécessite aucun proxy. profile.get renvoie le proxy avec ces quatre champs, mais ne renvoie jamais username ni password.
| Champ | Type | Par défaut | Signification / contraintes |
|---|---|---|---|
host | string | "" | IP / nom d’hôte du proxy |
port | int | 0 | Port — 1–65535, vérifié uniquement lorsque vous activez le proxy |
protocol | string | HTTP | HTTP, SOCKS4 ou SOCKS5 |
username | string | "" | Authentification (facultative) — jamais renvoyée par profile.get |
password | string | "" | Authentification (facultative) — jamais renvoyée par profile.get |
countryCode | string | "" | Sortie — pays sur 2 lettres, rempli par le test en direct |
lat | double | 0 | Sortie — rempli par le test en direct |
lon | double | 0 | Sortie — rempli par le test en direct |
timezone | string | "" | Sortie — nom IANA, rempli par le test en direct |
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"}' geo
Par défaut : {"source":"PROXY"}. Requiert l’application 1.4.5+. C’est d’ici que provient la localisation d’un profil, et il existe deux sources — choisissez-en une avec source. PROXY utilise la localisation lue lors du test en direct du proxy. CUSTOM vous permet de définir vous-même les coordonnées, le fuseau horaire et la région, sans proxy — vous pouvez ainsi placer un profil à Tokyo tout en faisant transiter le trafic n’importe où, ou nulle part. Les trois flags hook_geo_* activent ensuite chaque partie indépendamment : GPS, région + langue, et fuseau horaire.
⚠️ Attention aux noms de champs : geo les écrit latitude/longitude, tandis que proxy ci-dessus utilise les formes courtes lat/lon. Ce sont deux objets distincts, pas des alias — les noms courts dans une charge utile geo sont tout simplement ignorés.
| Champ | Type | Par défaut | Signification / contraintes |
|---|---|---|---|
source | string | PROXY | Obligatoire. Exactement PROXY ou CUSTOM — une valeur absente ou mal orthographiée renvoie BAD_REQUEST, elle n’est jamais interprétée silencieusement comme PROXY |
latitude | double | 0 | Obligatoire pour CUSTOM — doit être comprise entre -90 et 90 ; 0/0 compte comme non défini |
longitude | double | 0 | Obligatoire pour CUSTOM — doit être comprise entre -180 et 180 ; 0/0 compte comme non défini |
countryCode | string | "" | Obligatoire pour CUSTOM — 2 lettres, par ex. JP. Insensible à la casse en entrée, toujours renvoyé en majuscules |
timezone | string | "" | Obligatoire pour CUSTOM — nom IANA, par ex. Asia/Tokyo. Seule sa non-vacuité est vérifiée — voir l’avertissement ci-dessous |
language | string | "" | Facultatif — code ISO 639-1 à 2 lettres comme ja, et non une balise complète comme ja-JP. Déduit de countryCode s’il est laissé vide, et toujours stocké en minuscules. Seul CUSTOM peut le définir explicitement ; avec PROXY, il est toujours déduit |
⚠️
source: CUSTOMdoit arriver complet : une paire de coordonnées différente de0/0et dans les limites, uncountryCodeà 2 lettres et untimezone. S’il en manque un seul, l’appel renvoieBAD_REQUEST— il ne se rabat pas sur le proxy. L’application ne fait jamais de géocodage et ne se connecte jamais en ligne pour compléter ces valeurs à votre place. Si aucune source n’est finalement exploitable, aucun hook de géolocalisation n’est chargé et la localisation réelle transparaît.
🛑
timezoneest le seul champ qui n’est pas vraiment vérifié. On vérifie seulement qu’il n’est pas vide — jamais par rapport à la base IANA. Une faute de frappe commeAsia/Tokyooest acceptée, renvoieok=true, est renvoyée telle quelle parprofile.get, puis se résout silencieusement en GMT sur l’appareil. Aucune erreur n’est signalée nulle part, copiez donc le nom exactement. Les coordonnées sont l’inverse — elles sont contrôlées et une valeur hors limites échoue explicitement avecBAD_REQUEST.
CUSTOM — définir une localisation à la main, sans proxy
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e geo '{"source":"CUSTOM","latitude":35.6812,"longitude":139.7671,"countryCode":"JP","timezone":"Asia/Tokyo","language":"ja"}' PROXY — prendre la localisation du proxy (par défaut)
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e geo '{"source":"PROXY"}' deviceMock
Par défaut : OFF. Fait passer l’appareil pour un autre modèle. Définissez "enabled":true ainsi que n’importe lequel de ces champs — tous des chaînes facultatives (vides par défaut), chacune correspondant à une propriété Android Build. À partir de la 1.5.9+, vous pouvez vous passer entièrement de ce bloc et envoyer plutôt deviceTemplate — random tire un appareil de la base de l’application, un id issu de device.templates en choisit un précis — et l’application remplit chaque champ et l’active pour vous.
| Champ | Correspond à | Exemple |
|---|---|---|
manufacturer | Build.MANUFACTURER | Samsung |
brand | Build.BRAND | samsung |
model | Build.MODEL | SM-S918B |
device | Build.DEVICE (nom de code) | 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 | Nom d’appareil affiché | 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"}' Ou, à partir de la 1.5.9+, laissez l’application tirer un appareil aléatoire de sa base — sans aucun JSON (random puise indifféremment dans les modèles intégrés et importés ; mettez à sa place un id issu de device.templates pour choisir un appareil précis) :
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 deviceTemplate:s:random sim
Par défaut : OFF. Usurpe la SIM/l’opérateur. Définissez "enabled":true et fournissez jusqu’à deux cartes dans simCards. La liste est toujours normalisée à exactement deux : une troisième carte est ignorée silencieusement — l’appel renvoie quand même ok=true — et une carte unique est complétée par une seconde carte vide, c’est pourquoi profile.get en renvoie toujours deux. À partir de la 1.5.9+, vous pouvez vous passer entièrement de ce bloc et envoyer plutôt simCountries — l’application génère de vraies données d’opérateur pour chaque emplacement et les active pour vous. Chaque carte :
| Champ | Type | Par défaut | Signification / contraintes |
|---|---|---|---|
slotIndex | int | 0 | Emplacement SIM — attribué selon la position de la carte dans le tableau (0, puis 1) ; la valeur envoyée est ignorée |
carrierName | string | "" | Nom de l’opérateur (par ex. AT&T) |
countryIso | string | "" | Code pays ISO (par ex. us) — stocké en minuscules. Notez que c’est l’inverse de geo.countryCode, stocké en majuscules |
mcc | string | "" | Mobile Country Code (par ex. 310) |
mnc | string | "" | Mobile Network Code (par ex. 410) |
operatorCode | string | "" | Code opérateur = mcc + mnc (par ex. 310410) |
phoneNumber | string | "" | Numéro de téléphone |
iccid | string | "" | Numéro de série de la SIM (ICCID) |
imsi | string | "" | IMSI |
networkType | string | "" | Type de réseau — voir les valeurs acceptées ci-dessous ; une valeur non reconnue est ignorée en silence |
networkType est débarrassé des espaces superflus et comparé sans tenir compte de la casse, et chaque génération accepte plusieurs graphies :
| Valeur | Également accepté | Génération de réseau |
|---|---|---|
NR 5G | NR, 5G | 5G |
LTE | 4G | 4G |
WCDMA | UMTS, 3G | 3G |
GSM | 2G | 2G |
⚠️ Toute valeur hors de ce tableau désactive silencieusement l’usurpation du type de réseau pour cette carte — aucune erreur, aucun
BAD_REQUEST, la valeur est simplement stockée et jamais utilisée. Notez queNR 5Gcontient une espace :NR5Gn’est pas reconnu et tombe précisément dans ce piège silencieux.
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"}]}' Ou, à partir de la 1.5.9+, laissez l’application générer les deux cartes à partir de codes pays — sans aucun JSON (l’emplacement 0 reçoit le premier code, l’emplacement 1 le second ; un seul code ne remplit que l’emplacement 0) :
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 'simCountries:s:["US","GB"]' gmails
Par défaut : vide. Une liste de comptes Google virtuels — seules les adresses @gmail.com sont acceptées. La liste remplace la précédente ; [] la vide. Aucun : à l’intérieur, donc content call fonctionne :
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]"]' Exemple complet
Un profil de zéro jusqu’à l’activation, étape par étape. Les étapes 5, 6 et 7 proposent chacune plusieurs façons d’arriver au même résultat — choisissez-en une par étape ; les onglets permettent de passer de l’une à l’autre. Chaque commande est présentée sous sa forme adb shell. À la fin, les deux recettes condensent toute la séquence en un seul bloc à copier et exécuter, et la section Dépannage propose la même chose sous forme de script à exécuter sur l’appareil.
En un coup d’œil
- 01 Vérifier que l’API est prête
- 02 Créer le profil
- 03 Ajouter les applications cibles
- 04 Ajouter des comptes Gmail virtuels
- 05 Choisir l’identité de l’appareil
- 06 Choisir les cartes SIM
- 07 Réseau et localisation
- 08 Ajuster les hook flags
- 09 Sauvegarder le profil sortant
- 10 Activer
- 11 Vérifier
- 12 Ensuite : cloner, arrêter, supprimer
Espaces réservés utilisés ci-dessous
<your_access_token>— la clé issue de Paramètres → Développeur → Headless API<profile_id>— l’id renvoyé par l’étape 2<active_profile_id>/<job_id>— étape 9 uniquement, issus destatusetbackup.start
Une lecture avant toute chose. Elle vous indique si le Premium, l’interrupteur de la fonctionnalité et la fraîcheur de la licence sont en ordre — les trois conditions dont dépendent tous les autres appels.
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method status --extra token:s:<your_access_token>
# expect "premium":true, "featureEnabled":true, "freshnessOk":true
# anything else: fix that first — see Status and Error codes above Tout le reste dépend de l’id renvoyé ici. Un nouveau profil démarre avec chaque hook flag sur ON (sauf hook_spoof_uptime), aucune application cible, et proxy, deviceMock et sim tous sur OFF.
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.create --extra token:s:<your_access_token> --extra name:s:Demo
# → Bundle[{data={"id":"a1b2c3d4-..."}, ok=true}]
# copy that id — it is <profile_id> in every command below Seules les applications de cette liste sont usurpées. Ajoutez-les une par une par nom de paquet ; toute application non listée continue de voir l’appareil réel.
# one call per app — the package name, not the display name
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
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.instagram.android
# check the list (adding the same package twice returns BAD_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> Les adresses que les applications cibles verront comme des comptes Google connectés. Requiert hook_virtual_accounts, activé par défaut. Sautez cette étape et les applications ne verront aucun compte Google.
# @gmail.com only; the list replaces the previous one, [] clears it
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]"]' Trois façons d’obtenir le même résultat — un bloc deviceMock avec enabled:true. Laissez l’application tirer un appareil, désignez un modèle, ou écrivez chaque champ vous-même.
# 1.5.9+ — one call, no JSON: the app rolls a device from its database
# (built-in and imported templates alike) and switches deviceMock on for you
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 deviceTemplate:s:random # 1.5.9+ — first see what is available; "id" is what you send back
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method device.templates --extra token:s:<your_access_token>
# → [{"id":"asus|ASUS_AI2401|AI2401_A","manufacturer":"asus","label":"ROG Phone 8","isCustom":false}, ...]
# built-in id → content call works — single quotes are REQUIRED, | is a shell pipe
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 'deviceTemplate:s:asus|ASUS_AI2401|AI2401_A'
# imported (custom:) id → broadcast ONLY; the extra colon breaks content call
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e deviceTemplate 'custom:samsung|e3qxeea|SM-S928B' # any version — write every Build field yourself; "enabled":true is the switch
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"}' A et B requièrent l’application 1.5.9+ et ne vont jamais dans le même appel que C. Les exécuter l’un après l’autre ne pose pas de problème — le dernier appel l’emporte, et A / B tirent de nouvelles valeurs à chaque exécution.
Même principe pour sim : générez les cartes à partir de codes pays, ou écrivez vous-même les deux cartes. Dans tous les cas, le profil se retrouve avec exactement deux emplacements.
# 1.5.9+ — see which countries the generator knows ("code" is what you send)
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method sim.countries --extra token:s:<your_access_token>
# → [{"code":"AF","country":"Afghanistan"}, ..., {"code":"GB","country":"United Kingdom"}, ..., {"code":"US","country":"United States"}, ...]
# two cards: slot 0 = US, slot 1 = GB — carrier, number, ICCID, IMSI all generated
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 'simCountries:s:["US","GB"]'
# or a single card — slot 1 is left empty
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 'simCountries:s:["US"]' # any version — two cards, every field yourself; a third card is dropped silently
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"}]}' # 1.5.9+ — device (step 5) and SIM (step 6) in ONE broadcast: validated together, saved together
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e simCountries '["US","GB"]' -e deviceTemplate random A et C requièrent l’application 1.5.9+. sim et simCountries dans un même appel donnent BAD_REQUEST. C est atomique — un id de modèle incorrect fait échouer tout l’appel et la SIM n’est pas appliquée non plus.
La destination du trafic et l’endroit où l’appareil prétend se trouver sont deux réglages distincts. proxy achemine le trafic et fournit aussi, par défaut, la localisation ; geo avec source: CUSTOM définit la localisation à la main et ne nécessite aucun proxy. Sautez cette étape et le profil conserve l’IP réelle et la localisation réelle.
# the proxy is tested live (device needs internet, up to ~8s);
# one that fails returns PROXY_INVALID and is not saved
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"}'
# with auth: add "username":"…","password":"…" — never echoed back by profile.get
# location follows the proxy by default; this line only matters if geo was CUSTOM before
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e geo '{"source":"PROXY"}' # no proxy at all — the location is yours; coordinates, countryCode and timezone are all required
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e geo '{"source":"CUSTOM","latitude":35.6812,"longitude":139.7671,"countryCode":"JP","timezone":"Asia/Tokyo","language":"ja"}'
# timezone is NOT validated: a typo silently becomes GMT — copy the IANA name exactly # traffic through the proxy, GPS / timezone / locale from your own values —
# a deliberate mismatch (IP in one country, GPS in another); geo.source decides what the hooks use
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"}'
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e geo '{"source":"CUSTOM","latitude":35.6812,"longitude":139.7671,"countryCode":"JP","timezone":"Asia/Tokyo","language":"ja"}' Un profil avec proxy nécessite une fois le consentement VPN système, accordé depuis l’écran Headless API de l’application — sans lui, l’activation réussit quand même, mais le proxy ne se connectera pas et l’appel renvoie INTERNAL.
Tous les flags sauf hook_spoof_uptime sont déjà sur ON, la plupart des profils sautent donc cette étape. Ne la faites que pour désactiver certains hooks, ou pour activer l’usurpation de la durée de fonctionnement. Comme une mise à jour remplace toute la table, lisez-la d’abord et renvoyez-la complète.
# every flag is already ON (except hook_spoof_uptime), so most profiles skip this step.
# an update REPLACES the whole map — read it first, then send it back complete:
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.get --extra token:s:<your_access_token> --extra id:s:<profile_id>
# example: Wi-Fi + Bluetooth spoofing off, uptime spoofing on, everything else at its default
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_hide_dev_opts":true,"hook_hide_vpn":true,"hook_hide_airplane_mode":true,"hook_hide_proxy":true,"hook_hide_root":true,"hook_hide_lsposed":true,"hook_spoof_installer":true,"hook_package_info":true,"hook_lan_scan_block":true,"hook_identifiers_partly":true,"hook_identifiers_fully":true,"hook_wifi":false,"hook_nearby_wifi":true,"hook_nearby_bluetooth":false,"hook_realistic_sensor":true,"hook_sensor_accelerometer":true,"hook_sensor_gyroscope":true,"hook_sensor_light":true,"hook_sensor_magnetometer":true,"hook_sensor_fused":true,"hook_sensor_pressure":true,"hook_sensor_roster":true,"hook_spoof_uptime":true,"hook_virtual_accounts":true,"hook_geo_gps":true,"hook_geo_locale":true,"hook_geo_timezone":true}' Le seul filet de sécurité qui existe : activer le nouveau profil efface les données des applications cibles. Si le profil actif en ce moment contient des sessions ou des données à conserver, sauvegardez-le avant de basculer. Les deux appels *.start ne fonctionnent que sur le profil actif.
# activating wipes the target apps' data — if the CURRENTLY active profile has anything worth keeping, save it first
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method status --extra token:s:<your_access_token>
# → "activeProfileId" is the profile to back up
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method backup.start --extra token:s:<your_access_token> --extra id:s:<active_profile_id>
# → {"jobId":"f0e1d2c3-...", "type":"backup", ...} — poll until "state" is DONE (or FAILED):
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method backup.job --extra token:s:<your_access_token> --extra jobId:s:<job_id>
# later, once that profile is active again, pour it back:
# adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method restore.start --extra token:s:<your_access_token> --extra id:s:<active_profile_id> Le moment où l’identité devient effective. Le profil précédemment actif est désactivé pour vous — inutile d’appeler profile.deactivate au préalable.
# force-stops every target app, CLEARS ITS DATA, and brings it back with the new identity.
# no confirmation dialog — this comment is the only warning you get
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.setActive --extra token:s:<your_access_token> --extra id:s:<profile_id>
# → Bundle[{data={"id":"a1b2...","isActive":true}, ok=true}]
# BUSY? a backup / restore job still holds the slot — retry until it stops Relisez le profil et confirmez ce que les hooks vont utiliser : les blocs générés ou écrits à la main avec enabled:true, le proxy avec le résultat de son test en direct, et geo pointant vers la source choisie.
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.get --extra token:s:<your_access_token> --extra id:s:<profile_id>
# → "isActive":true, "deviceMock":{"enabled":true,...}, "sim":{"enabled":true,"simCards":[...]}, "proxy":{...}, "geo":{...}
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method status --extra token:s:<your_access_token>
# → "activeProfileId":"<profile_id>" Le profil est prêt. Voici les appels dont vous aurez besoin ensuite.
# a second identity with the same settings — device re-rolled, SIM numbers regenerated, name generated
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.duplicate --extra token:s:<your_access_token> --extra id:s:<profile_id>
# stop spoofing (no id needed — it deactivates whichever profile is active)
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.deactivate --extra token:s:<your_access_token>
# delete the profile — its backups under /sdcard/HideMyAndroid_Backups/ go with it
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.delete --extra token:s:<your_access_token> --extra id:s:<profile_id> Deux recettes complètes
Les étapes ci-dessus, chacune condensée en un bloc à copier et exécuter. A est le chemin le plus court sur 1.5.9+ ; B se passe complètement du générateur et du proxy et fonctionne sur 1.4.5+. Dans les deux cas, remplacez <profile_id> après la première commande.
Recette A — tout généré
Appareil aléatoire, cartes SIM pour US + GB, trafic et localisation via un proxy. Sept commandes.
# Recipe A — everything generated (app 1.5.9+). The shortest path to a working profile.
# 1. create — 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. 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. virtual Gmail account
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]"]'
# 4. device + SIM in one call — a random device, slot 0 US, slot 1 GB (both enabled and saved)
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e simCountries '["US","GB"]' -e deviceTemplate random
# 5. proxy — tested live (~8s); the location follows it
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"}'
# 6. activate — clears the target app's data
adb shell content call --uri content://com.wowsoftware.hidemyandroid.headless --method profile.setActive --extra token:s:<your_access_token> --extra id:s:<profile_id>
# 7. 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> Recette B — tout à la main
Chaque champ Build, chaque champ SIM et la localisation écrits par vous ; ni proxy, ni générateur.
# Recipe B — everything by hand (app 1.4.5+). No generator, no proxy: you control every value.
# 1. create — 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. 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. 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. device — every Build field yourself
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. SIM — two cards, every field yourself
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. location — custom, no proxy (all four fields required; timezone is not validated)
adb shell am broadcast -a com.wowsoftware.hidemyandroid.HEADLESS_UPDATE -p com.wowsoftware.hidemyandroid -e token <your_access_token> -e id <profile_id> -e geo '{"source":"CUSTOM","latitude":35.6812,"longitude":139.7671,"countryCode":"JP","timezone":"Asia/Tokyo","language":"ja"}'
# 7. activate — clears the target app's data
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> Codes d’erreur
En cas d’échec, vous obtenez ok=false avec l’une de ces valeurs d’error_code (les broadcasts renvoient result=1) :
| Code | Signification | Solution |
|---|---|---|
UNAUTHORIZED | Token manquant ou incorrect | Utilisez votre clé actuelle ; régénérez-la en cas de doute |
FEATURE_DISABLED | La Headless API est désactivée | Activez-la dans Paramètres → Développeur → Headless API |
BAD_REQUEST | Paramètre ou JSON incorrect | Vérifiez les champs obligatoires, la validité du JSON, les adresses gmail uniquement, l’absence d’application en double, des paquets qui appartiennent au profil, un code pays / id de modèle listé par les appels de découverte — et jamais sim avec simCountries ni deviceMock avec deviceTemplate dans un même appel |
NOT_FOUND | Ce profil, cette tâche ou cette sauvegarde n’existe pas | Vérifiez l’id avec profile.list, backup.job ou backup.list |
BUSY | Une tâche de sauvegarde / restauration occupe encore le créneau | error_message indique le jobId en cours — attendez la fin de la tâche, puis réessayez ; après une annulation, le créneau peut rester occupé au-delà de l’état CANCELLED, réessayez donc jusqu’à ce que BUSY cesse. Également renvoyé par profile.setActive / deactivate / delete tant qu’une tâche occupe le créneau |
REQUIRES_ACTIVE_PROFILE | backup.start / restore.start sur un profil qui n’est pas actif | Activez-le d’abord avec profile.setActive — il n’existe aucun flag pour passer outre |
NO_BACKUP | restore.start n’a trouvé aucune sauvegarde pour une application demandée (ou le profil n’en a aucune) | Consultez backup.list ; exécutez d’abord backup.start |
PROXY_INVALID | Le proxy a échoué au test en direct | Vérifiez host/port/protocole/authentification et la connexion internet de l’appareil ; il n’a pas été enregistré |
LICENSE_EXPIRED | Premium expiré | Renouvelez le Premium |
LICENSE_STALE | Licence non vérifiée en ligne récemment | Ouvrez l’application une fois pour la revalider (au moins toutes les 24 h pour une utilisation continue) |
INTERNAL | Erreur interne (E/S ou root) | Réessayez ; vérifiez que root/LSPosed fonctionnent |
Conseils & dépannage
- Un broadcast ne fait rien ? Vérifiez que vous avez inclus
-p com.wowsoftware.hidemyandroid— Android bloque les broadcasts sans ce paramètre. - Une valeur a été tronquée après un
:? Cette valeur contient un deux-points, donccontent calll’a tronquée. Envoyez-la plutôt via le broadcastHEADLESS_UPDATE. - Un broadcast JSON ne s’applique pas (souvent sous Windows) ? Entre un shell de bureau et le shell de l’appareil, les guillemets du JSON de
am broadcast(hookFlags,proxy,deviceMock,sim) sont facilement supprimés, si bien queaminterprète mal la valeur (vous pouvez la voir arriver comme une URI de donnéesdat=…) et rien ne change. La solution fiable consiste à garder le JSON hors de la ligne de commande — placez tout le workflow dans un fichier.sh(les guillemets simples préservent chaque JSON), puis poussez-le et exécutez-le sur l’appareil. Le script s’exécute sur l’appareil, il peut donc même récupérer l’id du nouveau profil et le réutiliser :bashpuis poussez-le sur l’appareil et exécutez-le :# setup.sh — Recipe A from 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. device + SIM generated from the database (1.5.9+): random device, slot 0 US, slot 1 GB am broadcast -a $PKG.HEADLESS_UPDATE -p $PKG -e token $K -e id $ID -e simCountries '["US","GB"]' -e deviceTemplate random # Recipe B alternative (any version) — write both blocks yourself instead: # 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"}' # 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"}]}' # 5. enable + set the proxy (tested live, ~8s) — the location follows it 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"}' # Or skip the proxy and set the location yourself (use INSTEAD of the proxy line, not after it): # am broadcast -a $PKG.HEADLESS_UPDATE -p $PKG -e token $K -e id $ID -e geo '{"source":"CUSTOM","latitude":35.6812,"longitude":139.7671,"countryCode":"JP","timezone":"Asia/Tokyo","language":"ja"}' # 6. activate (restarts the target app and clears its data) content call --uri $URI --method profile.setActive --extra token:s:$K --extra id:s:$ID # 7. verify content call --uri $URI --method profile.get --extra token:s:$K --extra id:s:$IDbashLes commandesadb push setup.sh /data/local/tmp/setup.sh adb shell sh /data/local/tmp/setup.shcontent callsimples (sans JSON) peuvent être saisies directement sans script. Dans Git Bash, préfixez les lignesadbparMSYS_NO_PATHCONV=1pour que le chemin sur l’appareil ne soit pas réécrit. - Les modifications n’apparaissent pas ? L’application cible doit redémarrer — activer un profil s’en charge pour vous, et efface les données de cette application dans la même étape, afin qu’elle redémarre avec la nouvelle identité et sans rien conserver de l’état précédent.
PROXY_INVALIDpour un proxy fiable ? L’appareil a besoin d’internet pour le test, limité à ~8 s ; un proxy lent peut donc dépasser le délai.BUSYpour une tâche déjà annulée ?backup.cancelfait passer la tâche àCANCELLED(et renseignefinishedAt) immédiatement, mais letarqu’elle a lancé ne peut pas être interrompu et continue de tourner, donc le créneau reste occupé.backup.jobafficheCANCELLEDalors que le créneau est encore occupé, et aucun champ n’indique l’état du créneau — ne considérez pasCANCELLEDcomme « créneau libre » ; réessayez simplementprofile.setActive/deactivate/deletejusqu’à ce qu’ils cessent de renvoyerBUSY. (Une tâche qui se termine normalement enDONEouFAILEDlibère le créneau presque aussitôt.)Binding not well formedpour un id de modèle copié directement depuisdevice.templates? Les modèles importés ont des ids qui commencent parcustom:, et ce deux-points casse la formekey:type:valuede--extra— l’outilcontentaffiche[ERROR] Binding not well formedsuivi de son texte d’aide, et la requête n’atteint jamais l’application. Envoyez-le plutôt avec le broadcastHEADLESS_UPDATE(-e deviceTemplate 'custom:…'). Les ids intégrés (brand|product|model) ne contiennent pas de deux-points et fonctionnent avec l’un ou l’autre transport — mais entourez-les de guillemets simples, sinon le shell interprète|comme un pipe (sh: e3qxeea: not found) et rien n’est envoyé.