Qué es Playwright MCP: instalación y ajustes de proxy

Publicado:

21 min de lectura

Acar Diveroli
Autor: Acar Diveroli
Marco de esquinas en cruz: logo de Proxynet, un aspa y el de Playwright MCP, sobre filas de IP tenues; etiqueta INTEGRATION

Cuando le dices a Claude Code o a Cursor «abre esta página y lee el precio de los tres primeros productos», el asistente casi siempre trae el HTML en bruto de la página. Si el precio se carga con JavaScript, se queda con un esqueleto vacío. Playwright MCP cubre ese hueco: pone un navegador real detrás del asistente y ofrece los clics y la escritura como llamadas a herramientas. La instalación es una sola línea. Las preguntas llegan después: desde qué IP sale el navegador, dónde se escriben el usuario y la contraseña del proxy, y si el agente puede ir a cualquier sitio que quiera.

En este artículo explicamos qué es Playwright MCP y cómo funciona, en qué se diferencia el árbol de accesibilidad de una captura de pantalla, la instalación en cuatro clientes habituales, los flags que de verdad sirven, el ajuste del proxy (incluido el proxy con autenticación), la restricción de orígenes con --allowed-origins y por qué esa restricción no se considera un límite de seguridad. Comprobamos los flags el día de la redacción en el README oficial y en la salida de --help. Los ejemplos se ejecutaron con @playwright/mcp 0.0.82 a través de un proxy de prueba local.

¿Qué es Playwright MCP?

Playwright MCP es, según la definición de su repositorio oficial, un servidor de Model Context Protocol que ofrece automatización del navegador mediante Playwright. Tiene dos piezas. Playwright es la biblioteca que maneja Chromium, Firefox y WebKit desde el código, y la tratamos a fondo en Qué es Playwright y cómo usarlo con un proxy. MCP es el protocolo que conecta las aplicaciones de IA con herramientas externas de una forma estándar.

Aquí no volvemos a explicar el protocolo. Basta con esto: la aplicación del asistente (el host) arranca el servidor MCP como un proceso local, el servidor anuncia la lista de herramientas que tiene junto con sus esquemas, y el modelo llama a esas herramientas cuando las necesita. La separación entre host, client y server, los métodos de transporte y los riesgos a nivel de protocolo están en Qué es MCP (Model Context Protocol): guía detallada.

Las herramientas que ofrece Playwright MCP son acciones del navegador: browser_navigate, browser_click, browser_type, browser_fill_form, browser_snapshot, browser_take_screenshot, browser_tabs y otras parecidas. En la versión 0.0.82 la instalación por defecto anunció 25 herramientas. Al añadir --caps=vision,pdf llegaron también el clic por coordenadas y la generación de PDF, y la cifra subió a 32. La diferencia con escribir tú mismo un script de navegador es que los pasos los decide el modelo: tú indicas el objetivo y el modelo elige qué enlace pulsar mirando la página. El funcionamiento general del bucle de un agente está en Agentes de IA: planificación, herramientas y memoria.

¿Cómo funciona Playwright MCP?

Una petición pasa de principio a fin por estos pasos:

  1. La aplicación host ejecuta el comando de la configuración: npx @playwright/mcp@latest. El servidor se conecta por stdio y anuncia su lista de herramientas.
  2. Escribes una tarea en lenguaje natural. El modelo llama a la herramienta browser_navigate con la dirección.
  3. El servidor arranca el navegador en la primera llamada a una herramienta. Sin --browser, en nuestra prueba se abrió el Google Chrome instalado en el sistema; la ventana es visible por defecto y se oculta con --headless.
  4. Cuando la página termina de cargar, el servidor genera la dirección de la página, el título y una instantánea (snapshot) del árbol de accesibilidad. En 0.0.82 la respuesta de browser_navigate guardó esa instantánea como archivo YAML en el directorio .playwright-mcp de la carpeta de trabajo y devolvió su ruta, mientras que browser_snapshot devolvió el árbol directamente dentro de la respuesta.
  5. Cada elemento del árbol tiene una referencia: link "Travel" [ref=e21]. El modelo indica con esa referencia el elemento que quiere pulsar: browser_click, target: e21.
  6. El servidor ejecuta la acción con Playwright y muestra además en la respuesta el código que ha ejecutado: await page.getByRole('link', { name: 'Travel' }).click();. Después vuelve la instantánea de la página nueva y el bucle continúa.

