Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Make 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
- 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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Generate 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.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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 equal or deep-equal, or a global exact-child setting is active.
  • Fix: Return that node to the default contain behavior 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-snapshots accepts 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: contain reduces churn, while equal and deep-equal protect 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.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

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:

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.