Accessibility Tree: How Browsers and AI Tools Use It

EngineeringAugust 22, 20267 min readBy PinVari
Accessibility Tree: How Browsers and AI Tools Use It

The accessibility tree is a live model of a user interface in which every element is a named node with a role, a label, a value, and a screen frame. Browsers, screen readers, UI tests, and AI coding tools all read it to answer one question: what is this control, and what can I do with it?

Most explanations stop at "it's the thing screen readers use." That hides the part that matters when you debug UI with an agent.

If you live in Claude Code or Codex, this layer decides whether the agent edits the button you meant.

A screenshot gives the model pixels. The accessibility tree gives it AXButton "Save changes" at a known frame.

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 renders, so 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 maps a pixel back to the object that owns it.

In the browser this tree is derived from the DOM plus ARIA. On native macOS the same concept ships as AXUIElement, the type behind the macOS Accessibility API.

Same idea, two runtimes: a hierarchy of named, queryable nodes.

Key

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 decorative wrappers.

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 as 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. That is the root cause of a large share of 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 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 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. 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 is one launch: Xcode → Open Developer Tool → Accessibility Inspector. Point it at any running app, hover, and it reports role, label, value, and frame.

Learning the Accessibility Inspector on Mac is the fastest way to see why an element is or is not named. It shows the same data your code receives.

Chrome DevTools a11y pane

  • Platform: Browser
  • What it shows: Computed role, name, name-source chain
  • Best for: Debugging one web element

chrome://accessibility

  • Platform: Browser
  • What it shows: Full internal tree for a tab
  • Best for: Seeing the whole page tree

Accessibility Inspector

  • Platform: macOS
  • What it shows: Role, label, value, frame under the cursor
  • Best for: Native and Electron apps

VoiceOver Utility

  • Platform: macOS
  • What it shows: How a node is announced
  • Best for: Real assistive-tech behavior
Tip

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 bug before wasting an agent round-trip.

Where does the accessibility tree go empty?

Some surfaces expose almost nothing. This is the part optimistic tutorials skip, and it is 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 and you get a generic group with no role and no name.

Electron and Chromium apps have a second problem. They build the accessibility tree lazily, and often start cold, so the first query returns a bare, unlabeled group.

Setting AXManualAccessibility to true wakes the engine. A short bounded retry (around 150ms) gives it time to populate real labels.

Chromium also stashes identity in AXDOMIdentifier and AXDOMClassList. A title-less node can still be named from its DOM id or class.

Heads up

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

That gap has a direct cost. Screenshots waste Claude Code tokens because pixel data is a poor way to describe UI state.

The accessibility tree replaces inference with a fact. That is why AI agents can know which UI element you mean: the frame and the name travel together, so "this" binds to a real node.

PinVari is built on 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 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 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. One click inside PinVari connects Claude Code, Cursor, VS Code or Codex — or paste one CLI line from pinvari.com/connect.

PinVari → Connect → your agent (one click)
Get PinVari — $39 →