Les sites modernes ont appris à reconnaître les navigateurs automatisés (Selenium, Puppeteer, Playwright) et bloquent leurs requêtes. Les navigateurs sans tête laissent des dizaines de traces numériques, que les systèmes anti-bot utilisent pour détecter l'automatisation en quelques millisecondes. Dans ce guide, nous examinerons toutes les méthodes de camouflage des navigateurs sans tête avec des exemples de code en Python et JavaScript, afin que vos scrapers fonctionnent de manière stable sans blocages.
Cet article est destiné aux développeurs qui s'occupent de web scraping, d'automatisation des tests ou de collecte de données à partir de sites protégés. Nous examinerons les détails techniques de la détection et des solutions pratiques pour contourner la protection.
Comment les sites détectent les navigateurs sans tête : méthodes principales
Les systèmes anti-bot utilisent une vérification multi-niveaux du navigateur, en analysant des centaines de paramètres. Les navigateurs sans tête se distinguent des navigateurs normaux par de nombreux signes qui ne peuvent pas être cachés simplement en remplaçant le User-Agent. Comprendre les méthodes de détection est la première étape vers un camouflage efficace.
Marqueurs JavaScript d'automatisation
La méthode la plus courante consiste à vérifier les propriétés JavaScript qui n'apparaissent que dans les navigateurs automatisés :
navigator.webdriver— retournetruedans Selenium et Puppeteerwindow.chrome— absent dans Chrome sans têtenavigator.plugins.length— égal à 0 en mode sans têtenavigator.languages— souvent un tableau vide ou ne contient que "en-US"navigator.permissions— l'API fonctionne différemment en mode sans tête
Analyse du Chrome DevTools Protocol
Puppeteer et Playwright contrôlent le navigateur via le Chrome DevTools Protocol (CDP). La présence d'une connexion CDP peut être détectée par des vérifications JavaScript spéciales qui analysent les objets window.cdc_ ou vérifient les anomalies dans le comportement des événements de souris et de clavier.
Canvas et WebGL Fingerprinting
Les navigateurs sans tête génèrent des empreintes Canvas et WebGL identiques, car ils utilisent le rendu logiciel au lieu du rendu matériel. Les systèmes anti-bot créent un élément Canvas invisible, dessinent du texte ou des formes dessus et calculent le hachage de l'image. Si des milliers d'utilisateurs ont un hachage identique, c'est un signe de bots.
Analyse comportementale
Les systèmes modernes (DataDome, PerimeterX, Cloudflare Bot Management) analysent les mouvements de la souris, la vitesse de défilement, les modèles de clics. Les navigateurs sans tête effectuent des actions instantanément et sans délais naturels, ce qui révèle l'automatisation. Les événements sont également analysés : dans un navigateur normal, un événement mousemove se produit toujours avant un clic, tandis que les bots cliquent souvent sans mouvement préalable de la souris.
Important : Les systèmes anti-bot modernes utilisent l'apprentissage automatique pour analyser des centaines de paramètres simultanément. Camoufler un seul paramètre (par exemple, User-Agent) ne protégera pas contre le blocage — une approche globale est nécessaire.
Suppression de navigator.webdriver et d'autres marqueurs JavaScript
La propriété navigator.webdriver est le moyen le plus simple de détecter Selenium et d'autres outils WebDriver. Dans un navigateur normal, cette propriété retourne undefined, tandis que dans un navigateur automatisé, elle retourne true. Il est possible de la supprimer en exécutant du code JavaScript avant le chargement de la page.
Selenium (Python) : suppression de webdriver via CDP
Pour Selenium, il faut utiliser le Chrome DevTools Protocol pour exécuter du JavaScript avant le chargement de n'importe quelle page :
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument('--disable-blink-features=AutomationControlled')
driver = webdriver.Chrome(options=options)
# Suppression de navigator.webdriver via CDP
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': '''
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
'''
})
driver.get('https://example.com')
L'option --disable-blink-features=AutomationControlled désactive le drapeau que Chrome ajoute en mode automatisation. C'est une protection de base qui doit être combinée avec d'autres méthodes.
Puppeteer (Node.js) : camouflage via Page.evaluateOnNewDocument
Dans Puppeteer, la méthode page.evaluateOnNewDocument() est utilisée pour exécuter du code avant le chargement de la page :
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: true,
args: ['--disable-blink-features=AutomationControlled']
});
const page = await browser.newPage();
// Suppression de webdriver et d'autres marqueurs
await page.evaluateOnNewDocument(() => {
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
// Ajout de l'objet chrome
window.chrome = {
runtime: {}
};
// Émulation des plugins
Object.defineProperty(navigator, 'plugins', {
get: () => [1, 2, 3, 4, 5]
});
});
await page.goto('https://example.com');
})();
Playwright : options de camouflage intégrées
Playwright dispose d'un camouflage plus avancé par défaut, mais une configuration supplémentaire est tout de même nécessaire :
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({
headless: true,
args: ['--disable-blink-features=AutomationControlled']
});
const context = await browser.newContext({
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
});
const page = await context.newPage();
await page.addInitScript(() => {
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
});
await page.goto('https://example.com');
})();
Camouflage du Chrome DevTools Protocol
Puppeteer et Playwright laissent des traces de connexion CDP qui peuvent être détectées en analysant les objets window. Les systèmes anti-bot recherchent des variables avec le préfixe cdc_, $cdc_ ou __webdriver_, qui sont créées par Chrome lors de la connexion via le DevTools Protocol.
Suppression des variables CDP
Le script suivant supprime toutes les variables liées à l'automatisation de l'objet window :
await page.evaluateOnNewDocument(() => {
// Suppression de toutes les variables avec le préfixe cdc_
const cdcProps = Object.keys(window).filter(prop =>
prop.includes('cdc_') ||
prop.includes('$cdc_') ||
prop.includes('__webdriver_')
);
cdcProps.forEach(prop => {
delete window[prop];
});
// Redéfinition de document.__proto__ pour cacher CDP
const originalQuery = document.querySelector;
document.querySelector = function(selector) {
if (selector.includes('cdc_')) return null;
return originalQuery.call(this, selector);
};
});
Utilisation de versions patchées de Chromium
Il existe des versions modifiées de Chromium qui ne laissent pas de traces CDP. Par exemple, la bibliothèque puppeteer-extra avec le plugin puppeteer-extra-plugin-stealth applique automatiquement des dizaines de patchs pour camoufler CDP.
Configuration de User-Agent et des en-têtes HTTP
Les navigateurs sans tête utilisent des chaînes User-Agent obsolètes ou irréalistes. Par exemple, Puppeteer ajoute par défaut le mot "HeadlessChrome" au User-Agent. De plus, il est nécessaire de configurer des en-têtes supplémentaires qui sont présents dans les requêtes des navigateurs normaux.
User-Agent actuels pour le camouflage
Utilisez des User-Agent récents de navigateurs réels. Voici des exemples pour 2024 :
# Chrome 120 sur Windows 10
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
# Chrome 120 sur macOS
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
# Firefox 121 sur Windows
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0
Configuration des en-têtes dans Selenium
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument('user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36')
# En-têtes supplémentaires via CDP
driver.execute_cdp_cmd('Network.setUserAgentOverride', {
"userAgent": 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
"platform": 'Win32',
"acceptLanguage": 'en-US,en;q=0.9'
})
Configuration des en-têtes dans Puppeteer
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
await page.setExtraHTTPHeaders({
'Accept-Language': 'en-US,en;q=0.9',
'Accept-Encoding': 'gzip, deflate, br',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Sec-Fetch-Site': 'none',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-User': '?1',
'Sec-Fetch-Dest': 'document'
});
Les en-têtes Sec-Fetch-* sont critiques — ils sont apparus dans Chrome 76+ et leur absence révèle de vieilles versions de navigateurs ou des bots.
Émulation de Canvas et WebGL Fingerprint
Le fingerprinting Canvas et WebGL est une méthode puissante de détection, car les navigateurs sans tête génèrent des empreintes identiques. Les systèmes anti-bot créent un Canvas invisible, dessinent du texte dessus et calculent le hachage des pixels. Si des milliers de requêtes ont le même hachage, ce sont des bots.
Ajout de bruit dans le Canvas
Le script suivant ajoute un bruit aléatoire dans l'empreinte Canvas, rendant chaque requête unique :
await page.evaluateOnNewDocument(() => {
const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
const originalToBlob = HTMLCanvasElement.prototype.toBlob;
const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
// Fonction d'ajout de bruit
const addNoise = (canvas, context) => {
const imageData = originalGetImageData.call(context, 0, 0, canvas.width, canvas.height);
for (let i = 0; i < imageData.data.length; i += 4) {
imageData.data[i] += Math.floor(Math.random() * 10) - 5;
imageData.data[i + 1] += Math.floor(Math.random() * 10) - 5;
imageData.data[i + 2] += Math.floor(Math.random() * 10) - 5;
}
context.putImageData(imageData, 0, 0);
};
HTMLCanvasElement.prototype.toDataURL = function() {
addNoise(this, this.getContext('2d'));
return originalToDataURL.apply(this, arguments);
};
});
Émulation des paramètres WebGL
WebGL révèle des informations sur la carte graphique et les pilotes. En mode sans tête, ces paramètres révèlent un rendu logiciel :
await page.evaluateOnNewDocument(() => {
const getParameter = WebGLRenderingContext.prototype.getParameter;
WebGLRenderingContext.prototype.getParameter = function(parameter) {
// Émulation d'une vraie carte graphique
if (parameter === 37445) {
return 'Intel Inc.';
}
if (parameter === 37446) {
return 'Intel Iris OpenGL Engine';
}
return getParameter.call(this, parameter);
};
});
Le paramètre 37445 est UNMASKED_VENDOR_WEBGL, et 37446 est UNMASKED_RENDERER_WEBGL. En mode sans tête, ils retournent "Google SwiftShader", ce qui révèle l'automatisation.
Selenium Stealth : solutions prêtes à l'emploi pour Python
La bibliothèque selenium-stealth applique automatiquement des dizaines de patchs pour camoufler Selenium. C'est la solution la plus simple pour les développeurs Python, qui ne nécessite pas de configuration manuelle de chaque paramètre.
Installation et configuration de base
pip install selenium-stealth
from selenium import webdriver
from selenium_stealth import stealth
from selenium.webdriver.chrome.options import Options
options = Options()
options.add_argument("--headless")
options.add_argument("--no-sandbox")
options.add_argument("--disable-dev-shm-usage")
driver = webdriver.Chrome(options=options)
# Application des patchs stealth
stealth(driver,
languages=["en-US", "en"],
vendor="Google Inc.",
platform="Win32",
webgl_vendor="Intel Inc.",
renderer="Intel Iris OpenGL Engine",
fix_hairline=True,
)
driver.get("https://bot.sannysoft.com")
driver.save_screenshot("test.png")
La bibliothèque supprime automatiquement navigator.webdriver, ajoute window.chrome, émule des plugins, camoufle WebGL et applique encore 20+ patchs. Cela couvre 80% des cas de détection.
Configuration avancée avec proxy
Pour un camouflage complet, combinez selenium-stealth avec des proxies résidentiels — ils fournissent de vraies adresses IP d'utilisateurs domestiques, ce qui est critique pour contourner les systèmes anti-bot avancés :
from selenium.webdriver.common.proxy import Proxy, ProxyType
proxy = Proxy()
proxy.proxy_type = ProxyType.MANUAL
proxy.http_proxy = "ip:port"
proxy.ssl_proxy = "ip:port"
capabilities = webdriver.DesiredCapabilities.CHROME
proxy.add_to_capabilities(capabilities)
driver = webdriver.Chrome(desired_capabilities=capabilities, options=options)
stealth(driver, languages=["en-US", "en"], vendor="Google Inc.", platform="Win32")
Puppeteer Extra Stealth Plugin pour Node.js
Pour Puppeteer, il existe un plugin puppeteer-extra-plugin-stealth, qui est la solution la plus avancée pour camoufler les navigateurs sans tête dans l'écosystème JavaScript. Il contient 23 modules indépendants, chacun camouflant un aspect particulier de l'automatisation.
Installation et utilisation de base
npm install puppeteer-extra puppeteer-extra-plugin-stealth
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());
(async () => {
const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser.newPage();
await page.goto('https://bot.sannysoft.com');
await page.screenshot({ path: 'test.png' });
await browser.close();
})();
Ce que camoufle le Stealth Plugin
Le plugin applique automatiquement les patchs suivants :
- Suppression de
navigator.webdriver - Ajout de l'objet
window.chrome - Émulation de l'API
navigator.permissions - Camouflage des
navigator.pluginsetnavigator.mimeTypes - Émulation du fingerprinting Canvas et WebGL
- Camouflage du User-Agent et des langues
- Correction des anomalies dans le contentWindow des iframes
- Émulation de l'API Battery, des appareils multimédias, WebRTC
Configuration avec proxy et paramètres supplémentaires
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
const AdblockerPlugin = require('puppeteer-extra-plugin-adblocker');
puppeteer.use(StealthPlugin());
puppeteer.use(AdblockerPlugin({ blockTrackers: true }));
(async () => {
const browser = await puppeteer.launch({
headless: true,
args: [
'--proxy-server=http://your-proxy:port',
'--disable-web-security',
'--disable-features=IsolateOrigins,site-per-process'
]
});
const page = await browser.newPage();
// Authentification du proxy
await page.authenticate({
username: 'your-username',
password: 'your-password'
});
await page.setViewport({ width: 1920, height: 1080 });
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
})();
Playwright : configuration anti-détection
Playwright a une architecture plus sophistiquée par rapport à Puppeteer et laisse moins de traces d'automatisation. Cependant, pour contourner les systèmes anti-bot avancés, une configuration supplémentaire est nécessaire. Pour Playwright, il existe un port du plugin stealth — playwright-extra.
Installation de playwright-extra
npm install playwright-extra playwright-extra-plugin-stealth playwright
const { chromium } = require('playwright-extra');
const stealth = require('playwright-extra-plugin-stealth');
chromium.use(stealth());
(async () => {
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
viewport: { width: 1920, height: 1080 },
locale: 'en-US',
timezoneId: 'America/New_York'
});
const page = await context.newPage();
await page.goto('https://bot.sannysoft.com');
await page.screenshot({ path: 'test.png' });
await browser.close();
})();
Configuration du contexte du navigateur pour un camouflage maximal
Playwright permet de créer des contextes de navigateur isolés avec des paramètres individuels. Cela est utile pour le multi-comptes ou le scraping parallèle :
const context = await browser.newContext({
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36',
viewport: { width: 1440, height: 900 },
locale: 'en-US',
timezoneId: 'America/Los_Angeles',
permissions: ['geolocation'],
geolocation: { latitude: 37.7749, longitude: -122.4194 },
colorScheme: 'light',
deviceScaleFactor: 2,
isMobile: false,
hasTouch: false,
// Configuration du proxy pour le contexte
proxy: {
server: 'http://your-proxy:port',
username: 'user',
password: 'pass'
}
});
Les paramètres geolocation et timezoneId doivent correspondre à l'adresse IP du proxy, sinon les systèmes anti-bot détecteront une incohérence (par exemple, une IP de Californie, mais un fuseau horaire de New York).
Rotation des proxies pour réduire le risque de blocage
Même un navigateur sans tête parfaitement camouflé peut être bloqué s'il utilise une seule adresse IP pour des centaines de requêtes. Les systèmes anti-bot modernes analysent la fréquence des requêtes d'une seule IP et bloquent les activités suspectes. La rotation des proxies est un élément essentiel de la protection lors du scraping.
Types de proxies pour le scraping : comparaison
| Type de proxy | Vitesse | Trust Score | Mieux pour |
|---|---|---|---|
| Datacenter | Très élevé (50-200 ms) | Faible | Sites simples, scraping en masse |
| Résidentiels | Moyenne (300-1000 ms) | Élevé | Sites protégés, réseaux sociaux |
| Mobiles | Faible (500-2000 ms) | Très élevé | Applications mobiles, Instagram, TikTok |
Pour le scraping de sites protégés (places de marché, réseaux sociaux, plateformes publicitaires), des proxies résidentiels sont recommandés, car ils disposent de vraies IP d'utilisateurs domestiques et ne sont pas inscrits sur les listes noires des systèmes anti-bot.
Mise en œuvre de la rotation des proxies dans Puppeteer
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());
const proxyList = [
'http://user1:pass1@proxy1:port',
'http://user2:pass2@proxy2:port',
'http://user3:pass3@proxy3:port'
];
async function scrapeWithRotation(urls) {
for (let i = 0; i < urls.length; i++) {
const proxy = proxyList[i % proxyList.length];
const browser = await puppeteer.launch({
headless: true,
args: [`--proxy-server=${proxy}`]
});
const page = await browser.newPage();
try {
await page.goto(urls[i], { waitUntil: 'networkidle2' });
const data = await page.evaluate(() => document.body.innerText);
console.log(data);
} catch (error) {
console.error(`Erreur sur ${urls[i]} :`, error);
} finally {
await browser.close();
}
// Délai entre les requêtes
await new Promise(resolve => setTimeout(resolve, 2000));
}
}
scrapeWithRotation([
'https://example1.com',
'https://example2.com',
'https://example3.com'
]);
Rotation via des proxies basés sur des sessions
Certains fournisseurs de proxies (y compris ProxyCove) proposent une rotation basée sur des sessions — chaque requête reçoit automatiquement une nouvelle IP sans avoir à redémarrer le navigateur. Cela se réalise via un format spécial d'URL de proxy :
// Format : username-session-RANDOM:password@gateway:port
const generateSessionProxy = () => {
const sessionId = Math.random().toString(36).substring(7);
return `http://username-session-${sessionId}:password@gateway.proxycove.com:12321`;
};
const browser = await puppeteer.launch({
args: [`--proxy-server=${generateSessionProxy()}`]
});
Comment tester la qualité du camouflage : outils de test
Après avoir configuré le camouflage, il est nécessaire de vérifier à quel point votre navigateur sans tête imite un utilisateur normal. Il existe plusieurs sites spécialisés qui analysent des dizaines de paramètres du navigateur et montrent quelles traces d'automatisation restent.
Outils de test principaux
- bot.sannysoft.com — vérifie plus de 15 paramètres de détection, y compris webdriver, objet Chrome, plugins, Canvas
- arh.antoinevastel.com/bots/areyouheadless — spécialisé dans la détection de Chrome sans tête
- pixelscan.net — analyse avancée du fingerprint avec visualisation de tous les paramètres
- abrahamjuliot.github.io/creepjs — analyse la plus détaillée (plus de 200 paramètres), montre le niveau de confiance du navigateur
- iphey.com — vérification de l'adresse IP pour déterminer si elle appartient à un proxy ou à un VPN
Automatisation des tests
Créez un script pour vérifier automatiquement le camouflage après chaque modification des paramètres :
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());
async function testStealth() {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
// Test 1 : Sannysoft
await page.goto('https://bot.sannysoft.com');
await page.screenshot({ path: 'test-sannysoft.png', fullPage: true });
// Test 2 : Are you headless
await page.goto('https://arh.antoinevastel.com/bots/areyouheadless');
const headlessDetected = await page.evaluate(() => {
return document.body.innerText.includes('You are not Chrome headless');
});
console.log('Headless détecté :', !headlessDetected);
// Test 3 : Propriété Webdriver
const webdriverPresent = await page.evaluate(() => navigator.webdriver);
console.log('navigator.webdriver :', webdriverPresent);
// Test 4 : Objet Chrome
const chromePresent = await page.evaluate(() => !!window.chrome);
console.log('Objet window.chrome présent :', chromePresent);
await browser.close();
}
testStealth();
Liste de contrôle du camouflage réussi
Votre navigateur sans tête est correctement camouflé si :
navigator.webdriverretourneundefinedwindow.chromeexiste et contient un objetruntimenavigator.plugins.lengthest supérieur à 0- Le fournisseur et le renderer WebGL montrent une vraie carte graphique, et non SwiftShader
- Le fingerprint Canvas est unique pour chaque session
- Le User-Agent correspond à la version actuelle de Chrome/Firefox
- L'adresse IP du proxy n'est pas sur les listes noires (vérification via iphey.com)
- Le fuseau horaire et la locale correspondent à la géolocalisation de l'adresse IP
Conclusion
Le camouflage des navigateurs sans tête est une tâche complexe qui nécessite une attention particulière à des dizaines de paramètres. Les systèmes anti-bot modernes utilisent l'apprentissage automatique et analysent des centaines de caractéristiques du navigateur simultanément, donc un simple remplacement de User-Agent ne fonctionne plus. Pour un scraping réussi, il est nécessaire de combiner plusieurs méthodes de protection.
Les éléments clés d'un camouflage efficace : suppression des marqueurs JavaScript d'automatisation (navigator.webdriver, variables CDP), émulation du fingerprinting Canvas et WebGL, configuration d'en-têtes HTTP réalistes et utilisation de proxies de qualité. Les solutions prêtes à l'emploi (selenium-stealth pour Python, puppeteer-extra-plugin-stealth pour Node.js) couvrent 80% des cas, mais pour contourner des protections avancées, une configuration supplémentaire est nécessaire.
Un point critique est le choix des proxies. Même un navigateur parfaitement camouflé sera bloqué s'il utilise des adresses IP sur des listes noires ou effectue trop de requêtes depuis une seule IP. Pour le scraping de sites protégés, nous recommandons d'utiliser des proxies résidentiels avec rotation automatique — ils offrent un score de confiance élevé et un risque minimal de blocage, car ils utilisent de vraies IP d'utilisateurs domestiques au lieu d'adresses de serveurs.
Testez régulièrement la qualité du camouflage via des services spécialisés (bot.sannysoft.com, pixelscan.net) et adaptez les paramètres aux changements dans les systèmes anti-bot. Le scraping est une course permanente entre les développeurs de bots et les créateurs de protections, donc une configuration qui fonctionne aujourd'hui peut nécessiter une mise à jour dans quelques mois.