mit einem Klick
play
// Run Playwright scripts and inspect durable browser sessions with flat agent-first commands
// Run Playwright scripts and inspect durable browser sessions with flat agent-first commands
| name | play |
| description | Run Playwright scripts and inspect durable browser sessions with flat agent-first commands |
| context | fork |
Run Playwright scripts with zero boilerplate. No imports, no browser lifecycle, no await keywords for the built-in globals.
Use play in two modes:
play 'goto("https://example.com"); log(title())'
# Inline code
play 'goto("https://example.com"); log(text("h1"))'
# Script file
play check-homepage.play.ts
# Pipe / heredoc
echo 'goto("https://example.com"); screenshot()' | play
play << 'EOF'
goto("https://example.com")
assert(text("h1") === "Example Domain", "heading correct")
EOF
Use named sessions when the browser needs to stay alive across commands. Each session is also persisted under .play/sessions/<session-id>/, so inspection still works after the worker exits.
play do auto-opens the session if needed. Pass --headed and --devtools on the first do when you want a visible Chromium session.
play do agent1 'goto("https://example.com")' --headed --devtools
play console agent1
play events agent1 --limit 20
play net agent1 --limit 20
play dom agent1
play status
play close agent1
Use play open only when you want to start the browser before sending actions:
play open agent1 --headed --devtools
play do agent1 'goto("https://example.com"); click("More information")'
play close agent1
Use play capture to run one action batch and get only the console emitted during that batch:
play capture agent1 'goto("http://localhost:3000"); click("Save")'
Use play probe to install temporary session-lifetime instrumentation without editing app code:
play probe agent1 'window.__lastSave' --file app.js --line 120
play probes agent1
play unprobe agent1
play debug still handles live page-debugger control for pause/step/eval/source work.
Key debugger commands:
play debug status <name>play debug pause <name>play debug continue <name>play debug step-over <name>play debug step-into <name>play debug step-out <name>play debug eval <name> '<expr>'play debug query <name> '<expr>'play debug source <name> [file start end]Use -q with debugger status and step commands for one-line summaries instead of JSON blobs.
For inspection, prefer the flat commands:
play console <name>play events <name>play net <name>play dom <name> [selector]play capture <name> '<actions>'play probe <name> ...play probes <name>play unprobe <name> [probeId]Inside scripts, browser console output is buffered separately from log(...). Use consoleCursor(), consoleSince(cursor), capture(async () => ...), consoleLogs(limit?), and clearConsole() when you need precise temporary inspection.
# Navigate and extract
play 'goto("https://example.com"); log(url()); log(text("h1"))'
# Work against a detected local dev server
play 'goto(); click("Sign in"); wait("**/dashboard"); log(title())'
# Screenshot or PDF
play 'goto("https://example.com"); screenshot("homepage.png")'
play 'goto("https://example.com"); pdf("page.pdf")'
# Assertions with exit codes
play 'goto("https://example.com"); assert(visible("h1"), "heading visible")'
# Use the raw Playwright page object when needed
play 'goto("https://example.com"); const resp = await page.request.get("/api/health"); log(await resp.text())'
All built-in globals are auto-awaited.
| Category | Functions |
|---|---|
| Navigation | goto(url?) reload() back() forward() |
| Interaction | click(sel) dblclick(sel) fill(sel, val) type(sel, text) press(key) check(sel) uncheck(sel) select(sel, val) hover(sel) focus(sel) clear(sel) upload(sel, path) drag(from, to) |
| Extraction | text(sel) texts(sel) attr(sel, name) html(sel) value(sel) count(sel) visible(sel) title() url() content() table(sel?) evaluate(fn) |
| Waiting | wait(target) sleep(ms) |
| Media | screenshot(path?) pdf(path?) |
| Output | log(...args) capture(async () => ...) consoleCursor() consoleSince(cursor) consoleLogs(limit?) clearConsole() |
| Assertions | assert(condition, message?) |
| Escape Hatches | page browser context |
click("Submit") and similar helpers resolve selectors in this order:
fill() prefers labels and placeholders. click() prefers roles.
| Flag | Short | Description |
|---|---|---|
--headed | -h | Show browser window |
--slow | -s | Slow motion delay in ms |
--port | -p | Dev server port for goto() |
--url | -u | Base URL for goto() |
--timeout | Action timeout in ms | |
--browser | chromium, firefox, or webkit | |
--device | Emulate a device such as "iPhone 14" | |
--devtools | Auto-open Chromium DevTools | |
--quiet | -q | Suppress session status noise and prefer terse debugger output |