Skip to main content
Back to Blog
Guide
2026-07-14

Playwright CLI Accessibility Snapshots and Element References Explained

Understand Playwright CLI accessibility snapshots, use short-lived element refs safely, scope agent context, and troubleshoot stale or missing references.

Playwright CLI accessibility snapshot with semantic elements and current browser references

A Playwright CLI snapshot is a YAML accessibility-tree view of the current page, with short-lived refs such as e5 attached to interactive elements. Read the newest snapshot, choose the ref for the element the agent just observed, perform one action such as playwright-cli click e5, and read the new snapshot returned afterward. Refs are stable only within their snapshot and can become invalid when the page changes. A snapshot is not a screenshot, a CSS selector, or a complete accessibility audit.

That observe-act-observe loop is the core of the dedicated playwright-cli agent interface. It gives a coding agent a compact semantic representation instead of making it infer every control from pixels or send a large page DOM through its context. This guide explains what the output guarantees, where it does not, and how to use refs without creating brittle browser workflows.

What a Playwright CLI Snapshot Contains

After each browser command, playwright-cli reports the current page URL and title plus a link to a timestamped snapshot under .playwright-cli/. The file represents the page as an accessibility tree. Headings, text, lists, form controls, links, and other semantic nodes appear in a concise nested structure. Interactive nodes receive refs that another CLI command can target.

A simplified TodoMVC snapshot looks like this:

- heading "todos" [level=1]
- textbox "What needs to be done?" [ref=e5]
- listitem:
  - checkbox "Toggle Todo" [ref=e10]
  - text: "Buy groceries"
- contentinfo:
  - text: "1 item left"
  - link "All" [ref=e20]
  - link "Active" [ref=e21]
  - link "Completed" [ref=e22]

The text and roles help an agent understand intent. The ref is an action handle for that observed state. e5 is not derived from an HTML id and does not promise to be e5 in another browser, session, page state, or later snapshot. The official documentation defines the format as e followed by a number, unique within one snapshot, and assigned to interactive elements.

Automatic snapshots are also evidence about what the accessibility layer exposes. If a control appears as an unnamed button, the output tells you the agent and assistive technology lack a meaningful accessible name. That signal is useful, but it is only one part of accessibility quality.

Snapshot, Screenshot, ARIA Assertion, or DOM Query?

Several Playwright features use similar language. Choose by the question you need to answer:

NeedBest toolOutputImportant limitation
Let an agent understand and target semantic controlsplaywright-cli snapshotYAML accessibility tree with refsRefs are tied to current observed state
Verify pixels, layout, canvas, or visual overlapplaywright-cli screenshotImage artifactPixels do not explain roles or accessible names
Assert an accessibility-tree contract in a test fileexpect(locator).toMatchAriaSnapshot()Test assertion and diffThis is a Playwright Test/API feature, not an agent ref
Inspect a property not represented in the snapshotplaywright-cli eval or a documented locator formEvaluated page data or direct targetRequires a deliberate query and stronger review
Find a stable element across repeatable scripted runsUser-facing Playwright locator or test idLocator expressionIt is not a ref to the exact element just observed

Playwright 1.60 expanded the programmatic ARIA snapshot API with page-level snapshots and optional boxes for AI consumption. That release-note feature does not change the basic agent CLI contract: the CLI's snapshot command returns an accessibility representation and refs for interaction. Do not claim that every CLI snapshot includes bounding boxes, and do not paste an agent ref into a Playwright Test locator.

For a map, canvas editor, or custom widget with no accessible element, a semantic snapshot may not expose an actionable target. The agent CLI has a separate vision capability with screenshots and coordinate commands. Use that only when the interface genuinely lacks a semantic target; it is not a reason to skip accessible markup in an application you control.

The Correct Ref Lifecycle

The safest mental model is a lease, not an identity. A ref gives the agent permission to address the element represented in the current observation. A navigation, reload, route change, dialog transition, list update, or other page mutation may invalidate that lease. The next command returns an updated snapshot from which the next ref should be selected.

Use this sequence:

  1. Observe the current page output.
  2. Open or read the linked snapshot.
  3. Match the intended control by role, accessible name, surrounding text, and state.
  4. Use its current ref in one action.
  5. Inspect the returned page state and snapshot.
  6. Re-plan from the new state rather than assuming the previous ref map survived.