Gracias a esa línea de código puedes convertir más tarde la exploración del agente en un script de Playwright corriente. El flag --codegen elige el lenguaje de esa salida (typescript, python, java, csharp o none).

¿Por qué el árbol de accesibilidad es más útil que una captura de pantalla?

El árbol de accesibilidad es la estructura que el navegador genera para los lectores de pantalla. Según la definición de MDN, lleva cuatro datos por cada elemento: nombre, descripción, rol y estado. Playwright exporta ese árbol como YAML; el detalle del formato está en la documentación de aria snapshots. La instantánea de nuestra página de prueba (books.toscrape.com) empezaba así:

yaml
- generic [active] [ref=e1]:
  - banner [ref=e2]:
    - generic [ref=e5]:
      - link "Books to Scrape" [ref=e6] [cursor=pointer]:
        - /url: index.html
      - text: We love being scraped!
  # ... (recortado)
            - list [ref=e19]:
              - listitem [ref=e20]:
                - link "Travel" [ref=e21] [cursor=pointer]:
                  - /url: catalogue/category/books/travel_2/index.html

En ese texto el modelo lee directamente qué es un enlace, qué es un botón y qué es un cuadro de texto. Con una captura de pantalla tiene que sacar la misma información de los píxeles y después estimar las coordenadas del punto que hay que pulsar.

Árbol de accesibilidad (browser_snapshot)Captura de pantalla (browser_take_screenshot)
Datos que van al modeloTexto (YAML)Imagen (PNG o JPEG)
¿Hace falta un modelo con visión?No
¿Cómo se apunta a un elemento?Con el valor ref, de forma exactaPor coordenadas, si --caps=vision está activo
Detalle que no se veColor, maquetación, contenido de una imagenLa función de los elementos sin nombre accesible
Trabajo para el que encajaNavegación, formularios, lectura de datosVerificación visual, revisión de diseño

La descripción de la propia herramienta dice lo mismo: no se pueden realizar acciones a partir de la captura de pantalla; para las acciones se usa la instantánea. Aun así, no pienses que el texto sale gratis. En nuestra prueba la página de inicio del listado de libros generó un árbol de unos 32 mil caracteres, y los esquemas de las 25 herramientas rondaron los 20 mil caracteres. Son recuentos de caracteres; la equivalencia en tokens depende del modelo y no la medimos. El README es franco en este punto: a los agentes de programación que trabajan con una base de código grande les recomienda la vía de Playwright CLI, que no carga en el contexto los esquemas de las herramientas ni el árbol, y sitúa MCP en los trabajos que exigen un estado persistente del navegador y un razonamiento paso a paso sobre la página. --snapshot-mode=none desactiva la instantánea automática en las respuestas, y --mobile hace que se abran las páginas móviles, más ligeras.

¿Cómo se instala Playwright MCP?

Lo único que necesitas es Node.js 18 o una versión más reciente y un cliente compatible con MCP. El paquete no se instala a mano; el cliente lo ejecuta con npx en cada arranque. La entrada que el README llama «configuración estándar» es la misma en la mayoría de los clientes:

json
{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["@playwright/mcp@latest"]
    }
  }
}

El lugar donde se escribe esa entrada cambia según el cliente:

ClienteInstalación
Claude Codeclaude mcp add playwright npx @playwright/mcp@latest
Claude DesktopLa entrada estándar se añade al archivo claude_desktop_config.json, que se abre desde SettingsDeveloperEdit Config
CursorCursor SettingsMCPAdd new MCP Server, tipo command, comando npx @playwright/mcp@latest
VS CodeEl comando code --add-mcp o .vscode/mcp.json; en este archivo la clave superior es servers, no mcpServers

Si en Claude Code vas a pasar flags al servidor, pon -- en medio. Según la documentación de MCP de Claude Code, todo lo que va después del doble guion se pasa al comando del servidor sin tocar:

bash
claude mcp add --scope project playwright -- npx @playwright/mcp@latest --headless --isolated

