Accessibility Tree: How Browsers and AI Tools Use It

The accessibility tree is a structured, live model of a user interface in which every element becomes a named node carrying a role, a label, a value, and a screen frame. Browsers, screen readers, UI test frameworks, and a newer class of AI coding tools all read the accessibility tree to answer one question about any control on screen: what is this, and what can I do with it? Most explanations stop at "it's the thing screen readers use," and that framing hides the part that matters when you are debugging UI with an agent.
If you live in Claude Code or Codex, this is the layer that decides whether your agent edits the button you meant or a similar-looking one three divs away. A screenshot gives the model pixels to interpret. The accessibility tree gives it AXButton "Save changes" at a known frame, already named.
What is the accessibility tree, exactly?
The accessibility tree is a parallel model of the UI built for machines, not for pixels. It sits alongside whatever the app actually renders, and it exists so that software can inspect and drive an interface without reading the screen visually.
Each node answers attribute queries. Ask for its role and you get button, textbox, or link. Ask for its name and you get the accessible label a user would hear. Ask for its value and a text field hands back its contents. Every node also reports a frame in screen coordinates, which is what lets you map a pixel back to the object that owns it.
In the browser this tree is derived from the DOM plus ARIA attributes. On native macOS the same concept ships as AXUIElement, the type behind the whole macOS Accessibility API. Same idea, two runtimes: a hierarchy of named, queryable nodes.
The accessibility tree is not a screenshot service. It hands back structured objects — a node that knows it is a button titled "Submit," at a specific frame, currently enabled. That structure is the entire value.
How does a browser build the accessibility tree?
A browser computes the accessibility tree from the DOM, not separately from it. When the page renders, the engine walks the DOM and produces one accessible node per meaningful element, dropping purely decorative wrappers along the way.
Three things determine each node. The role comes from the tag or an explicit ARIA role — a <button> becomes button, a <div role="tab"> becomes tab. The name is computed from a chain: aria-label, then a linked aria-labelledby, then the element's own text or alt. The state captures disabled, checked, expanded, and similar flags.
This is why ARIA matters. A <div> styled to look like a button is invisible to the tree unless you give it role="button" and an accessible name. A control that has no role and no name simply is not there for anything reading the tree, which is the root cause of a large share of both screen-reader bugs and agent misfires.
The tree also updates as the DOM changes. Toggle a menu open and the corresponding node flips expanded to true; that live quality is what test frameworks and automation depend on.
How do you view the accessibility tree on Mac and in Chrome?
You do not have to guess what the tree contains. Both the browser and the OS ship inspectors that show you the exact node any tool will see.
For the accessibility tree view in Chrome, open DevTools, select an element in the Elements panel, and open the Accessibility pane on the side. It shows that node's computed role, name, and the property chain that produced the name. For the full picture, chrome://accessibility dumps the internal tree for a tab.
On macOS, how to use Accessibility Inspector comes down to one launch: it is bundled with Xcode under Xcode, Open Developer Tool, Accessibility Inspector. Point it at any running app, hover, and it reports the role, label, value, and frame of whatever is under the cursor. Learning the Accessibility Inspector on Mac is the fastest way to understand why an element is or is not named, because it shows you the same data your code receives.
| Inspector | Platform | What it shows | Best for |
|---|---|---|---|
| Chrome DevTools a11y pane | Browser | Computed role, name, name-source chain | Debugging one web element |
| chrome://accessibility | Browser | Full internal tree for a tab | Seeing the whole page tree |
| Accessibility Inspector | macOS | Role, label, value, frame under cursor | Native + Electron apps |
| VoiceOver Utility | macOS | How a node is announced | Real assistive-tech behavior |
When an agent keeps grabbing the wrong control, inspect that control first. If Accessibility Inspector shows an empty name, no tool can resolve it by name, and you have found the actual bug before you have wasted a single agent round-trip.
Where does the accessibility tree go empty?
The honest limit: some surfaces expose almost nothing. This is the part optimistic tutorials skip, and it is exactly where naive "just read the tree" approaches fall apart.
A <canvas> element, a WebGL scene, a game, a Figma document, and some custom-drawn Electron views render pixels the accessibility layer never sees. Query the node under your pointer there and you get a generic group with no role and no name.
Electron and Chromium apps have a second, subtler problem. They build the accessibility tree lazily, and often start cold, so the first query returns a bare, unlabeled group. Setting the AXManualAccessibility attribute to true wakes the engine, and a short bounded retry (around 150ms) gives it time to populate real labels. Chromium also stashes identity in AXDOMIdentifier and AXDOMClassList, so a title-less node can still be named from its DOM id or class.
If a tool claims it always resolves the exact element, be skeptical. On canvas, games, and remote-desktop windows the tree is genuinely empty, and the only correct fallback is on-device OCR of the region plus a confidence score — never a silent guess.
Why do AI coding agents read the accessibility tree?
Because it turns "fix this" into a named target. When you point at a component and speak, the difference between a pixel guess and a resolved answer is whether your agent receives AXButton "Continue" with a frame, or a raw image it has to interpret.
That gap has a direct cost. Screenshots waste Claude Code tokens because pixel data is the least efficient way to describe UI state, and the model still has to infer which region you meant. The accessibility tree replaces that inference with a fact, which is why AI agents can know which UI element you mean at all: the frame and the name travel together, so the word "this" binds to a real node.
PinVari is built on exactly this layer. Hold ⌥⌘A, circle a control, and speak; it resolves the named element under your ink from the accessibility tree, attaches a confidence score and whether you circled or dwelled, and hands your own agent a resolved, executable instruction over a local MCP server on 127.0.0.1. It runs on-device, brings no API keys, and ships as a one-time $39 launch license rather than a subscription. The tree is the reason your agent gets a target instead of a hunch.
FAQ
What is the accessibility tree in simple terms?
It is a machine-readable version of everything on screen, where each control is a node with a role (button, link, textbox), an accessible name, a value, and a position. Software reads it to understand and operate a UI without looking at pixels, which is how screen readers, automation tools, and AI agents all target the right element.
How do I view the accessibility tree in Chrome?
Open DevTools, pick an element in the Elements panel, and open the Accessibility pane to see that node's role, name, and name-source chain. For the entire tree of a tab, load chrome://accessibility and expand the page you want to inspect.
How do I use Accessibility Inspector on Mac?
Launch it from Xcode under Open Developer Tool, Accessibility Inspector, then hover over any running app. The Accessibility Inspector on Mac reports the role, label, value, and frame of the element under the cursor, which is the same data an accessibility-based tool would read in code.
Is the accessibility tree the same as the DOM?
No. The DOM is the full document structure a browser renders; the accessibility tree is a filtered, computed view derived from the DOM plus ARIA, containing only meaningful controls with resolved roles and names. Decorative wrappers in the DOM usually do not appear in the tree at all.
Why is my element missing from the accessibility tree?
Usually it has no role and no accessible name — a styled <div> with no role and no label is invisible to the tree. Canvas, WebGL, and some custom-drawn views also expose nothing, in which case tools fall back to OCR because the tree cannot help.
Do AI coding agents need the accessibility tree?
They do not require it, but it makes them far more accurate. Reading the tree lets an agent target AXButton "Save" instead of guessing which button in a screenshot you meant, which cuts wrong-element edits and the token cost of sending full images.
Hand your agent the exact element
PinVari resolves what you point at into a named, executable instruction — on-device, no keys, your own agent. If you run Claude Code, it is one command.
claude mcp add pinvariGet PinVari — $39 →


