Retour au Centre de connaissances
Empreinte

Empreinte getClientRects : cohérence DOMRect

Interpréter les contrôles DOMRect de CreepJS sans confondre géométrie vide, texte fragmenté ou rapport absent avec une identité matérielle.

BotBrowser Team

Documentation

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.

L'empreinte getClientRects concerne la géométrie de mise en page, pas les en-têtes Client Hints. Un rectangle peut changer parce que la boîte sélectionnée, le fragment de texte ou le contexte des coordonnées change. BotBrowser documente un bruit déterministe ClientRects, désactivé par défaut, et une graine pour reproduire les métriques des polices ; cela ne garantit pas l'accord de toutes les méthodes géométriques ni l'acceptation par CreepJS. Un rapport DOMRect utile distingue l'objet mesuré, l'API et le prédicat exact avant d'attribuer une cause.

Voir la vidéo

Cette vidéo en anglais suit la même question que l'article : les quatre appels géométriques de CSSOM View renvoient des formes différentes, donc un nombre de fragments, un rectangle englobant et une sélection ne peuvent pas se lire comme une seule valeur. Elle montre les trois états du rapport (absent, liste vide et rectangle de dimension nulle), les trois sorties de la réduction englobante, et deux sessions de console enregistrées sur une fixture contrôlée de même origine : deux expressions natives saisies à la main, le panneau de la fixture imprimant la troisième lecture. Elle ne montre ni collecte par un site ni verdict tiers, et une différence géométrique n'identifie ni appareil, ni personne, ni mécanisme de modification. L'audio est en anglais.

TL;DR

  • Element.getClientRects() renvoie une liste de fragments de boîte ; getBoundingClientRect() la réduit à un rectangle, avec des cas distincts pour une liste vide et des dimensions nulles. Longueur de liste et dimensions répondent à des questions différentes.
  • La géométrie de Range peut décrire des fragments de texte sélectionné, pas nécessairement toute la boîte de bordure d'un élément.
  • La révision CreepJS 10aa6724cd33a1015db1574211890518cd04f0cc conserve quatre tableaux géométriques et applique plusieurs contrôles propres à ses éléments de test, pas un test universel d'identité.
  • Rapport DOMRect absent, liste de fragments vide et rectangle contenant des zéros sont des états distincts.
  • lied représente l'évaluation de cohérence de cette révision. Il ne prouve ni l'auteur d'une modification, ni l'identité d'un appareil, ni la décision d'un site externe.

Contents

Element et Range produisent une liste de fragments ou un rectangle calculé ; rapport absent, liste vide et rectangle dégénéré restent distincts.

Quatre surfaces géométriques

CSSOM View définit Element.getClientRects() à partir des boîtes CSS d'un élément. Un élément en ligne réparti sur plusieurs lignes peut produire plusieurs fragments, plutôt qu'un rectangle continu. La liste conserve leur séparation, y compris les fragments de taille nulle. Sans boîte CSS associée, l'élément produit une liste vide. « La valeur ClientRects » manque donc de précision : il peut s'agir d'une liste, d'un membre choisi, d'une union dérivée ou d'une empreinte condensée de plusieurs éléments de test.

Element.getBoundingClientRect() réduit la géométrie à un rectangle. La spécification distingue une liste vide, une liste dont tous les rectangles ont une largeur ou une hauteur nulle, puis le cas restant d'union. Le premier renvoie un rectangle à zéro ; le deuxième renvoie le premier rectangle. Sinon, l'union inclut les rectangles dont la hauteur ou la largeur n'est pas nulle : la condition utilise OR. Cette dernière branche n'efface pas les exceptions précédentes. Un rectangle placé ailleurs qu'à l'origine, de hauteur nulle, n'équivaut pas à l'absence de fragments.

MDN décrit le rectangle de l'élément comme incluant les espacements internes et la bordure, avec des coordonnées relatives à la zone visible. Comparer ce résultat à width: 100px exige de tenir compte du modèle de boîte, sans supposer que toute largeur renvoyée égale la déclaration CSS. Largeur du contenu et boîte de bordure sont différentes. Un rapport ne gardant qu'une largeur arrondie perd le choix d'API et le modèle de boîte.

Range.getClientRects() concerne une portion sélectionnée du document. La méthode englobante correspondante réduit sa liste en distinguant aussi les cas vide, à dimensions nulles et d'union. Une sous-chaîne sélectionnée n'a pas nécessairement les limites de son élément conteneur : l'une décrit le texte choisi, l'autre peut inclure toute la boîte. L'analyse des mesures de texte traite la surface distincte Canvas measureText() ; les champs TextMetrics ne sont pas des listes de fragments DOMRect.