--scope project escribe la entrada en el archivo .mcp.json de la raíz del proyecto; si añades el archivo al repositorio, el equipo usa el mismo ajuste. Cuando probamos el comando, en el archivo apareció la versión con flags de la entrada estándar de arriba. Puedes comprobar la conexión con claude mcp list o, dentro de una sesión, con /mcp. El detalle del lado de VS Code está en la documentación de MCP de VS Code.

La etiqueta @latest descarga la versión actual en cada arranque. El paquete cambia deprisa: los nombres de flags de este artículo pertenecen a 0.0.82. Si quieres el mismo comportamiento en todo el equipo, fija la versión (@playwright/mcp@0.0.82) y mira la salida de npx @playwright/mcp@latest --help antes de actualizar.

¿Qué flags son los más útiles?

La salida de ayuda de 0.0.82 enumera unas cincuenta opciones. Las que te encuentras en el uso diario son estas:

FlagQué hace
--headlessEjecuta el navegador sin ventana. Por defecto tiene ventana
--browser <nombre>chrome, firefox, webkit o msedge
--isolatedMantiene el perfil en memoria y no lo escribe en disco; al cerrar la sesión se borran las cookies
--user-data-dir <ruta>Directorio del perfil persistente
--storage-state <ruta>Carga cookies iniciales y almacenamiento local en una sesión aislada
--proxy-server <dirección>Servidor proxy: http://servidor:3128 o socks5://servidor:8080
--proxy-bypass <dominios>Dominios que no pasan por el proxy, separados por comas
--allowed-origins <lista>Orígenes a los que el navegador puede hacer peticiones, separados por punto y coma
--blocked-origins <lista>Orígenes que se bloquean; se evalúa antes que la lista de permitidos
--caps <lista>Capacidades adicionales: vision, pdf, devtools
--config <ruta>Archivo de configuración JSON
--timeout-navigation <ms>Tiempo de espera de la navegación, 60000 por defecto

Cada flag tiene su variable de entorno equivalente (como PLAYWRIGHT_MCP_PROXY_SERVER o PLAYWRIGHT_MCP_ALLOWED_ORIGINS). Probamos la variable del proxy y dio el mismo resultado que el flag.

¿Cómo se configura un proxy en Playwright MCP?

Para un proxy que no pide credenciales, es decir, cuando tu IP de salida está añadida a la lista de IP autorizadas del panel, basta con un solo flag:

json
{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": [
        "@playwright/mcp@latest",
        "--headless",
        "--isolated",
        "--proxy-server=http://pr.proxynet.io:8000",
        "--proxy-bypass=localhost,127.0.0.1"
      ]
    }
  }
}

Ejecutamos esta configuración con nuestro proxy de prueba local: cada página que abrió el agente quedó en el registro del proxy como una línea CONNECT. El dominio que añadimos a la lista de --proxy-bypass, en cambio, no apareció nunca en el registro, así que se conectó directamente. Si estás probando tu servidor de desarrollo local, no olvides la entrada localhost; de lo contrario, el agente intenta llegar a la página de tu propia máquina a través del proxy.

SOCKS5 también funciona: --proxy-server=socks5://pr.proxynet.io:1080. En nuestra prueba la página se abrió y al servidor SOCKS5 le llegó el nombre de dominio, es decir, la resolución DNS se quedó del lado del proxy. Con SOCKS5 no se admiten usuario y contraseña; la causa es Chromium, y el detalle está en el artículo sobre Playwright y proxy que citamos arriba. La parte de producto está en la página de Proxies SOCKS5.

Puedes confirmar que el proxy está de verdad en uso preguntándoselo al agente: «Abre https://httpbin.org/ip y escribe la IP que ves». Si la dirección que devuelve no es tu propia IP, el tráfico pasa por el proxy.

¿Cómo se define un proxy con usuario y contraseña?

Lo primero que se le ocurre a cualquiera es incrustar las credenciales en la dirección: --proxy-server=http://user:pass@pr.proxynet.io:8000. No funciona. Cuando lo probamos el servidor arrancó, pero la primera navegación devolvió este error:

text
Error: browserBackend.callTool: net::ERR_INVALID_AUTH_CREDENTIALS at https://httpbin.org/ip

