Playwright MCP: custo em tokens vs ler a página em markdown
Rodamos o servidor Playwright MCP real e o markdown do FastAF em 11 páginas públicas e contamos tokens. Página mediana: 9.874 vs 5.083, com exceções nos dois sentidos.

Uma leitura de página com o Playwright MCP custa uma mediana de 9.874 tokens no nosso teste, contra 5.083 para as mesmas páginas em markdown pelo FastAF. É cerca do dobro de tokens, não cem vezes mais. A dispersão, porém, é grande: de 0,4x numa página a 4x em outra. Medimos 11 páginas públicas em 19 de outubro de 2026 com o @playwright/mcp 0.0.83 e contamos os tokens com o tiktoken o200k_base.
Não encontramos uma medição por página do Playwright MCP que pudéssemos reproduzir, então fizemos uma. O método e o script estão abaixo, junto com os casos em que o navegador é a ferramenta certa.
Quantos tokens o Playwright MCP usa por página?
Iniciamos o servidor real (@playwright/mcp 0.0.83, a mais recente no npm nesta data, rodando o Playwright 1.64 alpha) em modo headless via stdio, com o SDK Python oficial do MCP como cliente. Para cada página, o cliente chamou browser_navigate e depois browser_snapshot, e contamos cada caractere que o modelo teria recebido. Na 0.0.83, browser_navigate devolve só um link para um arquivo de snapshot (78 a 168 tokens), então ler a página exige a segunda chamada. O outro braço foi o /v1/scrape do FastAF com formats=markdown, primeiro simples e com dynamic=true só quando a chamada simples falhava ou as frases de verificação não apareciam.
“Funcionou” significa que duas frases definidas de antemão estavam presentes no que o modelo veria. Os tokens são da execução 1 de 3 e cobrem navigate mais snapshot.
| Página | HTML bruto | Snapshot do Playwright | Playwright --mobile |
Markdown do FastAF |
|---|---|---|---|---|
| MDN, Fetch API (docs) | 41.439 | 7.481 | 6.367 | 4.110 |
| Docs do Python, asyncio tasks (docs longa) | 50.276 | 34.405 | 33.354 | 15.236 |
| Artigo do Guardian (notícia) | 101.462 | 6.343 | 6.129 | 3.585 |
| Estante BILLY da IKEA (produto) | 336.714 | 10.017 | 7.812 | 5.092 |
| Wikipedia, Model Context Protocol | 79.923 | 24.931 | 3.864 (dobrado) | 21.784 |
| GitHub, python-sdk (repositório) | 135.152 | 9.874 | 6.807 | 5.083 |
| crates.io, serde (app renderizado em JS) | n/d (404) | 4.693 | 4.767 | 1.408 (5 créditos) |
| Página inicial do Hacker News (listagem) | 11.694 | 13.649 | 13.649 | 3.365 |
| Post do blog de engenharia da Anthropic | 51.697 | 11.689 | 11.447 | 6.115 |
| PyPI, requests (pacote) | 73.730 | 7.931 | 4.840 (rala) | 20.165 |
| GOV.UK, alíquotas 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” é um GET simples, só para dar escala. O crates.io devolveu um shell 404 para ele. Os tempos ficaram próximos: uma página do Playwright já aquecido levou uma mediana de 0,5 s (a primeira chamada depois do início somou 0,4 a 0,9 s), e o FastAF uma mediana de 0,5 s em três execuções, com renderização dinâmica de 6 a 7 s. As contagens de tokens do Playwright variaram menos de 2% entre execuções, exceto no Guardian (5.671 a 6.343) e na página do GitHub (9.376 a 9.874). A saída em markdown da Wikipedia pelo FastAF foi de 21.784 tokens em duas chamadas e 9.513 em outras duas, então trate essa linha como uma faixa.
Por que um snapshot é maior que o markdown?
Um snapshot é uma árvore de acessibilidade em YAML. Cada nó carrega um papel, um nível de aninhamento e um id [ref=...] para o agente poder clicar nele, e cada link gasta uma linha com o seu destino - /url:. Só as linhas de URL, contadas à parte, somam 18% dos tokens do snapshot nas páginas (9% nos docs do Python, 25% no Hacker News). O Hacker News é o caso mais claro: o layout em tabela vira table > rowgroup > row > cell vários níveis abaixo antes da primeira notícia, e o snapshot é 4x o markdown.
O markdown não tem refs e quase nenhuma estrutura, então páginas ricas em prosa saem cerca de 2x menores. Duas páginas não seguiram esse padrão. O markdown do PyPI (20.165) manteve a página inteira, incluindo a lista de arquivos e os classificadores, enquanto o snapshot (7.931) não. O markdown da Wikipedia ficou a 13% do snapshot. O resumo honesto é que o snapshot é um pouco maior na maioria das páginas e a estrutura é o que você paga, mas uma página com muito texto pode custar mais em markdown.
Quanto isso custa em dólares?
A página de preços da Anthropic lista o Claude Sonnet 5.5 a $2 por milhão de tokens de entrada e o Claude Fable 5.1 a $10 (ambos em 19 de outubro de 2026, página de preços). Nossas contagens usam um tokenizador da OpenAI, então as do Claude vão diferir um pouco; o que vale confiar são as proporções. Na página mediana:
| Por 1.000 leituras de página | Tokens | Entrada Sonnet 5.5 | Entrada Fable 5.1 |
|---|---|---|---|
| HTML bruto | 51,7 M | $103,39 | $516,97 |
| Snapshot do Playwright MCP | 9,9 M | $19,75 | $98,74 |
Playwright MCP, --mobile |
6,4 M | $12,73 | $63,67 |
| Markdown do FastAF | 5,1 M | $10,17 mais 1.000 créditos | $50,83 mais 1.000 créditos |
No pacote Starter ($10 por 20.000 créditos), 1.000 scrapes simples custam $0,50, então o FastAF fica perto de $10,70 no Sonnet contra $19,75 do snapshot. É cerca da metade, e só de entrada. Uma leitura de página também fica no contexto em todos os turnos seguintes, a menos que você use cache ou a descarte, então uma execução longa a paga mais de uma vez. As definições de tools são um custo fixo por sessão: o Playwright MCP lista 25 tools (5.250 tokens), o servidor MCP do FastAF 15 (3.831).
Dá para deixar o Playwright MCP mais barato?
Dá, e o README do pacote diz isso: recomenda o Playwright CLI com skills para agentes de programação porque mantém as árvores de acessibilidade fora do contexto do modelo. Dentro do MCP, a flag --mobile (documentada como economia de tokens) reduziu a mediana de 9.874 para 6.367 aqui. Ela tem um porém. Na Wikipedia derrubou 24.931 tokens para 3.864 porque o layout mobile dobra as seções: 1 parágrafo no snapshot em vez de 22. No PyPI perdeu o campo de licença e reprovou na nossa verificação. Não leia um snapshot menor como o mesmo conteúdo.
Há outras alavancas na lista de tools que não medimos: browser_find devolve os nós que casam, com contexto, em vez da árvore toda; browser_snapshot aceita depth e filename; e browser_navigate já escreve em um arquivo em vez de no chat. Se você sabe qual parte da página precisa, elas vencem qualquer leitura da página inteira.
Quando o navegador é a ferramenta certa?
Quando a tarefa é interação: clicar por uma interface, preencher um formulário, um fluxo atrás de um login seu, uma página em que o próximo passo depende do que o último clique fez. Os refs do snapshot existem para isso, e o markdown não tem nada em que clicar.
Também tentamos uma pergunta do Stack Overflow e a deixamos fora da tabela: respondeu com uma página de verificação de bot (HTTP 403), e o FastAF devolveu 400 e 422 target_unavailable sem cobrança. As verificações de bot de um site são decisão do dono; o FastAF lê páginas públicas e não tenta passar por elas, e não comparamos ferramentas contra elas.
Apps em JavaScript são o caso intermediário. No crates.io o primeiro snapshot do Playwright teve 35 tokens porque o app ainda não tinha carregado; um segundo, depois de uma espera, deu 4.693. A chamada simples do FastAF devolveu 422, e a renderização com dynamic=true custou 5 créditos e 1.408 tokens em 6,3 s. Veja por que um fetch volta vazio e renderização de JavaScript. Uma correção: nossa primeira frase de verificação para o crates.io não casava com a forma como a página divide o texto, então a corrigimos e rodamos as duas ferramentas de novo nessa página.
Quando o trabalho é ler uma página pública e responder a partir dela, ler basta, e a API de web scraping ou a tool scrape_page faz isso em uma chamada. Para a configuração no Claude Code, no Cursor e no Codex, veja busca na web via MCP.
Como reproduzir isso?
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)")
Executado em 19 de outubro de 2026 contra duas das páginas acima, imprimiu:
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)
O snapshot do GOV.UK deu 3.038 aqui contra 3.378 na tabela porque as páginas mudam entre execuções. Nossa execução completa acrescentou as verificações das frases-agulha, uma nova tentativa depois de 3 s de espera para snapshots ralos, três repetições e o braço --mobile. O tempo todo rodamos o Chromium num notebook na Itália, e as URLs são as mesmas da tabela, então você pode repetir.
Resumindo
Em 11 páginas públicas, uma leitura com o Playwright MCP levou uma mediana de 9.874 tokens e o markdown 5.083: cerca da metade, não um centésimo. O snapshot gasta tokens com refs, papéis e URLs; o --mobile o enxuga mas pode perder conteúdo; e o snapshot ainda pode ganhar em páginas que são quase só estrutura. Use o navegador quando precisar clicar, digitar ou entrar em algo seu, e leia a página como markdown quando só precisar do que ela diz. Pegue 500 créditos grátis e rode o script nas páginas que o seu agente mais lê. Preços e limites estão na página de preços e na documentação.