Debug Playwright scripts where an LLM chooses the next browser action
Playwright Trace Viewer is strong for browser automation. BrowserTrace is for the extra failure context in LLM-guided browser runs: the prompt, model output, action label, screenshot, URL, status, and first error in one local timeline.
Improving this guide or a Playwright + LLM adapter note? Use the First PR Recipe to keep the first contribution small and reviewable.
Try the local demo first
uvx --from "browsertrace[ui]" browsertrace doctor
uvx --from "browsertrace[ui]" browsertrace demo
uvx --from "browsertrace[ui]" browsertrace
Open http://127.0.0.1:3000 and inspect the failed checkout-agent run before adding BrowserTrace to your own Playwright script. From a source checkout, python examples/playwright_llm_loop_example.py creates a no-network Playwright + LLM-shaped trace with prompt/messages, DOM and accessibility snippets, selector, retry, and error fields.
If your script uses Playwright's sync API instead of playwright.async_api, BrowserTrace also supports run.snapshot_sync(page, action=...); see the sync Playwright snapshot example.
Capture the LLM decision points
from browsertrace import Tracer
tracer = Tracer()
async with tracer.run("playwright llm agent") as run:
await page.goto("https://example.com")
await run.snapshot(page, action="opened example.com")
prompt = "Choose the selector for the checkout button"
decision = await llm_choose_next_action(prompt, page)
await page.click(decision["selector"])
await run.snapshot(
page,
action="clicked model-selected element",
model_input=prompt,
model_output=decision,
)
Snapshots pull the current Playwright URL and screenshot, then attach the model input and model output you pass in.
What this adds to Playwright traces
- The LLM prompt or messages that caused the browser action.
- The model response, selected selector, or structured action plan.
- DOM snippets, accessibility tree text, console errors, network errors, and retry counters when you pass them as model input or metadata.
- The screenshot and URL at the moment the decision was made.
- A browser-agent-first timeline that marks the first failed step.
- A standalone HTML export for issues, pull requests, and team review.
Keep browser artifacts out of long-term model context
For Playwright + LLM loops, the browser artifact boundary matters. Screenshots, URLs, and raw trace files should be durable local artifacts for debugging, not base64 screenshots copied into every future model turn.
Pass image pixels to the model only when the next model call needs a typed image content block. Otherwise, pass compact metadata such as artifact id, dimensions, digest, status, and error, while keeping the full screenshot available in the BrowserTrace timeline.
This keeps later prompts smaller and avoids confusing the model with stale browser evidence, while still letting humans inspect the exact screenshot and URL that produced the failed action.
Share only what is safe
browsertrace list
browsertrace export <run_id> -o full.html
browsertrace export <run_id> --redact -o public.html
browsertrace export <run_id> --public -o public.html
Use --public before attaching a real trace to a public issue or community thread. Use individual redaction flags when you want to keep some fields visible.
For a compact checklist, see the share-safe export recipe.