En el registro del proxy vimos que la petición llegó sin credenciales y recibió un 407. El error fue el mismo cuando no escribimos ninguna credencial. Es decir, el flag solo transporta el esquema, el servidor y el puerto.

La solución es el archivo de configuración. El campo browser.launchOptions del JSON que se pasa con --config se traslada a las opciones de arranque del propio Playwright, y ahí está el objeto proxy:

json
{
  "browser": {
    "isolated": true,
    "launchOptions": {
      "headless": true,
      "proxy": {
        "server": "http://pr.proxynet.io:8000",
        "username": "user",
        "password": "pass"
      }
    }
  },
  "network": {
    "allowedOrigins": ["https://books.toscrape.com", "https://httpbin.org"]
  }
}

La entrada del lado del cliente solo apunta al archivo:

json
{
  "mcpServers": {
    "playwright": {
      "command": "npx",
      "args": ["@playwright/mcp@latest", "--config=playwright-mcp.json"]
    }
  }
}

Probamos esta pareja con nuestro proxy local que exige usuario y contraseña: el navegador recibió primero un 407, envió las credenciales y la página se abrió. Es más seguro escribir la ruta del archivo como ruta absoluta, porque el directorio en el que el cliente arranca el servidor cambia según la aplicación.

Como la contraseña va a quedar en un archivo en texto plano, toma dos precauciones: no añadas el archivo al repositorio y, si puedes, crea un usuario de proxy aparte para este trabajo. Si no quieres escribir la contraseña en ningún sitio, con la lista de IP autorizadas vuelves a la instalación de un solo flag del apartado anterior. La comparación de los dos métodos está en Autenticación de proxy: user:pass o lista blanca de IP.

¿Cómo se restringen los orígenes que puede visitar el agente?

Darle un navegador a un modelo significa que cada página que lee puede susurrarle instrucciones. Cómo funciona la inyección indirecta de prompts y por qué una lista de permitidos es más sólida que una lista de bloqueo lo explicamos en Acceso web seguro para LLM: límites y permisos. Playwright MCP ofrece una implementación ya hecha de esa idea:

json
"args": [
  "@playwright/mcp@latest",
  "--allowed-origins=https://books.toscrape.com;https://httpbin.org"
]

Un origen se compone de esquema, dominio y puerto; la lista se separa con punto y coma. Su equivalente en el archivo de configuración es el array network.allowedOrigins, que acepta un comodín de puerto con la forma http://localhost:*. --blocked-origins hace lo contrario y se evalúa primero; cuando se usa sin lista de permitidos, toda dirección que no esté en la lista sigue abierta.

En nuestra prueba, un agente que intentó ir a una dirección de fuera de la lista recibió esta respuesta: net::ERR_BLOCKED_BY_CLIENT. Tampoco se cargó una imagen de fuera de la lista que pusimos dentro de una página permitida, así que la regla cubre los subrecursos además de la navegación.

Tres observaciones muestran qué significa esa advertencia en la práctica:

  • Las redirecciones se saltan la lista. Cuando una dirección local de la lista de permitidos redirigió con un 302 a un sitio de fuera de la lista, la página se abrió y el agente leyó su contenido.
  • Aun así puede abrirse una conexión a la dirección bloqueada. Vimos una línea CONNECT en el registro del proxy para el dominio bloqueado. La página no se cargó, pero el navegador sí conectó con ese servidor.
  • El tráfico en segundo plano del propio navegador no está sujeto a la regla. Las peticiones de Chrome a sus servicios de actualización y de cuentas pasaron por el proxy con independencia de la lista. Si pagas el tráfico por GB, esas peticiones también suman en el contador.

Entre las herramientas por defecto están también browser_evaluate y browser_run_code_unsafe. La descripción de la segunda es clara: ejecuta JavaScript arbitrario en el proceso del servidor y equivale a una ejecución remota de código. El acceso al sistema de archivos está limitado por defecto a la carpeta de trabajo y las direcciones file:// están bloqueadas; --allow-unrestricted-file-access quita ese límite, así que no lo uses salvo que haga falta.

