Principle:Puppeteer Puppeteer Accessibility Tree Inspection
| Knowledge Sources | |
|---|---|
| Domains | Accessibility, Testing |
| Last Updated | 2026-02-12 00:00 GMT |
Overview
Accessibility tree inspection is the principle of querying the browser's internal accessibility tree to audit ARIA attributes, roles, states, and the hierarchical structure that assistive technologies use to interpret page content.
Description
Accessibility Tree Inspection provides a way to capture and examine the accessibility tree that the browser constructs from the DOM. The accessibility tree is a parallel representation of the page's structure, built by the browser's accessibility engine, that describes every element in terms meaningful to assistive technologies like screen readers, braille displays, and voice control software.
Each node in the accessibility tree (a SerializedAXNode) contains:
- Role: The WAI-ARIA role of the element (e.g., "button", "heading", "navigation", "textbox", "image"), which tells assistive technology what kind of control or landmark the element represents.
- Name: The accessible name computed from the element's content, labels, aria-label, aria-labelledby, or other naming mechanisms.
- Value: The current value for interactive elements (e.g., the text content of an input field, the selected option in a dropdown).
- Description: Additional descriptive text provided by aria-describedby or other description mechanisms.
- States and properties: Boolean and enumerated properties including:
- disabled, expanded, focused, modal, readonly, required, selected
- checked and pressed (which can be true, false, or "mixed" for tri-state controls)
- multiline, multiselectable
- level (for headings), valuemin, valuemax (for range controls)
- autocomplete, haspopup, invalid, orientation
- Children: Nested nodes forming the tree hierarchy.
- Element handle: An optional back-reference to the DOM element that produced this accessibility node.
The inspection supports two modes:
- Full tree snapshot: Captures the entire accessibility tree of the page, representing the complete view that a screen reader would perceive.
- Subtree snapshot: Captures only the accessibility subtree rooted at a specific element, useful for focused inspection of a component.
An important feature is the ability to filter uninteresting nodes, which removes elements that are typically invisible to assistive technologies (generic containers, empty text nodes, presentational elements). This produces a cleaner tree that better represents what a screen reader user would actually experience.
Usage
Use accessibility tree inspection for auditing the accessibility compliance of web applications. This includes verifying that interactive elements have appropriate ARIA roles, checking that form fields have accessible names, ensuring that heading hierarchy is correct, confirming that dynamic content updates are announced properly, and validating that the page structure makes sense when stripped of its visual presentation. This principle is particularly valuable in automated accessibility testing pipelines integrated into CI/CD.
Theoretical Basis
The accessibility tree is a computed representation derived from the DOM, influenced by CSS, ARIA attributes, and browser heuristics:
ACCESSIBILITY TREE MODEL
DOM Tree Accessibility Tree
+-- <nav> +-- navigation "Main Nav"
| +-- <ul> | +-- list
| +-- <li> | +-- listitem
| +-- <a> | +-- link "Home"
+-- <main> +-- main
+-- <h1> +-- heading "Title" (level: 1)
+-- <form> +-- form "Search"
+-- <input> +-- textbox "Query" (focused: true)
+-- <button> +-- button "Submit"
Pseudocode for accessibility tree inspection:
1. Full tree snapshot:
tree = await page.accessibility.snapshot()
// Returns root SerializedAXNode with children
// tree = {
// role: "RootWebArea",
// name: "Page Title",
// children: [
// { role: "navigation", name: "Main Nav", children: [...] },
// { role: "main", children: [...] }
// ]
// }
2. Filtered snapshot (interesting nodes only):
tree = await page.accessibility.snapshot({ interestingOnly: true })
// Removes generic containers, empty text, presentational elements
// Retains only nodes with roles, names, or interactive states
3. Element-scoped snapshot:
element = await page.$('#search-form')
tree = await page.accessibility.snapshot({ root: element })
// Returns subtree starting from the form element
// tree = {
// role: "form",
// name: "Search",
// children: [
// { role: "textbox", name: "Query", value: "" },
// { role: "button", name: "Submit" }
// ]
// }
NODE FILTERING ALGORITHM:
For each node in the tree:
IF interestingOnly:
isInteresting = (
node has a focusable role OR
node has an accessible name OR
node has a meaningful role (not "generic", not "none") OR
node has a value OR
node has a description
)
IF NOT isInteresting AND node has children:
promote children to parent level // flatten boring containers
ELSE IF NOT isInteresting:
remove node entirely
The key insight is that the accessibility tree is not a simple mapping of the DOM. The browser applies complex heuristics, ARIA attribute processing, and CSS visibility rules to determine what appears in the accessibility tree and how it is structured. Inspecting this computed tree directly is far more reliable than attempting to infer accessibility from DOM inspection alone.