Recommended Free Tools
Use Playwright’s toMatchAriaSnapshot() assertion to compare a page or locator’s accessible structure with a YAML template. The template describes roles, accessible names, text, and selected states—not the raw DOM—so a test can detect meaningful accessibility changes while ignoring implementation details. This guide shows page-wide and scoped assertions, partial and exact matching, regular expressions, generated and external snapshots, version requirements, and fixes for common failures.
What a Playwright ARIA snapshot contains
An ARIA snapshot is a nested, YAML-like representation of the accessible elements exposed by a page or locator. Each node uses a role and, when useful, an accessible name. Text and states or attributes can follow the node. Indentation expresses parent-child relationships.
- heading "Title" [level=1]
- checkbox [checked]
- textbox "Email" [invalid]: not-an-email
This is an accessibility view of the interface. It is not a DOM dump, CSS snapshot, or pixel comparison. A refactor from a <div> to a semantic element can leave the snapshot unchanged if the exposed role, name, and state remain the same.
The syntax and matching rules are documented in the Playwright ARIA snapshots guide. Check the version installed in your project before copying an example because the APIs were introduced in different releases.
Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallMake your first ARIA snapshot assertion
Assert the whole page
After navigating, pass a multiline template to the page assertion. The official example verifies the TodoMVC heading and input:
import { test, expect } from '@playwright/test';
test('todo page has its primary controls', async ({ page }) => {
await page.goto('https://demo.playwright.dev/todomvc/');
await expect(page).toMatchAriaSnapshot(`
- heading "todos"
- textbox "What needs to be done?"
`);
});
A page assertion checks the document body. Use it when the test is intentionally concerned with the page-level accessible outline. Page-level toMatchAriaSnapshot() is documented as added in Playwright v1.60.
Scope the assertion to a locator
Most tests are less brittle when they select the component under test first. Any locator can be the assertion target:
const main = page.getByRole('main');
await expect(main).toMatchAriaSnapshot(`
- heading "Account settings"
- textbox "Email"
- button "Save changes"
`);
A locator-scoped snapshot excludes unrelated navigation, banners, and footers. The LocatorAssertions reference describes this form and the string-template assertion as available from v1.49.
Write snapshot nodes with roles, names, and states
Nested roles and accessible names
Indent children beneath their parent. Include names when the name is part of the behavior that must not change:
- list "Links":
- listitem:
- link "Home"
- listitem:
- link "About"
Accessible names may come from visible text, an associated label, or composed content. A link can also match a URL property when the destination matters:
- link "Documentation" /docs/
Use the role and name that a keyboard or assistive-technology user would encounter. Avoid encoding incidental wrapper elements or styling classes.
States, attributes, and text
Square brackets express states or attributes exposed in the accessibility tree, such as [checked] or [level=1]. A colon introduces text associated with the node:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
- checkbox "Subscribe" [checked]
- textbox "Email" [invalid]: not-an-email
Keep state assertions for behavior that is important to the test. If a validation message is intentionally variable, match its stable role and use a regular expression for the changing part.
Choose partial or exact child matching
Default: contain
By default, child matching uses contain. The children named in the template must be present in order, but additional children are allowed. This is useful for a menu that gains optional items or a list whose unrelated entries are not part of the test:
- list:
- listitem: Feature A
A template can omit a name or attribute when only existence or role matters:
- button
This checks that a button is present without coupling the test to its current label.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Require the exact immediate child list with equal
Set /children: equal when the specified children must be the complete list, in order:
- list:
- /children: equal
- listitem: Feature A
- listitem: Feature B
With equal, an extra sibling or a missing item fails the assertion. The comparison applies to that node’s direct children.
Require exact descendants with deep-equal
Use deep-equal when nested descendants must also match exactly. This is appropriate for a tightly specified composite widget, but it creates more maintenance when legitimate content is added:
- navigation "Primary":
- /children: deep-equal
- link "Home":
- /children: deep-equal
- link "Pricing":
- /children: deep-equal
You can set a global default with expect.toMatchAriaSnapshot.children and override it inside an individual snapshot. Prefer local overrides when only one component needs strictness; a global exact policy can make unrelated tests fail after harmless additions.
Match dynamic names and text safely
ARIA snapshot matching is case-sensitive, collapses whitespace, and is order-sensitive. A changing title or count should use a regular expression rather than a value that expires:
- heading /Issues d+/
The expression is matched against the accessible name or text represented by that node. Keep the pattern narrow enough to catch a real regression; /.*/ would accept almost any value and remove the test’s purpose. If order is not a product requirement, scope separate assertions to the individual controls instead of forcing one large ordered tree.
Capture a snapshot or let the runner generate it
Capture the YAML programmatically
locator.ariaSnapshot() returns a promise containing the current snapshot string:
const snapshot = await page.getByRole('main').ariaSnapshot();
console.log(snapshot);
Use this when investigating an unexpected accessibility tree, logging a fixture during development, or building a snapshot template by hand. The Locator API marks ariaSnapshot() as added in v1.49.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesGenerate an assertion template
An empty template asks the test runner to generate the expected snapshot:
await expect(page.getByRole('main')).toMatchAriaSnapshot('');
The runner waits up to the configured maximum expect timeout while the page settles. If the generated result is not what you want, edit the template before committing it; generation is not a substitute for deciding which roles, names, and states are contractually important.
Rank #4
Update stored snapshots from the command line
When an intentional UI change is made, run:
npx playwright test --update-snapshots
# short form
npx playwright test -u
Playwright updates mismatched snapshots and can produce patch files for review and application. The documented source-update methods are patch (the default), 3way, and overwrite. Review generated changes as code: an update should explain a deliberate accessibility change, not merely silence a failure.
Keep snapshots in separate .aria.yml files
Inline templates keep the expected structure beside the test. A named file is easier to browse when a component has a large tree or several tests share an organizational convention:
Free tools Windows power users keep installed
One-click scans. No signup required.
await expect(page.getByRole('main')).toMatchAriaSnapshot({
name: 'main.aria.yml'
});
Playwright places the file in a test-specific snapshot directory by default; the snapshot-path template is configurable. The named-file form is documented for locator assertions from v1.50. PageAssertions also documents named snapshot files. Keep filenames stable and descriptive, and commit the file with the test so a reviewer can inspect the complete accessibility contract.
A complete component test
The following example combines a scoped locator, partial matching, a state, and a dynamic heading:
import { test, expect } from '@playwright/test';
test('issues panel exposes the expected controls', async ({ page }) => {
await page.goto('https://example.test/issues');
const panel = page.getByRole('region', { name: 'Issues' });
await expect(panel).toMatchAriaSnapshot(`
- heading /Issues d+/
- textbox "Filter issues"
- checkbox "Open only" [checked]
- list:
- listitem: First reported issue
`);
});
The list intentionally uses the default contain behavior, so the test protects the first visible item without freezing every result. If the product requirement changes to “these are the only two choices,” add /children: equal at the list node and enumerate both items.
Check your installed Playwright version
| Capability | Documented availability | Where to verify |
|---|---|---|
locator.ariaSnapshot() |
Added in v1.49 | Locator API |
locator.ariaSnapshotJSON() |
Added in v1.63 | Locator API |
| String-template locator assertion | Added in v1.49 | LocatorAssertions |
| Named-file locator assertion | Added in v1.50 | LocatorAssertions |
Page-level toMatchAriaSnapshot() |
Added in v1.60 | PageAssertions |
If an example is rejected as an unknown method or option, compare npx playwright --version with the version annotations in the official references. Upgrade deliberately, or use a locator assertion supported by the version already pinned in your project.
Troubleshoot failing ARIA snapshot tests
“Unknown method” or TypeScript errors
- Cause: The installed Playwright release predates the API, or the project imports a different test package.
- Fix: Check
npx playwright --version, consult the version table above, and update the package and lockfile together if the project can move versions.
The snapshot is empty or missing expected nodes
- Cause: The locator resolves to the wrong element, content has not rendered, or the UI is hidden from the accessibility tree.
- Fix: Inspect
await locator.ariaSnapshot(), use a role- or label-based locator for the intended region, and wait for a meaningful application condition before asserting.
A harmless extra item causes a failure
- Cause: The template uses
equalordeep-equal, or a global exact-child setting is active. - Fix: Return that node to the default
containbehavior when additional children are valid. Keep exact matching only where the complete set and order are requirements.
A renamed label breaks many tests
- Cause: Tests intentionally bind to exact accessible names.
- Fix: Keep exact names for user-facing contracts. For values that are expected to vary, omit the name when only the role matters or use a focused regular expression.
Text differs only in spacing or capitalization
- Cause: Matching is case-sensitive; whitespace is collapsed but capitalization is not normalized.
- Fix: Correct the accessible text if the change is a bug. Otherwise use a deliberate regex or assert a less volatile ancestor rather than weakening every node.
An update command records an unwanted change
- Cause:
--update-snapshotsaccepts the current tree without deciding whether it is correct. - Fix: Review the patch, revert accidental changes, and update only after confirming the new roles, names, order, and states are intended.
Design snapshots for reliable tests
- Scope first: Prefer a component locator for a component test; reserve page-wide snapshots for page-level accessibility contracts.
- Assert behavior, not markup: Roles, accessible names, states, and required text survive many DOM and CSS refactors.
- Use the weakest matching mode that proves the requirement:
containreduces churn, whileequalanddeep-equalprotect complete menus or fixed structures. - Keep dynamic values controlled: Regexes document which part may change and still fail on an unexpected format.
- Split unrelated contracts: Several small locator assertions usually identify the failing component faster than one enormous page tree.
- Review generated files: Treat snapshots as test source, with normal code review and ownership.
Or skip the browser setup
When you need a rendered image or PDF of a URL alongside your Playwright work—not an ARIA assertion—ScreenshotNeo provides a single website-screenshot API request. It accepts cookie or consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.
Use the API documentation at screenshotneo.com/docs/ for all options. A minimal cURL request is:
Best Value
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
The same request in Python:
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
And in Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot failed: ${res.status}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo also supports full-page and element captures, dark mode, device presets or custom viewports, retina scale, PDF paper and page-range controls, custom CSS and JavaScript, clicks, selector or network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone and geolocation, transparent backgrounds, resizing, configurable-TTL caching, signed image links, asynchronous webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Parameter names used by other screenshot APIs are accepted to ease migration.
The Free plan includes 1,000 screenshots each month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan, and yearly billing provides two months free. Create a free ScreenshotNeo account to try it without a card.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →FAQ
Do ARIA snapshots replace keyboard and screen-reader testing?
No. They assert the serialized accessibility structure exposed at the moment of the test. Keep interaction tests and manual or assistive-technology checks for focus behavior, announcements, and real user flows.
Can I use a snapshot for visual pixel approval?
No. A snapshot does not contain colors, spacing, fonts, or pixels. Use a visual screenshot tool for appearance and an ARIA snapshot for the accessible tree.
Should every test store a separate snapshot file?
No. Inline templates are often clearest for short contracts. Named files are useful when the tree is large, shared, or reviewed independently from the test logic.
Why does child order matter?
ARIA snapshot matching is order-sensitive. This lets a test catch a reordered menu or list; if order is intentionally flexible, assert smaller locators or design a template that does not encode an unrelated sequence.
Frequently Asked Questions
Do ARIA snapshots replace keyboard and screen-reader testing?
No. They assert the serialized accessibility structure exposed at the moment of the test. Keep interaction tests and manual or assistive-technology checks for focus behavior, announcements, and real user flows.
Can I use a snapshot for a visual pixel approval?
No. A snapshot does not contain colors, spacing, fonts, or pixels. Use a visual screenshot tool for appearance and an ARIA snapshot for the accessible tree.
Should every test store a separate snapshot file?
No. Inline templates are often clearest for short contracts. Named files are useful when the tree is large, shared, or reviewed independently from the test logic.
Why does child order matter?
ARIA snapshot matching is order-sensitive. This lets a test catch a reordered menu or list; if order is intentionally flexible, assert smaller locators or design a template that does not encode an unrelated sequence.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

