AntiDetect
Funzionalità Tecnologia Prezzi Per chi è
Docs Blog FAQ
Lingua
EnglishItalianoDeutschEspañolРусский
Scarica

Chrome headless è un vicolo cieco

Il nuovo headless ha chiuso il divario aperto dal vecchio headless. Non ha chiuso quello sottostante. Se stai ancora scegliendo fra headless e headful, stai ottimizzando la variabile sbagliata — e c'è una terza opzione che non costa quasi nulla.

Due modalità headless, una sola reputazione

Fino a Chrome 112, --headless significava il vecchio headless: un percorso binario separato che non era davvero Chrome. Aveva uno user agent suo contenente la stringa HeadlessChrome, nessun supporto alle estensioni, nessun chrome.runtime, nessun elenco di plugin e un percorso di rendering che saltava grandi parti della pipeline reale. Rilevarlo era una riga di codice.

Chrome 112 ha introdotto il nuovo headless (--headless=new, e da Chrome 132 semplicemente --headless). È il browser vero con la finestra non disegnata. Le estensioni funzionano, l'elenco dei plugin è popolato, chrome.runtime esiste e lo user agent non si annuncia più. Ha chiuso quasi ogni segnale che perdeva la vecchia modalità.

La reputazione è rimasta comunque, e in gran parte a ragione. Il nuovo headless ha rimosso le tracce facili. Quello che non ha rimosso è lo strato sotto di esse.

Cosa lo tradisce ancora

SwiftShader, quello che chiude la sessione

Il segnale più affidabile in assoluto, e quello su cui inciampano quasi tutti. Senza GPU — che è lo stato normale di un server — Chrome ripiega sulla rasterizzazione software, e WebGL riporta:

UNMASKED_VENDOR_WEBGL   → "Google Inc. (Google)"
UNMASKED_RENDERER_WEBGL → "ANGLE (Google, Vulkan 1.3.0 (SwiftShader Device ...))"

Quella coppia esiste su zero dispositivi consumer. Non "raramente": zero. Nessuno naviga su Instagram con il rendering software. Non è un segnale probabilistico che alza un punteggio; è un segnale categorico che chiude la sessione.

È anche il motivo per cui --disable-gpu è un consiglio pessimo in questo caso d'uso. Il flag viene copiato in massa da thread di risoluzione problemi su Docker dove risolve un crash, e forza esattamente il ripiego di cui sopra.

La finestra che non c'è

Headless deve comunque inventarsi una finestra, e l'invenzione si vede. outerWidth e outerHeight spesso coincidono con innerWidth e innerHeight, perché non c'è chrome di cui tenere conto — un Chrome desktop vero ha circa 16 pixel di differenza in orizzontale e 85-90 in verticale. screenX e screenY stanno a zero. screen.availHeight è uguale a screen.height, il che significa che su quella macchina non esiste da nessuna parte una barra delle applicazioni o un dock.

Non si muove mai niente

Nessun movimento del mouse, nessuna inerzia dello scorrimento, nessun focus e blur mentre l'utente cambia finestra, nessun visibilitychange quando una scheda passa in secondo piano. Cloudflare Turnstile e i suoi pari osservano queste cose di continuo, non come singolo controllo. Una sessione con un fingerprint pulito e zero eventi di input è una sessione che ha superato ogni test statico e fallito l'unico dinamico.

Lo stack sottostante

Headless non cambia i fingerprint TLS o HTTP/2 — il che è una buona notizia sul serio, dato che una build Chromium vera ti dà handshake da Chrome veri in entrambi i casi. Non cambia nemmeno la superficie CDP, che è dove l'automazione viene beccata davvero. Cambiare modalità non sposta né l'una né l'altra.

Quattro strati. Headless ne ripara uno e ne rompe un altro; i due sotto non li tocca.

Perché i plugin stealth hanno smesso di funzionare

puppeteer-extra-plugin-stealth e i suoi discendenti applicano una serie di patch JavaScript all'avvio del documento: nascondono webdriver, popolano navigator.plugins, falsificano chrome.runtime e così via. Nel 2019 spesso bastava.

