Torna al blog

Come nascondere l'uso di Selenium e Puppeteer

Scopri come nascondere efficacemente l'uso di Selenium e Puppeteer dai sistemi di protezione anti-bot. Metodi pratici, esempi di codice e tecniche collaudate per mascherare l'automazione.

📅26 dicembre 2025
```html

Guida completa per mascherare Selenium e Puppeteer dalla rilevazione

I moderni sistemi di protezione anti-bot riconoscono facilmente i browser automatizzati attraverso decine di segnali: dalle variabili JavaScript alle peculiarità del comportamento di WebDriver. I siti utilizzano Cloudflare, DataDome, PerimeterX e soluzioni proprie che bloccano fino al 90% delle richieste da Selenium e Puppeteer nella configurazione standard.

In questa guida esamineremo tutti i metodi di mascheramento dell'automazione: dalle impostazioni di base alle tecniche avanzate per eludere la rilevazione. Otterrete soluzioni pronte con esempi di codice per Python e Node.js, che funzionano contro la maggior parte dei sistemi di protezione.

Come i siti rilevano l'automazione

I sistemi di protezione anti-bot analizzano il browser in base a molti parametri contemporaneamente. Anche se nascondi un segnale, gli altri riveleranno l'automazione. Comprendere tutti i metodi di rilevazione è la chiave per una mascheratura efficace.

Indicatori di WebDriver

Il metodo più semplice di rilevazione è controllare le variabili JavaScript che sono presenti solo nei browser automatizzati:

// Queste variabili rivelano Selenium/Puppeteer
navigator.webdriver === true
window.navigator.webdriver === true
document.$cdc_ // Variabile specifica di ChromeDriver
window.document.documentElement.getAttribute("webdriver")
navigator.plugins.length === 0 // I browser automatizzati non hanno plugin
navigator.languages === "" // Lista di lingue vuota

Cloudflare e sistemi simili controllano queste proprietà in primo luogo. Se anche solo una restituisce un risultato positivo, la richiesta viene bloccata.

Fingerprinting del browser

I sistemi avanzati creano un'impronta unica del browser basata su decine di parametri:

  • Canvas Fingerprinting — rendering di immagini nascoste e analisi dei dati dei pixel
  • WebGL Fingerprinting — parametri del renderer grafico e della scheda video
  • Audio Context — caratteristiche uniche dell'elaborazione audio
  • Fonts Fingerprinting — elenco dei font installati nel sistema
  • Screen Resolution — risoluzione dello schermo, profondità del colore, area disponibile
  • Timezone & Language — fuso orario, lingue del browser, locale del sistema

I browser automatizzati spesso presentano combinazioni atipiche di questi parametri. Ad esempio, Headless Chrome non ha plugin, ma supporta WebGL: tale combinazione è estremamente rara tra gli utenti reali.

Analisi comportamentale

I sistemi moderni tracciano i modelli di comportamento:

  • Movimenti del mouse — i bot muovono il cursore in linee rette o non lo muovono affatto
  • Velocità delle azioni — compilazione istantanea dei moduli, velocità di clic non umana
  • Modelli di scrolling — salti bruschi invece di uno scrolling fluido
  • Eventi della tastiera — assenza di ritardi naturali tra i tasti
  • Frequenza delle richieste — intervalli troppo regolari tra le azioni

Importante: DataDome e PerimeterX utilizzano l'apprendimento automatico per analizzare il comportamento. Sono addestrati su milioni di sessioni e possono riconoscere un bot anche con una corretta mascheratura dei parametri tecnici, se il comportamento appare innaturale.

Mascheramento di base di Selenium

Selenium WebDriver nella configurazione standard lascia molte tracce. Esaminiamo una configurazione passo-passo per minimizzare la rilevazione utilizzando Python e ChromeDriver.

Disattivazione del flag webdriver

Il primo passo è nascondere la variabile navigator.webdriver. Questo si fa tramite il Chrome DevTools Protocol:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options

# Configurazione delle opzioni di Chrome
chrome_options = Options()

# Disattiviamo il flag di automazione
chrome_options.add_experimental_option("excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)

# Creiamo il driver
driver = webdriver.Chrome(options=chrome_options)

# Rimuoviamo webdriver tramite CDP
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        Object.defineProperty(navigator, 'webdriver', {
            get: () => undefined
        })
    '''
})

driver.get('https://example.com')

Configurazione di User-Agent e altri header

I browser headless spesso utilizzano stringhe User-Agent obsolete o specifiche. È necessario impostare un User-Agent attuale di un browser reale:

# User-Agent attuale di Chrome su 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}')

# Argomenti aggiuntivi per la mascheratura
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')

# Dimensione della finestra come un utente reale
chrome_options.add_argument('--window-size=1920,1080')
chrome_options.add_argument('--start-maximized')

Aggiunta di plugin e lingue

I browser automatizzati non hanno plugin e spesso mostrano una lista di lingue vuota. Risolviamo questo tramite CDP:

driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        Object.defineProperty(navigator, 'languages', {
            get: () => ['en-US', 'en', 'ru']
        });
        
        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: "Chrome PDF Plugin"
                },
                {
                    0: {type: "application/pdf", suffixes: "pdf", description: ""},
                    description: "",
                    filename: "mhjfbmdgcfjbbpaeojofohoefgiehjai",
                    length: 1,
                    name: "Chrome PDF Viewer"
                }
            ]
        });
        
        Object.defineProperty(navigator, 'platform', {
            get: () => 'Win32'
        });
    '''
})

Esempio completo di configurazione di Selenium

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
import random

def create_stealth_driver():
    chrome_options = Options()
    
    # Impostazioni di base per la mascheratura
    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}')
    
    # Dimensione della finestra
    chrome_options.add_argument('--window-size=1920,1080')
    chrome_options.add_argument('--start-maximized')
    
    driver = webdriver.Chrome(options=chrome_options)
    
    # Script di mascheratura tramite CDP
    stealth_script = '''
        Object.defineProperty(navigator, 'webdriver', {get: () => undefined});
        Object.defineProperty(navigator, 'languages', {get: () => ['en-US', 'en']});
        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

# Utilizzo
driver = create_stealth_driver()
driver.get('https://bot.sannysoft.com/')  # Sito per testare la rilevazione

Configurazione di Puppeteer per eludere la rilevazione

Puppeteer ha gli stessi problemi di rilevazione di Selenium. Tuttavia, per Node.js esiste una libreria pronta chiamata puppeteer-extra-plugin-stealth, che automatizza la maggior parte delle impostazioni di mascheramento.

Installazione di puppeteer-extra

npm install puppeteer puppeteer-extra puppeteer-extra-plugin-stealth

Configurazione di base con il plugin stealth

const puppeteer = require('puppeteer-extra');
const StealthPlugin = require('puppeteer-extra-plugin-stealth');

// Colleghiamo il plugin di mascheratura
puppeteer.use(StealthPlugin());

(async () => {
    const browser = await puppeteer.launch({
        headless: 'new', // Nuova modalità headless di 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();
    
    // Impostiamo il viewport
    await page.setViewport({
        width: 1920,
        height: 1080,
        deviceScaleFactor: 1
    });
    
    // Impostiamo 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');
    
    // Header aggiuntivi
    await page.setExtraHTTPHeaders({
        'Accept-Language': 'en-US,en;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/');
    
    // Screenshot per verifica
    await page.screenshot({ path: 'test.png' });
    
    await browser.close();
})();

Configurazione manuale senza plugin

Se desideri un controllo completo o non puoi utilizzare librerie di terze parti, configura la mascheratura manualmente:

const puppeteer = require('puppeteer');

(async () => {
    const browser = await puppeteer.launch({
        headless: 'new',
        args: ['--no-sandbox', '--disable-setuid-sandbox']
    });
    
    const page = await browser.newPage();
    
    // Ridefiniamo webdriver e altre proprietà
    await page.evaluateOnNewDocument(() => {
        Object.defineProperty(navigator, 'webdriver', {
            get: () => undefined
        });
        
        Object.defineProperty(navigator, 'languages', {
            get: () => ['en-US', 'en']
        });
        
        Object.defineProperty(navigator, 'plugins', {
            get: () => [1, 2, 3, 4, 5]
        });
        
        // Mascheriamo Chrome headless
        Object.defineProperty(navigator, 'platform', {
            get: () => 'Win32'
        });
        
        window.chrome = {
            runtime: {}
        };
        
        // Ridefiniamo 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();
})();

Configurazione per eludere Cloudflare

Cloudflare utilizza metodi avanzati di rilevazione. Per eludere è necessario aggiungere ritardi casuali e simulare azioni:

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 casuale
    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)]);
    
    // Passaggio alla pagina
    await page.goto(url, { waitUntil: 'networkidle2' });
    
    // Aspettiamo la verifica di Cloudflare (di solito 5-10 secondi)
    await page.waitForTimeout(8000);
    
    // Movimento casuale del mouse
    await page.mouse.move(100, 100);
    await page.mouse.move(200, 200);
    
    const content = await page.content();
    await browser.close();
    
    return content;
}

Combattere il fingerprinting JavaScript

Il fingerprinting JavaScript è la creazione di un'impronta unica del browser basata su molti parametri. Anche se hai nascosto il webdriver, i sistemi analizzano centinaia di altre proprietà per identificare l'automazione.

Vettori principali di fingerprinting

I sistemi di protezione anti-bot controllano i seguenti parametri:

Parametro Cosa viene controllato Rischio di rilevazione
navigator.webdriver Presenza del flag di automazione Critico
navigator.plugins Numero e tipi di plugin Alto
window.chrome Presenza dell'API di Chrome Medio
navigator.permissions API delle autorizzazioni del browser Medio
screen.colorDepth Profondità di colore dello schermo Basso
navigator.hardwareConcurrency Numero di core della CPU Basso

Script di mascheratura complesso

Lo script seguente ridefinisce la maggior parte delle proprietà problematiche. Implementalo tramite CDP (Selenium) o evaluateOnNewDocument (Puppeteer):

const stealthScript = `
    // Rimuoviamo webdriver
    Object.defineProperty(navigator, 'webdriver', {
        get: () => undefined
    });
    
    // Aggiungiamo oggetto chrome
    window.chrome = {
        runtime: {},
        loadTimes: function() {},
        csi: function() {},
        app: {}
    };
    
    // Ridefiniamo permissions
    const originalQuery = window.navigator.permissions.query;
    window.navigator.permissions.query = (parameters) => (
        parameters.name === 'notifications' ?
            Promise.resolve({ state: Notification.permission }) :
            originalQuery(parameters)
    );
    
    // Mascheriamo i plugin
    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: "Chrome PDF Plugin"
                },
                {
                    0: {type: "application/pdf", suffixes: "pdf"},
                    description: "Portable Document Format",
                    filename: "internal-pdf-viewer",
                    length: 1,
                    name: "Chrome PDF Viewer"
                },
                {
                    0: {type: "application/x-nacl"},
                    description: "Native Client Executable",
                    filename: "internal-nacl-plugin",
                    length: 2,
                    name: "Native Client"
                }
            ];
        }
    });
    
    // Lingue
    Object.defineProperty(navigator, 'languages', {
        get: () => ['en-US', 'en']
    });
    
    // Piattaforma
    Object.defineProperty(navigator, 'platform', {
        get: () => 'Win32'
    });
    
    // Venditore
    Object.defineProperty(navigator, 'vendor', {
        get: () => 'Google Inc.'
    });
    
    // Rimuoviamo le tracce di Selenium
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Array;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Promise;
    delete window.cdc_adoQpoasnfa76pfcZLmcfl_Symbol;
    
    // Battery API (assente in headless)
    if (!navigator.getBattery) {
        navigator.getBattery = () => Promise.resolve({
            charging: true,
            chargingTime: 0,
            dischargingTime: Infinity,
            level: 1
        });
    }
