Passa al contenuto principale

Playwright MCP: la guida pratica approfondita (2026)

Intermedio

playwright-mcp di Microsoft è a ~35k stelle su GitHub e — secondo i registri MCP mantenuti dalla community — è attualmente il server MCP più installato del pianeta, davanti persino al GitHub MCP ufficiale e al Figma MCP. Se usi Claude Code, Cursor, Codex, Windsurf o Claude Desktop e hai mai chiesto al tuo agente di "controllare il sito" o "prendere dati da quella dashboard", è questo lo strumento che fa il lavoro vero.

Quasi tutte le guide si fermano all'install da due righe. Questa pagina è la parte che conta dopo: cosa fa davvero lo strumento sotto il cofano, le modalità che la gente non sa esistano, e gli spigoli — costo in token, sicurezza, lock del profilo browser — che spuntano intorno alla seconda settimana.

What you'll learn
  • Capire perché la modalità accessibility-snapshot (default) non è solo più veloce della vision — è un paradigma di automazione diverso che l'LLM tratta in modo deterministico
  • Conoscere i tre modi profilo — persistente, isolato, estensione browser — e quando ciascuno è la scelta giusta
  • Attivare i pacchetti di capability opt-in (network, storage, devtools, vision, pdf, testing) con --caps e capire perché sono disattivati di default
  • Vedere il vero costo in token di Playwright MCP in una sessione Claude Code e sapere quando Playwright-as-a-Skill vince invece
  • Distribuire Playwright MCP come server HTTP/SSE standalone, in Docker, e in modo sicuro per run autonome (il masking dei secret è una comodità, non un confine di sicurezza)

Perché questo server ha divorato l'ecosistema

Playwright MCP è l'implementazione di riferimento del concetto "dai un browser a un LLM", e ha fatto due scommesse di design che si sono rivelate corrette:

  1. Snapshot strutturati di accessibilità come interfaccia primaria — non screenshot. Il modello riceve un albero compatto e deterministico di elementi (ruoli, nomi, ref). Nessun modello vision richiesto, nessuna allucinazione di coordinate, i token spesi in struttura invece che in pixel.
  2. Motore di automazione reale di Playwright sotto — stesse attese, stessi check di auto-actionability, stesso sistema di locator temprato da anni di QA in produzione. Niente di artigianale.

Risultato: a install fresco ti ritrovi con circa 50+ tool tra navigazione, compilazione form, tab, snapshot, screenshot, accesso alla console, ispezione network e alcune categorie opt-in. È una superficie ampia — il che ci porta dritti alla prima cosa che sorprende.

La modalità che stai davvero facendo girare

Di default il server MCP gira in modalità accessibility-snapshot. Quando il tuo agente chiama browser_snapshot non riceve uno screenshot — riceve un albero simile a YAML:

- Page URL: https://example.com/login
- role: main
- role: form
- role: textbox, name: "Email", ref: e12
- role: textbox, name: "Password", ref: e13
- role: button, name: "Sign in", ref: e14

L'agente chiama poi browser_click({ ref: "e14" }) — nessun selettore CSS inventato, nessuna coordinata indovinata. ref è un handle che il server ha coniato dal locator Playwright sottostante, quindi il click è affidabile quanto un page.getByRole('button', { name: 'Sign in' }).click() scritto a mano.

Ecco perché chi arriva da script Selenium/Puppeteer scritti da un LLM pensa "il browser use fatto dall'AI è rotto" — stava dando in pasto al modello HTML grezzo o screenshot. La modalità snapshot non ha quel failure mode, perché il modello non vede mai un selettore che potrebbe sbagliare.

Pro tip
  • Se il tuo agente sta indovinando selettori CSS, quasi sicuramente stai usando un MCP browser diverso — o hai disattivato gli snapshot.
  • Gli snapshot sono per pagina. Per gli iframe, chiama browser_snapshot esplicitamente dentro l'iframe; il tool espone la navigazione degli iframe.
  • I ref sono effimeri. Sono validi solo fino alla prossima mutazione della pagina — trattali come i fiber ID di React.

Pacchetti di capability opt-in (--caps)

Solo i tool sicuri e noiosi partono attivi. Quelli potenti stanno dietro al flag --caps e li attivi per singolo server:

