Playwright MCP: coste en tokens vs leer páginas en markdown
Usamos el servidor real de Playwright MCP y el markdown de FastAF en 11 páginas públicas y contamos tokens. Página mediana: 9.874 vs 5.083, con excepciones en los dos sentidos.

Leer una página con Playwright MCP cuesta una mediana de 9.874 tokens en nuestra prueba, frente a 5.083 para las mismas páginas en markdown desde FastAF. Es aproximadamente el doble de tokens, no cien veces más. Eso sí, la dispersión es amplia: de 0,4x en una página a 4x en otra. Medimos 11 páginas públicas el 19 de octubre de 2026 con @playwright/mcp 0.0.83 y contamos los tokens con tiktoken o200k_base.
No encontramos ninguna medición por página de Playwright MCP que pudiéramos reproducir, así que hicimos una. Abajo tienes el método y el script, junto con los casos en los que el navegador es la herramienta adecuada.
¿Cuántos tokens usa Playwright MCP por página?
Arrancamos el servidor real (@playwright/mcp 0.0.83, la última en npm a esta fecha, sobre Playwright 1.64 alpha) en modo headless por stdio, con el SDK oficial de MCP para Python como cliente. Para cada página, el cliente llamó a browser_navigate y luego a browser_snapshot, y contamos cada carácter que el modelo habría recibido. En la 0.0.83, browser_navigate solo devuelve un enlace a un archivo de snapshot (de 78 a 168 tokens), así que leer la página requiere la segunda llamada. El otro brazo fue /v1/scrape de FastAF con formats=markdown, primero sin más y con dynamic=true solo cuando la llamada simple fallaba o faltaban las frases de comprobación.
“Funcionó” significa que dos frases fijadas de antemano estaban presentes en lo que vería el modelo. Los tokens corresponden a la ejecución 1 de 3 e incluyen navigate más snapshot.
| Página | HTML bruto | Snapshot de Playwright | Playwright --mobile |
Markdown de FastAF |
|---|---|---|---|---|
| MDN, Fetch API (docs) | 41.439 | 7.481 | 6.367 | 4.110 |
| Docs de Python, asyncio tasks (docs largas) | 50.276 | 34.405 | 33.354 | 15.236 |
| Artículo de The Guardian (noticias) | 101.462 | 6.343 | 6.129 | 3.585 |
| Estantería BILLY de IKEA (producto) | 336.714 | 10.017 | 7.812 | 5.092 |
| Wikipedia, Model Context Protocol | 79.923 | 24.931 | 3.864 (plegada) | 21.784 |
| GitHub, python-sdk (repo) | 135.152 | 9.874 | 6.807 | 5.083 |
| crates.io, serde (app renderizada con JS) | n/d (404) | 4.693 | 4.767 | 1.408 (5 créditos) |
| Portada de Hacker News (listado) | 11.694 | 13.649 | 13.649 | 3.365 |
| Post del blog de ingeniería de Anthropic | 51.697 | 11.689 | 11.447 | 6.115 |
| PyPI, requests (paquete) | 73.730 | 7.931 | 4.840 (escueta) | 20.165 |
| GOV.UK, tipos de IVA | 19.415 | 3.378 | 3.337 | 1.392 |
| Mediana, 11 páginas | 51.697 | 9.874 | 6.367 | 5.083 |
| Total, 11 páginas | 901.502 | 134.391 | 102.373 | 87.335 |
“HTML bruto” es un GET simple, para tener una escala. crates.io le devolvió un shell con 404. Los tiempos fueron parecidos: una página de Playwright con el navegador ya caliente tardó una mediana de 0,5 s (la primera llamada tras el arranque añadió de 0,4 a 0,9 s), y FastAF una mediana de 0,5 s en tres ejecuciones, con el renderizado dinámico entre 6 y 7 s. Los recuentos de tokens de Playwright variaron menos del 2 % entre ejecuciones, salvo en The Guardian (de 5.671 a 6.343) y en la página de GitHub (de 9.376 a 9.874). La salida de FastAF para Wikipedia fue de 21.784 tokens en dos llamadas y de 9.513 en otras dos, así que trata esa fila como un rango.
¿Por qué un snapshot es más grande que el markdown?
Un snapshot es un árbol de accesibilidad en YAML. Cada nodo lleva un rol, un nivel de anidación y un id [ref=...] para que el agente pueda hacer clic en él, y cada enlace gasta una línea en su destino - /url:. Contamos solo las líneas de URL en un 18 % de los tokens del snapshot en el conjunto de páginas (un 9 % en la documentación de Python, un 25 % en Hacker News). Hacker News es el caso más claro: su maquetación en tabla se convierte en table > rowgroup > row > cell, varios niveles de profundidad antes de la primera noticia, y el snapshot es 4x el markdown.
El markdown no tiene refs y casi nada de estructura, así que las páginas con mucha prosa salen casi 2x más pequeñas. Dos páginas no siguieron ese patrón. El markdown de PyPI (20.165) conservó la página entera, con la lista de archivos y los clasificadores, mientras que el snapshot (7.931) no. El markdown de Wikipedia quedó a un 13 % del snapshot. El resumen honesto es que el snapshot es algo más grande en la mayoría de las páginas y lo que se paga es la estructura, pero una página con mucho texto puede costar más en markdown.
¿Cuánto cuesta eso en dólares?
La página de precios de Anthropic lista Claude Sonnet 5.5 a 2 $ por millón de tokens de entrada y Claude Fable 5.1 a 10 $ (ambos a 19 de octubre de 2026, página de precios). Nuestros recuentos usan un tokenizador de OpenAI, así que los de Claude diferirán algo; lo fiable son las proporciones. Con la página mediana:
| Por 1.000 lecturas de página | Tokens | Entrada en Sonnet 5.5 | Entrada en Fable 5.1 |
|---|---|---|---|
| HTML bruto | 51,7 M | 103,39 $ | 516,97 $ |
| Snapshot de Playwright MCP | 9,9 M | 19,75 $ | 98,74 $ |
Playwright MCP, --mobile |
6,4 M | 12,73 $ | 63,67 $ |
| Markdown de FastAF | 5,1 M | 10,17 $ más 1.000 créditos | 50,83 $ más 1.000 créditos |
Con el pack Starter (10 $ por 20.000 créditos), 1.000 scrapes simples cuestan 0,50 $, así que FastAF queda cerca de 10,70 $ en Sonnet frente a los 19,75 $ del snapshot. Es más o menos la mitad, y solo de entrada. Además, una página leída se queda en el contexto en todos los turnos siguientes salvo que la cachees o la descartes, de modo que una ejecución larga la paga más de una vez. Las definiciones de las tools son un coste fijo por sesión: Playwright MCP lista 25 tools (5.250 tokens), el servidor MCP de FastAF 15 (3.831).
¿Se puede abaratar Playwright MCP?
Sí, y el README del paquete lo dice él mismo: recomienda Playwright CLI con skills para los agentes de programación porque mantiene los árboles de accesibilidad fuera del contexto del modelo. Dentro de MCP, el flag --mobile (documentado como ahorro de tokens) bajó aquí la mediana de 9.874 a 6.367. Tiene una pega. En Wikipedia redujo 24.931 tokens a 3.864 porque el diseño móvil pliega las secciones: 1 párrafo en el snapshot en lugar de 22. En PyPI perdió el campo de licencia y no pasó nuestra comprobación. No interpretes un snapshot más pequeño como el mismo contenido.
Hay otras palancas en la lista de tools que no medimos: browser_find devuelve los nodos coincidentes con contexto en lugar del árbol entero, browser_snapshot acepta un depth y un filename, y browser_navigate ya escribe en un archivo en vez de en el chat. Si sabes qué parte de la página necesitas, esas opciones superarán a cualquier lectura de la página completa.
¿Cuándo es el navegador la herramienta adecuada?
Cuando la tarea es la interacción: hacer clic por una interfaz, rellenar un formulario, un flujo tras un login que es tuyo, una página donde el siguiente paso depende de lo que hizo el último clic. Las refs del snapshot existen para eso, y el markdown no tiene nada en lo que hacer clic.
También probamos una pregunta de Stack Overflow y la dejamos fuera de la tabla: respondió con una página de verificación anti-bot (HTTP 403), y FastAF devolvió 400 y 422 target_unavailable sin cobrar. Las comprobaciones anti-bot de un sitio son decisión de su dueño; FastAF lee páginas públicas y no intenta saltárselas, y no comparamos herramientas frente a ellas.
Las apps de JavaScript son el caso intermedio. En crates.io, el primer snapshot de Playwright fue de 35 tokens porque la app no se había cargado; un segundo, tras una espera, dio 4.693. La llamada simple de FastAF devolvió 422, y el renderizado con dynamic=true costó 5 créditos y 1.408 tokens en 6,3 s. Mira por qué un fetch devuelve una página vacía y el renderizado de JavaScript. Una corrección: nuestra primera frase de comprobación para crates.io no coincidía con cómo la página divide su texto, así que la arreglamos y volvimos a ejecutar ambas herramientas en esa página.
Cuando el trabajo es leer una página pública y responder a partir de ella, leer basta, y la API de web scraping o la tool scrape_page lo hacen en una sola llamada. Para la configuración en Claude Code, Cursor y Codex, mira la búsqueda web por MCP.
¿Cómo lo reproduzco?
import asyncio, os, sys, requests, tiktoken
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
enc = tiktoken.get_encoding("o200k_base")
tokens = lambda s: len(enc.encode(s, disallowed_special=()))
def fastaf_markdown(url, dynamic=False):
params = {"url": url, "formats": "markdown"}
if dynamic:
params.update(dynamic="true", wait=3000)
r = requests.get("https://api.fastaf.co/v1/scrape", params=params, timeout=120,
headers={"Authorization": f"Bearer {os.environ['FASTAF_API_KEY']}"})
return r.text if r.status_code == 200 else "", r.headers.get("X-FastAF-Credits-Used")
async def playwright_snapshot(urls):
# npm i @playwright/mcp@0.0.83 (the real server, over stdio, headless)
server = StdioServerParameters(command="node", cwd=os.getcwd(),
args=["node_modules/@playwright/mcp/cli.js", "--headless", "--isolated"])
out = {}
async with stdio_client(server) as (r, w), ClientSession(r, w) as s:
await s.initialize()
for url in urls:
nav = await s.call_tool("browser_navigate", {"url": url})
snap = await s.call_tool("browser_snapshot", {})
text = lambda res: "\n".join(c.text for c in res.content if c.type == "text")
out[url] = tokens(text(nav)) + tokens(text(snap))
return out
urls = sys.argv[1:]
pw = asyncio.run(playwright_snapshot(urls))
for url in urls:
md, credits = fastaf_markdown(url)
print(f"{url}\n playwright {pw[url]:>7,} tokens fastaf {tokens(md):>7,} tokens ({credits} credit)")
Ejecutado el 19 de octubre de 2026 sobre dos de las páginas de arriba, imprimió:
https://www.gov.uk/vat-rates
playwright 3,038 tokens fastaf 1,392 tokens (1 credit)
https://news.ycombinator.com/
playwright 13,647 tokens fastaf 3,323 tokens (1 credit)
El snapshot de GOV.UK salió aquí en 3.038 frente a 3.378 en la tabla porque las páginas cambian entre ejecuciones. Nuestra ejecución completa añadió las comprobaciones de las frases fijadas, un reintento tras 3 s de espera para los snapshots escuetos, tres repeticiones y el brazo --mobile. En todo momento usamos Chromium en un portátil en Italia, y las URL son las de la tabla, así que puedes volver a ejecutarlas.
En resumen
En 11 páginas públicas, una lectura con Playwright MCP tomó una mediana de 9.874 tokens y el markdown 5.083: más o menos la mitad, no una centésima parte. El snapshot gasta tokens en refs, roles y URL; --mobile lo recorta pero puede perder contenido; y el snapshot aún puede salir ganando en páginas que son sobre todo estructura. Usa el navegador cuando necesites hacer clic, escribir o iniciar sesión en algo tuyo, y lee la página como markdown cuando solo necesites lo que dice. Consigue 500 créditos gratis y ejecuta el script con las páginas que más lee tu agente. Los precios y límites están en la página de precios y en la documentación.