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.