Skip to main content
Read the accessibility hierarchy that the current app exposes to assistive technology. The CLI, TypeScript SDK, REST API, and React embed return the same versioned tree for iOS Simulator and Android Emulator sessions. Each read is a point-in-time snapshot. Read again after a tap, navigation, text change, or toggle to assert the new visible state. The operation is read-only: it cannot execute commands or reach a different device.

Install and authenticate

Install the CLI, sign in, and verify the active account:
For the TypeScript SDK, install the package and set an API key created in the run.cloud dashboard:
API keys belong in server-side code and CI secrets. Never put one in a browser bundle. The React package uses the signed session URL instead:

CLI

Create a session with a compatible app, keep its id, and release it when the shell exits:
Omit --json for an indented terminal view with roles, labels, identifiers, values, states, bounds, and children. accessibility is a shorter alias for accessibility-tree. Use --timeout <milliseconds> to set a client wait from 100 to 60,000 milliseconds; the default is 20,000.

TypeScript SDK

accessibilityTree is available on both platform clients. This complete iOS example installs an existing asset, reads the tree, changes the app, and reads again:
The Android form is identical apart from the platform client and asset:
Use cloud.simulators.accessibilityTree(id, { platform }) when the platform is chosen at runtime. Passing an AbortSignal stops the caller from waiting and does not release the session.

React embed

The signed viewer can read the same tree without exposing an API key to the browser. Keep the component and request bound to the same session URL:
The promise only accepts a response from the exact current iframe window and origin. It rejects with RemoteControlAccessibilityError for typed simulator failures, and with AbortError if its signal, iframe, or component lifecycle cancels the wait. onAccessibilityResult observes validated successes and failures.

Response schema

Every successful read returns SimulatorAccessibilitySnapshot:
Every node has a stable shape: Normalized roles are application, window, dialog, alert, group, scroll-view, list, list-item, text, heading, button, link, image, text-field, checkbox, switch, radio-button, slider, progress-indicator, tab, tab-bar, toolbar, menu, menu-item, web-view, keyboard, and other. states contains enabled, focused, selected, checked, expanded, focusable, clickable, scrollable, editable, and secure. checked is true, false, "mixed", or null. For iOS, native contains type, roleDescription, subrole, title, and help. For Android, it contains className, packageName, resourceId, contentDescription, checkable, longClickable, and password.

Accessibility assertions

Assert meaningful semantics instead of snapshotting the entire JSON document. This keeps tests useful when system containers or framework-generated nodes change:
Use role and label assertions for user-facing semantics, identifiers for app elements that you control, state assertions after interactions, bounds for visual placement, and child relationships for grouping and navigation order.

Authentication and failures

The API accepts only an active session owned by an organization available to the authenticated credential. Released sessions, expired credentials, wrong platform paths, and sessions owned by another organization fail without contacting another device. A signed viewer URL is scoped to its current device and lease; it cannot request a tree from a replacement lease or another iframe. SDK failures are RunCloudError values with stable codes such as active_session_not_found, simulator_session_ended, accessibility_unavailable, accessibility_timeout, accessibility_transport_error, and accessibility_invalid_response. The authenticated REST endpoint is:
For example:

Limits

  • A snapshot contains at most 500 nodes and 80 levels. Check truncated before treating absence as an assertion.
  • The tree reflects accessible elements, not every rendered view. Hidden, decorative, or accessibility-disabled elements may be absent.
  • Platform accessibility frameworks decide containment. UIKit commonly omits layout-only UIView and UIStackView containers, so visually grouped iOS controls can be direct children of the application node. Android often keeps layout containers in its source hierarchy. children preserves the source relationship; run.cloud does not infer groups from screen position.
  • iOS bounds are points. Android bounds are physical display pixels. Convert through screen.width and screen.height before using normalized tap coordinates.
  • Platform frameworks decide some roles and states. Keep the documented native fields when a normalized role is too broad for a platform-specific assertion.
  • IDs are unique within a snapshot. Framework-generated id and path values can change when the hierarchy changes; prefer an app-owned identifier.
  • Animated transitions and asynchronously rendered screens can produce an intermediate snapshot. Wait for an app-visible readiness condition, then read again.
  • Secure text field values are redacted at capture and every public validation boundary. The response reports states.secure: true and value: null.