Skip to main content
Helper functions for common tasks like getting console logs, waiting for page load, accessing CDP, and more.

getLatestLogs()

Retrieve captured browser console logs (up to 5000 per page, cleared on navigation).
async function getLatestLogs(options?: {
  page?: Page
  count?: number
  search?: string | RegExp
}): Promise<string[]>
Parameters:
  • page — Filter to specific page. If not provided, returns logs from all pages
  • count — Limit to last N logs
  • search — Filter logs matching string or regex pattern (returns matches with 5 lines context)
Examples:
// Get all logs
const logs = await getLatestLogs()
console.log(logs.join('\n'))

// Get logs from specific page
const pageLogs = await getLatestLogs({ page: state.page })

// Get last 20 logs
const recent = await getLatestLogs({ count: 20 })

// Search for errors
const errors = await getLatestLogs({ search: /error|fail/i, count: 50 })

waitForPageLoad()

Smart load detection that ignores analytics/ads and waits for page to be interactive.
async function waitForPageLoad(options: {
  page: Page
  timeout?: number
  pollInterval?: number
  minWait?: number
}): Promise<{
  success: boolean
  readyState: string
  pendingRequests: number
  waitTimeMs: number
  timedOut: boolean
}>
Parameters:
  • page — Page to wait for
  • timeout — Max wait time in ms (default: 5000)
  • pollInterval — How often to check in ms (default: 100)
  • minWait — Minimum wait time in ms (default: 0)
Examples:
// Wait after navigation
await state.page.goto('https://example.com', { waitUntil: 'domcontentloaded' })
await waitForPageLoad({ page: state.page, timeout: 5000 })

// Wait after action that triggers navigation
await state.page.click('a[href="/next"]')
const result = await waitForPageLoad({ page: state.page, timeout: 8000 })
console.log('Page loaded:', result.success)

getCDPSession()

Get Chrome DevTools Protocol session for sending raw CDP commands.
async function getCDPSession(options: { 
  page: Page 
}): Promise<ICDPSession>
Important: Always use getCDPSession({ page }), never page.context().newCDPSession() — the latter doesn’t work through the playwriter relay. Examples:
// Get CDP session
const cdp = await getCDPSession({ page: state.page })

// Send CDP commands
const metrics = await cdp.send('Page.getLayoutMetrics')
console.log(metrics)

// Enable domain
await cdp.send('Network.enable')

// Listen for events
cdp.on('Network.requestWillBeSent', (params) => {
  console.log('Request:', params.request.url)
})

refToLocator()

Convert a ref from a snapshot or screenshot to a Playwright locator string.
function refToLocator(options: { 
  ref: string
  page?: Page 
}): string | null
Parameters:
  • ref — The ref string (e.g., "e3", "submit-btn")
  • page — Optional page (defaults to current page)
Examples:
// Take snapshot
const snap = await snapshot({ page: state.page })

// Get locator for ref
const locator = refToLocator({ ref: 'e3' })
if (locator) {
  await state.page.locator(locator).click()
}

// With screenshot
await screenshotWithAccessibilityLabels({ page: state.page })
const selector = refToLocator({ ref: 'submit-btn' })
await state.page.locator(selector).click()

getCleanHTML()

Get cleaned HTML from a locator or page, with search and diffing support.
async function getCleanHTML(options: {
  locator: Locator | Page
  search?: string | RegExp
  showDiffSinceLastCall?: boolean
  includeStyles?: boolean
}): Promise<string>
Parameters:
  • locator — Playwright Locator or Page to get HTML from
  • search — Filter results to first 10 matching lines with 5 lines context
  • showDiffSinceLastCall — Return diff since last call (default: true, but false when search is provided)
  • includeStyles — Keep style and class attributes (default: false)
HTML Processing: The function cleans HTML for compact, readable output:
  • Removes tags: script, style, link, meta, noscript, svg, head
  • Unwraps nested wrappers: Empty divs/spans with no attributes that only wrap a single child are collapsed
  • Removes empty elements: Elements with no attributes and no content are removed
  • Truncates long values: Attribute values >200 chars and text content >500 chars are truncated
  • Keeps semantic attributes: href, name, type, aria-*, data-*, testid, qa, e2e, vimium-label, etc.
Examples:
// Get cleaned HTML from page
const html = await getCleanHTML({ locator: state.page })

// Get cleaned HTML from element
const formHtml = await getCleanHTML({ locator: state.page.locator('form') })

// Search within HTML
const matches = await getCleanHTML({ 
  locator: state.page, 
  search: /button/i 
})

// Disable diff to get full HTML
const fullHtml = await getCleanHTML({ 
  locator: state.page, 
  showDiffSinceLastCall: false 
})

// Include styles
const styledHtml = await getCleanHTML({ 
  locator: state.page, 
  includeStyles: true 
})

getPageMarkdown()