`;

Rimozione delle proprietà di WebDriver

ChromeDriver e altre implementazioni di WebDriver aggiungono variabili specifiche all'area globale. Queste variabili iniziano con il prefisso cdc_ e sono facilmente rilevabili dai sistemi di protezione.

Rilevamento delle variabili cdc

Puoi controllare la presenza di queste variabili con un semplice script:

// Ricerca di tutte le variabili cdc
for (let key in window) {
    if (key.includes('cdc_')) {
        console.log('Variabile WebDriver trovata:', key);
    }
}

// Variabili tipiche di ChromeDriver:
// cdc_adoQpoasnfa76pfcZLmcfl_Array
// cdc_adoQpoasnfa76pfcZLmcfl_Promise
// cdc_adoQpoasnfa76pfcZLmcfl_Symbol
// $cdc_asdjflasutopfhvcZLmcfl_

Metodo 1: Rimozione tramite CDP

Il modo più affidabile è rimuovere le variabili prima del caricamento della pagina tramite il Chrome DevTools Protocol:

from selenium import webdriver

driver = webdriver.Chrome()

# Rimuoviamo tutte le variabili cdc
driver.execute_cdp_cmd('Page.addScriptToEvaluateOnNewDocument', {
    'source': '''
        // Rimuoviamo le variabili cdc note
        const cdcProps = [
            'cdc_adoQpoasnfa76pfcZLmcfl_Array',
            'cdc_adoQpoasnfa76pfcZLmcfl_Promise',
            'cdc_adoQpoasnfa76pfcZLmcfl_Symbol',
            '$cdc_asdjflasutopfhvcZLmcfl_'
        ];
        
        cdcProps.forEach(prop => {
            delete window[prop];
        });
        
        // Rimuoviamo tutte le variabili contenenti 'cdc_'
        Object.keys(window).forEach(key => {
            if (key.includes('cdc_') || key.includes('$cdc_')) {
                delete window[key];
            }
        });
    '''
})

Metodo 2: Modifica di ChromeDriver

Un approccio più radicale è modificare il file binario di ChromeDriver, sostituendo la stringa cdc_ con un'altra sequenza di caratteri. Questo previene la creazione di queste variabili:

import re

def patch_chromedriver(driver_path):
    """
    Patching ChromeDriver, sostituendo 'cdc_' con una stringa casuale
    """
    with open(driver_path, 'rb') as f:
        content = f.read()
    
    # Sostituiamo tutte le occorrenze di 'cdc_' con 'dog_' (o qualsiasi altra stringa della stessa lunghezza)
    patched = content.replace(b'cdc_', b'dog_')
    
    with open(driver_path, 'wb') as f:
        f.write(patched)
    
    print(f'ChromeDriver patchato: {driver_path}')

# Utilizzo
patch_chromedriver('/path/to/chromedriver')

Attenzione: La modifica del file binario di ChromeDriver può compromettere il suo funzionamento. Fai sempre un backup prima del patching. Questo metodo non funziona con tutte le versioni di ChromeDriver.

Metodo 3: Utilizzo di undetected-chromedriver

La libreria undetected-chromedriver patcha automaticamente ChromeDriver all'avvio:

pip install undetected-chromedriver
import undetected_chromedriver as uc

# Creazione del driver con patching automatico
driver = uc.Chrome()

driver.get('https://nowsecure.nl/')  # Sito per testare la rilevazione
input('Premi Invio per chiudere...')
driver.quit()

Mascheramento di Canvas, WebGL e Audio API

Canvas, WebGL e Audio Fingerprinting sono metodi per creare un'impronta unica basata sulle peculiarità del rendering grafico e dell'elaborazione audio. Ogni combinazione di browser, OS e hardware produce un risultato unico.

Canvas Fingerprinting

I sistemi disegnano un'immagine nascosta su Canvas e analizzano i pixel risultanti. I browser headless spesso forniscono risultati atipici a causa dell'assenza di accelerazione GPU.

// Codice tipico per Canvas Fingerprinting
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.textBaseline = 'top';
ctx.font = '14px Arial';
ctx.fillText('Browser fingerprint', 2, 2);
const fingerprint = canvas.toDataURL();

Per proteggere, puoi aggiungere rumore casuale all'API Canvas:

const canvasNoiseScript = `
    // Aggiungiamo rumore casuale a Canvas
    const originalToDataURL = HTMLCanvasElement.prototype.toDataURL;
    const originalToBlob = HTMLCanvasElement.prototype.toBlob;
    const originalGetImageData = CanvasRenderingContext2D.prototype.getImageData;
    
    // Funzione per aggiungere rumore
    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) {
            // Aggiungiamo un rumore minimo a RGB (non visibile ad occhio)
            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);
    };
    
    // Ridefiniamo 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);
    };