Here is a manual version of the loop:

playwright-cli open https://demo.playwright.dev/todomvc/ --headed
playwright-cli snapshot --filename=empty-list.yaml

# Read empty-list.yaml and use the textbox ref reported there.
playwright-cli fill e5 "Review accessibility tree"
playwright-cli press Enter

# The page changed. Capture and read a new ref map before checking the item.
playwright-cli snapshot --filename=one-item.yaml
playwright-cli check e10

The example refs mirror the shape in the official documentation, but your values are output, not inputs to memorize. If one-item.yaml assigns the checkbox e12, use e12. A robust agent instruction says "use the checkbox ref from the latest snapshot," not "always check e10."

This behavior is intentionally different from a maintained test. A Playwright Test locator such as page.getByRole('checkbox', { name: 'Toggle Todo' }) stores the logic needed to find an element again and benefits from auto-waiting. A ref points to the exact element the agent just saw, which is efficient for an interactive terminal loop but unsuitable as a permanent selector in source code.

Take an On-Demand Snapshot

Every command normally returns a snapshot link, but an explicit snapshot is useful before a risky action, after waiting for an external state change, or when you want a named artifact:

playwright-cli snapshot
playwright-cli snapshot --filename=before-submit.yaml
playwright-cli snapshot "#main"
playwright-cli snapshot e34
playwright-cli snapshot --depth=4

These forms are documented for a full page, custom filename, CSS-selector scope, element-ref scope, and depth limit. Scoping and depth are context-budget controls, not merely formatting preferences. A large application shell can contain hundreds of navigation, menu, and table nodes unrelated to one form. A snapshot of #main, a known panel, or a current ref reduces noise and the chance that an agent chooses a same-named control elsewhere.

Scope only after you understand the page. An overly narrow selector can hide a validation summary, modal, toast, or navigation outcome that determines whether the action succeeded. Start broad enough to establish context, narrow for a focused interaction, then inspect a broad result when success can appear outside that region.

Depth has a similar tradeoff. A small value can make a deeply nested control disappear even though it is present and accessible. Increase depth or remove the limit before concluding that a control has no semantics.

Use Refs, CSS, or Playwright Locators Deliberately

The CLI accepts refs, CSS selectors, and Playwright locator strings for interaction. The official snapshot guidance prefers refs because they identify the element the agent just observed:

# Ref selected from the latest snapshot
playwright-cli click e10

# CSS alternatives
playwright-cli click "[data-testid='submit']"

# User-facing Playwright locator alternative
playwright-cli click "getByRole('button', { name: 'Submit' })"

Use a ref for an immediate action after observation. Use a user-facing locator when you need to express semantic intent and no usable ref is present, or when a reviewed workflow intentionally avoids depending on one generated snapshot. Use CSS when the application exposes a reliable contract such as a test id and the semantic representation is insufficient. Avoid deep structural CSS copied from browser developer tools; it usually encodes implementation details rather than user intent.

The key is not to mix lifetimes accidentally. A ref is strongest as an ephemeral handle. A locator is strongest as repeatable lookup logic. A selector can be strong when it targets an explicit test contract, but weak when it depends on nesting or generated class names.

Make Snapshot Output Efficient for Agents

Long output consumes agent context and can distract planning. Apply reductions in this order:

  1. Start with the automatic full-page snapshot to establish page identity and major regions.
  2. Scope to the feature area by selector or current ref.
  3. Limit depth only when nesting, rather than page breadth, is the source of noise.
  4. Give important artifacts descriptive filenames.
  5. Use raw output for shell processing only when page metadata is not needed.

The documented raw form strips page information and returns command output directly:

playwright-cli snapshot --raw | grep "button"

That can answer a narrow question, but grep is not a substitute for understanding hierarchy. Two "Delete" buttons may belong to different rows, and a text match alone discards the surrounding structure needed to choose safely. For consequential actions, inspect the relevant subtree rather than filtering to one line.

