Blog

AI-agent op het web: een echte Chrome met GPU voor Claude

Een Claude-agent (Playwright MCP, computer use) laten surfen in Chrome met GPU op een server: Xvfb vs Xorg dummy, Selenium, Cloudflare-botdetectie, metingen en installatie.

AI-agent op het web: een echte Chrome met GPU voor Claude

Een AI-agent die op het web handelt (een formulier invullen, aanbiedingen vergelijken, een dashboard in de gaten houden) heeft een echte browser nodig die continu draait, ergens anders dan op je laptop. Twee fouten zorgen ervoor dat hij al op de eerste pagina als bot wordt herkend:

  1. hem in headless-modus starten: Chrome meldt zichzelf dan als HeadlessChrome in zijn User-Agent;
  2. hem zonder GPU starten: de grafische kaart wordt SwiftShader (een geëmuleerde GPU), of WebGL verdwijnt helemaal.

Een desktop-pc heeft nooit deze kenmerken. De regel is dus eenvoudig: een echte Chrome, in een venster, op een virtueel scherm, met een echte GPU.

Dit artikel laat zien hoe je Chrome met de GPU laat draaien voor een Claude-agent, vergelijkt Xvfb en Xorg „dummy”, behandelt Selenium, en legt uit wat de GPU wel (of niet) verandert tegenover de botdetectie van Cloudflare. Alle metingen zijn reproduceerbaar: het script is openbaar.

De architectuur

UML-deploymentdiagram: de Claude-agent stuurt Chromium aan via Playwright MCP; Chromium toont op Xvfb en rendert op de Intel UHD 770-GPU; met x11vnc bekijk je het scherm via een SSH-tunnel

  • De agent (Claude Code of de Claude Agent SDK) beslist over de acties;
  • Playwright MCP stelt de browser als tools beschikbaar aan de agent (browser_navigate, browser_click, browser_type, browser_snapshot…) en stuurt Chromium aan via CDP (Chrome DevTools Protocol);
  • Chromium draait in venstermodus op een virtueel scherm Xvfb, en rendert op de GPU via ANGLE/Vulkan;
  • met x11vnc kun je het scherm bekijken en de controle overnemen (bijvoorbeeld voor tweestapsverificatie).

Het verloop van een actie:

UML-sequentiediagram: browser_navigate, Page.navigate via CDP, verzoek naar de site, eventuele Cloudflare-controles, GPU-rendering, snapshot teruggestuurd naar de agent

De metingen

Omstandigheden

  • Linux GPU-testserver, VM geconfigureerd zoals het Perf 2-aanbod (4 vCPU), Intel UHD 770-GPU gedeeld tussen meerdere VM’s (de VM ziet zijn eigen GPU-apparaat, /dev/dri, met de standaard Linux-driver), Debian 13;
  • Chromium 156, Playwright MCP 0.0.83, Selenium 4.31 + chromedriver 156, Xvfb (Xorg 21) en xserver-xorg-video-dummy 0.4.0;
  • de GPU werd tijdens de metingen niet door andere VM’s belast;
  • metingen van 29-10-2026.

Hoe het berekend wordt

De benchmark is een WebGL 2-pagina (webgl-bench.html):

  1. een canvas van 1920×1080;
  2. een fragment shader die 64 sinussen/cosinussen per pixel berekent, dus ongeveer 265 miljoen sinussen/cosinussen per beeld;
  3. ?draws=N tekent N fullscreen-beelden per frame (requestAnimationFrame);
  4. na elke frame leest readPixels één pixel uit: dat dwingt de browser om het renderen af te ronden, anders zou hij de commando’s in een wachtrij kunnen zetten en een flatteuze maar onjuiste score tonen;
  5. na 5 s: beelden/s = aantal beelden ÷ duur. We controleren ook dat het programma correct gelinkt is en dat de uitgelezen pixel de juiste kleur heeft.

Chrome wordt gestart met --disable-gpu-vsync --disable-frame-rate-limit om niet beperkt te worden tot 60 beelden/s. De CPU-belasting is het verschil tussen de tellers van /proc/stat over alleen de duur van de test, uitgedrukt in bezette vCPU’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

Resultaat 1: de GPU maakt het verschil (×20)

--headless=new, 10 beelden per frame:

Rendering1080p-beelden/sBezette CPU
SwiftShader (standaard, CPU)133,9 van de 4 vCPU
UHD 770, --use-angle=vulkan~2600,6 vCPU
UHD 770, --use-angle=gl-egl~230—

Met de GPU is de rendering 20 keer sneller en blijft de processor vrij. Voor een agent is dat het kernpunt: zonder GPU legt een zware pagina (kaart, dashboard, video) alle 4 vCPU’s vol, en vechten de agent, Playwright en het virtuele scherm om wat er overblijft.

