Playwright CLI in Claude Code: Autonome Browserbots
De eerste keer dat ik Claude Code een echte browser onbegeleid liet besturen, keek ik toe hoe een onboardingformulier van 12 vragen in slowmotion faalde. Pagina 1 werkte. Pagina 2 werkte. Pagina 3 — een lang-formaat tekstveld — bevroor. De agent drukte op Enter om door te gaan. Er gebeurde niets. Drukte nog een keer. Nog steeds niets. Toen deed het iets wat ik oprecht niet had verwacht: het maakte een screenshot, opende de paginabron, vond de keydown-handler, merkte op dat het tekstveld de Enter-toets opslokte in plaats van het door te laten bubbelen naar de submit-listener van het formulier, repareerde de handler, deployede opnieuw, voerde het formulier opnieuw uit, en pingde me toen alle 12 vragen schoon waren ingediend.
Die hele loop — testen, detecteren, repareren, opnieuw testen — duurde ongeveer elf minuten. Ik was de hele tijd op drie meter afstand van mijn toetsenbord geweest en had nul toetsaanslagen bijgedragen.
Het ding dat het liet werken was geen slimme prompt. Het was geen vaardigheid. Het was een schakelaar die ik een week eerder had omgezet: Playwright MCP inwisselen voor Playwright CLI als Claude Code's handen in de browser. Die ene verandering halveerde mijn browser-automatisering tokenrekening met ruwweg een factor 4, maakte debug-screenshots overzichtelijk om te beoordelen, en ontsloot een categorie agent die ik eerder niet echt had kunnen bouwen — autonome QA-loops, scrapers die overleven wanneer Google ze blokkeert, en bots achter logins die ingelogd blijven tussen runs door.
Dit is de volledige uitleg. Wat Playwright CLI is, waarom het specifiek beter is dan Chrome DevTools MCP en Playwright MCP voor Claude Code-werklasten, de drie productiepatronen waarvoor ik het nu gebruik, en de lelijke delen die niemand noemt in de lanceringsposts.
Waarom Playwright CLI Bestaat (En Waarom Het Niet Zomaar Nog Een MCP Is)
Microsoft bracht Playwright CLI begin 2026 uit als een bewuste aanvulling — geen vervanging — op Playwright MCP. De MCP-server bestaat nog steeds. Hij werkt nog steeds. Maar het team merkte iets op dat de rest van ons ook opviel: wanneer een codeeragent zoals Claude Code met een browser praat via MCP, stuurt elke afzonderlijke pagina-interactie een volledige toegankelijkheidsboom terug naar het contextvenster van het model. Op een complexe pagina is die boom 50.000 tokens. Per klik. Per scroll. Per toetsaanslag.
Vermenigvuldig dat met een QA-run van 50 stappen en je begrijpt waarom mijn Anthropic-dashboard alarm sloeg.
Playwright CLI draait de datastroom om. In plaats van de toegankelijkheidsboom in de modelcontext te streamen, slaat de CLI snapshots op als compacte YAML-bestanden op schijf. Het model leest alleen het deel waar het om vroeg, wanneer het erom vroeg. Dezelfde browser. Dezelfde Playwright API eronder. Een andere relatie tussen het model en de data.
De cijfers uit de publieke benchmarks komen overeen met wat ik zag op mijn eigen rekeningen:
- Playwright MCP: ~1,5M tokens per browserautomatiseringsrun (slechtste geval, volledige pagina's, meerdere beurten)
- Chrome DevTools MCP: ~330K tokens per run (beter — gerichte snapshots, enkele execute-aanroep batching)
- Playwright CLI: ruwweg 4x minder tokens dan Playwright MCP voor equivalent werk
Dat is geen marginale optimalisatie. Dat is het verschil tussen "ik kan deze agent de hele nacht draaien" en "ik kan deze agent veertig seconden draaien voordat facturering me vertelt te stoppen." Voor mensen die tokenkosten al agressief bijhouden — en als je dat niet doet, is mijn Claude Code tokenoptimalisatie-uitleg het lezen waard voordat je hier iets van bouwt — is Playwright CLI het antwoord op een probleem waarvan je misschien niet wist dat je het had.
Er is een tweede reden waarom het ertoe doet waar niemand over praat, en het kostte me een paar sessies om erachter te komen. Playwright CLI is een CLI. Geen daemon. Geen server. Geen protocol. Het is een binary die je aanroept met argumenten. Claude Code is erg goed in het aanroepen van binaries met argumenten. Het is minder goed in het beheren van een langlopende MCP-verbinding, het herstellen van MCP-timeouts, en het parsen van toegankelijkheidsbomen waar het niet om had gevraagd. Playwright CLI speelt in op Claude Code's werkelijke sterktes — bash, bestanden en kleine gerichte toolaanroepen.
Die afstemming is wat het testcollab-bericht aanwees als de echte reden waarom codeeragenten het prefereren. Tokenefficiëntie is de kop. Toolafstemming is de kern.
De Installatie (En Waarom Ik De Helft van Microsofts Aanbevolen Setup Oversla)
Je kunt Playwright CLI in Claude Code draaien binnen ongeveer negentig seconden. De installatie is schoner dan Playwright MCP, waarbij je vroeger een JSON-fragment moest kopiëren naar je mcp.json en maar moest hopen dat de versiestring niet zou afwijken.
De versie van de installatie die ik daadwerkelijk gebruik:
# Initialiseer een Playwright-project — maakt package.json, tsconfig, voorbeeldtests
npm init playwright@latest
# Installeer browserbinaries (Chromium, Firefox, WebKit + afhankelijkheden)
npx playwright install --with-deps
# Controleer of de CLI werkt
npx playwright --version
Als je het overal beschikbaar wilt hebben in plaats van per project:
npm install -g @playwright/cli@latest
playwright-cli install
playwright-cli install-browser
Microsoft levert ook een --skills-vlag (playwright-cli install --skills) die Playwright koppelt aan Claude Code's vaardigheidssysteem. Ik heb het geprobeerd. Het werkt prima. Maar ik praat liever rechtstreeks met de CLI via bash omdat het Claude duidelijkere foutoppervlakken geeft — wanneer iets fout gaat op de vaardigheidslaag, moet je de vaardigheid en het onderliggende commando debuggen. Wanneer iets fout gaat op de CLI-laag, vertelt de stderr je precies wat er is gebeurd.
Eenmaal geïnstalleerd is het oppervlak dat Claude Code daadwerkelijk gebruikt klein:
npx playwright codegen <url>— neem een sessie op, produceer een werkend testscriptnpx playwright test— voer tests uit (standaard headless, met venster via--headed)npx playwright test --debug— open de inspector, stap frame voor frame doornpx playwright show-trace trace.zip— bekijk een opgenomen trace achteraf
De eigenlijke Playwright CLI (het @playwright/cli-pakket) voegt een ander vocabulaire toe gericht op codeeragenten — open, goto, click, type, fill, select, check, hover, drag, upload, snapshot, screenshot, close. Claude heeft de neiging deze te combineren tot korte scripts in plaats van ze één voor één aan te roepen, wat het juiste instinct is.
Nu het deel dat ertoe doet: wat je er daadwerkelijk mee bouwt.
Patroon 1: De Autonome QA-Loop
Dit is de use case die me overtuigde. Ik had een onboardingformulier van meerdere pagina's — twaalf vragen, zes pagina's, conditionele vertakking op pagina vier, een beoordelingsscherm, een bewerk-vanuit-beoordeling-flow. Standaardwerk. Niet-standaard kapot.
De buglijst toen ik de run startte:
- De Enter-toets liet het formulier niet doorgaan op tekstveldpagina's — alleen de expliciete Volgende-knop deed dat
- De beoordelingspagina laadde niet in ongeveer 20% van de gevallen, en gaf een leeg component terug
- De Bewerken-knop op de beoordelingspagina werd geblokkeerd door een achtergebleven modale overlay als je eerder in de flow een modaal had weggeklikt
Ik wist van de eerste. De andere twee ontdekte ik omdat ik de agent liet draaien.
Het script dat Claude Code voor zichzelf schreef, enigszins opgeschoond:
import { test, expect } from '@playwright/test';
test('full onboarding flow — 12 questions, 6 pages', async ({ page }) => {
await page.goto('http://localhost:3000/onboarding');
for (let pageNum = 1; pageNum <= 6; pageNum++) {
await page.screenshot({
path: `screenshots/onboarding-page-${pageNum}.png`,
fullPage: true,
});
// Fill whatever inputs exist on this page
const inputs = await page.locator('input, textarea, select').all();
for (const input of inputs) {
const type = await input.getAttribute('type');
if (type === 'email') await input.fill('[email protected]');
else if (type === 'tel') await input.fill('555-0100');
else await input.fill('automated test response');
}
// Advance — explicit button click, not Enter
await page.getByRole('button', { name: /next|continue|review/i }).click();
await page.waitForLoadState('networkidle');
}
await expect(page.getByText(/thank you|submitted/i)).toBeVisible({
timeout: 10_000,
});
});
De Claude Code-instructie die het aanstuurde bestond uit vier zinnen: "Voer de test uit. Als hij faalt, maak een screenshot van het faalmoment, lees de broncode van het falende component, stel een fix voor, pas hem toe, herstart de devserver en voer opnieuw uit. Herhaal tot de test drie keer op rij slaagt. Vraag me niets onder P0."
De agent voerde de test uit. Hij faalde op pagina 3 — Enter-toets, de bug die ik kende. Het opende het tekstveldcomponent, vond de onKeyDown-handler die event.preventDefault() onvoorwaardelijk aanriep, beperkte het tot alleen Enter voorkomen wanneer Shift was ingedrukt (zodat meerregelige invoer nog werkte), sloeg op, herstartte dev, voerde opnieuw uit. Test passeerde pagina 3, faalde op pagina 4 — de lege beoordelingspagina. De agent vermoedde een race tussen de routelader en de formulierstate-hook, voegde een laadstatus toe, probeerde opnieuw. Geslaagd. Gefaald op de Bewerken-vanuit-beoordeling modale botsing. Schreef een klein effect dat modale overlays opruimde bij routewijziging. Drie keer op rij geslaagd. Gestopt. Schreef een samenvatting in qa-run.md.
Elf minuten. Drie echte bugs gevonden en gepatcht. Eén mens dat toekeek vanuit de andere kant van de kamer.
Het patroon, gedistilleerd:
- Test — Playwright CLI voert het script uit
- Detecteer — Bij falen: screenshot + broncode lezen + hypothese vormen
- Repareer — Pas de patch toe, herstart alles wat herstart moet worden
- Hertest — Loop tot N keer op rij groen, niet slechts één keer
De "N keer op rij"-vereiste doet veel werk. Een flaky test die één keer slaagt is niet gerepareerd. Drie opeenvolgende slagen is de kleinste steekproefgrootte waarbij je geloofwaardig kunt zeggen dat de fix heeft gehouden.
Dit is oprecht het dichtste dat ik Claude Code heb zien komen bij het gedrag van een junior QA-engineer die het ticket daadwerkelijk afmaakt. Als je wilt zien hoe dit soort loop componeert tot een bredere engineeringworkflow, legt het bericht over de Claude Code skills-stack de lagen daarboven uit — Superpowers, Skill Creator, de rest. Playwright CLI is de ogen en handen. Die vaardigheden zijn de hersenen.
Patroon 2: Adaptief Webscrapen (Wanneer Google Besluit Dat Het Genoeg Van Je Heeft)
Andere taak, andere les. Een vriend die een kleine tandartsmarketingservice runt, vroeg of ik contactgegevens kon ophalen — naam, adres, telefoon — voor elke tandarts in een paar specifieke postcodes in Californië. Handmatige onderzoekstijd per postcode: vier tot zes uur. Openbare informatie, gewoon vervelend om te verzamelen.
Het eerste script dat Claude schreef was het voor de hand liggende: zoek op Google naar dentist near 94110, parse de SERP, bezoek elk resultaat, extraheer het telefoonnummer van de contactpagina. Het werkte. Voor ongeveer dertig zoekopdrachten. Toen serveerde Google een CAPTCHA, toen een zachte blokkering, toen een harde snelheidslimiet.
De patch was het interessante deel. Zonder dat ik het promptte, voegde Claude drie gedragingen toe:
import { chromium } from 'playwright';
async function adaptiveSearch(query: string) {
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ' +
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
});
const page = await context.newPage();
// 1. Try Google first
await page.goto(`https://www.google.com/search?q=${encodeURIComponent(query)}`);
// 2. Detect blocking — captcha, "unusual traffic" page, empty results
const blocked = await page.locator('text=/unusual traffic|captcha|are you a robot/i').count();
if (blocked > 0) {
console.log('Google blocked — switching to DuckDuckGo');
await page.goto(`https://duckduckgo.com/?q=${encodeURIComponent(query)}`);
}
// 3. Random jitter between requests so the cadence doesn't look automated
await page.waitForTimeout(2000 + Math.random() * 3000);
return page;
}
Die ene fallback — Google naar DuckDuckGo wanneer geblokkeerd — bracht het script van "sterft na 30 zoekopdrachten" naar "draaide zes uur zonder toezicht." DuckDuckGo heeft niet de anti-bot-infrastructuur van Google, de SERP-layout is eenvoudiger te parsen, en voor een zoekopdracht als "dentist 94110" is de resultaatkwaliteit in wezen gelijkwaardig.
De tweede aanpassing was subtieler. Het telefoonnummer was zichtbaar op de SERP voor ongeveer 70% van de tandartslijsten — Google haalt het uit gestructureerde data en toont het inline. De naïeve scraper zou dat zichtbare nummer graag pakken en doorgaan. Het probleem: dat nummer is soms een marketingtrackingnummer, niet de daadwerkelijke lijn van de tandarts.
Dus werkte Claude de logica bij: zelfs wanneer een telefoonnummer zichtbaar is op de SERP, klik door naar de eigen contactpagina van de tandarts en haal het nummer daar vandaan. Langzamer per record. Hogere nauwkeurigheid. Het soort beslissing dat een zorgvuldig mens zou nemen en een slordige automatisering zou overslaan.
Het volledige verzamelscript draaide minder dan drie uur, trof ~430 tandartsen in Californië over vijf postcodes, en produceerde een CSV met naam, adres, telefoon, website, en (indien beschikbaar) openingstijden. Kosten in API-tokens, met Playwright CLI die de browser beheert in plaats van MCP: ongeveer $4,20.
Twee praktische regels die ik nu toepas op elke scraping-opdracht:
- Heb altijd een fallback-zoekmachine. Google is de beste bron tot het de slechtste bron is. Je script moet de overgang detecteren zonder dat jij erbij moet zitten.
- Vertrouw de SERP niet voor elk datapunt dat commerciële waarde heeft. Telefoonnummers, prijzen, openingstijden — klik door en verifieer. De extra latentie is goedkoper dan een contactlijst vol doodlopende nummers.
Als je iets complexers bouwt dan dit, behandelt mijn bericht over WebMCP voor Chrome AI-agenten het alternatief wanneer je Chrome-specifieke protocolfeatures nodig hebt die Playwright niet blootstelt.
Patroon 3: Persistente Loginsessies — De Ingelogde Bot
Dit is het patroon dat daadwerkelijk veranderde wat ik denk dat Claude Code kan doen.
Openbare pagina's scrapen is makkelijk. Alles achter een login is de echte frontier — en het meeste interessante werk gebeurt achter een login. Slack-kanalen. Schoolplatforms. Interne dashboards. SaaS-producten waarvoor je betaalt. De uitdaging is niet één keer inloggen. Het is ingelogd blijven, over runs heen, over dagen heen, over browser-herstarts heen, zonder dat je elke keer opnieuw inloggegevens intypt.
De persistente context van Playwright is het antwoord, en de meeste tutorials doen het verkeerd omdat ze storageState verwarren met launchPersistentContext. Ze zijn niet hetzelfde.
storageState is een snapshot van cookies + localStorage, gedumpt naar een JSON-bestand. Goed voor headless CI-runs waarbij je één keer inlogt, de staat opslaat, en deze hergebruikt over honderden testruns.
// Save after a successful login
await page.context().storageState({ path: 'auth.json' });
// Reuse in later runs
const context = await browser.newContext({ storageState: 'auth.json' });
launchPersistentContext is een echt browserprofiel op schijf. Cookies, cache, localStorage, IndexedDB, service worker-registraties, alles. Dit is wat je wilt wanneer je je moet gedragen als een daadwerkelijk ingelogde gebruiker over sessies heen — niet alleen een ingelogde testrunner.
import { chromium } from 'playwright';
const userDataDir = '/Users/mejba/.playwright-profiles/school-platform';
const context = await chromium.launchPersistentContext(userDataDir, {
headless: false, // first run only — log in by hand
viewport: { width: 1440, height: 900 },
});
const page = context.pages()[0] ?? await context.newPage();
await page.goto('https://school.example.com');
// Log in manually, complete 2FA, dismiss any onboarding modals
// Then close the browser. The profile is now persisted.
Het overdrachtspatroon is het deel waar ik een paar avonden over deed om het goed te krijgen. Eerste run: met venster, handmatig inloggen, handmatige 2FA, handmatig alles-wat-de-bot-niet-kan. Volgende runs: dezelfde userDataDir, maar headless, en je bent al geauthenticeerd. De cookies, de sessietokens, het apparaat-vingerafdrukgedoe — het leeft allemaal op schijf in die profielmap.
Voor een schoolplatformautomatisering die ik bouwde — een dagelijks script dat berichten ophaalt die door klasgenoten als "wins" zijn gemarkeerd, ze rangschikt op recentheid, en de top vijf liket — ziet de run er zo uit:
import { chromium } from 'playwright';
(async () => {
const context = await chromium.launchPersistentContext(
'/Users/mejba/.playwright-profiles/school-platform',
{ headless: true }
);
const page = await context.newPage();
await page.goto('https://school.example.com/channels/wins');
// Filter by newest — the platform's UI tab
await page.getByRole('tab', { name: 'Newest' }).click();
await page.waitForLoadState('networkidle');
// Scroll until we have 30 posts loaded
for (let i = 0; i < 5; i++) {
await page.mouse.wheel(0, 2000);
await page.waitForTimeout(800);
}
// Like the top 5 — but throttled, because the platform crashed
// when I tried to like 5 in 2 seconds during my first run
const likeButtons = await page
.locator('[data-testid="like-button"]')
.filter({ hasNotText: 'Liked' })
.all();
for (const button of likeButtons.slice(0, 5)) {
await button.click();
await page.waitForTimeout(1500); // throttle
}
await context.close();
})();
De vertraging in de loop is er vanwege een echte bug die ik veroorzaakte. Mijn eerste versie van het script klikte alle vijf likes in een Promise.all. De frontend van het platform is niet gebouwd om vijf gelijktijdige like-mutaties van dezelfde sessie te verwerken en het liet de React-boom crashen midden in de render. Claude ontdekte dat door het screenshot van de kapotte staat te lezen, de React-foutoverlay te vinden, de stacktrace te lezen, en te beslissen dat de fix een vertraging was in plaats van retry-logica.
Die iteratieve loop — breken, screenshot, de fout lezen, hypothese vormen, repareren, opnieuw uitvoeren — is exact dezelfde loop als Patroon 1. Ander domein, identieke vorm.
Verbinding Maken Met Een Reeds Draaiende Browser (CDP)
Er is een derde optie voor het "ingelogd"-probleem die de moeite waard is om te kennen, zelfs als je het niet vaak gebruikt: verbind Playwright met een Chrome-instantie die je zelf hebt gestart.
Start Chrome met de debuggerpoort open:
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
--remote-debugging-port=9222 \
--user-data-dir=/tmp/chrome-debug-profile
Laat Claude Code er dan verbinding mee maken vanuit een Playwright-script:
import { chromium } from 'playwright';
const browser = await chromium.connectOverCDP('http://localhost:9222');
const context = browser.contexts()[0]; // attach to the existing default context
const page = context.pages()[0] ?? await context.newPage();
Wanneer dit nuttig is: je hebt handmatig een complexe meerstaps-authenticatieflow doorlopen (SSO-redirects, hardwaresleutelprompts, captcha's) en je wilt dat de agent overneemt waar jij bent gestopt. Met venster, echte browser, echte cookies, geen profiel kopiëren. De beperking: CDP werkt alleen voor Chromium-gebaseerde browsers — niet Firefox of WebKit.
Ik gebruik dit bij misschien één op de twintig automatiseringen. Maar de keren dat ik het doe, lost niets anders hetzelfde probleem op.
Met Venster vs Headless — Een Regel, Geen Voorkeur
De standaard in CI is headless. De standaard tijdens ontwikkeling zou met venster moeten zijn voor de eerste run van elke nieuwe automatisering, en dan headless zodra het stabiel is.
De reden is debugasymmetrie. Wanneer een headless run faalt, heb je een screenshot, een trace, en je verbeelding. Wanneer een run met venster faalt, kun je de daadwerkelijke browser de daadwerkelijke fout zien maken in realtime. Het verschil tussen die twee debugervaringen is het verschil tussen een bug in twintig minuten fixen en een bug in drie uur fixen.
De vlag is simpelweg --headed:
npx playwright test --headed --debug
--debug voegt de inspector toe — pauzeer bij elke actie, stap erdoorheen, wijzig selectors live. Gebruik het één keer. Je gaat nooit meer terug naar print-debugging van Playwright.
De uitzondering: wanneer de agent zonder toezicht draait, moet het headless zijn. Runs met venster hebben een display-server nodig, worden afgebroken wanneer je sessie eindigt, en voegen echte overhead toe. De eenregelige omschakeling is wat je wilt — met venster tijdens de bouw, headless tijdens het draaien.
Waarvoor Ik Playwright CLI Niet Gebruik
Dit is het deel dat de meeste berichten overslaan. Drie dingen die ik probeerde en terugdraaide.
Zwaar netwerk-/prestatiedebuggen. Playwright CLI kan netwerklogs en traces vastleggen, maar voor serieus debuggen — waterfall-timings vergelijken, JavaScript-hotpaths profileren, CDP-level events inspecteren — is Chrome DevTools MCP oprecht beter. De execute-tool batcht acties in een enkele aanroep en de CDP-native data is rijker. Ik houd beide geïnstalleerd en grijp naar DevTools MCP wanneer de vraag is "waarom is deze pagina traag" in plaats van "werkte deze pagina."
Alles binnen iframes van een andere origin. Playwright gaat om met cross-origin iframes, maar de API wordt snel lelijk — frameLocator-ketens, zorgvuldige waitFor-plaatsing, en een permanent vermoeden dat de selectors de volgende deploy niet overleven. Voor advertentiewidgets, embedded Stripe/Plaid-flows of sociale loginpopups onderschep ik op de netwerklaag of automatiseer ik die stap gewoon niet. De kosten-batenverhouding is er niet.
E-mailbevestigingsflows. Playwright klikt graag op de link in de e-mail als je het de link geeft. Het moeilijke deel is de link krijgen. Mailbox-API's (Mailtrap, Mailosaur) lossen dit op; Playwright niet. Proberen om Gmail te scrapen voor de verificatie-e-mail is een pad naar ellende.
De eerlijke samenvatting: Playwright CLI is de juiste standaard voor browserautomatisering in Claude Code in 2026. Het is niet het juiste hulpmiddel voor prestatiewerk, exotische embed-flows, of e-mailplumbing. Weten waar de grenzen liggen bespaart je het leren ervan om 2 uur 's nachts.
De Bots Inplannen — Modal, Trigger, En De Desktop Cron-Valkuil
Een browserautomatisering die alleen draait wanneer je eraan denkt om het te draaien is een demo. Productie-browserautomatiseringen draaien op een schema.
Drie opties, elk geschikt voor een andere realiteit:
Modal — serverless Python met eersteklas Playwright-ondersteuning. Je definieert een functie met @modal.function(schedule=modal.Cron("0 9 * * *")) en Modal regelt de container, de browserbinaries, de runisolatie, de logs. Mijn dagelijkse nieuwsoverzichtbot draait hier. Ongeveer $0,40 per dag aan compute.
Trigger.dev — TypeScript-native, het JS-ecosysteem voelt dichterbij als je Playwright-scripts al TS zijn. Hun browser-task primitive is specifiek gebouwd voor Playwright-werklasten.
Desktop cron + headless — voor persoonlijke automatiseringen op je eigen laptop. Werkt. Valt om zodra je laptop slaapt, de wifi wisselt, of de browser updatet. Gebruik het niet voor iets dat ertoe doet.
Ik begon alles op desktop cron omdat het gratis was. Ik migreerde naar Modal na de derde gemiste run tijdens een vlucht. Totale maandelijkse rekening over vier geplande bots: minder dan $25. De moeite waard.
De Agentlaag Erboven
Zodra Playwright CLI is aangesloten en je eerste drie patronen werken, is de verleiding om steeds grotere scripts te blijven bouwen. Doe dat niet. De volgende stap is om agenten te bouwen die de scripts aanroepen.
Een dagelijks-nieuwsoverzicht-agent die:
- Wakker wordt om 8 uur 's ochtends
- Koppen ophaalt van drie RSS-feeds via gewoon HTTP (geen browser nodig)
- Claude vraagt om ze samen te vatten en te rangschikken
- Een Playwright CLI-script aanroept om de samenvatting te posten in een Slack-kanaal
- Het kanaal dertig minuten in de gaten houdt voor reacties via een persistente sessie
- Claude vraagt om reacties te formuleren op alles dat een reactie nodig heeft
- Een ander Playwright-script aanroept om de reacties te posten
Elk onderdeel is klein. De browserdelen zijn minimaal — een klik, een type, een screenshot, een afsluiting. Het agentredeneren leeft buiten de browser. De browser is slechts handen.
Deze scheiding is het hele punt van het prefereren van CLI boven MCP voor deze werkstromen. De browserlaag moet goedkoop, snel en dom zijn. De redeneerlaag moet zijn waar de tokens naartoe gaan. Wanneer de browserlaag ook tokens verslindt — wat Playwright MCP doet, op elke pagina — klopt de wiskunde niet meer op elke niet-triviale schaal.
De dichtstbijzijnde vergelijking die ik je kan geven: Playwright CLI is voor browserautomatisering wat bash is voor bestandssysteemautomatisering. Klein, scherp, scriptbaar. Makkelijk te componeren tot iets groters. Vergeetbaar op de manier waarop goede infrastructuur vergeetbaar hoort te zijn.
Veelgestelde Vragen
Is Playwright CLI een vervanging voor Playwright MCP?
Nee — Playwright CLI is een aanvullend hulpmiddel, geen vervanging. Gebruik CLI wanneer een codeeragent zoals Claude Code de browser bestuurt; gebruik MCP wanneer een autonome agentworkflow het standaard MCP-protocol nodig heeft. Microsoft onderhoudt beide bewust.
Hoeveel bespaart Playwright CLI daadwerkelijk aan tokens ten opzichte van Playwright MCP?
Publieke benchmarks en mijn eigen runs tonen ruwweg 4x minder tokens per sessie met Playwright CLI ten opzichte van Playwright MCP. De besparingen komen doordat CLI snapshots als compacte YAML op schijf opslaat in plaats van volledige toegankelijkheidsbomen in de modelcontext te streamen bij elke interactie.
Kan Playwright CLI me ingelogd houden tussen runs?
Ja — gebruik chromium.launchPersistentContext(userDataDir, { headless: false }) voor de eerste handmatige login, en voer dan volgende automatiseringen uit met dezelfde userDataDir in headless modus. Cookies, localStorage en sessietokens blijven allemaal op schijf bewaard.
Wanneer moet ik Chrome DevTools MCP gebruiken in plaats hiervan?
Grijp naar Chrome DevTools MCP wanneer de taak prestatieprofilering, netwerk-waterfallanalyse of diepgaand CDP-level debuggen is. Het is ook meer tokenefficiënt dan Playwright MCP voor die specifieke werklasten. Voor rechttoe-rechtaan automatisering en QA-loops wint Playwright CLI.
Kan Claude Code Playwright-scripts vanaf nul schrijven?
Ja — en het is betrouwbaar. Gebruik npx playwright codegen <url> om een initiële sessie op te nemen als je het script wilt seeden, en laat Claude het dan verfijnen. Voor de meeste automatiseringen beschrijf ik het doel in 2-3 zinnen en is het werkende script geschreven voordat ik mijn koffie op heb.
De Elf Minuten Die Veranderden Hoe Ik Bouw
Terug naar het onboardingformulier. Elf minuten, drie echte bugs gevonden en gerepareerd, nul toetsaanslagen van mij. Het ding waar ik steeds aan terugdenk is niet de snelheid — het is dat de loop zichzelf sloot. De agent schreef niet alleen code en stopte. Het schreef code, voerde de test uit, zag de fout, traceerde de oorzaak, paste de fix toe, en voerde de test opnieuw uit totdat het resultaat overeenkwam met het doel.
Die gesloten loop is wat browserautomatisering eindelijk laat aanvoelen als infrastructuur in plaats van theater. Playwright CLI heeft de loop niet uitgevonden. Het maakte hem goedkoop genoeg om te draaien.
Kies vanavond een van de drie patronen uit dit bericht. De QA-loop is het makkelijkst om mee te beginnen — wijs Claude naar een formulierrijke app die je onderhoudt, geef het de viervezinsinstructie van eerder, loop tien minuten weg. Kom terug. Kijk wat het heeft gevonden. De eerste keer dat de loop een echte bug vindt waarvan je niet wist, zul je begrijpen waarom ik veranderde hoe ik bouw.
Laten We Samenwerken
Op zoek naar het bouwen van AI-systemen, het automatiseren van workflows, of het opschalen van je tech-infrastructuur? Ik help je graag.
- Fiverr (maatwerk builds & integraties): fiverr.com/s/EgxYmWD
- Portfolio: mejba.me
- Ramlit Limited (enterprise-oplossingen): ramlit.com
- ColorPark (design & branding): colorpark.io
- xCyberSecurity (beveiligingsdiensten): xcybersecurity.io