BrowserTrace

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.

View repo Open exported trace Integration snippet Feedback issue

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

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.

BrowserTrace is not a replacement for Playwright Trace Viewer. It is a local layer for Playwright scripts where LLM decisions are part of the bug. Playwright + LLM feedback is tracked in issue #12.