`;

WebGL Fingerprinting

WebGL fornisce informazioni sulla scheda video e sui driver. I browser headless mostrano spesso SwiftShader (renderer software) invece della vera GPU:

const webglMaskScript = `
    // Mascheriamo i parametri 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);
    };
    
    // Anche per 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 del contesto audio

L'Audio API fornisce anche un'impronta unica. Aggiungiamo rumore all'elaborazione audio:

const audioMaskScript = `
    // Aggiungiamo rumore al contesto 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);
                // Aggiungiamo un rumore minimo
                for (let i = 0; i < array.length; i++) {
                    array[i] += Math.random() * 0.0001;
                }
            };
            return analyser;
        };
    }
`;

Imitazione del comportamento umano

Anche con una mascheratura tecnica perfetta, i bot si rivelano attraverso il comportamento. I sistemi di apprendimento automatico analizzano i modelli di movimenti del mouse, la velocità delle azioni e la sequenza degli eventi.

Ritardi casuali tra le azioni

Non utilizzare mai ritardi fissi. Gli utenti reali fanno pause di durata variabile:

import random
import time

def human_delay(min_seconds=1, max_seconds=3):
    """Ritardo casuale che imita un umano"""
    delay = random.uniform(min_seconds, max_seconds)
    time.sleep(delay)