Oggi non basta più, per una ragione strutturale e non di manutenzione. Ogni patch è un override JavaScript, e gli override JavaScript hanno una forma. I getter nativi si stringificano come [native code]; i sostituti no. Le proprietà del prototipo non compaiono come proprietà proprie; i sostituti sì. E nessuno script a livello di pagina raggiunge lo scope di un Web Worker, quindi qualsiasi valore corretto sul thread principale non concorda con la copia del worker.

I benchmark di rilevamento pubblicati nel 2026 riportano un'identificazione quasi totale delle sessioni con plugin stealth — un fornitore indica Playwright puro al 98,2% e le sessioni commerciali browserless in modalità stealth al 100%, con tassi di falsi positivi sotto l'1%. Quei numeri vengono da un'azienda che vende sistemi di rilevamento e vanno letti tenendolo presente, ma la direzione non è in discussione.

I plugin non sono scritti male. Stanno lavorando a un livello che non può esprimere la risposta.

L'opzione che non è nel menu

L'alternativa "headless o headful" nasconde la scelta che funziona davvero: Chrome headful su un display virtuale.

Su Linux, esegui Xvfb — un vero X server che renderizza in memoria invece che su un monitor. Chrome parte senza alcun flag --headless. È un browser completo, che disegna una finestra completa, con rendering GPU reale se l'host ne ha una. Non c'è alcuna modalità headless da rilevare perché non c'è alcuna modalità headless.

Xvfb :99 -screen 0 1920x1080x24 &
DISPLAY=:99 google-chrome --window-size=1920,1080

Cosa risolve: il segnale SwiftShader (con una GPU presente), i segnali sulla geometria della finestra, la chrome mancante, availHeight e l'intera classe di tracce del tipo "non c'è nessun display". Cosa non risolve: i leak di CDP e il comportamento. Quelli richiedono lavoro a parte.

Il costo sono qualche decina di megabyte di RAM per istanza e una riga nel tuo script di provisioning. Rispetto a mantenere un set di patch stealth contro un bersaglio in movimento, è quasi gratis.

Quando headless è ancora la scelta giusta

Niente di tutto questo rende headless inutile. Lo rende lo strumento sbagliato per un compito specifico.

Headless va bene per: test interni, generazione di screenshot e PDF, crawling di siti tuoi, scraping di siti senza difese anti-bot, pipeline di CI, controllo dei link, monitoraggio dell'uptime. Ovunque nessuno stia cercando di identificarti, headless è più veloce e più leggero e dovresti usarlo.

Headless è lo strumento sbagliato per: qualsiasi cosa dietro Cloudflare, Akamai, DataDome o PerimeterX; qualsiasi cosa che coinvolga un account loggato su una piattaforma a cui la cosa interessa; qualsiasi cosa in cui essere classificato come automazione abbia un costo.

La distinzione non è il livello di raffinatezza tecnica. È se c'è un avversario.

Una breve diagnosi

Se vuoi sapere a che punto è la tua configurazione attuale, quattro controlli in ordine di quanto ti dicono:

  1. Renderer WebGL. Leggi UNMASKED_RENDERER_WEBGL. Se nomina SwiftShader, fermati e sistema quello prima di ogni altra cosa; niente altro conta.
  2. Geometria della finestra. outerHeight - innerHeight dovrebbe essere circa 85-90 su Chrome desktop, e screen.availHeight dovrebbe essere più piccolo di screen.height.
  3. CreepJS. Caricalo e leggi le sezioni su headless e sul rilevamento delle bugie. È brutale su ciò che trova.
  4. Un bersaglio vero. Carica un sito che ti interessa davvero e vedi se ti arriva una sfida. Ogni test sintetico è un surrogato di questo.

Esegui gli stessi quattro controlli su un browser che guidi a mano sulla stessa macchina. Le differenze fra i due elenchi sono la tua lista di cose da fare.

Headful, sempre

I profili di P8 girano come finestre vere con rendering GPU vero. L'automazione li guida come farebbe una persona, senza nessuna modalità headless da nascondere.

Inizia gratis
Tutti gli articoli Prossimo: a WebRTC del tuo proxy non importa nulla