El límite real lo pones fuera: ejecuta el agente en una cuenta de usuario aparte o en un contenedor, sepáralo de tus sesiones personales con --isolated, no desactives el paso de aprobación de las llamadas a herramientas y, si es posible, haz una segunda comprobación de dominios en el proxy de salida. Los flags no sustituyen a esas capas, se suman a ellas.

Perfil y sesión: ¿persistente o aislado?

El modo por defecto es el perfil persistente: las cookies y los datos de inicio de sesión se guardan en disco, y en la sesión siguiente el agente sigue donde lo dejó. El directorio del perfil se deriva de la carpeta de trabajo del cliente, así que proyectos distintos reciben perfiles separados. El README trae un aviso: un perfil persistente solo lo puede usar un navegador a la vez. Si vas a abrir dos clientes en el mismo proyecto, dale al segundo --isolated o un --user-data-dir distinto.

--isolated arranca cada sesión limpia y lo borra todo cuando se cierra el navegador. En los trabajos de lectura de datos es el valor por defecto correcto. Si necesitas probar tu propia aplicación con la sesión iniciada, exportas las cookies una vez y las cargas con --storage-state; el formato está en la documentación de autenticación de Playwright. Ese archivo lleva tus claves de sesión, así que protégelo como una contraseña. El tercer modo es conectarse con --extension al Chrome que ya tienes abierto. El agente puede acceder entonces a todas tus pestañas con sesión iniciada, de modo que elige esta vía solo si sabes bien lo que haces.

Casos de uso

  • Comprobación de localización: hacer que el agente recorra cómo se ve tu sitio desde un país concreto. Apuntas el proxy al punto de salida de ese país y le pides al agente que informe de elementos como el idioma, la moneda y el aviso de cookies. El detalle está en la página de la solución de localización; en las comprobaciones que requieren el aspecto de una conexión doméstica real se usa Proxies residenciales.
  • Pruebas exploratorias: hacer que el agente recorra un flujo de tu propia aplicación y convertir el código de Playwright que genera en una prueba permanente. El montaje de pruebas desde distintos países está en la página de pruebas de aplicaciones.
  • Lectura puntual de datos de una página dinámica: obtener unos pocos valores de una página pública que se carga con JavaScript. Para un trabajo regular y de gran volumen el agente sale caro; el montaje permanente está en la página de la solución de extracción de datos, y si hace falta o no un navegador se trata en Páginas estáticas y dinámicas en web scraping.
  • Depuración: con las herramientas browser_console_messages y browser_network_requests el agente lee los errores de consola y las peticiones de red de la página y te los resume.

Aunque lo maneje un agente, lo que navega es un navegador y valen las mismas reglas: respeta el archivo robots.txt y las condiciones de uso del sitio, prefiere la API oficial si existe y mantén baja la frecuencia de peticiones. No recomendamos plugins para evadir la detección. Por qué los sitios intentan distinguir a los visitantes automatizados lo contamos en ¿Por qué los sitios bloquean a los agentes de compra con IA?.

Errores frecuentes

Lo que vesCausaQué hacer
net::ERR_INVALID_AUTH_CREDENTIALSEl proxy pide credenciales; no se han dado o se han incrustado en la direcciónEscribe username y password en el campo launchOptions.proxy del archivo de --config
net::ERR_PROXY_CONNECTION_FAILEDLa dirección o el puerto del proxy son incorrectos, o la salida choca con un cortafuegosPrueba la misma dirección con cURL
net::ERR_BLOCKED_BY_CLIENTLa dirección está fuera de --allowed-origins o dentro de --blocked-originsAñade el origen a la lista con su esquema y su puerto
En el segundo cliente no se abre el navegadorEl perfil persistente está bloqueado por otro navegador--isolated o un --user-data-dir distinto
El agente no llega a tu servidor localEl tráfico de localhost también va al proxy--proxy-bypass=localhost,127.0.0.1

