$git clone https://github.com/remorses/playwriterOther browser MCPs spawn a fresh Chrome — no logins, no extensions, instantly flagged by bot detectors, double the memory. Playwriter connects to your running browser instead. One Chrome extension, full Playwright API, everything you're already logged into.
| 1 | <div align='center'> |
| 2 | <br/> |
| 3 | <picture> |
| 4 | <source media="(prefers-color-scheme: dark)" srcset="banner-dark.png" /> |
| 5 | <source media="(prefers-color-scheme: light)" srcset="banner.png" /> |
| 6 | <img src="banner.png" alt="Playwriter - For browser automation MCP" width="400" height="278" /> |
| 7 | </picture> |
| 8 | <br/> |
| 9 | <br/> |
| 10 | <p>Let your agents control your own Chrome, via CLI or MCP. Your logins, extensions, cookies — already there.</p> |
| 11 | <br/> |
| 12 | </div> |
| 13 | |
| 14 | Other browser MCPs spawn a fresh Chrome — no logins, no extensions, instantly flagged by bot detectors, double the memory. Playwriter connects to **your running browser** instead. One Chrome extension, full Playwright API, everything you're already logged into. |
| 15 | |
| 16 | ## Installation |
| 17 | |
| 18 | 1. [**Install Extension**](https://chromewebstore.google.com/detail/playwriter-mcp/jfeammnjpkecdekppnclgkkffahnhfhe) from Chrome Web Store |
| 19 | |
| 20 | 2. Click extension icon on a tab → turns green when connected |
| 21 | |
| 22 | 3. Install the CLI and start automating the browser: |
| 23 | |
| 24 | ```bash |
| 25 | npm i -g playwriter |
| 26 | playwriter -s 1 -e 'await page.goto("https://example.com")' |
| 27 | ``` |
| 28 | |
| 29 | 4. Install the skill so your agent knows how to use Playwriter: |
| 30 | ```bash |
| 31 | npx -y skills add remorses/playwriter |
| 32 | ``` |
| 33 | |
| 34 | ## Quick Start |
| 35 | |
| 36 | ```bash |
| 37 | playwriter browser start # starts Chrome for Testing/Chromium with bundled Playwriter extension |
| 38 | playwriter session new # creates stateful sandbox, outputs session id (e.g. 1) |
| 39 | playwriter -s 1 -e 'await page.goto("https://example.com")' |
| 40 | playwriter -s 1 -e 'console.log(await snapshot({ page }))' |
| 41 | playwriter -s 1 -e 'await page.locator("aria-ref=e5").click()' |
| 42 | ``` |
| 43 | |
| 44 | > **Tip:** Always use single quotes for `-e` to prevent bash from interpreting `$`, backticks, and `\` in your JS code. Use double quotes for strings inside the JS. |
| 45 | |
| 46 | ## CLI Usage |
| 47 | |
| 48 | Each session has **isolated state**. Browser tabs are **shared** across sessions. |
| 49 | |
| 50 | ```bash |
| 51 | # Browser management |
| 52 | playwriter browser start # auto-finds Chrome for Testing or Chromium, with recording flags enabled |
| 53 | playwriter browser start /path/to/browser-binary |
| 54 | |
| 55 | # Session management |
| 56 | playwriter session new # creates stateful sandbox, outputs id (e.g. 1) |
| 57 | playwriter session list # show sessions + state keys |
| 58 | playwriter session reset <id> # fix connection issues |
| 59 | |
| 60 | # Execute (always use -s) |
| 61 | playwriter -s 1 -e 'await page.goto("https://example.com")' |
| 62 | playwriter -s 1 -e 'await page.click("button")' |
| 63 | playwriter -s 1 -e 'console.log(await page.title())' |
| 64 | ``` |
| 65 | |
| 66 | Create your own page to avoid interference from other agents: |
| 67 | |
| 68 | ```bash |
| 69 | playwriter -s 1 -e 'state.myPage = await context.newPage(); await state.myPage.goto("https://example.com")' |
| 70 | ``` |
| 71 | |
| 72 | Multiline: |
| 73 | |
| 74 | ```bash |
| 75 | playwriter -s 1 -e $' |
| 76 | const title = await page.title(); |
| 77 | console.log({ title, url: page.url() }); |
| 78 | ' |
| 79 | ``` |
| 80 | |
| 81 | ## Examples |
| 82 | |
| 83 | Variables in scope: `page`, `context`, `state` (persists between calls), `require`, and Node.js globals. |
| 84 | |
| 85 | **Persist data in state:** |
| 86 | |
| 87 | ```bash |
| 88 | playwriter -e "state.users = await page.$$eval('.user', els => els.map(e => e.textContent))" |
| 89 | playwriter -e "console.log(state.users)" |
| 90 | ``` |
| 91 | |
| 92 | **Intercept network requests:** |
| 93 | |
| 94 | ```bash |
| 95 | playwriter -e "state.requests = []; page.on('response', r => { if (r.url().includes('/api/')) state.requests.push(r.url()) })" |
| 96 | playwriter -e "await Promise.all([page.waitForResponse(r => r.url().includes('/api/')), page.click('button')])" |
| 97 | playwriter -e "console.log(state.requests)" |
| 98 | ``` |
| 99 | |
| 100 | **Set breakpoints and debug:** |
| 101 | |
| 102 | ```bash |
| 103 | playwriter -e "state.cdp = await getCDPSession({ page }); state.dbg = createDebugger({ cdp: state.cdp }); await state.dbg.enable()" |
| 104 | playwriter -e "state.scripts = await state.dbg.listScripts({ search: 'app' }); console.log(state.scripts.map(s => s.url))" |
| 105 | playwriter -e "await state.dbg.setBreakpoint({ file: state.scripts[0].url, line: 42 })" |
| 106 | ``` |
| 107 | |
| 108 | **Live edit page code:** |
| 109 | |
| 110 | ```bash |
| 111 | playwriter -e "state.cdp = await getCDPSession({ page }); state.editor = createEditor({ cdp: state.cdp }); await state.editor.enable()" |
| 112 | playwri |