Fingerprinting taux de rafraichissement : suivi
Comment le timing de requestAnimationFrame et les taux de rafraîchissement d'affichage créent des signaux d'empreinte, et les techniques pour contrôler le taux d'images au niveau du moteur.
Vous préférez la doc produit maintenue ?
Cet article a une page équivalente dans le centre de documentation. Utilisez les docs pour le flux canonique, les flags à jour et la référence durable.
Introduction
L'API requestAnimationFrame a été conçue pour aider les développeurs à créer des animations fluides en synchronisant les opérations de dessin avec le cycle de rafraîchissement de l'affichage. Au lieu d'utiliser des minuteurs arbitraires comme setTimeout, requestAnimationFrame appelle une fonction avant le prochain redessin de l'écran, typiquement au taux de rafraîchissement natif du moniteur. Cela donne des animations plus fluides, une meilleure efficacité énergétique et une expérience utilisateur plus réactive.
Cependant, la fréquence de rappel de requestAnimationFrame révèle directement le taux de rafraîchissement de l'affichage. Un moniteur standard à 60 Hz déclenche des rappels environ toutes les 16,67 millisecondes, tandis qu'un moniteur gaming à 144 Hz les déclenche toutes les 6,94 millisecondes. Un affichage à 120 Hz, un affichage à 240 Hz et un affichage à taux de rafraîchissement variable (VRR) produisent chacun des intervalles de rappel mesurablementr différents. Cette information est accessible à tout site web sans permission, ce qui en fait un signal de fingerprinting fiable et persistant.
Impact sur la vie privée
Le taux de rafraîchissement de l'affichage est une caractéristique matérielle à laquelle les utilisateurs pensent rarement dans le contexte de la vie privée. Contrairement aux cookies ou aux adresses IP, le taux de rafraîchissement est lié au matériel physique du moniteur et ne change pas entre les sessions de navigateur, les modes de navigation privée ou après l'effacement des données des sites.
Le risque de fingerprinting a augmenté significativement à mesure que la technologie d'affichage s'est diversifiée. Il y a une décennie, presque tous les moniteurs grand public fonctionnaient à 60 Hz, fournissant peu d'informations distinctives. Aujourd'hui, le marché inclut des panneaux à 60 Hz, 75 Hz, 90 Hz, 120 Hz, 144 Hz, 165 Hz, 240 Hz et 360 Hz. Les configurations multi-moniteurs peuvent rapporter des taux différents selon l'écran qu'occupe la fenêtre du navigateur. Les ordinateurs portables avec des fonctionnalités de taux de rafraîchissement dynamique (comme le ProMotion d'Apple à 120 Hz) ajoutent une variation supplémentaire.
Cette diversité signifie que l'information sur le taux d'images porte désormais une entropie significative. Un visiteur avec un moniteur à 165 Hz est significativement plus rare qu'un avec un affichage à 60 Hz, faisant du taux de rafraîchissement un signal précieux pour réduire l'identité. Combiné avec la résolution d'écran, la profondeur de couleur, les informations GPU et d'autres signaux liés à l'affichage, le taux d'images contribue à un profil matériel détaillé.
Le problème est aggravé par le fait que plusieurs API fuient cette information. En plus du timing de requestAnimationFrame, les animations CSS, l'API Screen et même le timing des rappels setTimeout (que le navigateur aligne sur le cycle d'affichage) peuvent tous révéler le taux de rafraîchissement.
Contexte technique
Comment requestAnimationFrame expose le taux de rafraîchissement
Lorsqu'un site web appelle requestAnimationFrame(callback), le navigateur invoque la fonction de rappel avant chaque redessin de l'écran. Le rappel reçoit un paramètre DOMHighResTimeStamp indiquant quand l'image a commencé. En mesurant l'intervalle entre des horodatages consécutifs, un site web peut déterminer le taux de rafraîchissement de l'affichage avec une haute précision.
La mesure est simple : collecter 30 à 60 horodatages d'images, calculer l'intervalle moyen et dériver la fréquence. Avec aussi peu que 10 images, le taux de rafraîchissement peut être déterminé de manière fiable. La mesure prend moins de 200 millisecondes sur un affichage à 60 Hz et est invisible pour l'utilisateur.
Animations et transitions CSS
Les animations CSS s'exécutent au taux de rafraîchissement de l'affichage par défaut. Une animation @keyframes qui dure exactement une seconde produira 60 images intermédiaires sur un affichage à 60 Hz et 144 images sur un affichage à 144 Hz. Bien que la spécification CSS ne garantisse pas une précision image par image, le timing des événements d'animation (animationstart, animationend, timing de transition) fuit tout de même des informations sur le taux de rafraîchissement.
Complexité du taux de rafraîchissement variable
Les affichages modernes avec la technologie de taux de rafraîchissement variable (G-Sync, FreeSync, ProMotion) peuvent changer leur taux de rafraîchissement dynamiquement en fonction du contenu. Cela crée une dimension de fingerprinting supplémentaire : non seulement le taux de rafraîchissement de base mais le schéma de comportement adaptatif devient un signal. Un affichage qui bascule entre 48 Hz et 120 Hz en fonction de l'activité du contenu produit un schéma de timing caractéristique qui est différent d'un affichage à taux fixe.
Configurations multi-moniteurs
Lorsqu'une fenêtre de navigateur s'étend sur plusieurs moniteurs ou se déplace entre des affichages avec des taux de rafraîchissement différents, le timing de requestAnimationFrame change en conséquence. Ce schéma de transition peut révéler des configurations multi-moniteurs, qui sont elles-mêmes un signal de fingerprinting.
Approches de protection courantes et leurs limitations
VPN et serveurs proxy
Les VPN n'ont aucun effet sur le taux de rafraîchissement de l'affichage. Le taux d'images est une propriété matérielle locale mesurée entièrement dans le pipeline de rendu du navigateur. Les outils de confidentialité au niveau du réseau ne peuvent pas le modifier.
Navigation privée et mode incognito
Les modes de navigation privée n'altèrent pas le taux de rafraîchissement de l'affichage ni le comportement de requestAnimationFrame. L'empreinte du taux d'images en mode incognito est identique à l'empreinte dans une fenêtre normale.
Extensions de navigateur
Les extensions qui tentent de modifier le comportement de requestAnimationFrame font face à des défis significatifs :
- Encapsuler le rappel : Une extension peut intercepter
requestAnimationFrameet limiter les rappels à un taux cible (par ex., 60 FPS). Cependant, cela crée un saccage visible dans les animations légitimes et est détectable en comparant le timing derequestAnimationFrameavec le timing des animations CSS, que l'extension ne contrôle peut-être pas. - Modifier les horodatages : Altérer le
DOMHighResTimeStamppassé aux rappels peut simuler un taux de rafraîchissement différent, mais les incohérences avecperformance.now(),Date.now()et le timing des transitions CSS révèlent la modification. - Bloquer l'API : Désactiver
requestAnimationFrameentièrement casse la plupart des applications web modernes qui s'en servent pour le rendu.
Le problème fondamental est que les extensions opèrent au niveau de l'API JavaScript et ne peuvent pas contrôler le pipeline de rendu réel. Le vrai taux de rafraîchissement de l'affichage influence plusieurs sous-systèmes du navigateur simultanément, et modifier une API sans contrôler toutes les autres crée des incohérences détectables.
Limitation au niveau du navigateur
Certains navigateurs offrent la limitation du taux d'images dans les paramètres développeur. Cette approche plafonne le taux de rendu mais ne fournit pas un contrôle précis, ne peut pas être définie par session et introduit souvent des artefacts visuels qui indiquent la limitation.
L'approche au niveau du moteur de BotBrowser
BotBrowser contrôle le taux d'images au niveau du pipeline de rendu du moteur du navigateur via le flag --bot-fps. Ce n'est pas un wrapper JavaScript ni un intercepteur d'API. La boucle de rendu elle-même fonctionne au taux spécifié, assurant que tous les signaux dépendants du taux d'images sont cohérents en interne.
Taux d'images basé sur le profil
En utilisant le mode profile, BotBrowser lit le taux d'images cible depuis le profil d'empreinte chargé :
chrome --bot-profile="/path/to/profile.enc" \
--bot-fps=profile \
--user-data-dir="$(mktemp -d)"
Le profil définit le taux de rafraîchissement attendu de l'affichage en fonction de l'appareil cible. Un profil représentant un ordinateur portable de bureau standard rapporte 60 FPS. Un profil de bureau gaming pourrait rapporter 144 FPS. Le pipeline de rendu fonctionne à ce taux, donc les rappels requestAnimationFrame, les animations CSS et tout autre timing dépendant des images s'alignent avec les caractéristiques d'affichage du profil.
Taux d'images personnalisé
Pour des cas d'utilisation spécifiques, vous pouvez définir un taux d'images exact :
chrome --bot-profile="/path/to/profile.enc" \
--bot-fps=60
Cela force le pipeline de rendu à 60 FPS indépendamment du taux de rafraîchissement réel de l'affichage hôte. Toutes les mesures dépendantes du timing rapporteront environ 16,67 ms par image.
Taux d'affichage réel
Lorsque vous souhaitez que le navigateur utilise le taux de rafraîchissement réel de l'affichage :
chrome --bot-profile="/path/to/profile.enc" \
--bot-fps=real
Cohérence au niveau du moteur
Parce que le contrôle est appliqué au niveau du pipeline de rendu, tous les signaux dépendants du taux d'images sont cohérents :
- Les rappels
requestAnimationFramese déclenchent au taux contrôlé - Les horodatages des images correspondent à l'intervalle attendu
- Les animations CSS avancent au bon rythme
- Le timing de
performance.now()pendant les images d'animation s'aligne avec le taux rapporté - Il n'y a pas de divergences entre le taux d'images mesuré par JavaScript et le comportement de rendu réel
Configuration et utilisation
Utilisation CLI de base
# Utiliser le taux d'images défini par le profil
chrome --bot-profile="/path/to/profile.enc" \
--bot-fps=profile \
--user-data-dir="$(mktemp -d)"
# 60 FPS fixe
chrome --bot-profile="/path/to/profile.enc" \
--bot-fps=60
# Taux d'affichage réel
chrome --bot-profile="/path/to/profile.enc" \
--bot-fps=real
Intégration Playwright
const { chromium } = require('playwright-core');
(async () => {
const browser = await chromium.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
'--bot-fps=60',
],
headless: true,
});
const context = await browser.newContext({ viewport: null });
const page = await context.newPage();
await page.goto('https://example.com');
// requestAnimationFrame se déclenchera à 60 FPS
await browser.close();
})();
Intégration Puppeteer
const puppeteer = require('puppeteer-core');
(async () => {
const browser = await puppeteer.launch({
executablePath: '/path/to/botbrowser/chrome',
args: [
'--bot-profile=/path/to/profile.enc',
'--bot-fps=profile',
],
headless: true,
defaultViewport: null,
});
const page = await browser.newPage();
await page.goto('https://example.com');
await browser.close();
})();
Combinaison avec la protection du timing
Pour un contrôle complet des signaux matériels, combinez le contrôle du taux d'images avec l'échelle de timing :
chrome --bot-profile="/path/to/profile.enc" \
--bot-fps=60 \
--bot-time-scale=1.0 \
--bot-noise-seed=42 \
--user-data-dir="$(mktemp -d)"
Vérification
Après avoir lancé BotBrowser avec un taux d'images configuré, vérifiez le résultat :
const measuredFps = await page.evaluate(() => {
return new Promise(resolve => {
const timestamps = [];
function frame(ts) {
timestamps.push(ts);
if (timestamps.length < 61) {
requestAnimationFrame(frame);
} else {
const intervals = [];
for (let i = 1; i < timestamps.length; i++) {
intervals.push(timestamps[i] - timestamps[i - 1]);
}
const avgInterval = intervals.reduce((a, b) => a + b) / intervals.length;
resolve({
fps: Math.round(1000 / avgInterval),
avgInterval: avgInterval.toFixed(2),
minInterval: Math.min(...intervals).toFixed(2),
maxInterval: Math.max(...intervals).toFixed(2),
});
}
}
requestAnimationFrame(frame);
});
});
console.log('Measured FPS:', measuredFps.fps);
console.log('Average interval:', measuredFps.avgInterval, 'ms');
Ce qu'il faut vérifier :
- Le FPS mesuré correspond à la valeur configurée (par ex., 60 pour
--bot-fps=60) - Les intervalles entre images sont cohérents avec le taux cible
- Les méthodes de mesure multiples (requestAnimationFrame, timing d'animation CSS) produisent le même résultat
- Les outils de test d'empreinte rapportent le taux de rafraîchissement attendu
Bonnes pratiques
-
Faites correspondre le FPS au matériel du profil. Un profil représentant un ordinateur portable de bureau standard devrait utiliser 60 FPS. Un profil de bureau gaming peut utiliser 120 ou 144. Des valeurs mal assorties affaiblissent la cohérence de l'empreinte.
-
Utilisez
--bot-fps=profilepour les workflows automatisés. Cela sélectionne automatiquement le bon taux d'images du profil, réduisant les erreurs de configuration. -
Combinez avec
--bot-time-scale. Le taux d'images et le timing d'exécution devraient s'aligner. Un profil d'appareil lent avec un taux d'images de 60 FPS devrait avoir des caractéristiques de timing qui correspondent au matériel d'entrée de gamme. -
Évitez les valeurs FPS arbitraires. Choisissez des valeurs qui correspondent au vrai matériel d'affichage : 24, 30, 48, 60, 75, 90, 120, 144, 165, 240. Des valeurs comme 73 ou 137 ne correspondent à aucun vrai moniteur et se remarqueraient.
-
Testez en mode headless. Les navigateurs headless n'ont pas d'affichage physique, donc le taux d'images est entièrement déterminé par la configuration de BotBrowser. Vérifiez que le FPS configuré est correctement rapporté en mode headless.
Questions fréquemment posées
Le fingerprinting du taux d'images fonctionne-t-il sur les appareils mobiles ?
Oui. Les appareils mobiles ont des taux de rafraîchissement variables (60 Hz, 90 Hz, 120 Hz), et de nombreux téléphones modernes supportent le basculement dynamique du taux de rafraîchissement. Le timing de requestAnimationFrame révèle le taux de rafraîchissement actuel sur les navigateurs mobiles comme sur les ordinateurs de bureau.
Les sites web peuvent-ils détecter que le FPS est contrôlé ?
Si le contrôle est appliqué au niveau JavaScript (en encapsulant requestAnimationFrame), oui, car les animations CSS et d'autres sources de timing peuvent rapporter un taux différent. BotBrowser contrôle le FPS au niveau du pipeline de rendu, donc toutes les sources de timing sont cohérentes.
--bot-fps affecte-t-il la lecture vidéo ?
La lecture vidéo utilise un pipeline de décodage séparé et n'est pas affectée par le flag --bot-fps. Les vidéos sont lues à leur taux d'images encodé. Seule la boucle de rendu et le timing d'animation sont contrôlés.
Que se passe-t-il avec le contenu à taux de rafraîchissement variable ?
BotBrowser applique un taux d'images fixe basé sur la configuration. C'est cohérent avec la façon dont la plupart des vrais navigateurs se comportent lorsqu'un moniteur à taux fixe est utilisé, ce qui reste la majorité des affichages.
Puis-je utiliser des valeurs FPS différentes pour différents onglets ?
Le flag --bot-fps s'applique à l'ensemble de l'instance du navigateur. Pour des taux d'images différents, lancez des instances de navigateur séparées avec des configurations différentes.
Comment le taux d'images interagit-il avec l'API visibility ?
Les navigateurs limitent typiquement requestAnimationFrame pour les onglets en arrière-plan. BotBrowser respecte ce comportement sauf si --bot-always-active est utilisé, ce qui maintient tous les onglets fonctionnant au taux d'images configuré indépendamment de l'état de visibilité.
La propriété Screen.refreshRate correspond-elle ?
Sur les navigateurs qui exposent screen.refreshRate ou des propriétés similaires, BotBrowser s'assure que ces valeurs sont cohérentes avec le taux d'images configuré par --bot-fps et le profil chargé.
Résumé
Le taux de rafraîchissement de l'affichage, mesurable via le timing de requestAnimationFrame, les animations CSS et les API associées, est un signal de fingerprinting matériel persistant que les outils de confidentialité standard ne peuvent pas traiter. BotBrowser contrôle le taux d'images au niveau du pipeline de rendu du moteur du navigateur via le flag --bot-fps, assurant que tous les signaux dépendants des images sont cohérents en interne. Combiné avec la protection du timing de performance, le contrôle Canvas et la gestion complète des profils, BotBrowser fournit une protection complète des signaux matériels pour les workflows axés sur la confidentialité.
Articles Connexes
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.