{
"mcpServers": {
"playwright": {
"command": "npx",
"args": ["@playwright/mcp@latest", "--caps=network,storage,pdf"]
}
}
}
CapCosa sbloccaPerché è off di default
networkMock delle richieste, offline, route interceptionPuò riscrivere il traffico in silenzio; serve intenzione
storageLettura/scrittura di cookie, localStorage, sessionStorageFurto di dati same-origin banale una volta on
devtoolsTracing, video recording, evidenziazione elementiArtefatti enormi, costo su disco
visionAzioni mouse su coordinate pixelBypassa il modello deterministico — vedi sotto
pdfSalvare la pagina corrente come PDFVa bene, solo rumore per la maggior parte delle sessioni
testingVerifica di elementi/testo/valori, generazione locatorNicchia di test-authoring, aggiunge una decina di tool
configRileggere la config risolta del serverSolo debug

Quello meno ovvio è vision. Attivarlo dà al modello browser_mouse_move_at_coordinates e simili. Cambia anche silenziosamente il profilo di failure dell'intera sessione, perché l'agente ripiegherà sul click a coordinate quando gli snapshot sono scomodi — e ora hai un browser guidato da un modello linguistico che fa matematica pixel-per-pixel. Attivalo solo quando un elemento canvas o un widget con accessibility rotta te lo impone.

I tre modi profilo

Qui vive il design interessante.

Guided walkthrough1 of 3
  1. Il server lancia Chromium contro una user-data directory per workspace (il path deriva da un hash della tua cartella di lavoro). Cookie, localStorage, password salvate e cronologia persistono tra le sessioni. Ottimo per dashboard autenticate. Spigolo: solo un'istanza alla volta può tenere il profilo — una seconda finestra Claude Code sulla stessa cartella andrà in errore. Punta --user-data-dir a una location condivisa e puoi condividere lo stato tra progetti.

Install: le quattro config che vuoi davvero

Locale standard (Claude Desktop / Claude Code / Cursor)

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

Isolato + auth precaricata (in stile CI, riproducibile)

{
"mcpServers": {
  "playwright": {
    "command": "npx",
    "args": [
      "@playwright/mcp@latest",
      "--isolated",
      "--storage-state", "/Users/me/.auth/github.json",
      "--caps=network"
    ]
  }
}
}

Agganciati alla mia vera tab Chrome (browser extension)

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

Server HTTP standalone (condividi un browser tra molti agenti)

# One-time on your workstation:
npx @playwright/mcp@latest --port 8931

# Then every client points at it:
{
"mcpServers": {
  "playwright": { "url": "http://localhost:8931/mcp" }
}
}

La modalità HTTP è quella che la gente si perde. Se fai girare quattro coding agent sulla stessa macchina, quattro installazioni npx separate di Playwright MCP lanciano ognuna il proprio Chromium. Un server HTTP condiviso mantiene un solo pool di browser, il che è più economico e più facile da osservare.

Docker: l'unica ricetta "headless server" supportata

# One-shot (stdio):
docker run -i --rm --init --pull=always mcr.microsoft.com/playwright/mcp

# Long-lived HTTP server on port 8931:
docker run -d -i --rm --init --pull=always \
--entrypoint node \
-p 8931:8931 \
mcr.microsoft.com/playwright/mcp \
/app/cli.js --headless --browser chromium --no-sandbox --port 8931 --host 0.0.0.0

Due cose che la doc nasconde: l'immagine Docker è solo Chromium headless (niente Firefox, niente WebKit, niente modalità headed), e --no-sandbox è obbligatorio dentro il container. Se ti serve Firefox o una vera GPU, fai girare il server sull'host.

La battaglia sul costo in token: MCP vs Skill vs CLI grezza

L'altra cosa di cui nessuno ti avverte: Playwright MCP è il server singolo più pesante che puoi attaccare a Claude Code, a circa 3.500 token di overhead di tool-schema per sessione — prima ancora di fare una chiamata. Quel numero vive nella tua context window per l'intera conversazione.

Misurazioni riportate dalla community (link sotto) danno un task tipico "testa questo sito":

ApproccioToken per il taskCosto Sonnet (approx)
Playwright MCP (cap di default)~114k~$0.34
Playwright CLI + un file Skill~27k~$0.08

L'approccio Skill spedisce un piccolo SKILL.md che documenta la CLI di Playwright e lascia l'agente shellare con bash. Lo schema del tool resta fuori dal contesto del modello finché non serve, e il file skill stesso viene letto una volta sola. Versioni recenti di Playwright MCP hanno ridotto questo gap non streamando più lo stato completo della pagina a ogni chiamata, ma l'overhead dello schema resta l'overhead dello schema.

Regola pratica: MCP per lavoro interattivo/esplorativo dove il modello ha bisogno di botta e risposta conversazionale con il DOM. Skill/CLI per job ripetibili — screenshot di una lista di URL, esecuzione di una suite di test, o qualsiasi cosa metteresti in un cron.

