Agent IA sur le web : un vrai Chrome avec GPU pour Claude
Un agent IA qui agit sur le web (remplir un formulaire, comparer des offres, suivre un tableau de bord) a besoin d’un vrai navigateur qui tourne en continu, ailleurs que sur votre portable. Deux erreurs le font repérer comme robot dès la première page :
- le lancer en mode headless : Chrome s’annonce alors lui-même comme
HeadlessChromedans son User-Agent ; - le lancer sans GPU : la carte graphique devient
SwiftShader(un GPU émulé), ou WebGL disparaît complètement.
Un PC de bureau n’a jamais ces caractéristiques. La règle est donc simple : un vrai Chrome, en fenêtre, sur un écran virtuel, avec un vrai GPU.
Cet article montre comment faire tourner Chrome avec le GPU pour un agent Claude, compare Xvfb et Xorg « dummy », couvre Selenium, et explique ce que le GPU change (ou pas) face à la détection de bots de Cloudflare. Toutes les mesures sont reproductibles : le script est public.
L’architecture
- L’agent (Claude Code ou le Claude Agent SDK) décide des actions ;
- Playwright MCP expose le navigateur à l’agent sous forme d’outils
(
browser_navigate,browser_click,browser_type,browser_snapshot…) et pilote Chromium par CDP (Chrome DevTools Protocol) ; - Chromium tourne en mode fenêtré sur un écran virtuel Xvfb, et fait son rendu sur le GPU via ANGLE/Vulkan ;
- x11vnc vous permet de regarder l’écran, et de reprendre la main (pour une double authentification, par exemple).
Le déroulé d’une action :
Les mesures
Conditions
- Serveur de test Linux GPU, VM configurée comme l’offre Perf 2 (4 vCPU), GPU Intel UHD 770 partagé entre plusieurs VM (la VM voit son propre périphérique GPU, /dev/dri, avec le pilote Linux standard), Debian 13 ;
- Chromium 156, Playwright MCP 0.0.83, Selenium 4.31 + chromedriver 156,
Xvfb (Xorg 21) et
xserver-xorg-video-dummy0.4.0 ; - le GPU n’était pas sollicité par d’autres VM pendant les mesures ;
- mesures du 29/10/2026.
Comment c’est calculé
Le banc d’essai est une page WebGL 2 (webgl-bench.html) :
- un canvas de 1920×1080 ;
- un fragment shader qui calcule 64 sinus/cosinus par pixel, soit environ 265 millions de sinus/cosinus par image ;
?draws=Ndessine N images plein écran par frame (requestAnimationFrame) ;- après chaque frame,
readPixelslit un pixel : cela oblige le navigateur à terminer le rendu, sinon il pourrait mettre les commandes en file d’attente et afficher un score flatteur mais faux ; - au bout de 5 s : images/s = nombre d’images ÷ durée. On vérifie aussi que le programme est bien lié et que le pixel lu a la bonne couleur.
Chrome est lancé avec --disable-gpu-vsync --disable-frame-rate-limit pour ne
pas être limité à 60 images/s. La charge CPU est la différence des compteurs
de /proc/stat pendant la seule durée du test, rapportée en vCPU occupés.
chromium --headless=new --use-angle=vulkan --ignore-gpu-blocklist \
--disable-gpu-vsync --disable-frame-rate-limit \
--enable-logging=stderr --v=0 "file:///root/webgl-bench.html?draws=10" \
2>&1 | grep -m1 RESULT
Résultat 1 : le GPU fait la différence (×20)
--headless=new, 10 images par frame :
| Rendu | Images 1080p/s | CPU occupé |
|---|---|---|
| SwiftShader (défaut, CPU) | 13 | 3,9 vCPU sur 4 |
UHD 770, --use-angle=vulkan | ~260 | 0,6 vCPU |
UHD 770, --use-angle=gl-egl | ~230 | — |
Avec le GPU, le rendu est 20 fois plus rapide et le processeur reste libre. Pour un agent, c’est le point clé : sans GPU, une page lourde (carte, tableau de bord, vidéo) sature les 4 vCPU, et l’agent, Playwright et l’écran virtuel se disputent ce qui reste.
Résultat 2 : Xvfb ou Xorg dummy, peu importe
On entend souvent qu’il faut remplacer Xvfb par Xorg avec le pilote dummy pour « faire plus vrai ». Mesuré, en mode fenêtré, 1 image par frame :
| Écran virtuel | Sans option | SwiftShader forcé | GPU (--use-angle=vulkan) |
|---|---|---|---|
| Xvfb | WebGL désactivé | 9,2 images/s | 67,6 images/s |
| Xorg + pilote dummy | WebGL désactivé | 8,7 images/s | 58,8 images/s, puis contexte WebGL perdu |
- Aucun des deux n’utilise le GPU par lui-même :
glxinfoaffichellvmpipe(rendu logiciel) sur les deux ; - sans option, Chrome désactive WebGL sur les deux ;
- avec le pilote dummy, notre essai GPU a perdu le contexte WebGL au bout de
quelques images (
eglCreateWindowSurface failed with error EGL_BAD_MATCH). Xvfb, lui, a été stable.
Le choix de l’écran virtuel est donc secondaire : c’est le GPU qui compte pour les performances, la plupart du temps. Restez sur Xvfb, plus simple, et ajoutez les deux options GPU à Chrome.
Résultat 3 : quel moteur de rendu voit le site
C’est ce que lit un script de détection (WEBGL_debug_renderer_info) :
| Configuration | Moteur de rendu WebGL annoncé |
|---|---|
--headless=new sans option | SwiftShader (CPU émulé) |
| Xvfb ou dummy, sans option | pas de WebGL |
| Selenium + Xvfb, sans option | pas de WebGL |
| Selenium + Xvfb, options GPU | Intel(R) UHD Graphics 770 |
| Playwright MCP, fenêtré sur Xvfb, options GPU | Intel(R) UHD Graphics 770 |
| headless, options GPU | Intel(R) UHD Graphics 770 |
Résultat 4 : headless = repéré tout de suite
Ce qu’un script JavaScript lit en une ligne sur la page, dans les quatre configurations (Chromium 156) :
| Headless sans GPU | Headless + GPU | Fenêtre Xvfb sans GPU | Fenêtre Xvfb + GPU | |
|---|---|---|---|---|
navigator.userAgent | ❌ HeadlessChrome/156… | ❌ HeadlessChrome/156… | ✅ Chrome/156… | ✅ Chrome/156… |
| Carte graphique (WebGL) | ❌ SwiftShader | ✅ Intel UHD Graphics 770 | ❌ aucune (WebGL coupé) | ✅ Intel UHD Graphics 770 |
screen | ❌ 800×600 | ❌ 800×600 | ✅ 1920×1080 | ✅ 1920×1080 |
| Taille de fenêtre | 780×580 | 780×580 | 945×1060 | 1919×1079 |
- Le mode headless se dénonce lui-même : le mot
HeadlessChromeest écrit dans le User-Agent, envoyé à chaque requête. C’est le signal le plus simple à bloquer, et tous les systèmes anti-bots le font. L’écran de 800×600 confirme le diagnostic ; - sans GPU, même en fenêtre, WebGL disparaît : aucun navigateur de bureau moderne n’est dans ce cas ;
- seule la dernière colonne ressemble à un vrai poste de travail : un Chrome en fenêtre sur un écran 1080p, avec une vraie carte graphique Intel.
Corriger le User-Agent à la main ne suffit pas : le mode headless a d’autres différences (taille d’écran, comportement du rendu, API absentes), et un User-Agent qui ne colle pas avec le reste est lui-même suspect. Le plus fiable est de ne pas utiliser le mode headless du tout : sur un serveur, c’est exactement à ça que sert Xvfb.
Résultat 5 : en fenêtre, le GPU décharge énormément le CPU
Le mode fenêtré a un coût : Chrome doit dessiner toute la page à l’écran. Sans GPU, c’est le processeur qui fait tout. Même animation WebGL 1080p, Chrome en fenêtre sur Xvfb, fréquence normale (60 images/s maximum), charge CPU mesurée sur toute la VM pendant le test :
| Chrome en fenêtre sur Xvfb | Images/s | CPU occupé (VM de 4 vCPU) |
|---|---|---|
| Sans GPU (SwiftShader) | 9,8 | 3,4 vCPU : la VM est saturée |
| Sans GPU, scène 3× plus lourde | 4,0 | 3,7 vCPU |
| Avec le GPU UHD 770 | 60 (fluide) | 0,3 vCPU |
| Avec le GPU, scène 3× plus lourde | 60 | 0,3 vCPU |
Avec le GPU, Chrome affiche 6 fois plus d’images en utilisant plus de 10 fois moins de CPU, soit environ 70 fois moins de CPU par image. Sans GPU, la VM est saturée et n’atteint même pas 10 images/s : l’agent, Playwright et le reste du système se battent pour les miettes, chaque action prend plus de temps, et les pages lourdes deviennent inutilisables. Avec le GPU, il reste 3,7 vCPU libres pour le travail utile.
C’est la combinaison gagnante : le mode fenêtré évite d’être repéré, et le GPU le rend gratuit pour le processeur.
Ce que le GPU change face à Cloudflare
Cloudflare (Bot Management, Turnstile) combine de nombreux signaux :
empreinte TLS et HTTP/2, réputation de l’adresse IP, tests JavaScript dans la
page, comportement (rythme, mouvements), modèles statistiques. Un navigateur
sans GPU se trahit vite dans les tests JavaScript : SwiftShader comme
carte graphique, ou pas de WebGL du tout, c’est une signature typique de
navigateur automatisé dans un datacenter.
Avec le GPU, Chrome annonce une vraie carte Intel et rend la page comme un PC de bureau. Concrètement, cela réduit les faux positifs : des CAPTCHA ou des blocages sur des sites où votre agent a parfaitement le droit d’aller.
Mais il faut être clair : CDP + pilote + bonne IP ne rend pas indétectable.
- le pilotage par CDP laisse lui-même des traces détectables ;
- les adresses de datacenter sont connues comme telles ;
- le comportement d’un agent (vitesse, enchaînement des actions) se repère ;
- les règles changent en permanence : ce qui passe aujourd’hui sera bloqué demain.
La bonne approche : se faire reconnaître
Pour un agent légitime, la voie durable est d’être identifié plutôt que caché :
- Web Bot Auth (« signed agents » chez Cloudflare) : l’agent signe ses requêtes HTTP avec une clé Ed25519 (HTTP Message Signatures, RFC 9421) et publie sa clé publique dans un annuaire ; les sites peuvent alors l’autoriser explicitement ;
- un User-Agent honnête, le respect de
robots.txtet des conditions d’utilisation, un débit raisonnable ; - sur vos propres sites derrière Cloudflare (tests E2E, supervision), une règle WAF qui laisse passer l’IP de votre serveur.
Mise en place
1. Paquets
apt install chromium xvfb x11vnc nodejs npm
2. Écran virtuel et VNC (systemd)
# /etc/systemd/system/xvfb.service
[Unit]
Description=Xvfb :99
[Service]
ExecStart=/usr/bin/Xvfb :99 -screen 0 1920x1080x24 -nolisten tcp
Restart=always
[Install]
WantedBy=multi-user.target
# /etc/systemd/system/x11vnc.service
[Unit]
Description=x11vnc sur :99 (localhost uniquement)
After=xvfb.service
Requires=xvfb.service
[Service]
ExecStart=/usr/bin/x11vnc -display :99 -localhost -forever -shared -nopw
Restart=always
[Install]
WantedBy=multi-user.target
systemctl enable --now xvfb x11vnc
# depuis votre ordinateur :
ssh -L 5900:localhost:5900 root@votre-serveur # puis un client VNC sur localhost:5900
VNC n’écoute que sur localhost : on y accède seulement par le tunnel SSH.
3. Playwright MCP avec le GPU
Fichier /root/mcp.json :
{
"browser": {
"browserName": "chromium",
"launchOptions": {
"executablePath": "/usr/bin/chromium",
"headless": false,
"args": ["--use-angle=vulkan", "--ignore-gpu-blocklist", "--no-sandbox"]
}
}
}
Avec Claude Code installé sur le serveur :
claude mcp add playwright --env DISPLAY=:99 -- \
npx @playwright/mcp@latest --config /root/mcp.json
Ou en serveur HTTP, si l’agent tourne ailleurs (tunnel SSH vers le port) :
DISPLAY=:99 npx @playwright/mcp@latest --config /root/mcp.json --port 8931
# point d'accès MCP : http://localhost:8931/mcp
Pour vérifier, demandez à l’agent d’ouvrir une page qui affiche le moteur de
rendu WebGL : il doit annoncer Intel(R) UHD Graphics 770.
4. Selenium + Xvfb
apt install python3-selenium chromium-driver
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
o = webdriver.ChromeOptions()
o.binary_location = "/usr/bin/chromium"
for a in ["--use-angle=vulkan", "--ignore-gpu-blocklist",
"--no-sandbox", "--window-size=1920,1080"]:
o.add_argument(a)
driver = webdriver.Chrome(options=o, service=Service("/usr/bin/chromedriver"))
xvfb-run -a -s "-screen 0 1920x1080x24" python3 mon_script.py
Avec le Selenium 4.31 de Debian, indiquez explicitement chromedriver via
Service(...) : sinon il ne le trouve pas (NoSuchDriverException).
Questions fréquentes
Headless ou fenêtré sur Xvfb ?
Fenêtré, sans hésiter. Le headless s’annonce HeadlessChrome et se fait
bloquer sur la plupart des sites protégés. Le mode fenêtré permet en plus de
suivre l’agent par VNC et de reprendre la main. Réservez le headless à vos
propres tests, sur vos propres sites.
Et le computer use de Claude (captures d’écran + clics) ? Il a besoin d’un vrai écran : Xvfb + un navigateur fenêtré, exactement le schéma ci-dessus. Le GPU rend chaque capture plus vite et laisse le CPU au reste.
Une offre Perf 1 suffit-elle ? Pour un agent qui navigue sur des sites classiques, oui. Les mesures ci-dessus ont été faites avec 4 vCPU (Perf 2), utile si l’agent ouvre plusieurs onglets ou des pages lourdes.
Essayer
Serveur Linux GPU avec Intel UHD 770 dans la VM, Mesa et Vulkan déjà installés. À partir de 14,99 € HT/mois, accès root, IPv6 dédiée. Voir aussi : Chrome avec le GPU sur un serveur Linux et Xvfb : guide pratique.