Guide complet pour masquer Selenium et Puppeteer de la détection
Les systèmes modernes de protection anti-bot reconnaissent facilement les navigateurs automatisés par des dizaines de signes : des variables JavaScript aux particularités du comportement de WebDriver. Les sites utilisent Cloudflare, DataDome, PerimeterX et leurs propres solutions, qui bloquent jusqu'à 90 % des requêtes provenant de Selenium et Puppeteer dans leur configuration standard.
Dans ce guide, nous examinerons toutes les méthodes de masquage de l'automatisation : des réglages de base aux techniques avancées pour contourner la détection. Vous obtiendrez des solutions prêtes à l'emploi avec des exemples de code pour Python et Node.js, qui fonctionnent contre la plupart des systèmes de protection.
Comment les sites détectent l'automatisation
Les systèmes de protection anti-bot analysent le navigateur selon de nombreux paramètres simultanément. Même si vous cachez un signe, les autres révéleront l'automatisation. Comprendre toutes les méthodes de détection est la clé d'un masquage efficace.
Indicateurs WebDriver
La méthode la plus simple de détection consiste à vérifier les variables JavaScript qui ne sont présentes que dans les navigateurs automatisés :
// Ces variables révèlent Selenium/Puppeteer
navigator.webdriver === true
window.navigator.webdriver === true
document.$cdc_ // Variable spécifique à ChromeDriver
window.document.documentElement.getAttribute("webdriver")
navigator.plugins.length === 0 // Les navigateurs automatisés n'ont pas de plugins
navigator.languages === "" // Liste des langues vide
Cloudflare et des systèmes similaires vérifient ces propriétés en premier. Si l'une d'elles renvoie un résultat positif, la requête est bloquée.
Fingerprinting du navigateur
Les systèmes avancés créent une empreinte unique du navigateur basée sur des dizaines de paramètres :
- Fingerprinting Canvas — rendu d'images cachées et analyse des données de pixels
- Fingerprinting WebGL — paramètres du moteur graphique et de la carte graphique
- Contexte Audio — caractéristiques uniques du traitement audio
- Fingerprinting des polices — liste des polices installées sur le système
- Résolution d'écran — résolution de l'écran, profondeur de couleur, zone accessible
- Fuseau horaire et langue — fuseau horaire, langues du navigateur, locale du système
Les navigateurs automatisés ont souvent des combinaisons atypiques de ces paramètres. Par exemple, Headless Chrome n'a pas de plugins, mais prend en charge WebGL — une telle combinaison est extrêmement rare chez les utilisateurs réels.
Analyse comportementale
Les systèmes modernes suivent les modèles de comportement :
- Mouvements de la souris — les bots déplacent le curseur en lignes droites ou ne le déplacent pas du tout
- Vitesse des actions — remplissage instantané des formulaires, vitesse de clics non humaine
- Modèles de défilement — sauts brusques au lieu d'un défilement fluide
- Événements de clavier — absence de délais naturels entre les frappes
- Fréquence des requêtes — intervalles trop réguliers entre les actions
Important : DataDome et PerimeterX utilisent l'apprentissage automatique pour analyser le comportement. Ils ont été formés sur des millions de sessions et peuvent reconnaître un bot même avec un masquage technique correct, si le comportement semble non naturel.
Masquage de base de Selenium
Selenium WebDriver dans sa configuration standard laisse de nombreuses traces. Examinons une configuration étape par étape pour minimiser la détection à l'aide de Python et ChromeDriver.
Désactivation du drapeau webdriver
La première étape consiste à cacher la variable navigator.webdriver. Cela se fait via le Chrome DevTools Protocol :
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
# Configuration des options Chrome
chrome_options = Options()
# Désactivation du drapeau d'automatisation
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)
# Création du driver
driver = webdriver.Chrome(options=chrome_options)
# Suppression du webdriver via CDP
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': '''
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
})
'''
})
driver.get('https://example.com')
Configuration de User-Agent et d'autres en-têtes
Les navigateurs headless utilisent souvent des chaînes User-Agent obsolètes ou spécifiques. Il est nécessaire de définir un User-Agent actuel d'un véritable navigateur :
# User-Agent actuel de Chrome sur Windows
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'
chrome_options.add_argument(f'user-agent={user_agent}')
# Arguments supplémentaires pour le masquage
chrome_options.add_argument('--disable-blink-features=AutomationControlled')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-gpu')
# Taille de la fenêtre comme un utilisateur réel
chrome_options.add_argument('--window-size=1920,1080')
chrome_options.add_argument('--start-maximized')
Ajout de plugins et de langues
Les navigateurs automatisés n'ont pas de plugins et affichent souvent une liste de langues vide. Corrigeons cela via CDP :
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': '''
Object.defineProperty(navigator, 'languages', {
get: () => ['fr-FR', 'fr', 'en']
});
Object.defineProperty(navigator, 'plugins', {
get: () => [
{
0: {type: "application/x-google-chrome-pdf", suffixes: "pdf", description: "Portable Document Format"},
description: "Portable Document Format",
filename: "internal-pdf-viewer",
length: 1,
name: "Plugin PDF Chrome"
},
{
0: {type: "application/pdf", suffixes: "pdf", description: ""},
description: "",
filename: "mhjfbmdgcfjbbpaeojofohoefgiehjai",
length: 1,
name: "Visionneuse PDF Chrome"
}
]
});
Object.defineProperty(navigator, 'platform', {
get: () => 'Win32'
});
'''
})
Exemple complet de configuration de Selenium
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import random
def create_stealth_driver():
chrome_options = Options()
# Réglages de base du masquage
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)
chrome_options.add_argument('--disable-blink-features=AutomationControlled')
# User-Agent
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'
chrome_options.add_argument(f'user-agent={user_agent}')
# Taille de la fenêtre
chrome_options.add_argument('--window-size=1920,1080')
chrome_options.add_argument('--start-maximized')
driver = webdriver.Chrome(options=chrome_options)
# Script de masquage via CDP
stealth_script = '''
Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
Object.defineProperty(navigator, 'languages', {get: () => ['fr-FR', 'fr']});
Object.defineProperty(navigator, 'platform', {get: () => 'Win32'});
window.chrome = {
runtime: {}
};
Object.defineProperty(navigator, 'plugins', {
get: () => [1, 2, 3, 4, 5]
});
'''
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': stealth_script
})
return driver
# Utilisation
driver = create_stealth_driver()
driver.get('https://bot.sannysoft.com/') # Site pour tester la détection
Configuration de Puppeteer pour contourner la détection
Puppeteer a les mêmes problèmes de détection que Selenium. Cependant, il existe une bibliothèque prête à l'emploi pour Node.js, puppeteer-extra-plugin-stealth, qui automatise la plupart des réglages de masquage.
Installation de puppeteer-extra
npm install puppeteer puppeteer-extra puppeteer-extra-plugin-stealth
Configuration de base avec le plugin stealth
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
// Activation du plugin de masquage
puppeteer.use(StealthPlugin());
(async () => {
const browser = await puppeteer.launch({
headless: 'new', // Nouveau mode headless de Chrome
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-accelerated-2d-canvas',
'--disable-gpu',
'--window-size=1920,1080',
'--disable-web-security',
'--disable-features=IsolateOrigins,site-per-process'
]
});
const page = await browser.newPage();
// Définition du viewport
await page.setViewport({
width: 1920,
height: 1080,
deviceScaleFactor: 1
});
// Définition du User-Agent
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');
// En-têtes supplémentaires
await page.setExtraHTTPHeaders({
'Accept-Language': 'fr-FR,fr;q=0.9',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
});
await page.goto('https://bot.sannysoft.com/');
// Capture d'écran pour vérification
await page.screenshot({ path: 'test.png' });
await browser.close();
})();
Configuration manuelle sans plugins
Si vous souhaitez un contrôle total ou ne pouvez pas utiliser des bibliothèques tierces, configurez le masquage manuellement :
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: 'new',
args: ['--no-sandbox', '--disable-setuid-sandbox']
});
const page = await browser.newPage();
// Redéfinir webdriver et d'autres propriétés
await page.evaluateOnNewDocument(() => {
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
Object.defineProperty(navigator, 'languages', {
get: () => ['fr-FR', 'fr']
});
Object.defineProperty(navigator, 'plugins', {
get: () => [1, 2, 3, 4, 5]
});
// Masquage de Chrome headless
Object.defineProperty(navigator, 'platform', {
get: () => 'Win32'
});
window.chrome = {
runtime: {}
};
// Redéfinir permissions
const originalQuery = window.navigator.permissions.query;
window.navigator.permissions.query = (parameters) => (
parameters.name === 'notifications' ?
Promise.resolve({ state: Notification.permission }) :
originalQuery(parameters)
);
});
await page.goto('https://example.com');
await browser.close();
})();
Configuration pour contourner Cloudflare
Cloudflare utilise des méthodes de détection avancées. Pour contourner cela, il est nécessaire d'ajouter des délais aléatoires et d'émuler des actions :
const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');
puppeteer.use(StealthPlugin());
async function bypassCloudflare(url) {
const browser = await puppeteer.launch({
headless: 'new',
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-web-security'
]
});
const page = await browser.newPage();
// User-Agent aléatoire
const userAgents = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'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',
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
];
await page.setUserAgent(userAgents[Math.floor(Math.random() * userAgents.length)]);
// Accéder à la page
await page.goto(url, { waitUntil: 'networkidle2' });
// Attendre la vérification de Cloudflare (généralement 5-10 secondes)
await page.waitForTimeout(8000);
// Mouvement de souris aléatoire
await page.mouse.move(100, 100);
await page.mouse.move(200, 200);
const content = await page.content();
await browser.close();
return content;
}
Lutte contre le fingerprinting JavaScript
Le fingerprinting JavaScript consiste à créer une empreinte unique du navigateur basée sur de nombreux paramètres. Même si vous avez caché le webdriver, les systèmes analysent des centaines d'autres propriétés pour détecter l'automatisation.
Principaux vecteurs de fingerprinting
Les systèmes de protection anti-bot vérifient les paramètres suivants :
| Paramètre | Ce qui est vérifié | Risque de détection |
|---|---|---|
| navigator.webdriver | Présence du drapeau d'automatisation | Critique |
| navigator.plugins | Nombre et types de plugins | Élevé |
| window.chrome | Présence de l'API Chrome | Moyen |
| navigator.permissions | API des permissions du navigateur | Moyen |
| screen.colorDepth | Profondeur de couleur de l'écran | Faible |
| navigator.hardwareConcurrency | Nombre de cœurs de processeur | Faible |
Script de masquage complet
Le script ci-dessous redéfinit la plupart des propriétés problématiques. Intégrez-le via CDP (Selenium) ou evaluateOnNewDocument (Puppeteer) :
const stealthScript = `
// Suppression du webdriver
Object.defineProperty(navigator, 'webdriver', {
get: () => undefined
});
// Ajout de l'objet chrome
window.chrome = {
runtime: {},
loadTimes: function() {},
csi: function() {},
app: {}
};
// Redéfinition des permissions
const originalQuery = window.navigator.permissions.query;
window.navigator.permissions.query = (parameters) => (
parameters.name === 'notifications' ?
Promise.resolve({ state: Notification.permission }) :
originalQuery(parameters)
);
// Masquage des plugins
Object.defineProperty(navigator, 'plugins', {
get: () => {
return [
{
0: {type: "application/x-google-chrome-pdf", suffixes: "pdf"},
description: "Portable Document Format",
filename: "internal-pdf-viewer",
length: 1,
name: "Plugin PDF Chrome"
},
{
0: {type: "application/pdf", suffixes: "pdf"},
description: "Portable Document Format",
filename: "internal-pdf-viewer",
length: 1,
name: "Visionneuse PDF Chrome"
},
{
0: {type: "application/x-nacl"},
description: "Native Client Executable",
filename: "internal-nacl-plugin",
length: 2,
name: "Native Client"
}
];
}
});
// Langues
Object.defineProperty(navigator, 'languages', {
get: () => ['fr-FR', 'fr']
});
// Plateforme
Object.defineProperty(navigator, 'platform', {
get: () => 'Win32'
});
// Fournisseur
Object.defineProperty(navigator, 'vendor', {
get: () => 'Google Inc.'
});
// Suppression des traces de Selenium
delete window.cdc_adoQpoasnfa76pfcZLmcfl_Array;
delete window.cdc_adoQpoasnfa76pfcZLmcfl_Promise;
delete window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol;
// API de batterie (absente en mode headless)
if (!navigator.getBattery) {
navigator.getBattery = () => Promise.resolve({
charging: true,
chargingTime: 0,
dischargingTime: Infinity,
level: 1
});
}
`;
Suppression des propriétés WebDriver
ChromeDriver et d'autres implémentations de WebDriver ajoutent des variables spécifiques dans l'espace global. Ces variables commencent par le préfixe cdc_ et sont facilement détectées par les systèmes de protection.
Détection des variables cdc
Vérifiez la présence de ces variables avec un simple script :
// Recherche de toutes les variables cdc
for (let key in window) {
if (key.includes('cdc_')) {
console.log('Variable WebDriver détectée :', key);
}
}
// Variables typiques de ChromeDriver :
// cdc_adoQpoasnfa76pfcZLmcfl_Array
// cdc_adoQpoasnfa76pfcZLmcfl_Promise
// cdc_adoQpoasnfa76pfcZLmcfl_Symbol
// $cdc_asdjflasutopfhvcZLmcfl_
Méthode 1 : Suppression via CDP
La méthode la plus fiable consiste à supprimer les variables avant le chargement de la page via le Chrome DevTools Protocol :
from selenium import webdriver
driver = webdriver.Chrome()
# Suppression de toutes les variables cdc
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
'source': '''
// Suppression des variables cdc connues
const cdcProps = [
'cdc_adoQpoasnfa76pfcZLmcfl_Array',
'cdc_adoQpoasnfa76pfcZLmcfl_Promise',
'cdc_adoQpoasnfa76pfcZLmcfl_Symbol',
'$cdc_asdjflasutopfhvcZLmcfl_'
];
cdcProps.forEach(prop => {
delete window[prop];
});
// Suppression de toutes les variables contenant 'cdc_'
Object.keys(window).forEach(key => {
if (key.includes('cdc_') || key.includes('$cdc_')) {
delete window[key];
}
});
'''
})
Méthode 2 : Modification de ChromeDriver
Une approche plus radicale consiste à modifier le fichier binaire de ChromeDriver, en remplaçant la chaîne cdc_ par une autre séquence de caractères. Cela empêche la création de ces variables :
import re
def patch_chromedriver(driver_path):
"""
Patche ChromeDriver en remplaçant 'cdc_' par une chaîne aléatoire
"""
with open(driver_path, 'rb') as f:
content = f.read()
# Remplace toutes les occurrences de 'cdc_' par 'dog_' (ou toute autre chaîne de même longueur)
patched = content.replace(b'cdc_', b'dog_')
with open(driver_path, 'wb') as f:
f.write(patched)
print(f'ChromeDriver patché : {driver_path}')
# Utilisation
patch_chromedriver('/path/to/chromedriver')
Attention : La modification du fichier binaire de ChromeDriver peut perturber son fonctionnement. Faites toujours une sauvegarde avant de patcher. Cette méthode ne fonctionne pas avec toutes les versions de ChromeDriver.
Méthode 3 : Utilisation de undetected-chromedriver
La bibliothèque undetected-chromedriver patch automatiquement ChromeDriver au démarrage :
pip install undetected-chromedriver
import undetected_chromedriver as uc
# Création d'un driver avec patch automatique
driver = uc.Chrome()
driver.get('https://nowsecure.nl/') # Site pour tester la détection
input('Appuyez sur Entrée pour fermer...')
driver.quit()
Masquage de Canvas, WebGL et Audio API
Le fingerprinting Canvas, WebGL et Audio consiste à créer une empreinte unique basée sur les caractéristiques du rendu graphique et du traitement audio. Chaque combinaison de navigateur, de système d'exploitation et de matériel donne un résultat unique.
Fingerprinting Canvas
Les systèmes dessinent une image cachée sur Canvas et analysent les pixels obtenus. Les navigateurs headless donnent souvent des résultats atypiques en raison de l'absence d'accélération GPU.
// Code typique de Fingerprinting Canvas
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.textBaseline = 'top';
ctx.font = '14px Arial';
ctx.fillText('Empreinte du navigateur', 2, 2);
const fingerprint = canvas.toDataURL();
Pour se protéger, vous pouvez ajouter du bruit aléatoire à l'API Canvas :
const canvasNoiseScript = `
// Ajout de bruit aléatoire à Canvas
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) {
// Ajout d'un bruit minimal au RGB (invisible à l'œil)
imageData.data[i] += Math.floor(Math.random() * 3) - 1;
imageData.data[i + 1] += Math.floor(Math.random() * 3) - 1;
imageData.data[i + 2] += Math.floor(Math.random() * 3) - 1;
}
context.putImageData(imageData, 0, 0);
};
// Redéfinir toDataURL
HTMLCanvasElement.prototype.toDataURL = function() {
if (this.width > 0 && this.height > 0) {
const context = this.getContext('2d');
addNoise(this, context);
}
return originalToDataURL.apply(this, arguments);
};
`;
Fingerprinting WebGL
WebGL fournit des informations sur la carte graphique et les pilotes. Les navigateurs headless montrent souvent SwiftShader (rendu logiciel) au lieu de la véritable GPU :
const webglMaskScript = `
// Masquage des paramètres WebGL
const getParameter = WebGLRenderingContext.prototype.getParameter;
WebGLRenderingContext.prototype.getParameter = function(parameter) {
// UNMASKED_VENDOR_WEBGL
if (parameter === 37445) {
return 'Intel Inc.';
}
// UNMASKED_RENDERER_WEBGL
if (parameter === 37446) {
return 'Intel Iris OpenGL Engine';
}
return getParameter.call(this, parameter);
};
// Également pour WebGL2
if (typeof WebGL2RenderingContext !== 'undefined') {
const getParameter2 = WebGL2RenderingContext.prototype.getParameter;
WebGL2RenderingContext.prototype.getParameter = function(parameter) {
if (parameter === 37445) {
return 'Intel Inc.';
}
if (parameter === 37446) {
return 'Intel Iris OpenGL Engine';
}
return getParameter2.call(this, parameter);
};
}
`;
Fingerprinting du contexte audio
L'API Audio donne également une empreinte unique. Ajoutons du bruit au traitement audio :
const audioMaskScript = `
// Ajout de bruit au contexte audio
const AudioContext = window.AudioContext || window.webkitAudioContext;
if (AudioContext) {
const originalCreateAnalyser = AudioContext.prototype.createAnalyser;
AudioContext.prototype.createAnalyser = function() {
const analyser = originalCreateAnalyser.call(this);
const originalGetFloatFrequencyData = analyser.getFloatFrequencyData;
analyser.getFloatFrequencyData = function(array) {
originalGetFloatFrequencyData.call(this, array);
// Ajout d'un bruit minimal
for (let i = 0; i < array.length; i++) {
array[i] += Math.random() * 0.0001;
}
};
return analyser;
};
}
`;
Imitation du comportement humain
Même avec un masquage technique parfait, les bots se trahissent par leur comportement. Les systèmes d'apprentissage automatique analysent les modèles de mouvements de la souris, la vitesse des actions et la séquence des événements.
Délais aléatoires entre les actions
N'utilisez jamais de délais fixes. Les utilisateurs réels font des pauses de différentes durées :
import random
import time
def human_delay(min_seconds=1, max_seconds=3):
"""Délai aléatoire imitant un humain"""
delay = random.uniform(min_seconds, max_seconds)
time.sleep(delay)
# Utilisation
driver.get('https://example.com')
human_delay(2, 4) # Pause de 2 à 4 secondes
element = driver.find_element(By.ID, 'search')
human_delay(0.5, 1.5) # Courte pause avant la saisie
element.send_keys('requête de recherche')
human_delay(1, 2)
Mouvement fluide de la souris
Les bots déplacent la souris en lignes droites ou téléportent le curseur. Les utilisateurs réels créent des trajectoires courbes avec accélération et décélération :
// Puppeteer : mouvement fluide de la souris
async function humanMouseMove(page, targetX, targetY) {
const steps = 25; // Nombre de points intermédiaires
const currentPos = await page.evaluate(() => ({
x: window.mouseX || 0,
y: window.mouseY || 0
}));
for (let i = 0; i <= steps; i++) {
const t = i / steps;
// Utilisation de l'easing pour la fluidité
const ease = t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
const x = currentPos.x + (targetX - currentPos.x) * ease;
const y = currentPos.y + (targetY - currentPos.y) * ease;
await page.mouse.move(x, y);
await page.waitForTimeout(Math.random() * 10 + 5);
}
// Sauvegarder la position
await page.evaluate((x, y) => {
window.mouseX = x;
window.mouseY = y;
}, targetX, targetY);
}
// Utilisation
await humanMouseMove(page, 500, 300);
await page.mouse.click(500, 300);
Défilement naturel
Les utilisateurs réels défilent de manière fluide, avec des arrêts pour lire le contenu :
async function humanScroll(page) {
const scrollHeight = await page.evaluate(() => document.body.scrollHeight);
const viewportHeight = await page.evaluate(() => window.innerHeight);
let currentPosition = 0;
while (currentPosition < scrollHeight - viewportHeight) {
// Étape de défilement aléatoire (200-500px)
const scrollStep = Math.floor(Math.random() * 300) + 200;
currentPosition += scrollStep;
// Défilement fluide
await page.evaluate((pos) => {
window.scrollTo({
top: pos,
behavior: 'smooth'
});
}, currentPosition);
// Pause pour "lire" le contenu (1-3 secondes)
await page.waitForTimeout(Math.random() * 2000 + 1000);
}
}
// Utilisation
await page.goto('https://example.com');
await humanScroll(page);
Saisie de texte naturelle
Les gens tapent à des vitesses différentes, font des fautes de frappe et les corrigent :
async function humanTypeText(page, selector, text) {
await page.click(selector);
for (let char of text) {
// Délai aléatoire entre les frappes (50-200ms)
const delay = Math.random() * 150 + 50;
await page.waitForTimeout(delay);
// 5 % de chance de faute de frappe
if (Math.random() < 0.05) {
// Tape un caractère aléatoire
const wrongChar = String.fromCharCode(97 + Math.floor(Math.random() * 26));
await page.keyboard.type(wrongChar);
await page.waitForTimeout(100 + Math.random() * 100);
// Supprime (Backspace)
await page.keyboard.press('Backspace');
await page.waitForTimeout(50 + Math.random() * 50);
}
await page.keyboard.type(char);
}
}
// Utilisation
await humanTypeText(page, '#search-input', 'exemple de requête de recherche');
Intégration de proxy pour une anonymité totale
Le masquage du navigateur est inutile si toutes les requêtes proviennent d'une seule adresse IP. Les systèmes de protection anti-bot suivent le nombre de requêtes de chaque IP et bloquent les activités suspectes. Les proxies sont un élément essentiel de toute automatisation sérieuse.
Choix du type de proxy
Différentes tâches nécessitent différents types de proxies :
| Type de proxy | Avantages | Application |
|---|---|---|
| Proxy résidentiel | Apparence d'un utilisateur réel | Scraping de données, accès à des contenus géo-restreints |
| Proxy datacenter | Rapidité et coût réduit | Tests de performance, automatisation à grande échelle |
| Proxy mobile | Accès à des contenus géo-restreints avec une IP mobile | Scraping de données, tests de localisation |
Bibliothèques et outils prêts à l'emploi
Voici quelques bibliothèques et outils utiles pour le masquage de Selenium et Puppeteer :
- puppeteer-extra — bibliothèque pour étendre Puppeteer avec des plugins.
- puppeteer-extra-plugin-stealth — plugin pour masquer Puppeteer.
- undetected-chromedriver — bibliothèque pour contourner la détection de ChromeDriver.
- selenium-stealth — bibliothèque pour masquer Selenium.
Test du niveau de détection
Pour tester le niveau de détection de votre configuration, vous pouvez utiliser des outils comme Sannysoft Bot Detection Test qui vous aidera à évaluer l'efficacité de vos techniques de masquage.
Conclusion
Masquer l'utilisation de Selenium et Puppeteer est un processus complexe qui nécessite une compréhension approfondie des systèmes de détection. En appliquant les techniques et les outils décrits dans ce guide, vous pouvez améliorer vos chances de succès dans l'automatisation tout en évitant les blocages.