Détection Android WebView avec CreepJS : limites
Distinguez les signaux WebView entre HTTP, JavaScript, workers et ponts applicatifs ; voyez ce que le code CreepJS vérifie sans le surinterpréter.
BotBrowser Team
Vous voulez la documentation structurée pour Empreinte ?
Cet article fait partie de la bibliothèque éditoriale. Pour les étapes de configuration, la référence et les mises à jour continues, passez directement à la section docs.
BotBrowser prend en charge les identités Android WebView déclarées pour des contrôles de compatibilité autorisés ; il ne peut pas décider comment un service anti-bot privé classe un navigateur intégré. La configuration WebView utilise un modèle explicite --user-agent contenant wv ; elle ne choisit pas de valeur X-Requested-With propre à une application. La question utile est plus précise : quelle couche a fourni chaque valeur, et quelles comparaisons la page peut-elle réellement effectuer ?
TL;DR
; wvdans un User-Agent indique une forme de WebView, pas une application particulière.X-Requested-Withetwindow.androiddépendent de l’application hôte ; aucun n’est universel.- Le module navigator de CreepJS compare certaines valeurs de la page à celles du worker et interroge User-Agent Client Hints.
- Une divergence établit que deux observations diffèrent ; elle n’en identifie pas la cause et ne prouve pas une automatisation.
Sommaire
- Regarder la vidéo
- L’application hôte n’est pas la surface du navigateur
- Origine de chaque signal
- Vérifications du code CreepJS épinglé
- Distinguer preuve WebView et autres conclusions
- Comparer des applications que vous possédez
- Conclusion pratique
Regarder la vidéo
Cette vidéo en anglais distingue les en-têtes de requête, le JavaScript de la page, les valeurs du worker et les ponts applicatifs facultatifs, puis montre ce qu’une exécution contrôlée du navigateur peut établir ou non. Elle n’authentifie pas une application hôte et ne reproduit pas un appareil Android WebView.
L’application hôte n’est pas la surface du navigateur
Android WebView est un composant de navigateur hébergé dans une application Android. Une page observe des propriétés du navigateur et des requêtes, tandis que l’application hôte peut choisir un User-Agent, ajouter des en-têtes ou exposer un pont JavaScript. Ce sont des choix distincts, de portée distincte, à relever séparément.
La documentation Android WebView de BotBrowser décrit comment ses réglages d’identité déclarée présentent une forme de User-Agent avec wv et des en-têtes applicatifs facultatifs. La question de détection est plus précise : que peut-on déduire de chaque surface, et que reste-t-il inconnu ? Pour la configuration et l’alignement d’identité, consultez le guide Android WebView ; pour les groupes de lectures indépendantes de CreepJS, consultez les groupes de signaux et limites d’observation de CreepJS.
Origine de chaque signal
| Signal | Couche observable | Ce qu’il peut étayer | Ce qu’il ne démontre pas seul |
|---|---|---|---|
User-Agent contenant ; wv | Requête HTTP et navigator.userAgent | Un UA de forme WebView a été présenté | L’application hôte ou l’actualité de la valeur |
Sec-CH-UA et navigator.userAgentData | En-têtes et JavaScript, si disponibles | Marque et plateforme exposées dans ce contexte | Que toutes les WebView Android exposent les mêmes indications |
navigator.platform | JavaScript de la page | Une observation de famille de plateforme | Modèle de l’appareil ou application hôte |
Valeurs WorkerNavigator | JavaScript du worker | L’accord de certaines valeurs entre page et worker | L’accord de l’une d’elles avec le matériel physique |
X-Requested-With | Requête HTTP, si l’application l’envoie | L’application a pu ajouter un en-tête évoquant un paquet | Un marqueur universel WebView ou une identité fiable |
window.android ou un autre pont | JavaScript, seulement s’il est injecté | L’hôte a exposé une interface nommée | Que toutes les applications le fassent ou que ses méthodes soient sûres |
Android expose l’User-Agent via WebSettings, et l’hôte peut le configurer. Android décrit également addJavascriptInterface comme une opération explicite de l’application ; celle-ci choisit le nom du pont. L’absence d’un pont ne permet donc pas d’écarter WebView, et son nom ne doit pas servir d’identifiant de paquet authentifié.
Les en-têtes et JavaScript doivent rester dans des lignes distinctes d’un relevé. Le serveur voit l’en-tête avant l’exécution du code ; le code voit les propriétés de son propre contexte. Une redirection, un service worker, un wrapper applicatif ou une version différente peut affecter une couche sans toucher aux autres.
Les familles de plateforme restent larges
L’helper CreepJS getReportedPlatform() ramène plusieurs désignations système à des familles générales. Dans son chemin User-Agent, android, linux et cros utilisent la même classification Linux. Le chemin navigator.platform regroupe aussi android, arm et linux dans cette famille. Cela sert au contrôle de cohérence, mais efface des distinctions : une famille Android cohérente n’identifie pas WebView et ne nomme pas l’application hôte.
Le module navigator effectue aussi un contrôle distinct par sous-chaîne qui reconnaît android parmi plusieurs libellés de plateforme. Il vérifie que la chaîne paraît connue dans cette révision, pas quelle application l’a produite. Conservez dans des colonnes séparées le champ brut, la famille normalisée et le résultat du contrôle. Un relevé qui ne garde que Android = true ne dit plus si la valeur venait de l’UA, de navigator.platform ou d’un en-tête de requête.
Cette séparation est utile pour comparer WebView, Chrome Custom Tabs et Chrome complet. Les trois peuvent fonctionner sur Android avec des combinaisons différentes d’identité du navigateur et de comportement applicatif. Le même classement général ne prouve pas que leurs marques, leurs en-têtes ou leurs ponts JavaScript sont identiques.
Les contrôles navigator ont des déclencheurs distincts
Le module épinglé ne traite pas toute valeur inhabituelle comme le même constat. Lorsque l’objet global chrome existe, il vérifie si navigator.userAgent contient navigator.appVersion. Il recherche aussi les espaces en début, en fin ou répétés et applique un contrôle de texte gibberish défini par le projet. Ce sont des observations sur la qualité de l’User-Agent. Le code compare ensuite userAgent à la valeur du worker et marque séparément cette différence de contexte.
Pour deviceMemory, la source accepte 0.25, 0.5, 1, 2, 4, 8, 16 et 32. Si performance.memory.jsHeapSizeLimit existe, elle convertit la limite en gigaoctets et vérifie si elle dépasse la mémoire déclarée. La valeur est aussi comparée à celle du worker. hardwareConcurrency a son propre contrôle d’égalité page/worker. Il s’agit de conditions séparées, pas d’un score Android unique.
Le chemin de langue compare les deux premiers caractères de navigator.language à ceux du premier élément de navigator.languages. Lorsque les deux champs de page ont une valeur vraie, le code renvoie le résultat de langue formaté après cette comparaison, que les préfixes correspondent ou non. Les comparaisons de langue avec le worker ont lieu uniquement hors de cette branche. La vérification des plugins est différente : le code associe navigator.plugins à navigator.mimeTypes et vérifie la cohérence de cette paire. Un relevé de compatibilité utile nomme la propriété et le déclencheur exacts au lieu de fusionner des contrôles sans rapport dans une étiquette WebView.
Client Hints dépend de sa disponibilité
Le module navigator CreepJS ne renvoie aucun résultat User-Agent Client Hints si navigator.userAgentData ou getHighEntropyValues() manque. Lorsque les deux existent, il demande platform, platformVersion, architecture, bitness, model et uaFullVersion, puis combine ces champs avec brands et mobile à faible entropie.
Avant l’affichage, le code écarte les marques dont le nom contient Not et retire Chromium de la liste présentée lorsqu’il y a plusieurs marques. Cette transformation appartient au format de sortie de la bibliothèque. Elle ne prouve ni que Chromium était absent du navigateur ni que chaque plateforme fournit les mêmes champs à haute entropie.
Distinguez trois résultats : API absente, valeur demandée omise ou valeur renvoyée. Les sources citées établissent le caractère conditionnel de Client Hints, sans attribuer de cause à une valeur omise. Notez l’état observé avant toute comparaison, afin de ne pas présenter une indication absente comme une indication incohérente.
Vérifications du code CreepJS épinglé
La révision publique de CreepJS citée ici est épinglée au commit 10aa6724cd33a1015db1574211890518cd04f0cc. Son module navigator reconnaît Android parmi plusieurs sous-chaînes possibles de navigator.platform. Il compare aussi la famille de système déduite de l’User-Agent à celle de la plateforme déclarée. C’est un contrôle de cohérence, pas une règle de classification WebView.
Le même module compare certaines valeurs de navigator dans la page à celles recueillies dans un worker. Le code compare platform, userAgent, deviceMemory, hardwareConcurrency, language et languages ; les comparaisons de langue avec le worker sont hors de la branche où les deux champs de langue de page ont une valeur vraie. Si l’API est disponible, son chemin User-Agent Client Hints demande notamment platform, platformVersion, architecture, bitness, model et uaFullVersion. Ce sont des détails du module navigator épinglé, pas la promesse que toute WebView Android fournisse chaque champ.
Le module headless distinct rapporte des groupes de conditions visibles du navigateur. Ses groupes ne doivent pas être réduits à un verdict Android WebView. L’analyse headless de CreepJS explique pourquoi ces groupes répondent à des questions différentes.
Le code autorise une affirmation limitée : les modules CreepJS inspectés peuvent comparer certaines surfaces et rapporter des conditions liées à headless. Ces contrôles n’authentifient pas le paquet Android qui a créé la WebView et ne révèlent pas la règle de décision d’un tiers.
Distinguer preuve WebView et autres conclusions
Utilisez quatre libellés dans un rapport de compatibilité plutôt qu’un verdict binaire :
| Libellé du rapport | Preuve minimale | Interprétation prudente |
|---|---|---|
| Contexte de famille Android | Observations cohérentes de plateforme Android et d’UA | Le contexte visible déclare une famille Android |
| Contexte de type WebView | UA ou marque de type WebView, avec requête et page relevées séparément | Le contexte présente une ou plusieurs propriétés associées à WebView |
| Différence entre contextes | Une comparaison identifiée page/worker ou en-tête/JavaScript diverge | Ces observations ne coïncident pas pendant cette exécution |
| Conclusion d’automatisation | Preuve indépendante et règle de décision documentée | Un signal côté page ne suffit pas |
Cette distinction compte lors de l’examen de l’alignement des marques du navigateur. Marque, plateforme et comportement de l’application intégrée sont liés, mais ne sont pas interchangeables. Un navigator.platform modifié n’explique pas un en-tête différent, sauf si le même relevé relie les deux observations et conserve leur provenance.
Un écart établit seulement une différence
Dans cette source, un écart page/worker établit que les valeurs comparées diffèrent dans les contextes observés. Il ne détermine pas si la valeur de page, celle du worker ou les deux sont attendues pour une version donnée. Il n’en identifie pas non plus la cause. Le code décrit sa comparaison, mais n’authentifie pas l’application, le système, le fournisseur du navigateur ni la politique d’un tiers.
Gardez quatre énoncés distincts : la valeur et sa couche ; la présence et la lisibilité du champ ; la comparaison exacte qui diverge, par exemple navigator.platform et platform côté worker ; puis la conséquence limitée au test de compatibilité que vous possédez. Seule une règle de décision indépendante et documentée permet une conclusion plus large sur l’automatisation.
N’étendez pas silencieusement un constat portant sur un champ au reste de la session. Un en-tête X-Requested-With différent ne renseigne pas à lui seul sur navigator.userAgentData, et un écart de worker ne décrit pas un pont applicatif. Cette séparation préserve l’utilité du diagnostic sans transformer une mesure limitée en affirmation d’identité.
Les résultats de polices forment aussi une surface distincte : l’analyse des tables de polices de CreepJS montre pourquoi un groupe de polices détecté n’identifie pas l’application qui héberge une WebView.
La conséquence en matière de confidentialité est concrète. window.android peut exposer des méthodes applicatives et Android avertit que les ponts JavaScript élargissent la frontière de sécurité. Un examen doit noter la présence d’un pont sans appeler des méthodes étrangères au test ni collecter des données applicatives inutiles.
Comparer des applications que vous possédez
Pour une application que vous possédez, comparez trois contextes sous la même version Android et la même version de l’application : sa WebView, une Chrome Custom Tab si le produit l’utilise, et Chrome complet. Gardez la même origine et la même action. Le tableau est un plan de capture, pas le compte rendu d’une exécution :
| Point de capture | À relever | À garder séparé |
|---|---|---|
| Requête | User-Agent, en-têtes Client Hints et X-Requested-With s’il existe | Navigation initiale et requêtes ultérieures |
| Page | navigator.userAgent, navigator.platform, champs disponibles de userAgentData | Absent, refusé et vide sont des états distincts |
| Worker | Champs correspondants de WorkerNavigator | Moment de création et origine du worker |
| Application hôte | Présence volontaire d’un pont et nom documenté | Ne pas appeler ses méthodes pour reconnaître le conteneur |
Versionnez ensemble Android, le fournisseur WebView, la version de l’application et la page de test. Comparer des fournisseurs différents peut faire passer une mise à jour légitime pour une incohérence. Pour chaque cellule différente, notez sa couche et si le champ était absent, indisponible ou différent ; ne transformez pas ces états en score unique.
Préserver le contexte et limiter la collecte
Utilisez la même action sur une page que vous possédez, la même origine et un moment de navigation comparable. Notez Android, le fournisseur WebView, l’application, le navigateur, la langue, l’état des autorisations et le type de contexte : WebView, onglet Chrome intégré ou Chrome complet. Ces éléments décrivent la comparaison ; ils ne constituent pas un verdict. Si une mise à jour change une valeur, conservez les deux versions au lieu de qualifier la nouvelle valeur de mensonge.
L’en-tête X-Requested-With, qui peut ressembler à un nom de paquet, ne doit être conservé que si la question de compatibilité le nécessite et si l’accès est autorisé. Un indicateur de présence ou une valeur masquée suffit souvent dans un rapport partagé. Un pont JavaScript peut exposer des méthodes ; notez son enregistrement volontaire et son nom documenté sans appeler des méthodes étrangères au test ni sérialiser des données applicatives. L’avertissement Android sur addJavascriptInterface en fait aussi une limite de sécurité.
Reliez chaque comparaison à sa source : capture de requête pour les en-têtes, capture de page pour navigator, capture du worker pour ses valeurs. Un relevé réduit peut conserver le nom du champ, son état, les versions et la paire comparée sans stocker le contenu utilisateur. Cela suffit à examiner une compatibilité autorisée tout en limitant la collecte accidentelle d’identifiants de paquet et de données applicatives.
Comparer des moments de requête équivalents
Capturez séparément la navigation principale et les requêtes ultérieures de sous-ressources. Une application peut n’ajouter un en-tête qu’à certaines requêtes ; celui d’une image ne doit donc pas être comparé au JavaScript du document final comme s’il s’agissait d’une observation unique. Reliez chaque requête à sa navigation, son origine, la version de l’application, celle du navigateur et l’état des autorisations. En cas de redirection, consignez chaque étape au lieu de traiter la première et la dernière URL comme une seule transaction. La comparaison décrit ce contexte et cet instant, pas tous les appareils partageant la même version majeure d’Android.
Questions fréquentes
; wv prouve-t-il que la requête vient d’Android WebView ?
Non. C’est une chaîne reconnaissable de l’User-Agent que l’application peut configurer. Elle renseigne sur la valeur présentée, sans prouver le paquet hôte ni l’origine de la requête.
CreepJS identifie-t-il l’application Android qui héberge la page ?
Les vérifications navigator citées comparent des valeurs visibles et celles du worker. Elles n’authentifient pas le paquet hôte. Un pont ou un en-tête injecté dépend de l’application ; ce n’est pas un signal universel d’identité CreepJS.
Une divergence page/worker signifie-t-elle que le navigateur est automatisé ?
Non. Cela signifie que les valeurs relevées diffèrent. Une mise à jour du navigateur, la disponibilité d’une API, le moment du contexte ou la configuration applicative peuvent aussi l’expliquer. Conservez les champs et l’environnement exacts avant d’élargir la conclusion.
Sources
- Module navigator de CreepJS à une révision épinglée
- Module headless de CreepJS à une révision épinglée
- Android
WebSettings.getUserAgentString - Interfaces JavaScript d’Android WebView
- MDN :
Navigator.userAgentData - Documentation Android WebView de BotBrowser
Conclusion pratique
Traitez l’identification de WebView comme une question de provenance, pas comme le test d’un jeton. Relevez séparément les en-têtes, les propriétés de page, les comparaisons du worker et les ponts facultatifs. Pour le QA d’applications que vous possédez, comparez des contextes équivalents et conservez les valeurs absentes ; une divergence est un constat de compatibilité utile, mais ne prouve ni l’identité de l’appareil ni une décision anti-automatisation d’un tiers.
Cet article fait partie du guide : Qu'est-ce qu'une empreinte de navigateur ?
Articles Connexes
Lire les signaux d’empreinte du navigateur
EmpreinteTables CreepJS : 51 noms et 14 retours possibles
EmpreinteClient Hints Fingerprinting : en-têtes HTTP et identité
EmpreinteSignaux Math de CreepJS : lire les champs
EmpreinteRapport WebGL de CreepJS : contextes et signaux
Empreinteua-parser-js : Client Hints, bots et un plafond de 500
Faites passer BotBrowser de la recherche à la production
Utilisez ces guides pour comprendre le modèle, puis passez à la validation multi-plateforme, aux contextes isolés et au déploiement navigateur prêt pour l'échelle.