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.123state.cdp = await getCDPSession({ page: state.page }) state.dbg = createDebugger({ cdp: state.cdp }) await state.dbg.enable()
123state.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']
12345// 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' })
1234567891011// 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()
12await state.dbg.setPauseOnExceptions({ state: 'uncaught' }) // Options: 'none', 'uncaught', 'all'
1curl https://playwriter.dev/resources/debugger-api.md
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.123state.cdp = await getCDPSession({ page: state.page }) state.editor = createEditor({ cdp: state.cdp }) await state.editor.enable()
12const matches = await state.editor.grep({ regex: /console\.log/ }) matches.forEach(m => console.log(m.url, m.lineNumber, m.lineContent))
12345await state.editor.edit({ url: 'https://example.com/app.js', oldString: 'const DEBUG = false', newString: 'const DEBUG = true' })
grep.1curl https://playwriter.dev/resources/editor-api.md
123456const cdp = await getCDPSession({ page: state.page }) const styles = await getStylesForLocator({ locator: state.page.locator('.btn'), cdp }) console.log(formatStylesAsText(styles))
1curl https://playwriter.dev/resources/styles-api.md
1234567891011// 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.getCDPSession to send raw Chrome DevTools Protocol commands:12345678910const 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')
getCDPSession({ page }), never context.newCDPSession(). The latter doesn't work through the Playwriter relay.