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

JavaScript Debugger, Live Code Editor, and CSS Inspector

Things no other browser MCP can do. Set breakpoints, step through JavaScript, inspect variables at runtime. Live-edit page scripts and CSS without reloading. Full Chrome DevTools Protocol access, not a watered-down subset.

JavaScript debugger

The createDebugger utility gives agents the same power as Chrome DevTools' Sources panel: set breakpoints, step through execution, inspect local variables, and evaluate expressions in scope.

Setup

state.cdp = await getCDPSession({ page: state.page }) state.dbg = createDebugger({ cdp: state.cdp }) await state.dbg.enable()

List scripts

Find loaded scripts by name or URL pattern:
state.scripts = await state.dbg.listScripts({ search: 'app' }) state.scripts.map(s => s.url) // => ['https://example.com/static/app.js', 'https://example.com/static/app-utils.js']

Set breakpoints

// By file and line number await state.dbg.setBreakpoint({ file: state.scripts[0].url, line: 42 }) // With a condition await state.dbg.setBreakpoint({ file: state.scripts[0].url, line: 42, condition: 'count > 10' })

Step through code

When execution hits a breakpoint:
// Inspect local variables in the current scope const vars = await state.dbg.inspectLocalVariables() console.log(vars) // Step through execution await state.dbg.stepOver() // next line await state.dbg.stepInto() // into function call await state.dbg.stepOut() // out of current function // Continue execution await state.dbg.resume()

Pause on exceptions

await state.dbg.setPauseOnExceptions({ state: 'uncaught' }) // Options: 'none', 'uncaught', 'all'

API reference

For the full debugger API, fetch the reference docs:
curl https://playwriter.dev/resources/debugger-api.md

Live code editor

The createEditor utility lets agents view and edit page scripts and CSS at runtime. Edits are in-memory and persist until the page reloads. Useful for toggling debug flags, patching broken code, or testing quick fixes without touching source files.

Setup

state.cdp = await getCDPSession({ page: state.page }) state.editor = createEditor({ cdp: state.cdp }) await state.editor.enable()

Search across all loaded scripts

const matches = await state.editor.grep({ regex: /console\.log/ }) matches.forEach(m => console.log(m.url, m.lineNumber, m.lineContent))

Edit source code

await state.editor.edit({ url: 'https://example.com/app.js', oldString: 'const DEBUG = false', newString: 'const DEBUG = true' })
Edits are in-memory only. They persist until the page reloads. The editor also supports searching across all loaded scripts with grep.

API reference

For the full editor API, fetch the reference docs:
curl https://playwriter.dev/resources/editor-api.md

CSS inspection

Inspect CSS styles applied to any element, like the browser DevTools "Styles" panel. Returns selector, source location (file:line), and declarations for each matching rule.
const cdp = await getCDPSession({ page: state.page }) const styles = await getStylesForLocator({ locator: state.page.locator('.btn'), cdp }) console.log(formatStylesAsText(styles))
For the full styles API, fetch the reference docs:
curl https://playwriter.dev/resources/styles-api.md

React component inspection

Inspect React component source locations and props (dev mode only):
// Get source file location const source = await getReactSource({ locator: state.page.locator('[data-testid="submit-btn"]') }) // => { fileName: '/src/Button.tsx', lineNumber: 42, columnNumber: 5, componentName: 'Button' } // Get full component info with props and hierarchy const info = await getReactComponentInfo({ locator: state.page.locator('[data-testid="submit-btn"]') }) // => { componentName: 'Button', source: {...}, hierarchy: [...], props: {...} }
getReactComponentInfo returns null for non-React elements and never throws. Props are sanitized so functions, DOM nodes, and circular references don't flood the output.

Raw CDP access

For anything not covered by the utilities above, use getCDPSession to send raw Chrome DevTools Protocol commands:
const cdp = await getCDPSession({ page: state.page }) // Get page metrics const metrics = await cdp.send('Page.getLayoutMetrics') // Get cookies const { cookies } = await cdp.send('Network.getCookies', { urls: [state.page.url()] }) // Performance metrics const { metrics: perfMetrics } = await cdp.send('Performance.getMetrics')
Always use getCDPSession({ page }), never context.newCDPSession(). The latter doesn't work through the Playwriter relay.