| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
Let your agents control your own Chrome, via CLI or MCP. Your logins, extensions, cookies — already there.
Other browser MCPs spawn a fresh Chrome — no logins, no extensions, instantly flagged by bot detectors, double the memory. Interpreter Chrome Extension connects to your running browser instead. One Chrome extension, full Playwright API, everything you're already logged into.
This repository is the Interpreter-maintained distribution of Playwriter. It preserves Playwriter's Git history, MIT license, copyright notice, package identity, and development workflow. Interpreter-specific extension, relay, protocol, and release changes are developed here; generally useful fixes should continue to be considered for upstream contribution.
The repository also pins the Playwriter-maintained Playwright fork as a Git submodule. Clone with --recurse-submodules, or run git submodule update --init before building the fork. See NOTICE for the public attribution boundary.
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 the Interpreter Chrome Extension workflow:
npx -y skills add remorses/playwriterplaywriter browser start # starts Chrome for Testing/Chromium with bundled Interpreter Chrome 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 -e to prevent bash from interpreting $, backticks, and \ in your JS code. Use double quotes for strings inside the JS.
Each session has isolated state. Browser tabs are shared across sessions.
# Browser management
playwriter browser start # auto-finds Chrome for Testing or Chromium with the bundled extension
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() });
'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 })"Using the CLI with the skill (step 4 above) is the recommended approach. For direct MCP server configuration, see MCP.md.
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.
| Playwright MCP | Interpreter Chrome Extension | |
|---|---|---|
| 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 |
| Playwright CLI | Interpreter Chrome Extension | |
|---|---|---|
| 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 |
| BrowserMCP | Interpreter Chrome Extension | |
|---|---|---|
| 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 |
| Jetski | Interpreter Chrome Extension | |
|---|---|---|
| Tools | 17+ tools | 1 tool |
| Subagent | Spawns for each browser task | Direct execution |
| Latency | High (agent overhead) | Low |
| Claude Extension | Interpreter Chrome Extension | |
|---|---|---|
| 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 |
| Built-in CDP | Interpreter Chrome Extension | |
|---|---|---|
| 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-port flag 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. Interpreter Chrome Extension runs silently — agents work autonomously without any confirmation dialogs, so you're never interrupted.
+---------------------+ +-------------------+ +-----------------+ | 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) +-----------------+
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
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.1const browser = await chromium.connectOverCDP('http://127.0.0.1:19988')View relay server logs to debug issues:
playwriter logfile # prints the log file path
# typically: ~/.playwriter/relay-server.logThe 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 -cIf Interpreter Chrome Extension is useful to you, consider sponsoring the project.
This repository is MIT-licensed and preserves Playwriter's upstream history and attribution. See LICENSE and NOTICE. Report security issues privately as described in SECURITY.md.
| Back | FazBrowse Home | New Git URL |