# Utilizzo
driver.get('https://example.com')
human_delay(2, 4)  # Pausa di 2-4 secondi

element = driver.find_element(By.ID, 'search')
human_delay(0.5, 1.5)  # Breve pausa prima dell'input

element.send_keys('search query')
human_delay(1, 2)

Movimento fluido del mouse

I bot muovono il mouse in linee rette o teletrasportano il cursore. Gli utenti reali creano traiettorie curve con accelerazione e decelerazione:

// Puppeteer: movimento fluido del mouse
async function humanMouseMove(page, targetX, targetY) {
    const steps = 25; // Numero di punti intermedi
    const currentPos = await page.evaluate(() => ({
        x: window.mouseX || 0,
        y: window.mouseY || 0
    }));
    
    for (let i = 0; i <= steps; i++) {
        const t = i / steps;
        // Utilizziamo easing per 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);
    }
    
    // Salviamo la posizione
    await page.evaluate((x, y) => {
        window.mouseX = x;
        window.mouseY = y;
    }, targetX, targetY);
}

// Utilizzo
await humanMouseMove(page, 500, 300);
await page.mouse.click(500, 300);

Scrolling naturale

Gli utenti reali scrollano in modo fluido, con pause per leggere il contenuto:

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) {
        // Passo di scroll casuale (200-500px)
        const scrollStep = Math.floor(Math.random() * 300) + 200;
        currentPosition += scrollStep;
        
        // Scorrimento fluido
        await page.evaluate((pos) => {
            window.scrollTo({
                top: pos,
                behavior: 'smooth'
            });
        }, currentPosition);
        
        // Pausa per "leggere" il contenuto (1-3 secondi)
        await page.waitForTimeout(Math.random() * 2000 + 1000);
    }
}