Vedi la pagina di Claude Code su costo in token di MCP per misurarlo nella tua sessione.

Il masking dei secret è una comodità, non un confine

Playwright MCP supporta una mappa secrets nella sua config:

{
"secrets": {
"OPENAI_API_KEY": "sk-real-key-here",
"GITHUB_TOKEN": "ghp_real"
}
}

Quando il server vede quelle stringhe esatte dentro una risposta di un tool, sostituisce indietro il nome della chiave prima di inoltrare il risultato al modello. È genuinamente utile — contenuto di pagina che riecheggia la tua API key non la farà più leakare nel transcript dell'LLM.

Ma il README del progetto è esplicito e lo ripete più volte: "Playwright MCP non è un confine di sicurezza." Concretamente:

  • Una pagina può rendere il tuo secret in un attributo title o in base64 e il masker non lo prenderà.
  • Qualsiasi cosa il modello chieda al browser di fare — incluso leggere document.cookie con un trucco su un campo form — viene comunque eseguita con l'autorità del tuo profilo reale.
  • La modalità estensione si aggancia al tuo Chrome di tutti i giorni. Ogni tab loggata diventa in linea di principio raggiungibile.

Tratta un agente con Playwright MCP + profilo persistente come tratteresti un nuovo dipendente con i tuoi cookie di admin: bene per task stretti e supervisionati, catastrofico su --dangerously-skip-permissions. Vedi Browser agentici e fiducia same-origin e Cosa il tuo agente carica per il threat model più ampio.

Cosa è cambiato di recente

Le release recenti (linea v0.0.79) vale la pena conoscerle perché cambiano i default:

  • --timeout-settle — il server ora aspetta un numero configurabile di ms (default 500) dopo ogni azione perché il lavoro innescato si stabilizzi prima di rispondere. Alzalo per SPA lente, abbassalo per test di performance.
  • Screenshot WebPbrowser_take_screenshot accetta type: "png" | "jpeg" | "webp" e inferisce dal filename. WebP è circa il 30–50% più piccolo di PNG a parità di qualità, vale la pena cambiare se fai molti screenshot.
  • Codegen output per Python / Java / C# — la cap testing ora emette scheletri di test in più linguaggi oltre a TypeScript.
  • Rilevamento evento download — sostituisce la precedente inferenza basata su errore; i download ora scatenano un evento vero così gli agenti possono aspettarli.
  • Relay CDP dell'estensione browser — irrobustito con validazione degli header sull'upgrade WebSocket.

Playbook di debug

Guided walkthrough1 of 5
  1. Lo snapshot è stale. Fai chiamare all'agente browser_snapshot di nuovo dopo ogni navigazione o submit di form — i ref dello snapshot precedente sono morti. Se ancora non trova l'elemento, il pulsante potrebbe essere dentro un iframe o Shadow DOM; espandi lo scope dello snapshot.

Concetti correlati da tenere dritti

Nessuna carta — aggiungine qualcuna per iniziare a studiare. 🃏

Quick check

Check yourself

0/5
  1. Di default, quando il tuo agente chiama browser_click, cosa identifica l'elemento target?
  2. Vuoi due finestre Claude Code sullo stesso repo, entrambe che usano Playwright MCP con il tuo profilo loggato. Qual è la mossa giusta?
  3. Quale valore di --caps cambia di più il profilo di sicurezza della tua sessione?
  4. Per un job batch ripetibile (screenshot di 200 URL ogni notte), qual è di solito lo strumento giusto?
  5. Configuri la mappa secrets con GITHUB_TOKEN=ghp_xxx. Una pagina include il token codificato in base64 in un campo nascosto. Cosa succede?

Quando Playwright MCP è lo strumento sbagliato

  • Ti serve login condiviso con una sessione di browsing umana in corso. Considera un agent browser a login condiviso come quello coperto in Browser agentici che ereditano i tuoi login — la modalità extension di Playwright MCP ci si avvicina, ma la UX su approvazioni e Spaces è diversa.
  • Stai testando code path di produzione e vuoi il vero test runner di Playwright. Usa @playwright/test direttamente; l'MCP è ottimizzato per l'esplorazione agentica, non per l'authoring di test in CI.
  • Il workload è al 100% scraping headless di HTML statico. Un fetch + parser semplice è ordini di grandezza più economico. Tieni il browser per pagine che davvero eseguono JavaScript.
  • Non puoi rischiare nessun leak di stato browser. Usa --isolated con uno snapshot fresco di --storage-state per run. Non usare la modalità extension contro il tuo Chrome quotidiano.

Fonti e letture ulteriori