Resultaat 2: Xvfb of Xorg dummy, maakt weinig uit

Je hoort vaak dat je Xvfb moet vervangen door Xorg met de dummy-driver om het „echter” te laten lijken. Gemeten, in venstermodus, 1 beeld per frame:

Virtueel schermZonder optiesSwiftShader geforceerdGPU (--use-angle=vulkan)
XvfbWebGL uitgeschakeld9,2 beelden/s67,6 beelden/s
Xorg + dummy-driverWebGL uitgeschakeld8,7 beelden/s58,8 beelden/s, daarna WebGL-context verloren
  • Geen van beide gebruikt uit zichzelf de GPU: glxinfo toont llvmpipe (softwarerendering) op allebei;
  • zonder opties schakelt Chrome WebGL uit op allebei;
  • met de dummy-driver verloor onze GPU-test na enkele beelden de WebGL-context (eglCreateWindowSurface failed with error EGL_BAD_MATCH). Xvfb bleef stabiel.

De keuze van het virtuele scherm is dus bijzaak: voor de prestaties telt meestal de GPU. Blijf bij Xvfb, dat is eenvoudiger, en voeg de twee GPU-opties toe aan Chrome.

Resultaat 3: welke renderer ziet de site

Dit is wat een detectiescript uitleest (WEBGL_debug_renderer_info):

ConfiguratieGemelde WebGL-renderer
--headless=new zonder optiesSwiftShader (geëmuleerde CPU)
Xvfb of dummy, zonder optiesgeen WebGL
Selenium + Xvfb, zonder optiesgeen WebGL
Selenium + Xvfb, GPU-optiesIntel(R) UHD Graphics 770
Playwright MCP, venstermodus op Xvfb, GPU-optiesIntel(R) UHD Graphics 770
headless, GPU-optiesIntel(R) UHD Graphics 770

Resultaat 4: headless = meteen herkend

Wat een JavaScript-script met één regel op de pagina uitleest, in de vier configuraties (Chromium 156):

Headless zonder GPUHeadless + GPUVenster op Xvfb zonder GPUVenster op Xvfb + GPU
navigator.userAgent❌ HeadlessChrome/156…❌ HeadlessChrome/156…✅ Chrome/156…✅ Chrome/156…
Grafische kaart (WebGL)❌ SwiftShader✅ Intel UHD Graphics 770❌ geen (WebGL uitgeschakeld)✅ Intel UHD Graphics 770
screen❌ 800×600❌ 800×600✅ 1920×1080✅ 1920×1080
Venstergrootte780×580780×580945×10601919×1079
  • De headless-modus verraadt zichzelf: het woord HeadlessChrome staat in de User-Agent, die bij elk verzoek wordt meegestuurd. Dat is het eenvoudigste signaal om te blokkeren, en alle antibotsystemen doen dat. Het scherm van 800×600 bevestigt de diagnose;
  • zonder GPU verdwijnt WebGL, zelfs in een venster: geen enkele moderne desktopbrowser zit in die situatie;
  • alleen de laatste kolom lijkt op een echte werkplek: een Chrome in een venster op een 1080p-scherm, met een echte Intel-grafische kaart.

De User-Agent met de hand aanpassen is niet genoeg: de headless-modus heeft nog andere verschillen (schermgrootte, renderingsgedrag, ontbrekende API’s), en een User-Agent die niet strookt met de rest is zelf verdacht. Het betrouwbaarst is om de headless-modus helemaal niet te gebruiken: op een server is dat precies waar Xvfb voor dient.

Resultaat 5: in een venster ontlast de GPU de CPU enorm

De venstermodus heeft een prijs: Chrome moet de hele pagina op het scherm tekenen. Zonder GPU doet de processor alles. Dezelfde WebGL-animatie in 1080p, Chrome in een venster op Xvfb, normale framerate (maximaal 60 beelden/s), CPU-belasting gemeten over de hele VM tijdens de test:

Chrome in een venster op XvfbBeelden/sBezette CPU (VM met 4 vCPU)
Zonder GPU (SwiftShader)9,83,4 vCPU: de VM is verzadigd
Zonder GPU, 3× zwaardere scène4,03,7 vCPU
Met de UHD 770-GPU60 (vloeiend)0,3 vCPU
Met de GPU, 3× zwaardere scène600,3 vCPU

Met de GPU toont Chrome 6 keer meer beelden en gebruikt het meer dan 10 keer minder CPU, dus ongeveer 70 keer minder CPU per beeld. Zonder GPU is de VM verzadigd en haalt hij zelfs geen 10 beelden/s: de agent, Playwright en de rest van het systeem vechten om de kruimels, elke actie duurt langer, en zware pagina’s worden onbruikbaar. Met de GPU blijven er 3,7 vCPU vrij voor nuttig werk.