APIForme renvoyéeComparaison respectant sa signification
Element.getClientRects()DOMRectList de fragments de boîteMême élément et mêmes positions de fragments
Element.getBoundingClientRect()Un DOMRect issu de l'algorithme englobantMême élément et même contexte de zone visible
Range.getClientRects()Liste pour la sélectionConserver les limites de sélection et la disposition
Range.getBoundingClientRect()Un rectangle obtenu par réduction de la listeConserver la sélection et les branches vide et à dimensions nulles

Les interfaces exposent x, y, width, height, top, right, bottom et left. Sérialiser ces champs ne rend pas leurs objets d'origine équivalents. MDN distingue également l'interface de liste en lecture seule d'un tableau JavaScript. Convertir la liste en tableau modifie le conteneur, pas l'opération de disposition ayant produit les entrées. Une empreinte condensée de ce tableau n'explique pas, à elle seule, un fragment différent.

Les comparaisons de la révision CreepJS

Le module DOMRect public copie les huit champs dans des objets simples et renvoie quatre tableaux : elementClientRects, elementBoundingClientRect, rangeClientRects et rangeBoundingClientRect. Pour les deux API de liste, la collecte lit le premier membre, pas tous les rectangles d'une page multiligne quelconque. Ce choix compte : une empreinte condensée du groupe ne prouve pas que tous les fragments de tous les éléments ont été examinés.

Le module comporte une fonction choisissant le rectangle préféré parmi liste de l'élément, rectangle englobant de l'élément, liste de la sélection et rectangle englobant de la sélection, selon les problèmes d'API déjà enregistrés. Cette fonction est distincte de la collecte des quatre tableaux. Affirmer que « CreepJS utilise toujours le rectangle englobant » supprimerait ces branches. Leurs alternatives ne signifient pas non plus que les quatre API doivent produire des rectangles identiques pour toute sélection.

Le contrôle de déplacement relève le top initial, applique une classe de déplacement, relève la position décalée, retire la classe puis mesure à nouveau. Il compare la restauration par rapport à cette mesure décalée. Il n'impose pas qu'un rectangle reste inchangé après une modification de disposition. Un échec de restauration et une position initiale différente sont deux comparaisons ; « la position a changé » ne les distingue pas.

Le contrôle arithmétique examine les relations entre côtés opposés, dimensions et origine des rectangles d'élément. Un autre contrôle compare les côtés gauche et droit de deux éléments précis censés correspondre. Les prédicats sont différents : l'arithmétique interne peut être cohérente alors que les deux éléments diffèrent. L'analyse des groupes CreepJS explique pourquoi une évaluation de groupe doit conserver son périmètre, sans devenir une affirmation sur une personne ou toutes les API.

Contrôle défini par le codeComparaisonCe qu'un échec ne prouve pas seul
Déplacement et restaurationPositions initiale, décalée et restauréeLa cause de l'écart
Arithmétique du rectangleRelations entre côtés, origine et dimensionsLa couche logicielle ayant fourni la valeur
Éléments égauxCôtés choisis de deux éléments précisL'égalité d'éléments arbitraires
Élément tournéAttente du code conditionnée par moteur et DPRUne signature universelle de géométrie
Élément fantômeSi les huit champs relevés sont tous nulsQue tout élément invisible doit avoir une géométrie nulle

La branche de rotation dépend du classement du moteur et, dans une branche, de devicePixelRatio. Les valeurs attendues sont des hypothèses d'implémentation, pas une table normative de conformité. Copier une empreinte condensée connue n'apporte ni le rectangle sous-jacent ni la preuve d'une mesure de la disposition originale. La conclusion justifiée est que cette révision compare un élément de test à une attente limitée, pas qu'un écart prouve un système d'exploitation.

lied peut aussi commencer avec des réserves déjà enregistrées concernant les quatre API géométriques ou String.fromCodePoint, avant les contrôles locaux. Un résultat final vrai n'identifie donc pas le premier prédicat responsable. Le module intercepte les erreurs, enregistre un test échoué et ne renvoie aucun résultat ; l'affichage prévoit séparément un état bloqué quand le rapport manque. Ce cas diffère d'un tableau correctement collecté contenant des zéros. Aucune exécution de CreepJS n'est revendiquée.

Les changements de disposition

Les coordonnées relatives à la zone visible changent quand le contenu se déplace par rapport à elle. MDN mentionne explicitement le défilement pour getBoundingClientRect(). Comparer avant et après un défilement modifie une entrée, même si la largeur CSS ne change pas. Ajouter les décalages peut servir à calculer des coordonnées du document, mais il faut identifier cette valeur dérivée au lieu de la comparer silencieusement à la coordonnée initiale.