Token efficiency should never mean omitting evidence. Keep a named before snapshot, a named screenshot when visual state matters, and a final snapshot showing the outcome for workflows that will be reviewed. Artifacts make an agent's claim independently inspectable.

What Snapshots Reveal About Accessibility

The tree exposes roles, accessible names, heading levels, control states, and semantic grouping as the browser presents them. It can reveal high-value defects:

  • An icon button has no accessible name.
  • A visual heading is exposed as plain text.
  • Two controls have the same ambiguous name.
  • A custom checkbox is not exposed as a checkbox.
  • Error text appears visually but is absent from the semantic subtree being inspected.
  • Focus lands on a control different from the one the agent expected.

However, a clean-looking snapshot does not establish WCAG conformance. It does not by itself evaluate color contrast, keyboard order across the whole flow, motion, target size, captions, cognitive clarity, zoom behavior, or every name-role-value rule. Nor does it replace testing with screen readers and keyboard-only interaction. Treat the snapshot as an accessibility-informed interaction model and one source of test evidence.

If your goal is a repeatable tree contract, implement reviewed ARIA snapshot assertions in Playwright Test. If your goal is automated rule detection, use an accessibility engine designed for that purpose. If your goal is agent navigation, use the CLI snapshot and current refs. Naming the purpose prevents false confidence.

Dynamic Pages, Dialogs, and Delayed State

Modern pages can mutate after an action without a full navigation. Search suggestions arrive, a table refreshes, or a client route replaces a panel. The returned snapshot is the new planning point even if the URL did not change. Do not use URL change as the only signal that refs may be stale.

Dialogs are a special case because they can block all further actions. The official snapshot best practices say to check command output for an open dialog and handle it before continuing. If a click reports a dialog, stop the planned sequence, inspect the state, use the documented dialog accept or dismiss capability as appropriate, and then obtain a fresh snapshot.

For state that changes outside a CLI action, such as a background job finishing, take an explicit snapshot before interacting again. A stale file on disk does not refresh itself. The timestamped path represents one observation, not a live accessibility tree.

Turn Snapshot Output into Reviewable Evidence

A useful snapshot artifact needs context beyond its YAML. Record the session, scenario, page URL, action that preceded it, and question the snapshot is meant to answer. A file named before-submit.yaml is valuable only if a reviewer can connect it to the right role and run. In parallel work, include the role or task identifier in the filename and artifact report.

Preserve both sides of an important transition when the claim depends on change. The before snapshot establishes available controls and state; the after snapshot establishes the semantic outcome. Add a screenshot when visual layout or styling is part of the claim. This combination lets a reviewer distinguish "the agent clicked a ref" from "the intended user-visible and accessibility-visible result occurred."

Do not line-diff timestamped CLI snapshots and call every changed ref a regression. Ref numbers are ephemeral, and unrelated dynamic content can move. Compare roles, accessible names, states, hierarchy, and expected user outcomes. If the semantic structure must become a stable, automated contract, encode a focused ARIA snapshot assertion in reviewed Playwright Test code rather than turning raw agent artifacts into an accidental golden file.

Finally, apply the same data controls used for screenshots and traces. Accessibility output can contain account names, entered form values, messages, and other page text. Retain only what the investigation requires and avoid publishing snapshots from production sessions.

Common Mistakes

Treating refs as stable selectors

Saving e42 in a script or prompt assumes an internal assignment will repeat. Save user intent in a test locator; read refs from current output in an agent loop.

Using a ref from another session

Refs are scoped to a snapshot, and sessions have separate browser instances and state. A ref from an admin session has no defined meaning in a user session.

Acting from an old snapshot after the page changes

The previous file remains readable, which can make it look authoritative. Its contents describe history. Use the snapshot returned by the most recent state-changing command.

Calling the snapshot an accessibility audit

The tree can surface semantic problems, but it is not a comprehensive standards evaluation. Report exactly what was inspected.

Confusing CLI snapshots with test assertions

playwright-cli snapshot produces an agent observation and refs. toMatchAriaSnapshot compares an expected semantic structure in test code. They solve related but different problems.

Limiting depth too aggressively

If a target vanishes after --depth=2, the depth limit may have hidden it. Re-run without the limit before blaming application accessibility.

Scoping away success or error feedback

