Agente de IA en la web: un Chrome real con GPU para Claude
Un agente de IA que actúa en la web (rellenar un formulario, comparar ofertas, seguir un panel de control) necesita un navegador real que funcione de forma continua, en otro sitio que no sea tu portátil. Dos errores hacen que lo detecten como robot desde la primera página:
- lanzarlo en modo headless: Chrome se anuncia entonces a sí mismo como
HeadlessChromeen su User-Agent; - lanzarlo sin GPU: la tarjeta gráfica pasa a ser
SwiftShader(una GPU emulada), o WebGL desaparece por completo.
Un PC de escritorio nunca tiene estas características. La regla es, por tanto, sencilla: un Chrome real, en ventana, en una pantalla virtual, con una GPU real.
Este artículo muestra cómo ejecutar Chrome con la GPU para un agente Claude, compara Xvfb y Xorg «dummy», cubre Selenium y explica lo que la GPU cambia (o no) frente a la detección de bots de Cloudflare. Todas las mediciones son reproducibles: el script es público.
La arquitectura
- El agente (Claude Code o el Claude Agent SDK) decide las acciones;
- Playwright MCP expone el navegador al agente en forma de herramientas
(
browser_navigate,browser_click,browser_type,browser_snapshot…) y controla Chromium por CDP (Chrome DevTools Protocol); - Chromium funciona en modo ventana sobre una pantalla virtual Xvfb y renderiza en la GPU mediante ANGLE/Vulkan;
- x11vnc te permite ver la pantalla y retomar el control (para una autenticación de doble factor, por ejemplo).
El desarrollo de una acción:
Las mediciones
Condiciones
- Servidor de pruebas Linux GPU, VM configurada como la oferta Perf 2 (4 vCPU), GPU Intel UHD 770 compartida entre varias VM (la VM ve su propio dispositivo GPU, /dev/dri, con el driver Linux estándar), Debian 13;
- Chromium 156, Playwright MCP 0.0.83, Selenium 4.31 + chromedriver 156,
Xvfb (Xorg 21) y
xserver-xorg-video-dummy0.4.0; - ninguna otra VM usaba la GPU durante las mediciones;
- mediciones del 29/10/2026.
Cómo se calcula
El banco de pruebas es una página WebGL 2 (webgl-bench.html):
- un canvas de 1920×1080;
- un fragment shader que calcula 64 senos/cosenos por píxel, es decir, unos 265 millones de senos/cosenos por imagen;
?draws=Ndibuja N imágenes a pantalla completa por frame (requestAnimationFrame);- después de cada frame,
readPixelslee un píxel: esto obliga al navegador a terminar el renderizado; si no, podría poner los comandos en cola y mostrar una puntuación halagadora pero falsa; - al cabo de 5 s: imágenes/s = número de imágenes ÷ duración. También se comprueba que el programa está bien enlazado y que el píxel leído tiene el color correcto.
Chrome se lanza con --disable-gpu-vsync --disable-frame-rate-limit para no
quedar limitado a 60 imágenes/s. La carga de CPU es la diferencia de los
contadores de /proc/stat durante la duración de la prueba únicamente,
expresada en vCPU ocupadas.
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
Resultado 1: la GPU marca la diferencia (×20)
--headless=new, 10 imágenes por frame:
| Renderizado | Imágenes 1080p/s | CPU ocupada |
|---|---|---|
| SwiftShader (por defecto, CPU) | 13 | 3,9 vCPU de 4 |
UHD 770, --use-angle=vulkan | ~260 | 0,6 vCPU |
UHD 770, --use-angle=gl-egl | ~230 | — |
Con la GPU, el renderizado es 20 veces más rápido y el procesador queda libre. Para un agente, es el punto clave: sin GPU, una página pesada (mapa, panel de control, vídeo) satura las 4 vCPU, y el agente, Playwright y la pantalla virtual se disputan lo que queda.
Resultado 2: Xvfb o Xorg dummy, da igual
Se oye a menudo que hay que sustituir Xvfb por Xorg con el driver dummy para «parecer más real». Medido, en modo ventana, 1 imagen por frame:
| Pantalla virtual | Sin opciones | SwiftShader forzado | GPU (--use-angle=vulkan) |
|---|---|---|---|
| Xvfb | WebGL desactivado | 9,2 imágenes/s | 67,6 imágenes/s |
| Xorg + driver dummy | WebGL desactivado | 8,7 imágenes/s | 58,8 imágenes/s, luego contexto WebGL perdido |
- Ninguno de los dos usa la GPU por sí mismo:
glxinfomuestrallvmpipe(renderizado por software) en ambos; - sin opciones, Chrome desactiva WebGL en ambos;
- con el driver dummy, nuestra prueba con GPU perdió el contexto WebGL al cabo
de unas pocas imágenes (
eglCreateWindowSurface failed with error EGL_BAD_MATCH). Xvfb, en cambio, fue estable.
La elección de la pantalla virtual es, por tanto, secundaria: lo que cuenta para el rendimiento es la GPU, la mayoría de las veces. Quédate con Xvfb, más sencillo, y añade las dos opciones de GPU a Chrome.
Resultado 3: qué motor de renderizado ve el sitio
Es lo que lee un script de detección (WEBGL_debug_renderer_info):
| Configuración | Motor de renderizado WebGL anunciado |
|---|---|
--headless=new sin opciones | SwiftShader (CPU emulada) |
| Xvfb o dummy, sin opciones | sin WebGL |
| Selenium + Xvfb, sin opciones | sin WebGL |
| Selenium + Xvfb, opciones GPU | Intel(R) UHD Graphics 770 |
| Playwright MCP, en ventana sobre Xvfb, opciones GPU | Intel(R) UHD Graphics 770 |
| headless, opciones GPU | Intel(R) UHD Graphics 770 |
Resultado 4: headless = detectado al instante
Lo que un script JavaScript lee en una línea en la página, en las cuatro configuraciones (Chromium 156):
| Headless sin GPU | Headless + GPU | Ventana Xvfb sin GPU | Ventana Xvfb + GPU | |
|---|---|---|---|---|
navigator.userAgent | ❌ HeadlessChrome/156… | ❌ HeadlessChrome/156… | ✅ Chrome/156… | ✅ Chrome/156… |
| Tarjeta gráfica (WebGL) | ❌ SwiftShader | ✅ Intel UHD Graphics 770 | ❌ ninguna (WebGL desactivado) | ✅ Intel UHD Graphics 770 |
screen | ❌ 800×600 | ❌ 800×600 | ✅ 1920×1080 | ✅ 1920×1080 |
| Tamaño de ventana | 780×580 | 780×580 | 945×1060 | 1919×1079 |
- El modo headless se delata a sí mismo: la palabra
HeadlessChromefigura en el User-Agent, que se envía con cada petición. Es la señal más sencilla de bloquear, y todos los sistemas anti-bots lo hacen. La pantalla de 800×600 confirma el diagnóstico; - sin GPU, incluso en ventana, WebGL desaparece: a ningún navegador de escritorio moderno le pasa esto;
- solo la última columna se parece a un puesto de trabajo real: un Chrome en ventana en una pantalla 1080p, con una tarjeta gráfica Intel real.
Corregir el User-Agent a mano no basta: el modo headless tiene otras diferencias (tamaño de pantalla, comportamiento del renderizado, API ausentes), y un User-Agent que no encaja con el resto es sospechoso en sí mismo. Lo más fiable es no usar el modo headless en absoluto: en un servidor, para eso sirve precisamente Xvfb.
Resultado 5: en ventana, la GPU descarga enormemente la CPU
El modo ventana tiene un coste: Chrome tiene que dibujar toda la página en pantalla. Sin GPU, el procesador lo hace todo. Misma animación WebGL 1080p, Chrome en ventana sobre Xvfb, frecuencia normal (60 imágenes/s como máximo), carga de CPU medida en toda la VM durante la prueba:
| Chrome en ventana sobre Xvfb | Imágenes/s | CPU ocupada (VM de 4 vCPU) |
|---|---|---|
| Sin GPU (SwiftShader) | 9,8 | 3,4 vCPU: la VM está saturada |
| Sin GPU, escena 3× más pesada | 4,0 | 3,7 vCPU |
| Con la GPU UHD 770 | 60 (fluido) | 0,3 vCPU |
| Con la GPU, escena 3× más pesada | 60 | 0,3 vCPU |
Con la GPU, Chrome muestra 6 veces más imágenes usando más de 10 veces menos CPU, es decir, unas 70 veces menos CPU por imagen. Sin GPU, la VM está saturada y ni siquiera llega a 10 imágenes/s: el agente, Playwright y el resto del sistema se pelean por las migajas, cada acción tarda más y las páginas pesadas se vuelven inutilizables. Con la GPU, quedan 3,7 vCPU libres para el trabajo útil.
Es la combinación ganadora: el modo ventana evita que te detecten, y la GPU hace que no le cueste nada al procesador.
Lo que cambia la GPU frente a Cloudflare
Cloudflare (Bot Management, Turnstile) combina numerosas señales: huella TLS
y HTTP/2, reputación de la dirección IP, pruebas JavaScript en la página,
comportamiento (ritmo, movimientos), modelos estadísticos. Un navegador
sin GPU se delata rápido en las pruebas JavaScript: SwiftShader como
tarjeta gráfica, o ningún WebGL, es una firma típica de navegador
automatizado en un centro de datos.
Con la GPU, Chrome anuncia una tarjeta Intel real y renderiza la página como un PC de escritorio. En la práctica, esto reduce los falsos positivos: CAPTCHA o bloqueos en sitios a los que tu agente tiene todo el derecho de ir.
Pero hay que ser claros: CDP + driver + buena IP no te hace indetectable.
- el control por CDP deja a su vez rastros detectables;
- las direcciones de centros de datos se conocen como tales;
- el comportamiento de un agente (velocidad, encadenamiento de acciones) se detecta;
- las reglas cambian constantemente: lo que pasa hoy se bloqueará mañana.
El buen enfoque: hacerse reconocer
Para un agente legítimo, la vía duradera es estar identificado en lugar de oculto:
- Web Bot Auth («signed agents» en Cloudflare): el agente firma sus peticiones HTTP con una clave Ed25519 (HTTP Message Signatures, RFC 9421) y publica su clave pública en un directorio; los sitios pueden entonces autorizarlo explícitamente;
- un User-Agent honesto, el respeto de
robots.txty de las condiciones de uso, un ritmo razonable; - en tus propios sitios detrás de Cloudflare (pruebas E2E, monitorización), una regla WAF que deje pasar la IP de tu servidor.
Puesta en marcha
1. Paquetes
apt install chromium xvfb x11vnc nodejs npm
2. Pantalla virtual y 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 en :99 (solo 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
# desde tu ordenador:
ssh -L 5900:localhost:5900 root@tu-servidor # y luego un cliente VNC en localhost:5900
VNC solo escucha en localhost: solo se accede a través del túnel SSH.
3. Playwright MCP con la GPU
Archivo /root/mcp.json:
{
"browser": {
"browserName": "chromium",
"launchOptions": {
"executablePath": "/usr/bin/chromium",
"headless": false,
"args": ["--use-angle=vulkan", "--ignore-gpu-blocklist", "--no-sandbox"]
}
}
}
Con Claude Code instalado en el servidor:
claude mcp add playwright --env DISPLAY=:99 -- \
npx @playwright/mcp@latest --config /root/mcp.json
O como servidor HTTP, si el agente se ejecuta en otro sitio (túnel SSH hacia el puerto):
DISPLAY=:99 npx @playwright/mcp@latest --config /root/mcp.json --port 8931
# punto de acceso MCP: http://localhost:8931/mcp
Para comprobarlo, pide al agente que abra una página que muestre el motor de
renderizado WebGL: debe anunciar 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 mi_script.py
Con el Selenium 4.31 de Debian, indica explícitamente chromedriver mediante
Service(...): si no, no lo encuentra (NoSuchDriverException).
Preguntas frecuentes
¿Headless o en ventana sobre Xvfb?
En ventana, sin dudarlo. El headless se anuncia como HeadlessChrome y lo
bloquean en la mayoría de los sitios protegidos. El modo ventana permite
además seguir al agente por VNC y retomar el control. Reserva el headless
para tus propias pruebas, en tus propios sitios.
¿Y el computer use de Claude (capturas de pantalla + clics)? Necesita una pantalla real: Xvfb + un navegador en ventana, exactamente el esquema anterior. La GPU renderiza cada captura más rápido y deja la CPU libre para lo demás.
¿Basta con una oferta Perf 1? Para un agente que navega por sitios corrientes, sí. Las mediciones anteriores se hicieron con 4 vCPU (Perf 2), útil si el agente abre varias pestañas o páginas pesadas.
Pruébalo
Servidor Linux GPU con Intel UHD 770 en la VM, Mesa y Vulkan ya instalados. Desde 14,99 € sin IVA/mes, acceso root, IPv6 dedicada. Ver también: Chrome con la GPU en un servidor Linux y Xvfb: guía práctica.