playwriter
Connects to your running Chrome browser, enabling AI agents to automate it via Playwright API with existing logins and extensions.
README
<div align='center'> <br/> <picture> <source media="(prefers-color-scheme: dark)" srcset="banner-dark.png" /> <source media="(prefers-color-scheme: light)" srcset="banner.png" /> <img src="banner.png" alt="Playwriter - For browser automation MCP" width="400" height="278" /> </picture> <br/> <br/> <p>Let your agents control your own Chrome, via CLI or MCP. Your logins, extensions, cookies — already there.</p> <br/> </div>
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.
Installation
-
Install Extension from Chrome Web Store
-
Click extension icon on a tab → turns green when connected
-
Install the CLI and start automating the browser:
npm i -g playwriter playwriter -s 1 -e 'await page.goto("https://example.com")' -
Install the skill so your agent knows how to use Playwriter:
npx -y skills add remorses/playwriter
Quick Start
playwriter browser start # starts Chrome for Testing/Chromium with bundled Playwriter extension
playwriter session new # creates stateful sandbox, outputs session id (e.g. 1)
playwriter -s 1 -e 'await page.goto("https://example.com")'
playwriter -s 1 -e 'console.log(await snapshot({ page }))'
playwriter -s 1 -e 'await page.locator("aria-ref=e5").click()'
Tip: Always use single quotes for
-eto prevent bash from interpreting$, backticks, and\in your JS code. Use double quotes for strings inside the JS.
CLI Usage
Each session has isolated state. Browser tabs are shared across sessions.
# Browser management
playwriter browser start # auto-finds Chrome for Testing or Chromium, with recording flags enabled
playwriter browser start /path/to/browser-binary
# Session management
playwriter session new # creates stateful sandbox, outputs id (e.g. 1)
playwriter session list # show sessions + state keys
playwriter session reset <id> # fix connection issues
# Execute (always use -s)
playwriter -s 1 -e 'await page.goto("https://example.com")'
playwriter -s 1 -e 'await page.click("button")'
playwriter -s 1 -e 'console.log(await page.title())'
Create your own page to avoid interference from other agents:
playwriter -s 1 -e 'state.myPage = await context.newPage(); await state.myPage.goto("https://example.com")'
Multiline:
playwriter -s 1 -e $'
const title = await page.title();
console.log({ title, url: page.url() });
'
Examples
Variables in scope: page, context, state (persists between calls), require, and Node.js globals.
Persist data in state:
playwriter -e "state.users = await page.$$eval('.user', els => els.map(e => e.textContent))"
playwriter -e "console.log(state.users)"
Intercept network requests:
playwriter -e "state.requests = []; page.on('response', r => { if (r.url().includes('/api/')) state.requests.push(r.url()) })"
playwriter -e "await Promise.all([page.waitForResponse(r => r.url().includes('/api/')), page.click('button')])"
playwriter -e "console.log(state.requests)"
Set breakpoints and debug:
playwriter -e "state.cdp = await getCDPSession({ page }); state.dbg = createDebugger({ cdp: state.cdp }); await state.dbg.enable()"
playwriter -e "state.scripts = await state.dbg.listScripts({ search: 'app' }); console.log(state.scripts.map(s => s.url))"
playwriter -e "await state.dbg.setBreakpoint({ file: state.scripts[0].url, line: 42 })"
Live edit page code:
playwriter -e "state.cdp = await getCDPSession({ page }); state.editor = createEditor({ cdp: state.cdp }); await state.editor.enable()"
playwriter -e "await state.editor.edit({ url: 'https://example.com/app.js', oldString: 'const DEBUG = false', newString: 'const DEBUG = true' })"
Screenshot with labels:
playwriter -e "await screenshotWithAccessibilityLabels({ page })"
MCP Setup
Using the CLI with the skill (step 4 above) is the recommended approach. For direct MCP server configuration, see MCP.md.
Visual Labels
Vimium-style labels for AI agents to identify elements:
await screenshotWithAccessibilityLabels({ page })
// Returns screenshot + accessibility snapshot with aria-ref selectors
await page.locator('aria-ref=e5').click()
Color-coded: yellow=links, orange=buttons, coral=inputs, pink=checkboxes, peach=sliders, salmon=menus, amber=tabs.
Comparison
vs Playwright MCP
| Playwright MCP | Playwriter | |
|---|---|---|
| Browser | Spawns new Chrome | Uses your Chrome |
| Extensions | None | Your existing ones |
| Login state | Fresh | Already logged in |
| Bot detection | Always detected | Can bypass (disconnect extension) |
| Collaboration | Separate window | Same browser as user |
Note: Playwriter video recording is 100x more efficient than Playwright video recording, which sends base64 images for every frame.
| Playwright CLI | Playwriter | |
|---|---|---|
| Browser | Spawns new browser | Uses your Chrome |
| Login state | Fresh | Already logged in |
| Extensions | None | Your existing ones |
| Captchas | Always blocked | Bypass (disconnect extension) |
| Collaboration | Separate window | Same browser as user |
| Capabilities | Limited command set | Anything Playwright can do |
| Raw CDP access | No | Yes |
| Video recording | File-based tracing | Native tab capture (30–60fps) |
vs BrowserMCP
| BrowserMCP | Playwriter | |
|---|---|---|
| Tools | 12+ dedicated tools | 1 execute tool |
| API | Limited actions | Full Playwright |
| Context usage | High (tool schemas) | Low |
| LLM knowledge | Must learn tools | Already knows Playwright |
vs Antigravity (Jetski)
| Jetski | Playwriter | |
|---|---|---|
| Tools | 17+ tools | 1 tool |
| Subagent | Spawns for each browser task | Direct execution |
| Latency | High (agent overhead) | Low |
vs Claude Browser Extension
| Claude Extension | Playwriter | |
|---|---|---|
| Agent support | Claude only | Any MCP client |
| Windows WSL | No | Yes |
| Context method | Screenshots (100KB+) | A11y snapshots (5-20KB) |
| Playwright API | No | Full |
| Debugger/breakpoints | No | Yes |
| Live code editing | No | Yes |
| Network interception | Limited | Full |
| Raw CDP access | No | Yes |
vs Built-in Chrome CDP (--remote-debugging-port)
| Built-in CDP | Playwriter | |
|---|---|---|
| Setup | Restart Chrome with special flags | Click extension icon |
| Confirmation dialog | Shows automation infobar agents can't dismiss | No blocking dialog |
| Autonomous agents | Interrupted by debug banners | Fully autonomous |
| User disruption | Banners appear mid-workflow | Silent — no interruption |
| Existing session | Must relaunch Chrome (lose state) | Uses your running browser |
Chrome's
--remote-debugging-portflag shows a persistent "controlled by automated software" banner that agents cannot dismiss. It pops up in the middle of your workflow whenever you're using the browser. Playwriter runs silently — agents work autonomously without any confirmation dialogs, so you're never interrupted.
Architecture
+---------------------+ +-------------------+ +-----------------+
| BROWSER | | LOCALHOST | | MCP CLIENT |
| | | | | |
| +---------------+ | | WebSocket Server | | +-----------+ |
| | Extension |<---------> :19988 | | | AI Agent | |
| +-------+-------+ | WS | | | +-----------+ |
| | | | /extension | | | |
| chrome.debugger | | | | | v |
| v | | v | | +-----------+ |
| +---------------+ | | /cdp/:id <--------------> | execute | |
| | Tab 1 (green) | | +-------------------+ WS | +-----------+ |
| | Tab 2 (green) | | | | |
| | Tab 3 (gray) | | Tab 3 not controlled | Playwright API |
+---------------------+ (no extension click) +-----------------+
Remote Access
Control Chrome on a remote machine over the internet using traforo tunnels:
On host:
npx -y traforo -p 19988 -t my-machine -- npx -y playwriter serve --token <secret>
From remote:
export PLAYWRITER_HOST=https://my-machine-tunnel.traforo.dev
export PLAYWRITER_TOKEN=<secret>
playwriter -s 1 -e 'await page.goto("https://example.com")'
Also works on a LAN without traforo (PLAYWRITER_HOST=192.168.1.10). Full guide with use cases (remote Mac mini, user support, multi-machine control): docs/remote-access.md
Security
- Local only: WebSocket server on
localhost:19988 - Origin validation: Only our extension IDs allowed (browsers can't spoof Origin)
- Explicit consent: Only tabs where you clicked the extension icon
- Visible automation: Chrome shows automation banner on controlled tabs
- No remote access: Malicious websites cannot connect
Playwright API
Connect programmatically (without CLI):
import { chromium } from 'playwright-core'
import { startPlayWriterCDPRelayServer, getCdpUrl } from 'playwriter'
const server = await startPlayWriterCDPRelayServer()
const browser = await chromium.connectOverCDP(getCdpUrl())
const page = browser.contexts()[0].pages()[0]
await page.goto('https://example.com')
await page.screenshot({ path: 'screenshot.png' })
// Don't call browser.close() - it closes the user's Chrome
server.close()
Or connect to a running server:
npx -y playwriter serve --host 127.0.0.1
const browser = await chromium.connectOverCDP('http://127.0.0.1:19988')
Troubleshooting
View relay server logs to debug issues:
playwriter logfile # prints the log file path
# typically: ~/.playwriter/relay-server.log
The relay log contains extension, MCP and WebSocket server logs. A separate CDP JSONL log is also created alongside it (see playwriter logfile). Both are recreated on each server start.
Example: summarize CDP traffic counts by direction + method:
jq -r '.direction + "\t" + (.message.method // "response")' ~/.playwriter/cdp.jsonl | uniq -c
Support
If Playwriter is useful to you, consider sponsoring the project.
Known Issues
- If all pages return
about:blank, restart Chrome (Chrome bug inchrome.debuggerAPI) - Browser may switch to light mode on connect (Playwright issue)
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。