Install xa11y
Install the library
Section titled “Install the library”cargo add xa11yAdds the current release to Cargo.toml. The platform backend is picked by target, so there are no feature flags to choose.
pip install xa11yRequires Python 3.9+. Pre-built wheels are available for Linux (x86_64, aarch64), macOS (x86_64, aarch64), and Windows (x86_64).
npm install @crowecawcaw/xa11yRequires Node.js 18+. Pre-built native binaries are published for Linux (x86_64, aarch64), macOS (x86_64, aarch64), and Windows (x86_64, aarch64).
Install the CLI
Section titled “Install the CLI”The xa11y command-line tool is the fastest way to inspect an application
before writing selectors against it. All three installs provide the same
xa11y command, but the process that runs it differs:
cargo install xa11y # native binarypip install xa11y # Python package, runs in the Python interpreternpm install @crowecawcaw/xa11y # Node package, runs in the Node processThat difference matters for the macOS permission grants below.
See CLI for the command reference.
Grant platform permissions
Section titled “Grant platform permissions”macOS needs two permissions:
- Accessibility, under System Settings → Privacy & Security. The pane is named Accessibility through macOS 26 and Device Control and Data Access on macOS 27 and newer. Grant permission to your terminal (or IDE).
- Screen & System Audio Recording (macOS 26+), under System Settings → Privacy & Security → Screen & System Audio Recording. Grant permission to your terminal. Without it, the accessibility API exposes menu bars alone. Window content such as buttons and text fields stays invisible.
Grant the permissions to the process that runs xa11y, which is usually your
terminal or IDE. When a script, agent, or CI job launches xa11y instead, grant
that process: the resolved Python interpreter for pip install
(python -c 'import sys; print(sys.executable)'), the Node process for the
npm package, or the xa11y binary for cargo install. TCC matches the
resolved on-disk binary, not the symlink, so grant the real interpreter path
rather than a virtualenv python symlink.
After changing permissions, restart your terminal for them to take effect. App::by_name() (Rust) or xa11y.App.by_name() (Python) will return a PermissionDenied error with setup instructions if either permission is missing.
Input simulation and screenshots each need one more grant on macOS. Those pages list what and why.
Linux needs AT-SPI2 running, which is the default on GNOME and most desktop environments, and nothing else to grant. Electron and Chromium-based apps (VS Code, Cursor, Chrome) require an additional launch flag to expose their accessibility tree. That flag, and the command for checking whether the bus can see a given application at all, are in Platform Details.
Windows
Section titled “Windows”Windows works as installed. UI Automation is available in any interactive desktop session.
Verify the install
Section titled “Verify the install”Start any application with a window, then:
xa11y appsA list of running applications with their process IDs means the install and the permissions are both good. An empty list on macOS means the permissions have not taken effect yet, so restart the terminal.
Next steps
Section titled “Next steps”- Your first xa11y script drives a running application end to end in about ten minutes.
- Testing in CI covers the same setup on a machine with no display and no permissions granted.