A form-only snapshot may exclude a toast or page-level error summary. Inspect the region where the product communicates the result, not only the region where the action began.

Choosing by visible text alone

Repeated labels are common. Consider role, accessible name, parent region, state, and surrounding content before selecting a ref.

Troubleshooting Snapshot and Ref Problems

SymptomProbable causeCorrect next step
"Ref not found" after a click or navigationRef came from an older stateRun a new snapshot and select the target again
Expected button is absentDepth or selector scope is too narrowRemove --depth or widen the scoped region
Control appears without a useful nameApplication accessibility defectConfirm in the DOM/accessibility tools and fix the product's semantic labeling
Snapshot is extremely largeWhole-page output includes unrelated shell contentScope to the relevant selector/ref and use a sensible depth
Several identical names appearContext is ambiguousInspect parent regions or use a reviewed role/test-id locator
Screenshot shows a control that snapshot omitsCanvas/custom widget or missing semanticsPrefer fixing semantics; use vision mode only when the UI genuinely requires coordinates
Ref works in one terminal but not anotherCommands target different sessionsName the session explicitly and verify active sessions
Snapshot does not show a background updateFile is a past observationRun playwright-cli snapshot again after the external change
Commands stop after a modal actionA browser dialog is blockingHandle the reported dialog, then re-snapshot

If a missing element is safety-critical, do not fall back immediately to arbitrary eval code or a guessed coordinate. First remove snapshot limits, confirm the correct tab and session, inspect visual state, and determine whether the application has an accessibility defect. A fallback should be an explicit engineering decision, not an agent's silent escape hatch.

Frequently Asked Questions

Does every playwright-cli command create a snapshot?

The official model says commands return current page information and a snapshot link, making the latest command output the normal next observation. Use explicit playwright-cli snapshot when you need an on-demand, scoped, depth-limited, or named file.

How long is an element ref valid?

It is valid within the state represented by its snapshot and may be invalidated when the page changes. Treat every navigation or mutation as a reason to use the newly returned snapshot. Do not assign a time duration such as "five minutes"; validity is about page state, not elapsed time.

Are refs more reliable than CSS selectors?

For the immediate next action, Playwright recommends refs because they point to the exact element the agent just saw. For a maintained test that must rediscover an element on later runs, user-facing locators or explicit test ids are the appropriate durable contracts.

Can I snapshot only one component?

Yes. The documented command accepts a CSS selector or an element ref as a scope, for example playwright-cli snapshot "#main" or playwright-cli snapshot e34. Ensure the scope does not hide outcome messages you need to verify.

What does --depth do?

It limits tree depth to reduce nested output. It does not wait for more content or improve accessibility. A low depth can omit deeply nested targets, so remove the limit during diagnosis.

Is a snapshot the same as a screenshot?

No. A snapshot is semantic YAML derived from the accessibility tree; a screenshot is a pixel image. Use both when a scenario requires semantic targeting and visual evidence.

Can a snapshot prove my site is accessible?

No. It can expose useful roles, names, and structure and can reveal defects, but full accessibility assessment also needs automated rules, keyboard testing, visual checks, assistive-technology testing, and human judgment against applicable requirements.

Why did the ref number change even though the label did not?

Refs are generated for a snapshot rather than assigned as permanent element identities. A re-render or different tree composition can produce a different number for the same user-facing control. Match intent from current semantics instead of comparing ref numbers.

How do snapshots help debug a failed Playwright Test?

Run the test with npx playwright test --debug=cli, attach the dedicated CLI to the session name printed by the runner, and call playwright-cli snapshot on the paused state. The debugging and trace guide covers that workflow without confusing live refs with post-run trace snapshots.

Related Playwright CLI Guides

Start with installing Playwright CLI if the executable or browser is not ready. Use the complete Playwright CLI guide for the full command landscape, and the sessions, dashboard, and attach guide when refs appear to cross browser instances. For reusable agent instructions, explore the QASkills directory and the dedicated Playwright CLI skill.

The authoritative behavior is documented in Playwright's official snapshots guide, agent quickstart, capability map, and release notes. The operational rule is simple: observe the current semantic state, act through a target grounded in that observation, and verify the new state before continuing.