También hay errores de costumbre que no entran en la tabla:

  • Tomar la lista de permitidos por una medida de seguridad. Una redirección se salta la lista; monta el aislamiento a nivel de proceso y de red.
  • Abrirle al agente tu perfil personal de Chrome. El perfil donde están tus sesiones de correo y de banca no debe estar en manos de un modelo que lee contenido externo.
  • Pedir una captura de pantalla para cada tarea. Las acciones ya se hacen sobre la instantánea; la imagen solo sirve para la verificación visual.
  • Trabajar en equipo con @latest. Los nombres de los flags pueden cambiar de una versión a otra; fija la versión.
  • Dejar el rastreo regular en manos del agente. Cada paso cuesta una llamada al modelo. Explora con el agente, convierte el código generado en un script y ejecuta ese script.

Guía de decisión

NecesidadRecomendación
Que el asistente lea una página cargada con JavaScriptPlaywright MCP, --headless --isolated
Que el agente salga desde un país concretoEl punto de salida de ese país con --proxy-server
Proxy con usuario y contraseñalaunchOptions.proxy en el archivo de --config
No quieres escribir la contraseña en un archivoLista de IP autorizadas y --proxy-server por sí solo
Limitar el agente a unos pocos sitios--allowed-origins, más aislamiento de proceso y de red
Agente de programación en una base de código grandeEl Playwright CLI que recomienda el README
Rastreo diario de cientos de páginasNo un agente, sino un script escrito con la biblioteca Playwright
Aprender el protocolo y sus riesgosNuestra guía de MCP

Preguntas frecuentes

¿Playwright MCP es gratis?

Sí. El paquete se publica con licencia Apache 2.0 y se ejecuta con npx sin coste. El gasto viene de dos sitios: los esquemas de herramientas y las instantáneas de página que procesa el modelo, y el tráfico de proxy que consumes.

¿Qué diferencia hay entre Playwright MCP y la biblioteca Playwright?

Con la biblioteca los pasos los programas tú, y el script sigue el mismo camino cada vez que se ejecuta. Con el servidor MCP los pasos los decide el modelo; tú solo indicas el objetivo. Lo primero es barato y previsible para trabajos repetidos, lo segundo es rápido para explorar y para tareas puntuales. Los detalles de proxy del lado de la biblioteca (proxy por context, rotación, tabla de errores) están en nuestro artículo sobre Playwright y proxy.

¿Qué navegador usa? ¿Hace falta tener Chrome instalado?

Sin --browser, en nuestra prueba se abrió el Google Chrome del sistema. Puedes cambiarlo con --browser firefox, webkit o msedge, o señalar un ejecutable de navegador concreto con --executable-path.

¿Es lo mismo que Browser Use?

El objetivo es el mismo: que un modelo maneje un navegador. Browser Use es una biblioteca de agentes en Python independiente y ejecuta el bucle por su cuenta. Playwright MCP solo ofrece las herramientas; el bucle lo ejecuta el asistente que ya usas (Claude Code, Cursor, VS Code).

¿Se puede usar con un proxy rotativo?

Se puede, pero un navegador abre muchas conexiones para una sola página, y en una pasarela que cambia de IP en cada conexión esas conexiones pueden salir desde direcciones distintas. Al leer páginas independientes no es un problema. Si no quieres que la IP cambie a mitad de un flujo de varios pasos, elige Proxies de sesión fija. Cómo funciona la rotación está en nuestro artículo sobre la rotación de IP.

¿Usar un proxy hace desaparecer las pantallas de verificación?

No. Un proxy solo cambia desde qué IP sale la petición. Las señales que deja un navegador controlado por automatización y la frecuencia de peticiones siguen igual. La vía duradera es una frecuencia razonable, páginas permitidas y, si existe, la API oficial.

En resumen

Playwright MCP le da a tu asistente un navegador real y le hace leer la página como árbol de accesibilidad. La instalación es una sola línea: npx @playwright/mcp@latest. Para el proxy basta con --proxy-server; si hacen falta usuario y contraseña, incrustarlos en la dirección acaba en ERR_INVALID_AUTH_CREDENTIALS, y el sitio correcto es el objeto launchOptions.proxy del archivo de configuración. --allowed-origins acota el terreno del agente, pero no cubre las redirecciones y, en palabras de la propia documentación, no es un límite de seguridad; monta el aislamiento a nivel de proceso y de red. Fija la versión, explora con el agente y pasa el trabajo repetido a un script. Los tipos de proxy adecuados para el punto de salida de tu agente los encuentras en nuestros servicios de proxy.