123456789// Full page snapshot await snapshot({ page: state.page }) // Output: // - banner: // - link "Home" [id="nav-home"] // - navigation: // - link "Docs" [data-testid="docs-link"] // - link "Blog" role=link[name="Blog"]
state.page.locator(). If multiple elements share the same locator, a >> nth=N suffix is added to make it unique.| Parameter | Type | Default | Description |
page | Page | required | Playwright page to snapshot |
frame | Frame | - | Snapshot a specific iframe instead |
locator | Locator | - | Scope snapshot to a subtree |
search | string | RegExp | - | Filter results (first 10 matches with context) |
showDiffSinceLastCall | boolean | true | Return diff since last snapshot |
interactiveOnly | boolean | false | Only show interactive elements |
format | string | - | Output format |
12345// Search by string or regex await snapshot({ page: state.page, search: /button|submit/i }) // Search for obstacles after navigation await snapshot({ page: state.page, search: /cookie|consent|accept|login/i })
search is provided, diffing is disabled by default so the search filters the full content.12345678910// First call: returns full snapshot await snapshot({ page: state.page }) // After an action: returns only changes (+ added, - removed) await state.page.locator('button').click() await snapshot({ page: state.page }) // Output: // - button "Submit" // + button "Submit" [disabled] // + status "Sending..."
"No changes since last snapshot".12345// Always get full content (disable diff) await snapshot({ page: state.page, showDiffSinceLastCall: false }) // Combine search + diff (both disabled by default, enable explicitly) await snapshot({ page: state.page, search: /error/i, showDiffSinceLastCall: true })
123456789// Full page: ~150 lines (sidebar, nav, header, footer, everything) await snapshot({ page: state.page }) // Scoped to main: ~20 lines (just the content area) await snapshot({ locator: state.page.locator('main') }) // Scope to a dialog, form, or section await snapshot({ locator: state.page.locator('[role="dialog"]') }) await snapshot({ locator: state.page.locator('form#checkout') })
contentFrame():12const frame = await state.page.locator('iframe').contentFrame() await snapshot({ frame })
12345678// Snapshot shows: role=radio[name="Nope, Vanilla"] await state.page.getByRole('radio', { name: 'Nope, Vanilla' }).click() // Snapshot shows: role=link[name="SIGN IN"] await state.page.locator('role=link[name="SIGN IN"]').click() // Snapshot shows: [data-testid="docs-link"] await state.page.locator('[data-testid="docs-link"]').click()
1234await getCleanHTML({ locator: state.page.locator('body') }) await getCleanHTML({ locator: state.page, search: /button/i }) await getCleanHTML({ locator: state.page, showDiffSinceLastCall: false }) await getCleanHTML({ locator: state.page, includeStyles: true }) // keep class/style attrs
snapshot().123456const content = await getPageMarkdown({ page: state.page }) // Output: // # Article Title // Author: John Doe | Site: example.com | Published: 2024-01-15 // > Article excerpt or description // The main article content as plain text...
search and showDiffSinceLastCall.| Method | Best for | Output |
snapshot() | Interactive elements, forms, navigation | Accessibility tree with locators |
getCleanHTML() | Raw HTML structure, style debugging | Cleaned HTML |
getPageMarkdown() | Articles, blog posts, documentation | Plain text with title/author |
screenshotWithAccessibilityLabels() | Visual layouts, grids, dashboards | Image + text (see visual labels) |