> Agent-readable docs index: /llms.txt. Download /docs.zip to grep all markdown files locally.

---
title: Use Cases
description: Practical examples of what you can do with Playwriter, from QA testing to task automation.
icon: lucide:lightbulb
---

Playwriter gives agents and scripts access to your **real Chrome browser** with all your logins, extensions, and cookies. Here are some things people use it for.

## Web development

Let your coding agent **verify its own work** in a real browser. The agent writes code, then uses Playwriter to navigate to the dev server, check the rendered page, take screenshots, and fix issues, all in one loop.

```bash
# Agent writes React component, then verifies
playwriter -s 1 -e 'await page.goto("http://localhost:3000/new-feature")'
playwriter -s 1 -e 'console.log(await snapshot({ page }))'
# Agent sees broken layout, fixes the code, checks again
```

<Aside>
  <Note>
    The agent works in **your browser**, so it sees the same thing you do. No headless rendering differences.
  </Note>
</Aside>

Because Playwriter exposes the **full Playwright API**, agents can also set breakpoints with `createDebugger`, inspect CSS with `getStylesForLocator`, live-edit source with `createEditor`, and intercept network requests. All from the same session.

## QA testing

Run tests against your **real Chrome profile** with real login state. No need to set up test accounts or mock authentication.

```bash
# Test authenticated flows without login setup
playwriter -s 1 -e 'await page.goto("https://myapp.com/dashboard")'
playwriter -s 1 -e 'console.log(await snapshot({ page, search: /error|warning/i }))'

# Verify forms, buttons, navigation
playwriter -s 1 -e 'await page.locator("button:has-text(\"Save\")").click()'
playwriter -s 1 -e 'console.log(await snapshot({ page, search: /success|saved/i }))'
```

Great for manual QA workflows that agents can now automate: fill forms, click through flows, verify results, and report back.

## Task automation

Automate repetitive browser tasks that need your logged-in session.

**Download a YouTube playlist:**

```bash
playwriter -s 1 -e $'
state.page = context.pages().find(p => p.url() === "about:blank") ?? await context.newPage()
await state.page.goto("https://www.youtube.com/playlist?list=PLxxxxxx")
await waitForPageLoad({ page: state.page, timeout: 5000 })
const videos = await state.page.$$eval("a#video-title", els => els.map(e => ({ title: e.textContent.trim(), href: e.href })))
console.log(JSON.stringify(videos, null, 2))
'
```

**Bulk fill forms:**

```bash
# Read CSV data and fill a form for each row
playwriter -s 1 -f fill-forms.js
```

**Export data from authenticated dashboards:**

```bash
playwriter -s 1 -e $'
state.page = context.pages().find(p => p.url() === "about:blank") ?? await context.newPage()
await state.page.goto("https://analytics.example.com/export")
const [download] = await Promise.all([
  state.page.waitForEvent("download"),
  state.page.click("button:has-text(\"Export CSV\")")
])
await download.saveAs("/tmp/analytics.csv")
console.log("Saved to /tmp/analytics.csv")
'
```

## API reverse engineering

Use **network interception** to discover undocumented APIs behind JavaScript-rendered pages.

```bash
# Start intercepting API calls
playwriter -s 1 -e $'
state.page = context.pages().find(p => p.url() === "about:blank") ?? await context.newPage()
state.responses = []
state.page.on("response", async res => {
  if (res.url().includes("/api/")) {
    try { state.responses.push({ url: res.url(), status: res.status(), body: await res.json() }) } catch {}
  }
})
'

# Navigate and interact — API calls are captured
playwriter -s 1 -e 'await state.page.click("button.load-more")'

# Inspect captured API schemas
playwriter -s 1 -e 'state.responses.forEach(r => console.log(r.status, r.url.slice(0, 100)))'
playwriter -s 1 -e 'console.log(JSON.stringify(state.responses[0].body, null, 2).slice(0, 2000))'
```

This is much faster than scraping the DOM. The agent captures the real API calls, inspects their schemas, and can replay them with different parameters.

## Remote support

Control a user's browser to **fix issues remotely**. The user starts a tunnel, shares the URL, and you can see exactly what they see.

```bash
# User runs on their machine
npx -y traforo -p 19988 -- npx -y playwriter serve --token SHARED_SECRET

# You connect from anywhere
export PLAYWRITER_HOST=https://user-machine-tunnel.traforo.dev
export PLAYWRITER_TOKEN=SHARED_SECRET
playwriter session new
playwriter -s 1 -e 'console.log(await snapshot({ page }))'
```

The user sees Chrome's automation banner so they always know when their browser is being controlled. They can revoke access by closing the terminal. See [Remote Access](/docs/remote-access) for the full guide.

## Screen recording

Have the agent **record what it's doing** as an MP4 video. The recording uses `chrome.tabCapture` and survives page navigation.

```bash
# Start recording
playwriter -s 1 -e 'await recording.start({ page, outputPath: "/tmp/demo.mp4" })'

# Do things — recording continues through navigation
playwriter -s 1 -e 'await page.goto("https://example.com")'
playwriter -s 1 -e 'await page.click("a")'

# Stop and save
playwriter -s 1 -e 'await recording.stop({ page })'
```

Useful for creating **demo videos**, recording bug reproductions, or documenting workflows. The agent can also speed up idle sections with `createDemoVideo` to produce polished demos.

## Scraping JS-heavy sites

Sites like Instagram, Twitter, and Facebook return empty HTML shells to `curl` and `fetch`. Playwriter renders them in a **real browser** with your logged-in session.

```bash
playwriter -s 1 -e $'
state.page = context.pages().find(p => p.url() === "about:blank") ?? await context.newPage()
await state.page.goto("https://www.instagram.com/p/ABC123/", { waitUntil: "domcontentloaded" })
await waitForPageLoad({ page: state.page, timeout: 8000 })
const content = await getPageMarkdown({ page: state.page, showDiffSinceLastCall: false })
console.log(content)
'
```

The agent can dismiss cookie modals, scroll through lazy-loaded content, click through carousels, and extract data from the fully rendered page.
