Retour au blog

Comment masquer l'utilisation de Selenium et Puppeteer

Découvrez comment dissimuler efficacement l'utilisation de Selenium et Puppeteer des systèmes de protection anti-bot. Méthodes pratiques, exemples de code et techniques éprouvées de camouflage de l'automatisation.

📅26 décembre 2025
```html

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.

```