Extract main page content as plain text using Mozilla Readability (same algorithm as Firefox Reader View). Strips navigation, ads, sidebars, and other clutter.
async function getPageMarkdown(options: {
  page: Page
  search?: string | RegExp
  showDiffSinceLastCall?: boolean
}): Promise<string>
Parameters:
  • page — Page to extract content from
  • search — Filter content to first 10 matching lines with 5 lines context
  • showDiffSinceLastCall — Return diff since last call (default: true, but false when search is provided)
Output Format:
# Article Title

Author: John Doe | Site: example.com | Published: 2024-01-15

> Article excerpt or description

The main article content as plain text, with paragraphs preserved...
Examples:
// Extract article content
const content = await getPageMarkdown({ 
  page: state.page, 
  showDiffSinceLastCall: false 
})
console.log(content)

// Search within content
const apiDocs = await getPageMarkdown({ 
  page: state.page, 
  search: /API/i 
})
Use cases:
  • Extract article text for LLM processing without HTML noise
  • Get readable content from news sites, blogs, documentation
  • Compare content changes after interactions

getLocatorStringForElement()

Get stable Playwright selector from an element.
async function getLocatorStringForElement(
  element: Locator | ElementHandle
): Promise<string>
Examples:
const locator = state.page.locator('[id="submit-btn"]')
const selector = await getLocatorStringForElement(locator)
console.log(selector) // => "getByRole('button', { name: 'Save' })"

createDebugger()

Set breakpoints, step through code, inspect variables at runtime. Useful for debugging issues that only reproduce in browser. Always fetch https://playwriter.dev/resources/debugger-api.md first with curl or webfetch tool for full API documentation.
function createDebugger(options: { 
  cdp: ICDPSession 
}): Debugger
Examples:
const cdp = await getCDPSession({ page: state.page })
const dbg = createDebugger({ cdp })
await dbg.enable()

const scripts = await dbg.listScripts({ search: 'app' })
await dbg.setBreakpoint({ file: scripts[0].url, line: 42 })

// When paused:
// - dbg.inspectLocalVariables()
// - dbg.stepOver()
// - dbg.resume()

createEditor()

View and live-edit page scripts and CSS at runtime. Edits are in-memory (persist until reload). Always read https://playwriter.dev/resources/editor-api.md first with curl or webfetch tool for full API documentation.
function createEditor(options: { 
  cdp: ICDPSession 
}): Editor
Examples:
const cdp = await getCDPSession({ page: state.page })
const editor = createEditor({ cdp })
await editor.enable()

const matches = await editor.grep({ regex: /console\.log/ })
await editor.edit({ 
  url: matches[0].url, 
  oldString: 'DEBUG = false', 
  newString: 'DEBUG = true' 
})

getStylesForLocator()

Inspect CSS styles applied to an element, like browser DevTools “Styles” panel. Always fetch https://playwriter.dev/resources/styles-api.md first with curl or webfetch tool for full API documentation.
async function getStylesForLocator(options: {
  locator: Locator
  cdp: ICDPSession
}): Promise<StylesResult>
Examples:
const cdp = await getCDPSession({ page: state.page })
const styles = await getStylesForLocator({
  locator: state.page.locator('.btn'),
  cdp
})
console.log(formatStylesAsText(styles))

getReactSource()

Get React component source location (dev mode only).
async function getReactSource(options: { 
  locator: Locator 
}): Promise<{
  fileName: string
  lineNumber: number
  columnNumber: number
  componentName: string
}>
Examples:
const source = await getReactSource({ 
  locator: state.page.locator('[data-testid="submit-btn"]') 
})
console.log(source)
// => { fileName: 'Button.tsx', lineNumber: 42, columnNumber: 8, componentName: 'Button' }

resizeImage()

Shrink an image in-place so it consumes fewer tokens when read back into context.
async function resizeImage(options: {
  input: string | Buffer
  maxDimension?: number
  width?: number
  height?: number
  fit?: 'inside' | 'cover' | 'contain' | 'fill'
  quality?: number
  output?: string
}): Promise<{
  buffer: Buffer
  mimeType: 'image/jpeg'
  path?: string
}>
Parameters:
  • input — File path or Buffer
  • maxDimension — Max pixels on longest edge (default: 1568, Claude-optimal)
  • width — Explicit target width in px (aspect ratio preserved unless both width+height set)
  • height — Explicit target height in px
  • fit — How to fit when both width+height specified (default: ‘inside’)
  • quality — JPEG quality 1-100 (default: 80)
  • output — Output file path (defaults to overwriting input file)
Examples:
// Resize screenshot to optimal size
await state.page.screenshot({ path: './screenshot.png', scale: 'css' })
await resizeImage({ input: './screenshot.png' })

// Custom dimensions
await resizeImage({ 
  input: './image.jpg', 
  width: 800, 
  output: './resized.jpg' 
})

Build docs developers (and LLMs) love