Dat is de winnende combinatie: de venstermodus voorkomt dat je wordt herkend, en de GPU maakt hem gratis voor de processor.

Wat de GPU verandert tegenover Cloudflare

Cloudflare (Bot Management, Turnstile) combineert talloze signalen: TLS- en HTTP/2-vingerafdruk, reputatie van het IP-adres, JavaScript-tests in de pagina, gedrag (tempo, bewegingen), statistische modellen. Een browser zonder GPU verraadt zich snel in de JavaScript-tests: SwiftShader als grafische kaart, of helemaal geen WebGL, is een typische signatuur van een geautomatiseerde browser in een datacenter.

Met de GPU meldt Chrome een echte Intel-kaart en rendert het de pagina zoals een desktop-pc. Concreet vermindert dat de valse positieven: CAPTCHA’s of blokkades op sites waar je agent gewoon mag komen.

Maar laten we duidelijk zijn: CDP + driver + goed IP maakt je niet ondetecteerbaar.

  • aansturing via CDP laat zelf detecteerbare sporen na;
  • datacenteradressen zijn als zodanig bekend;
  • het gedrag van een agent (snelheid, opeenvolging van acties) valt op;
  • de regels veranderen voortdurend: wat vandaag lukt, wordt morgen geblokkeerd.

De juiste aanpak: jezelf laten herkennen

Voor een legitieme agent is de duurzame weg om geïdentificeerd te zijn in plaats van verborgen:

  • Web Bot Auth („signed agents” bij Cloudflare): de agent ondertekent zijn HTTP-verzoeken met een Ed25519-sleutel (HTTP Message Signatures, RFC 9421) en publiceert zijn publieke sleutel in een register; sites kunnen hem dan expliciet toelaten;
  • een eerlijke User-Agent, respect voor robots.txt en de gebruiksvoorwaarden, een redelijk verzoektempo;
  • op je eigen sites achter Cloudflare (E2E-tests, monitoring), een WAF-regel die het IP van je server doorlaat.

Installatie

1. Pakketten

apt install chromium xvfb x11vnc nodejs npm

2. Virtueel scherm en 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 op :99 (alleen localhost)
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
# vanaf je eigen computer:
ssh -L 5900:localhost:5900 root@jouw-server   # daarna een VNC-client op localhost:5900

VNC luistert alleen op localhost: je bereikt het uitsluitend via de SSH-tunnel.

3. Playwright MCP met de GPU

Bestand /root/mcp.json:

{
  "browser": {
    "browserName": "chromium",
    "launchOptions": {
      "executablePath": "/usr/bin/chromium",
      "headless": false,
      "args": ["--use-angle=vulkan", "--ignore-gpu-blocklist", "--no-sandbox"]
    }
  }
}

Met Claude Code geïnstalleerd op de server:

claude mcp add playwright --env DISPLAY=:99 -- \
  npx @playwright/mcp@latest --config /root/mcp.json

Of als HTTP-server, als de agent ergens anders draait (SSH-tunnel naar de poort):

DISPLAY=:99 npx @playwright/mcp@latest --config /root/mcp.json --port 8931
# MCP-endpoint: http://localhost:8931/mcp

Ter controle vraag je de agent een pagina te openen die de WebGL-renderer toont: die moet Intel(R) UHD Graphics 770 melden.

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 mijn_script.py

Geef met de Selenium 4.31 van Debian chromedriver expliciet op via Service(...): anders vindt hij het niet (NoSuchDriverException).

Veelgestelde vragen

Headless of venstermodus op Xvfb? Venstermodus, zonder twijfel. Headless meldt zich als HeadlessChrome en wordt op de meeste beschermde sites geblokkeerd. In venstermodus kun je de agent bovendien via VNC volgen en de controle overnemen. Bewaar headless voor je eigen tests, op je eigen sites.

En computer use van Claude (screenshots + klikken)? Dat heeft een echt scherm nodig: Xvfb + een browser in venstermodus, precies het schema hierboven. De GPU rendert elke screenshot sneller en laat de CPU vrij voor de rest.

Is een Perf 1-aanbod genoeg? Voor een agent die gewone sites bezoekt, ja. De metingen hierboven zijn gedaan met 4 vCPU (Perf 2), handig als de agent meerdere tabbladen of zware pagina’s opent.

Probeer het

Linux GPU-server met Intel UHD 770 in de VM, Mesa en Vulkan al geïnstalleerd. Vanaf €14,99 excl. btw/mnd, root-toegang, eigen IPv6-adres. Zie ook: Chrome met de GPU op een Linux-server en Xvfb: praktische gids.