Le retour à la ligne modifie les fragments. Un même texte peut avoir un DOMRectList.length différent dans une colonne étroite et dans une colonne large. Le rectangle englobant résume ces fragments et peut inclure de l'espace qu'aucune ligne n'occupe. Comparer uniquement ce rectangle masque parfois une fragmentation différente ; ne lire que le premier fragment ignore les suivants. Aucun de ces cas ne démontre un remplacement de police.

Les transformations CSS affectent la géométrie. Un élément tourné doit être comparé à rotation et origine de référence identiques, pas à ses dimensions CSS sans rotation. Le rectangle englobant n'est pas le tracé du polygone visible. Une branche de détection consacrée à la rotation exige donc son propre contexte. La largeur mesurée n'est pas la longueur d'un côté tourné sans calcul géométrique supplémentaire.

Une sélection Range ajoute une entrée : les nœuds ou positions de texte choisis. Passer d'un élément entier à une sous-chaîne peut changer légitimement la liste du Range tout en laissant la boîte de l'élément intacte. CSSOM View traite aussi différemment le texte et les boîtes sélectionnés. Nommer Range.getClientRects() sans conserver la sélection ne permet pas une comparaison précise de deux captures de « la même page ».

Les polices appartiennent au contexte de disposition, mais une variation de rectangle n'est pas une recherche de nom de police. Disponibilité des polices, remplacement, texte, largeur du conteneur et styles peuvent tous compter. La documentation des mesures de polices décrit les contrôles ClientRects ; elle ne fournit pas un DOMRect de référence pour chaque texte, sélection ou disposition. La graine rend reproductible le bruit documenté, pas toutes les variations de mise en page.

Le contrôle fantôme reste lié à son élément de test. « Invisible pour une personne » recouvre plusieurs états de rendu et ne définit pas un modèle de boîte CSS unique. Un élément hors écran peut participer à la disposition ; un élément sans boîte associée suit un autre chemin. Généraliser ce contrôle à toute invisibilité remplacerait la condition concrète du code par une affirmation plus large non étayée.

Matrice des états DOMRect

La première question est de savoir si une géométrie a été obtenue. Exception du collecteur, liste vide et rectangle de taille nulle exigent des états différents. Remplacer tout échec par un rectangle à zéro efface cette différence et peut donner l'impression qu'un contrôle a examiné des données jamais collectées. Un null choisi par l'application n'est pas non plus un résultat natif DOMRectList.

État observéInterprétation limitéeEntrée suivante à comparer
Aucun rapportRapport absent, cause non établiePhase de collecte et catégorie d'erreur disponible
Liste avec length === 0Aucun fragment renvoyé par cet appelBoîte associée ou contexte de sélection
Largeur ou hauteur nulleGéométrie présente avec une dimension dégénéréeAPI, position et autre dimension
Longueur de liste différenteStructure de fragments différenteTexte, largeur, sélection et instant de disposition identiques
Échec arithmétiqueLes champs ne respectent pas ce prédicatChamps originaux et nom du prédicat
Seule l'empreinte du groupe changeUne entrée sérialisée diffèreTableau, élément et champs avant attribution

Ces cas proviennent des sources, pas d'observations mesurées. Par exemple, une liste hypothétiquement vide suivie d'un rectangle à zéro peut respecter la réduction prévue. Ce n'est pas une preuve de modification détectée. Un rapport affirmant une lecture réussie sans conserver la longueur ne distingue pas non plus ce cas d'une valeur absente ajoutée par son propre sérialiseur.

Un deuxième exemple hypothétique est un texte multiligne produisant davantage de fragments quand le conteneur rétrécit. Le constat utile est une entrée de disposition modifiée et une fragmentation différente. Aucune dimension précise ni identité d'appareil n'est prédite. Dans un troisième cas, l'élément reste fixe mais la sous-chaîne choisie change : le Range varie alors qu'une comparaison de l'élément peut rester stable. Chaque cas conserve la question réellement posée à l'API.

Un quatrième cas est une évaluation CreepJS privée de son motif individuel. lied ne permet pas de choisir entre réserves héritées sur la géométrie ou String.fromCodePoint, échec de restauration, échec arithmétique et attente propre à un élément. Le motif diagnostique nommé est plus informatif qu'une cause supposée attachée au booléen. Cela n'exige ni tous les rectangles d'une page ni l'exportation d'une empreinte réutilisable à un tiers.

