xa11y
xa11y — Cross-Platform Accessibility Client Library for Python.
- Quick start:
>>> import xa11y >>> app = xa11y.locator('application[name="Safari"]') >>> app.child("button[name='Submit']").press() >>> for element in app.descendant("button").elements(): ... print(element.name)
Exceptions
The target app advertises an accessibility tree but it is empty. |
|
The requested action is not supported on the target element. |
|
An action received invalid data (e.g. |
|
The selector string has invalid syntax. |
|
Accessibility permissions have not been granted. |
|
An OS-level accessibility error occurred. |
|
No element in the tree matched the given selector. |
|
An operation exceeded its timeout. |
|
Base exception for all xa11y errors. |
Classes
A running application — the entry point for accessibility queries. |
|
A live element with lazy navigation. |
|
An accessibility event delivered to subscribers. |
|
Accessibility event type constants. |
|
Input-simulation façade for synthesised pointer and keyboard events. |
|
One drawn annotation box: the tag in the image, and the element it |
|
A resilient element reference that re-queries on each interaction. |
|
An element that matched an |
|
A bounding rectangle in logical screen coordinates (device-independent |
|
A captured image: raw RGBA8 pixels plus dimensions and mapping. |
|
One OS-owned shell surface — the taskbar, a desktop panel, the dock, the |
|
A live event subscription. |
Functions
|
Get the effective process-wide default timeout, in seconds. |
|
Construct an |
|
Create a top-level Locator searching from the system root. |
|
Capture pixels from the screen. |
|
Set the process-wide default timeout, in seconds. |
Package Contents
- exception xa11y.AccessibilityNotEnabledError
Bases:
XA11yErrorThe target app advertises an accessibility tree but it is empty.
Raised on Linux when a Chromium/Electron app is launched without
--force-renderer-accessibility(or theACCESSIBILITY_ENABLED=1environment variable), so the renderer accessibility bridge never populates the window’s subtree.Initialize self. See help(type(self)) for accurate signature.
- exception xa11y.ActionNotSupportedError
Bases:
XA11yErrorThe requested action is not supported on the target element.
Initialize self. See help(type(self)) for accurate signature.
- exception xa11y.InvalidActionDataError
Bases:
XA11yErrorAn action received invalid data (e.g.
Locator.nth(0), or a text-selection range withstart > end).Initialize self. See help(type(self)) for accurate signature.
- exception xa11y.InvalidSelectorError
Bases:
XA11yErrorThe selector string has invalid syntax.
Initialize self. See help(type(self)) for accurate signature.
- exception xa11y.PermissionDeniedError
Bases:
XA11yErrorAccessibility permissions have not been granted.
Initialize self. See help(type(self)) for accurate signature.
- exception xa11y.PlatformError
Bases:
XA11yErrorAn OS-level accessibility error occurred.
Initialize self. See help(type(self)) for accurate signature.
- exception xa11y.SelectorNotMatchedError
Bases:
XA11yErrorNo element in the tree matched the given selector.
Carries a structured diagnosis (tenet 6) so the failure is understandable without re-running it under manual tree dumps. All attributes are always present (
None/[]when not applicable); the same content is rendered into the exception message.Initialize self. See help(type(self)) for accurate signature.
- candidates: list[str]
Bounded near-miss candidates, e.g. same-role elements with different names, or the running applications for app lookups.
- condition: str | None
What the operation was waiting for / trying to find, if known.
- elapsed: float | None
Always
Nonefor this class (present for attribute parity withTimeoutError).
- last_observed: str | None
What the failing operation last observed (e.g.
'selector matched 2 element(s); nth(5) requested').
- scope: str | None
Bounded rendering of the search scope: a depth-limited tree dump for scoped locators, or the application list for rootless ones.
- selector: str | None
The selector that failed to match.
- exception xa11y.TimeoutError
Bases:
XA11yErrorAn operation exceeded its timeout.
Carries a structured diagnosis (tenet 6): what the wait was for (
condition+selector), what it last observed, and — when the selector never matched — bounded scope context (candidates+scope). All attributes are always present (None/[]when not applicable); the same content is rendered into the message, e.g.:Timeout after 60.0s; waiting for: visible; selector: dialog[name^="Submit"]; last observed: selector never matched; candidates: window "Untitled — MyApp" search scope (bounded): ...
Initialize self. See help(type(self)) for accurate signature.
- candidates: list[str]
Bounded near-miss candidates (same role, different attributes). Collected only when the selector never matched during the wait.
- condition: str | None
What the wait was for:
'visible','attached','press target actionable (visible && enabled)','event matching predicate','custom predicate', …
- elapsed: float | None
Wall-clock seconds the operation waited before giving up.
- last_observed: str | None
The last poll’s observation:
'matched button "Export" (visible=false, enabled=true, focused=false)'vs'selector never matched'.
- scope: str | None
Bounded rendering of the search scope. Collected only when the selector never matched during the wait.
- selector: str | None
The selector being resolved, when the wait had one.
- exception xa11y.XA11yError
Bases:
ExceptionBase exception for all xa11y errors.
Initialize self. See help(type(self)) for accurate signature.
- class xa11y.App
A running application — the entry point for accessibility queries.
- as_element() Element
Get an
Elementhandle for the application root.Useful for invoking Element-level methods (
children(),parent(), etc.) without going through a locator.
- static by_name(name: str, *, timeout: float | None = None) App
Find an application by exact name.
Polls the accessibility API until the app appears or
timeout(seconds) elapses.timeout=None(the default) uses the process-wide default timeout — 5 seconds unless overridden viaset_default_timeout()or theXA11Y_DEFAULT_TIMEOUTenvironment variable. Passtimeout=0for a single attempt with no waiting. Only “not found” errors trigger a retry; other errors fail fast.
- static by_pid(pid: int, *, timeout: float | None = None) App
Find an application by process ID.
This is the supported way to wait for a freshly launched process to surface in the accessibility tree: the lookup polls until the app becomes reachable through the platform bridge or
timeout(seconds) elapses, covering the gap between the process starting and its accessibility registration completing. There is no need to hand-roll a poll overApp.list(). Where the platform supports it (macOS AX, Windows UIA), the lookup attaches to the process directly instead of filtering app enumeration, so an app whose window is still unnamed mid-startup is found as soon as the accessibility API can reach it. Seeby_namefortimeoutsemantics.
- dump(max_depth: int | None = None) str
Render this application’s accessibility tree as an indented string.
Returns the string without printing it. Same depth semantics as
tree(). This is the primary inspection helper — callprint(app.dump())to discover the role and name of every element in the app before writing selectors.For the same output from the shell, use
xa11y tree --app NAME.
- static find(predicate: collections.abc.Callable[[App], bool], *, timeout: float | None = None) App
Find an application matching
predicate.predicateis called with anAppfor each running application on every poll; the first for which it returns truthy is returned. A falsy return means “not this one, keep polling”; if the predicate raises, the search aborts immediately and that exception propagates. Seeby_namefortimeoutsemantics. There is no need to hand-roll a poll overApp.list().Use this when neither a name nor a PID alone identifies the target — e.g. a Qt dialog that registers as its own accessibility application sharing the host process’s PID:
app = xa11y.App.find( lambda a: a.pid == pid and a.name.startswith("My Dialog"), timeout=30.0, )
- static foreground(*, timeout: float | None = None) App
Resolve the application that currently holds the system foreground.
Queries the platform’s foreground mechanism directly rather than enumerating and tagging by pid. The result is the foreground process’s
Applicationnode — one per process on every platform — not the exact window holding the focus; on Windows that is the synthesized node of the foreground process (the modal case, issues #304/#305), and this stays reliable when an app shows a modal dialog. To reach the exact foreground window, callwindows()and pick the entry reportingactive. “Nothing focused” retries untiltimeout; seeby_namefortimeoutsemantics. The returned app hasis_foreground == True.
- static list() list[App]
List all running applications.
Single enumeration, no polling. To wait for an app that is still starting up, use
by_pid/by_name/findwith atimeoutinstead of polling this in a loop.
- subscribe() Subscription
Subscribe to accessibility events from this application.
- tree(max_depth: int | None = None) dict
Capture this application’s accessibility tree as a recursive dict.
Each dict has keys
role,name,value, andchildren(a list of dicts with the same shape).max_depthlimits traversal:0= only the application node,1= application + direct children (typically windows),None= full subtree.Equivalent to
Element.tree(...)on the application’s root element.
- windows() list[Element]
List the top-level windows of this application.
Each call queries the provider; results are not cached. The windows are the application’s top-level windows with role
windowordialog, in enumeration order. On Windows the application entry is a synthesized process node whose children are the process’s top-level windows (main window plus modal dialogs). On Linux the answer is process-complete:App::windows_withmerges the filtered children of every same-pid AT-SPI Application entry (an app that registers several entries reports its whole process), so the results need not be the direct children of this node and no single z-order spans them. Callingwindowson a non-application element fails withActionNotSupportedError.
- property focused: bool
Deprecated alias for
is_foreground.Deprecated since version Use:
is_foreground. “focused” refers to element keyboard focus elsewhere in the API; accessing this property emits aDeprecationWarning.
- property is_foreground: bool
Whether this application is the foreground application.
Named
is_foregroundbecause “focused” is reserved for element-level keyboard focus (Element.focused) elsewhere in the API; this is the foreground-application flag. Populated for apps obtained vialist()andfind(). A point-in-time snapshot taken when theAppwas resolved.Tagging is window-precise. On Windows apps surface as one synthesized
Applicationnode per process, so a pid match there is unambiguous; on Linux the AT-SPI registry can surface several entries for one pid, and only the entry reporting the window-levelactiveflag getsis_foreground. Useforeground()to resolve the foreground application directly, then pick the exact foreground window from itswindows().
- property name: str
- property pid: int | None
- class xa11y.Element
A live element with lazy navigation.
- activate() None
Activate this window: bring it to the foreground and give it focus.
- blur() None
Remove keyboard focus from this element.
- close() None
Close this window.
- collapse() None
Collapse this element.
- decrement() None
Decrement this element’s value.
- dump(max_depth: int | None = None) str
Render the subtree rooted at this element as an indented string.
Returns the string without printing. Same depth semantics as
tree(). Useful as a first step when writing a test against an unfamiliar app — callprint(app.dump())to discover the role and name of every element, then turn those into selectors.For the same output from the shell, use
xa11y tree --app NAME.
- enter_fullscreen() None
Put this window in native fullscreen (macOS
AXFullScreen).Distinct from
maximize;restoreleaves fullscreen. RaisesActionNotSupportedErroron platforms with no fullscreen accessibility API (Windows/Linux).
- expand() None
Expand this element (e.g. tree node, combo box).
- focus() None
Move keyboard focus to this element.
- increment() None
Increment this element’s value (e.g. slider, spinner).
- maximize() None
Maximize this window.
Distinct from
enter_fullscreen: this drives the platform’s maximized state, not native fullscreen. RaisesActionNotSupportedErroron a platform without an accessible maximize (macOS exposes no readable or writable zoom state).
- minimize() None
Minimize this window.
- move_to(x: int, y: int) None
Move this window to the given logical screen coordinates (top-left origin).
- perform_action(action: str) None
Perform an action by
snake_casename.
- press() None
Click / invoke this element.
- resize_to(width: int, height: int) None
Resize this window to the given logical width and height.
Raises
InvalidActionDataErrorif either dimension is 0.OverflowErrorif either is negative or exceedsu32.
- restore() None
Restore this window to its normal state (from minimized/maximized/fullscreen).
- scroll_into_view() None
Scroll this element into view.
- select() None
Select this element (e.g. list item, tab).
- select_text(start: int, end: int) None
Select the text range from
starttoend(0-based offsets).
- set_numeric_value(value: float) None
Set this element’s numeric value.
- set_value(value: str) None
Replace this element’s text value.
Show this element’s context menu.
- subscribe() Subscription
Subscribe to accessibility events for this element (typically an app).
- toggle() None
Toggle this element’s checked state.
- tree(max_depth: int | None = None) dict
Capture the subtree rooted at this element as a recursive dict snapshot.
Each dict has keys
role,name,value, andchildren(a list of dicts with the same shape).max_depthlimits traversal:0= only this node,1= node + direct children,None= full subtree.Use this when you need to inspect or analyze the tree programmatically. For an indented human-readable string, see
dump(). For ad-hoc exploration from the shell, see thexa11y treeCLI command.
- type_text(text: str) None
Insert text at the current cursor position.
- property actions: list[str]
- property active: bool
Whether this element is the active (foreground) window.
The window that currently receives the user’s input. Meaningful for window-like elements (windows, dialogs);
Falseelsewhere. Distinct fromfocused, which is element-level keyboard focus.
- property busy: bool
- property checked: str | None
Tri-state toggle value:
'on','off','mixed', orNone.Nonemeans the element has no checked state (it is not a checkbox / radio button / toggle). These four are the only possible values. Compare against them explicitly —bool(element.checked)isTruefor every non-Nonevalue, including'off':is_checked = element.checked == "on"
- property description: str | None
- property editable: bool
- property enabled: bool
- property expanded: bool | None
- property focusable: bool
- property focused: bool
- property fullscreen: bool | None
Whether the window is fullscreen.
None= unknown / not a window.
- property max_value: float | None
- property maximized: bool | None
Whether the window is maximized.
None= unknown / not a window.
- property min_value: float | None
- property minimized: bool | None
Whether the window is minimized.
Nonemeans unknown (the element is not a window, or the platform cannot report the state). Never a guessedFalse.
- property modal: bool
- property name: str | None
- property numeric_value: float | None
- property pid: int | None
- property raw: dict[str, object]
Platform-specific raw data attached to this element.
Keys are provider-defined (e.g.
"ax_role"on macOS,"uia_control_type"on Windows). Values are JSON-compatible (strings, numbers, booleans, lists, nested dicts). Intended for debugging and platform-specific queries — prefer the cross-platform fields (role,name, etc.) for portable logic.
- property required: bool
- property role: str
- property selected: bool
- property stable_id: str | None
- property value: str | None
- property visible: bool
- class xa11y.Event
An accessibility event delivered to subscribers.
- property app_name: str
- property app_pid: int
- property event_type: str
- property state_flag: str | None
For
state_changedevents: the flag that changed (e.g.'checked').Nonefor other event types.
- property state_value: bool | None
For
state_changedevents: the new boolean value of the flag.Nonefor other event types.
- class xa11y.EventType
Accessibility event type constants.
Each constant’s value is the string carried in
Event.event_type, so handlers can compare against the constant or the literal string interchangeably.- ANNOUNCEMENT: str = 'announcement'
- FOCUS_CHANGED: str = 'focus_changed'
- MENU_CLOSED: str = 'menu_closed'
- MENU_OPENED: str = 'menu_opened'
- NAME_CHANGED: str = 'name_changed'
- SELECTION_CHANGED: str = 'selection_changed'
- STATE_CHANGED: str = 'state_changed'
- STRUCTURE_CHANGED: str = 'structure_changed'
- TEXT_CHANGED: str = 'text_changed'
- VALUE_CHANGED: str = 'value_changed'
- WINDOW_ACTIVATED: str = 'window_activated'
- WINDOW_CLOSED: str = 'window_closed'
- WINDOW_DEACTIVATED: str = 'window_deactivated'
- WINDOW_OPENED: str = 'window_opened'
- class xa11y.InputSim
Input-simulation façade for synthesised pointer and keyboard events.
Targets are either a
(x, y)tuple in logical screen coordinates (same space asElement.bounds), or anElement(uses its bounds centre); each backend converts to physical device pixels at the OS boundary. Key values are strings: printable characters are literal ("a","7",";"); named keys use their Pascal name ("Enter","ArrowUp","F5"); modifiers are"Shift","Ctrl","Alt","Meta".Input simulation is distinct from the accessibility action layer — prefer
Locator.press()/Locator.type_text()when the target exposes the semantic action. UseInputSimfor gestures with no a11y equivalent (drag-and-drop, scroll wheels, global shortcuts).- chord(key: str, held: list[str] = ...) None
Tap
keywhile the keys inheldare held down.
- click(target: tuple[int, int] | Element, *, button: MouseButtonName = 'left', count: int = 1, held: list[str] | None = None, anchor: AnchorName | tuple[int, int] | None = None) None
Click at
target.buttonselects the mouse button,countrepeats the click (2= double-click),heldlists keys held down for the duration, andanchorpicks the point inside anElement’s bounds — a named anchor or an(dx, dy)offset from its top-left corner.anchoris ignored whentargetis a raw tuple.
- drag(start: tuple[int, int] | Element, end: tuple[int, int] | Element, *, button: MouseButtonName = 'left', held: list[str] | None = None, duration: float = 0.15) None
Drag from
starttoend.buttonselects the button held during the drag,heldlists keys held for its duration, anddurationis the total drag time in seconds.
- key_down(key: str) None
Press
keywithout releasing it. Pair withkey_up().For a whole tap use
press(); to hold modifiers around one tap usechord(). This is the primitive for sequences neither expresses, such as holding a key across several other actions.
- key_up(key: str) None
Release a key previously pressed with
key_down().
- mouse_down(button: MouseButtonName = 'left') None
Press a mouse button at the current pointer location, without releasing it.
Pair with
mouse_up(); for a whole click useclick(). Takes no target — the button is pressed wherever the pointer already is, so callmove_to()first to position it.
- mouse_up(button: MouseButtonName = 'left') None
Release a mouse button at the current pointer location.
- move_to(target: tuple[int, int] | Element) None
Move the pointer to
targetwithout pressing any button.
- press(key: str) None
Tap a key (press + release).
- scroll(target: tuple[int, int] | Element, dx: int = 0, dy: int = 0) None
Scroll at
target.dxpositive → right,dypositive → down.
- type_text(text: str) None
Type literal text into the currently focused control.
- class xa11y.LegendEntry
One drawn annotation box: the tag in the image, and the element it came from.
A model reads a tag off the PNG;
selectoris what acts on the element that tag labels:entry = next(e for e in shot.legend if e.tag == "B1") app.locator(entry.selector).set_value("42")
- property color: tuple[int, int, int]
The box colour as an
(r, g, b)tuple, for correlating a box with its entry by eye.
- property group: int
1-based, matching the position of this element’s locator in
annotate=.
- property name: str | None
The element’s accessible name, when it has one.
- property role: str
The element’s role, snake_case as everywhere else.
- property selector: str
A selector usable as-is against the same scope the group had —
"button:nth(7)".
- property tag: str
What is drawn in the box —
"B7". A group letter and a 1-based index, with no separator that downscaling could lose.
- class xa11y.Locator
A resilient element reference that re-queries on each interaction.
Locators never hold a live reference to a UI element. Instead, they store a selector and resolve it on demand, making them immune to staleness. Action methods auto-wait for the element to appear before acting, using the process-wide default timeout (5 seconds unless overridden via
set_default_timeout()or theXA11Y_DEFAULT_TIMEOUTenvironment variable).wait_*methods use the same default when no explicittimeout=is passed.- activate() None
Activate the matched window: bring it to the foreground and give it focus.
- blur() None
Remove keyboard focus from the matched element.
- close() None
Close the matched window.
- collapse() None
Collapse the matched element.
- count() int
Count matching elements.
- decrement() None
Decrement the matched element (slider, spinner).
- dump(max_depth: int | None = None) str
Render the subtree rooted at the matched element as an indented string.
Returns the string without printing it. Same depth and resolution semantics as
tree().
- enter_fullscreen() None
Put the matched window in native fullscreen.
Distinct from
maximize;restoreleaves fullscreen.
- exists() bool
Check if a matching element exists.
- expand() None
Expand the matched element.
- focus() None
Set keyboard focus on the matched element.
- increment() None
Increment the matched element (slider, spinner).
- maximize() None
Maximize the matched window.
Distinct from
enter_fullscreen: this drives the platform’s maximized state, not native fullscreen.
- minimize() None
Minimize the matched window.
- move_to(x: int, y: int) None
Move the matched window to the given logical screen coordinates (top-left origin).
- perform_action(action: str) None
Perform an action by snake_case name.
- press() None
Click / invoke the matched element.
- resize_to(width: int, height: int) None
Resize the matched window to the given logical dimensions.
Raises
InvalidActionDataErrorif either dimension is 0, before any auto-wait polling begins.OverflowErrorif either is negative or exceedsu32.
- restore() None
Restore the matched window to its normal state (from minimized, maximized, or fullscreen).
This is the inverse of
minimize,maximize, andenter_fullscreen: it clears every special state the platform can clear. There is deliberately no separate “exit fullscreen” method — leaving fullscreen is the same absolute state write this performs.
- scroll_into_view() None
Scroll the matched element into the visible area.
- select() None
Select the matched element (list item, tab, etc.).
- select_text(start: int, end: int) None
Select a text range within the matched element (0-based offsets).
- set_numeric_value(value: float) None
Set the numeric value of the matched element (slider, spinner).
- set_value(value: str) None
Set the text value of the matched element.
Show the context menu for the matched element.
- toggle() None
Toggle the matched element (checkbox, switch).
- tree(max_depth: int | None = None) dict
Capture the subtree rooted at the matched element as a recursive dict.
Each dict has keys
role,name,value, andchildren(a list of dicts with the same shape).max_depthlimits traversal:0= only this node,1= node + direct children,None= full subtree.Resolves the selector once; fails fast with
SelectorNotMatchedErrorif no match — does not auto-wait.
- type_text(text: str) None
Type text at the current cursor position on the matched element.
- wait_detached(timeout: float | None = None) None
Wait until the element is removed from the tree.
Wait until the element is hidden or removed.
- wait_unfocused(timeout: float | None = None) Element
Wait until the element does not have keyboard focus.
- wait_until(predicate: collections.abc.Callable[[Element | None], bool], timeout: float | None = None) None
Wait until an arbitrary predicate is satisfied.
A predicate that raises aborts the wait immediately and propagates the exception — it is not swallowed as “not yet” (which would resurface later as a misleading timeout). Mirrors
App.find.
- wait_visible(timeout: float | None = None) Element
Wait until the element is visible, polling the provider.
timeout=None(the default) uses the process-wide default timeout — seeset_default_timeout(). Applies to allwait_*methods.
- property selector: str
The CSS-like selector string for this locator.
- class xa11y.Omission
An element that matched an
annotate=selector but is not in the image.Reported rather than dropped: a legend that disagreed with the picture, with no way to find out why, is what this exists to prevent.
- property name: str | None
The element’s accessible name, when it has one.
- property reason: OmissionReasonName
Why it could not be drawn: no bounds at all, zero-area bounds, or bounds outside what was captured (a second monitor, or outside an explicit
region).
- property role: str
The element’s role, snake_case.
- property selector: str
The selector that would reach this element.
- class xa11y.Rect
A bounding rectangle in logical screen coordinates (device-independent points) on every platform, origin at the top-left of the primary display.
Same coordinate space as
screenshot(region=...)and input targets, so bounds pass straight through. To index into a captured image multiply by the screenshot’sscale(physical = logical * scale).- property height: int
- property width: int
- property x: int
- property y: int
- class xa11y.Screenshot
A captured image: raw RGBA8 pixels plus dimensions and mapping.
widthandheightdescribe the actual returned image.scaleis a compatibility hint for simple single-display captures; use the explicit coordinate methods for mixed-DPI, cropped, or resized images.pixelshas lengthwidth * height * 4.legend,omittedandtruncateddescribe whatannotate=drew. They are[],[]and0on an unannotated capture, so consumers need no version check.- crop(x: int, y: int, width: int, height: int) Screenshot
Crop by image pixels while preserving coordinate mapping.
- desktop_rect_to_image(x: int, y: int, width: int, height: int) list[Rect]
Convert a desktop rectangle to one image rectangle per display piece.
- desktop_to_image(x: int, y: int) tuple[int, int]
Convert a desktop point to a pixel in this image.
- image_to_desktop(x: int, y: int) tuple[int, int]
Convert an image pixel to a desktop point suitable for input.
- resize(width: int, height: int) Screenshot
Resize image pixels while scaling coordinate mapping.
- save_png(path: str | bytes | object) None
Encode as PNG and write to
path. Acceptsstr,bytesoros.PathLike.
- to_png() bytes
Encode the image as a PNG and return the bytes.
- property height: int
- property legend: list[LegendEntry]
One entry per drawn box, in group order and then match order.
- property mapping_available: bool
Whether desktop/image coordinate conversion metadata is available.
- property omitted: list[Omission]
Elements that matched an
annotate=selector but could not be drawn, each with the reason.
- property pixels: bytes
Raw RGBA8 pixel bytes (
width * height * 4).
- property scale: float
- property truncated: int
How many matched elements were not described at all because the annotation cap was reached.
0when the cap did not bite.
- property width: int
- class xa11y.ShellSurface
One OS-owned shell surface — the taskbar, a desktop panel, the dock, the menu bar, a process’s status items, the desktop, or an open flyout.
ShellSurfaceis not anElement. It represents the surface as a whole and provides alocator()to search its accessibility tree, exactly asAppdoes for an application.- as_element() Element
Get an
Elementhandle for the surface root.Useful for invoking Element-level methods (
children(),parent(), etc.) without going through a locator.
- static by_kind(kind: ShellSurfaceKindName, *, timeout: float | None = None) ShellSurface
Wait for exactly one shell surface of
kind.kindis the snake_case kind name —ShellSurfaceKindNameabove is the full set, and is the only place this file spells them out. An unknown name raisesValueErrorbefore the accessibility API is touched.Polls until a single surface of that kind exists or
timeout(seconds) elapses — seeApp.by_namefortimeoutsemantics. The wait is what makes the Windows overflow workflow a one-liner: press the taskbar’s “Show Hidden Icons” button, then wait for the flyout:taskbar = xa11y.ShellSurface.by_kind("taskbar", timeout=0) taskbar.locator("button[name='Show Hidden Icons']").press() flyout = xa11y.ShellSurface.by_kind("flyout", timeout=3.0)
Raises
SelectorNotMatchedErrorboth when no surface of that kind is present and when several are — ambiguity is refused rather than first-matched, with the candidates on the exception’scandidatesattribute so the caller can disambiguate vialist()and a pid.
- dump(max_depth: int | None = None) str
Render this surface’s accessibility tree as an indented string.
Returns the string without printing it. Same depth semantics as
tree(). This is the primary inspection helper — callprint(surface.dump())to discover the role and name of every element in the surface before writing selectors.
- static list() list[ShellSurface]
List the OS shell surfaces currently on screen.
Single enumeration, no polling. The listing is live:
flyoutsurfaces appear only while they are open, and enumerating never opens, closes, focuses, or presses anything. A platform with no surface of a given kind simply returns none — that is honest scope, not a failure.
- tree(max_depth: int | None = None) dict
Capture this surface’s accessibility tree as a recursive dict.
Each dict has keys
role,name,value, andchildren(a list of dicts with the same shape).max_depthlimits traversal:0= only the surface root,1= root + direct children,None= full subtree.
- property kind: ShellSurfaceKindName
What this surface is, as a snake_case string (
"taskbar","status_items", …). The same spelling in both bindings, in the CLI’s--shellflag, and in theshell_kindraw attribute on the surface root.
- property name: str
The owning app for per-app surfaces (
"Safari"menu bar), the platform’s own name otherwise ("Taskbar","Dock"). Falls back to the kind when the platform vends no name for the root.
- property pid: int | None
Owning process where the platform reports one honestly. On Windows this is the shell host (explorer.exe), because UIA carries no per-icon owner — documented as the host, never faked.
- xa11y.get_default_timeout() float
Get the effective process-wide default timeout, in seconds.
Resolution order: the
set_default_timeout()value, else theXA11Y_DEFAULT_TIMEOUTenvironment variable, else the built-in 5.0.
- xa11y.screenshot(*, element: Element | None = None, region: tuple[int, int, int, int] | None = None, annotate: list[Locator | str] | None = None) Screenshot
Capture pixels from the screen.
With no arguments, captures the full primary display. Pass
elementto capture the pixels under an element’s current bounds, orregionas(x, y, width, height)to capture an explicit rectangle in logical screen coordinates. Passing both raisesValueError.annotatedraws a numbered box over every element each locator matches, and fills inScreenshot.legend,Screenshot.omittedandScreenshot.truncated. Each entry is one group, with its own colour and tag letter, and must be scoped to an application:app.locator("button"). An entry that is neither aLocatornor astrraisesTypeError.A rootless group raises
InvalidSelectorError— a barestr, orlocator(), searches every application, and each entry’s<selector>:nth(n)would then count within one application while the legend counts across all of them. The two agree only for a single application, so the selector on an entry would name a different element than the box it labels.Cropping and annotating are independent: annotations outside the captured area land in
omittedrather than being clamped to an edge.- shot = xa11y.screenshot(
element=app.locator(“window”).element(), annotate=[app.locator(“button”), app.locator(“text_field”)],
)
- xa11y.set_default_timeout(timeout: float) None
Set the process-wide default timeout, in seconds.
Becomes the default for every auto-waiting action method,
wait_*call, and app lookup (App.by_name/App.by_pid/App.find) that doesn’t pass an explicittimeout=. An explicit per-calltimeout=always wins. Takes precedence over theXA11Y_DEFAULT_TIMEOUTenvironment variable (seconds, read once at import).Pass
0for “single attempt, no polling” semantics. RaisesValueErrorfor negative or non-finite values.