// Utilizzo
await page.goto('https://example.com');
await humanScroll(page);

Input di testo naturale

Le persone digitano a velocità diverse, fanno errori di battitura e li correggono:

async function humanTypeText(page, selector, text) {
    await page.click(selector);
    
    for (let char of text) {
        // Ritardo casuale tra i tasti (50-200ms)
        const delay = Math.random() * 150 + 50;
        await page.waitForTimeout(delay);
        
        // 5% di probabilità di errore di battitura
        if (Math.random() < 0.05) {
            // Digitiamo un carattere casuale
            const wrongChar = String.fromCharCode(97 + Math.floor(Math.random() * 26));
            await page.keyboard.type(wrongChar);
            await page.waitForTimeout(100 + Math.random() * 100);
            // Cancelliamo (Backspace)
            await page.keyboard.press('Backspace');
            await page.waitForTimeout(50 + Math.random() * 50);
        }
        
        await page.keyboard.type(char);
    }
}

// Utilizzo
await humanTypeText(page, '#search-input', 'example search query');

Integrazione di proxy per completa anonimato

La mascheratura del browser è inutile se tutte le richieste provengono da un solo indirizzo IP. I sistemi di protezione anti-bot monitorano il numero di richieste da ciascun IP e bloccano attività sospette. I proxy sono un componente obbligatorio di qualsiasi automazione seria.

Scelta del tipo di proxy

Diverse attività richiedono diversi tipi di proxy:

Tipo di proxy Vantaggi Applicazione
Proxy residenziali Maggiore anonimato, meno probabilità di essere bloccati Scraping di dati, accesso a contenuti geo-bloccati
Proxy datacenter Velocità elevate, costi inferiori Automazione di massa, test di carico
Proxy mobili Indirizzi IP variabili, maggiore anonimato Accesso a contenuti limitati, scraping di dati

Librerie e strumenti pronti

Esistono diverse librerie e strumenti che possono semplificare la mascheratura dell'automazione. Ecco alcune delle più popolari:

  • puppeteer-extra — estensione di Puppeteer con plugin per la mascheratura
  • selenium-stealth — libreria per mascherare Selenium
  • undetected-chromedriver — ChromeDriver che elude i sistemi di rilevazione
  • proxy-rotation — libreria per gestire la rotazione dei proxy

Testare il livello di rilevazione

È importante testare frequentemente il livello di rilevazione delle tue automazioni. Puoi utilizzare strumenti come SannySoft Bot Detection per verificare se il tuo setup è stato rilevato.

Conclusione

Mascherare l'automazione dei browser è un compito complesso ma necessario per evitare il blocco da parte dei sistemi di protezione anti-bot. Seguendo le tecniche e i metodi descritti in questa guida, puoi migliorare significativamente le tue possibilità di successo.

```