API Docs

Accessibility API Module

This module provides access to macOS's powerful Accessibility API, allowing you to:

  • Inspect UI elements in any application
  • Monitor window and element changes
  • Programmatically interact with UI elements

Basic Usage

// Get the focused UI element
const element = hs.ax.focusedElement();
console.log(element.role, element.title);

// Watch an application's element for window creation events. Notifications bubble up
// from anywhere in the application's hierarchy, so this fires for every new window,
// not just one specific window.
const app = hs.application.frontmost();
hs.ax.on(app.axElement(), hs.ax.notificationTypes.windowCreated, (notification, element) => {
    console.log("New window:", element.title);
});

// Watch a specific element (e.g. a text field found via findByRole) for value changes.
// Watching a specific element scopes the notification to just that element, rather
// than the whole application's hierarchy.
const field = hs.ax.findByRole(hs.ax.roles.textField, app.axElement())[0];
hs.ax.on(field, hs.ax.notificationTypes.valueChanged, (notification, element) => {
    console.log("Field changed:", element.value);
});

Note: Requires accessibility permissions in System Preferences.

Types

This module provides the following types:

Properties

hs.ax.notificationTypes

{[key: string]: string}
A dictionary containing all of the notification types that can be used with hs.ax.on()

hs.ax.roles

{[key: string]: string}
A dictionary containing all of the known accessibility roles that elements can have, for use with hs.ax.findByRole() and similar

Methods

hs.ax.systemWideElement() -> HSAXElement

Get the system-wide accessibility element
hs.ax.systemWideElement() -> HSAXElement
HSAXElement
The system-wide AXElement, or nil if accessibility is not available
const sys = hs.ax.systemWideElement()

hs.ax.applicationElement(element) -> HSAXElement

Get the accessibility element for an application
hs.ax.applicationElement(element) -> HSAXElement
Name Type Description
element HSApplication An HSApplication object
HSAXElement
The AXElement for the application, or nil if accessibility is not available
const app = hs.application.frontmost()
const ax = hs.ax.applicationElement(app)

hs.ax.windowElement(window) -> HSAXElement

Get the accessibility element for a window
hs.ax.windowElement(window) -> HSAXElement
Name Type Description
window HSWindow An HSWindow object
HSAXElement
The AXElement for the window, or nil if accessibility is not available
const win = hs.window.focusedWindow()
const ax = hs.ax.windowElement(win)

hs.ax.elementAtPoint(point) -> HSAXElement

Get the accessibility element at the specific screen position
hs.ax.elementAtPoint(point) -> HSAXElement
Name Type Description
point HSPoint An HSPoint object containing screen coordinates
HSAXElement
The AXElement at that position, or nil if none found
const el = hs.ax.elementAtPoint({x: 100, y: 200})

hs.ax.on(element, notification, listener) -> None

Register a listener for AX events on a specific element
hs.ax.on(element, notification, listener) -> None
Name Type Description
element HSAXElement An HSAXElement to watch. Passing an application's element causes matching notifications to bubble up from anywhere in that application's hierarchy (e.g. AXWindowCreated for any window in the app, not just one); passing a specific descendant element scopes the notification to just that element
notification JSValue An event name, or an array of event names, to watch for with the same listener
listener function A function called with the notification name and the accessibility element it applies to
None
Throws an Error on failure; wrap calls in try/catch to handle it.
When `notification` is an array, registration is all-or-nothing: if any one of them fails, none are left registered.
const app = hs.application.frontmost()
try {
    hs.ax.on(app.axElement(), hs.ax.notificationTypes.windowCreated, (notification, element) => {
        console.log("New window:", element.title)
    })

    // Watch for several notifications with the same handler
    hs.ax.on(app.axElement(), [hs.ax.notificationTypes.windowCreated, hs.ax.notificationTypes.windowMoved], (notification, element) => {
        console.log(notification, element.title)
    })
} catch (err) {
    console.error(err.message)
}

hs.ax.off(element, notification, listener) -> None

Remove a previously registered listener for AX events on a specific element
hs.ax.off(element, notification, listener) -> None
Name Type Description
element HSAXElement The HSAXElement that was passed to `on`
notification JSValue The event name, or array of event names, to stop watching
listener function The function/lambda provided when adding the watcher
None
const app = hs.application.frontmost()
hs.ax.off(app.axElement(), hs.ax.notificationTypes.windowCreated, myHandler)

hs.ax.once(element, notification, listener) -> None

Register a listener that fires at most once for AX events on a specific element
hs.ax.once(element, notification, listener) -> None
Name Type Description
element HSAXElement An HSAXElement to watch - see `on` for the application-vs-descendant bubbling behavior
notification JSValue An event name, or an array of event names, to watch for with the same listener
listener function Called once (per registered notification name), then automatically removed
None
Throws an Error on failure; wrap calls in try/catch to handle it.
const app = hs.application.frontmost()
try {
    hs.ax.once(app.axElement(), hs.ax.notificationTypes.windowCreated, (notification, element) => {
        console.log("First new window:", element.title)
    })
} catch (err) {
    console.error(err.message)
}

hs.ax.focusedElement() -> HSAXElement

Fetch the focused UI element
hs.ax.focusedElement() -> HSAXElement
HSAXElement
An HSAXElement representing the focused UI element, or nil if none was found
const el = hs.ax.focusedElement()
console.log(el.role + " " + el.title)

hs.ax.findByRole(role, parent) -> HSAXElement[]

Find AX elements matching a given role
hs.ax.findByRole(role, parent) -> HSAXElement[]
Name Type Description
role string The role name to search for (e.g. "AXButton", or hs.ax.roles.button)
parent HSAXElement An HSAXElement to search within
HSAXElement[]
An array of matching HSAXElement objects
const app = hs.application.frontmost()
const buttons = hs.ax.findByRole(hs.ax.roles.button, app.axElement())

hs.ax.findByTitle(title, parent) -> HSAXElement[]

Find AX elements whose title contains a given string
hs.ax.findByTitle(title, parent) -> HSAXElement[]
Name Type Description
title string The string to search for within element titles
parent HSAXElement An HSAXElement to search within
HSAXElement[]
An array of matching HSAXElement objects
const app = hs.application.frontmost()
const matches = hs.ax.findByTitle("OK", app.axElement())

hs.ax.printHierarchy(element, maxDepth) -> None

Print the accessibility hierarchy of an element to the Console
hs.ax.printHierarchy(element, maxDepth) -> None
Name Type Description
element HSAXElement An HSAXElement to print. If omitted, the system-wide element is used
maxDepth number Maximum number of levels to traverse. Defaults to 5
None
const app = hs.application.frontmost()
hs.ax.printHierarchy(app.axElement(), 3)