Un relevé de comparaison limité

Un relevé minimal peut répondre sans conserver tout le texte de la page ni chaque valeur géométrique. Garder api, un identifiant non sensible de l'élément de test, le type de sélection, la longueur de liste si applicable, l'état de collecte et le prédicat nommé. Ajouter la révision du code pour CreepJS. Un contrôle n'est pas « standard » parce que la méthode de mesure est normalisée : algorithme d'API et attentes du détecteur constituent deux couches distinctes.

ChampEffet sur l'interprétation
apiSépare Element/Range et liste/rectangle
selectionTypeDistingue élément et sous-chaîne
fragmentCountConserve les états vide et fragmenté
coordinateSpaceIdentifie coordonnées de zone visible ou conversion dérivée
layoutContextNomme largeur, défilement et rotations pertinents
collectionStateDistingue collecte réussie, vide et échouée
rule et sourceRevisionRattachent l'évaluation au prédicat et au code réels

Ces noms forment un schéma proposé pour l'assistance, pas les clés de sortie CreepJS, sauf les tableaux explicitement nommés. Il ne faut pas noter fragmentCount: 0 si la collecte a échoué avant l'obtention d'une liste. Remplacer une évaluation absente par une chaîne vide ferait aussi croire à une comparaison exécutée sans résultat défavorable. Minimiser les données et représenter correctement les états servent le même diagnostic.

Le réglage documenté --bot-noise-client-rects=true active le bruit déterministe et reste désactivé par défaut. --bot-noise-seed est documenté pour reproduire les métriques des polices. Cela ne prouve ni une couverture identique d'Element et Range, ni le maintien de toutes les attentes arithmétiques d'un détecteur, ni l'anonymat, ni l'acceptation par un service. Ces résultats demanderaient leurs propres preuves. --bot-noise-text-rects=true est un autre contrôle, pas un substitut implicite au réglage ClientRects.

La séquence utile consiste à identifier API et état, vérifier sélection et entrées de disposition, puis examiner le prédicat nommé. Si ces entrées manquent, seul un écart géométrique inexpliqué subsiste. Lui attribuer système d'exploitation, modèle d'appareil ou mécanisme dépasserait le relevé. Le suivi minimal reproduit l'élément précis, sans élargir la collecte à d'autres signaux d'identité.

Questions fréquentes sur ClientRects

ClientRects désigne-t-il Client Hints ?

Non. getClientRects() est géométrique. Client Hints transmet des informations du navigateur par un autre mécanisme. Un en-tête ne prouve rien sur la disposition d'un élément et un rapport DOMRect n'établit pas les en-têtes envoyés.

Une empreinte condensée différente localise-t-elle le rectangle ?

Non. Elle résume des entrées sérialisées. Sans tableau, élément et champs sous-jacents, elle ne localise pas l'écart. Elle justifie l'examen du groupe, pas une attribution indépendante de l'entrée changée ou de sa cause.

Element et Range doivent-ils toujours correspondre ?

Non. Une boîte et une sélection textuelle peuvent couvrir des contenus différents. Une correspondance propre à un élément de test ne garantit rien pour une sélection arbitraire, un texte multiligne ou des boîtes tournées.

Un rectangle à zéro prouve-t-il un blocage ?

Non. La réduction d'une liste vide peut le produire ; les boîtes dégénérées constituent un autre état. L'affichage d'un rapport absent par CreepJS est séparé. Il faut conserver si l'appel a produit liste, rectangle ou aucun rapport.

L'attente du test de rotation est-elle une norme web ?

Non. Le code fixé utilise une branche conditionnée par moteur et DPR. CSSOM View définit les méthodes, pas les empreintes attendues du détecteur. Une révision ultérieure peut modifier cette branche sans renommer l'API.

Une graine garantit-elle un résultat identique partout ?

Non. La graine documentée concerne le bruit reproductible. Texte, largeur, sélection, transformations ou coordonnées différents changent toujours la question géométrique. Le réglage seul ne prouve ni équivalence entre appareils ni résultat du détecteur.

Sources

Conclusion pratique

Un rapport utile d'empreinte getClientRects identifie une API, un objet choisi et une comparaison précise. Conserver les états vide, dégénéré et échoué ; séparer les prédicats CreepJS de la géométrie normalisée. Si seuls une empreinte condensée ou un booléen restent, la cause n'est pas résolue. Vérifier le contexte d'API ou de l'élément avant de modifier un réglage ou d'attribuer une identité matérielle.

#fingerprinting#polices#confidentialité

Cet article fait partie du guide : Qu'est-ce qu'une empreinte de navigateur ?

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.