Authenticate and create a session
Install the CLI and sign in:Coordinate and input conventions
Points use normalized display coordinates. The top-left corner is{ x: 0, y: 0 }, the center is { x: 0.5, y: 0.5 }, and the bottom-right corner is
{ x: 1, y: 1 }. Both endpoints are valid. Coordinates follow the current
display orientation, so the same point always refers to the same visible part
of the screen after rotation.
swipe and gesture durations are in milliseconds. A gesture has 2 to 1,000
ordered steps, starts with begin, ends with end, and may have move steps
between them. Every step has either one point or two points, and the point count
cannot change during a gesture. delayMs is the wait before the next step; each
delay can be 0 to 5,000 milliseconds and their sum cannot exceed the request
timeout. The final end step has no next step, so omit its delay or set it to 0.
Swipe duration defaults to 300 milliseconds. Key and button holds default to 50
milliseconds. Scroll deltas are normalized from -1 to 1 and at least one axis
must be nonzero. Provide both x and y when anchoring a scroll. Digital Crown
delta must be nonzero and between -10,000 and 10,000.
typeText accepts 1 to 10,000 US ASCII characters, plus tabs and line feeds.
Use pressKey when the physical key matters. Modifiers are shift, control,
alt, and meta; each represents the left modifier key. A key or button hold
can last 20 to 30,000 milliseconds. Swipe duration can be 50 to 30,000
milliseconds.
CLI
Replaceios with android to use the same command on an Android session.
These commands return stable JSON with --json:
--timeout <milliseconds> from 100 to 60,000
(default 15,000), --request-id <id>, and --json. Request ids can contain
letters, numbers, ., _, :, and -, up to 128 characters.
Capture either platform as a PNG:
TypeScript SDK
Install the SDK on Node.js 20 or newer:interact method and named methods for every
action:
cloud.ios and cloud.android provide:
Interaction and screenshot options accept
requestId, timeoutMs, and signal.
Aborting a signal stops the caller from
waiting; it does not release the session and cannot undo an action that the
simulator has already accepted.
Use cloud.simulators when the platform is selected at runtime. Its methods
take the same arguments, plus { platform: "ios" | "android" } in the options
object.
REST API
Send an interaction to:platform is ios or android. Authenticate with the same bearer API key used
by the SDK:
requestId and timeoutMs to any action:
Screenshot is a separate binary endpoint on both platforms:
image/png for an active session owned by the authenticated user.
Send X-Run-Cloud-Request-ID with a 1-to-128-character correlation id. If you
omit it, the API generates one and returns it in the same response header.
Screenshot failures use the same JSON envelope as interactions, with
action: "screenshot" and a stable screenshot_* error code.
Acknowledgements and errors
A successful interaction returns HTTP 200 and a typed result:result object except reload,
toggleSoftwareKeyboard, and simulateMemoryWarning, which omit result.
Errors keep the same envelope in REST, SDK metadata, and CLI JSON:
invalid_interaction. A released, expired, or unknown
session uses active_session_not_found. An action outside the platform matrix
uses unsupported_action. Transport failures and timeouts are marked
retryable when another attempt may succeed. Check the HTTP status as well as
error.code; do not retry an invalid request or unsupported action.
Interaction codes are invalid_interaction, active_session_not_found,
simulator_capacity_unavailable, unsupported_action, duplicate_request,
interaction_cancelled, interaction_timeout, interaction_transport_error,
interaction_invalid_response, and interaction_failed. Screenshot codes are
invalid_screenshot_request, active_session_not_found,
simulator_capacity_unavailable, screenshot_cancelled, screenshot_timeout,
screenshot_transport_error, screenshot_invalid_response, and
screenshot_failed.
The CLI reports locally invalid arguments as a non-retryable invalid_request
JSON error before authenticating. The SDK rejects invalid arguments with
TypeError or RangeError before making a request.
The CLI writes the JSON error to stderr and exits nonzero. Pressing Ctrl-C while
an interaction is pending returns status cancelled, code
interaction_cancelled, and exit code 130. A CLI timeout returns status
timed_out and code interaction_timeout. Screenshot capture uses
screenshot_cancelled, screenshot_timeout, screenshot_transport_error, and
screenshot_invalid_response. Neither cancellation nor timeout releases the
session.
SDK API failures throw RunCloudError. Interaction failures can populate
code, retryable, details, requestId, sessionId, platform, action,
interactionStatus, acceptedAt, completedAt, and durationMs. A caller
AbortSignal rejects with its abort reason instead. For session creation,
isSimulatorCapacityError(error) narrows the exact retry-safe capacity 503;
other authentication, validation, and service errors do not match it.
Platform capabilities
Button support differs by device:
On iOS,
home, appSwitcher, and recents are momentary navigation actions;
durationMs does not turn them into long presses. Physical buttons honor the
requested hold duration on both platforms.
Render options are colorBlendedLayers, colorCopiedImages,
colorMisalignedImages, colorOffscreenRendered, and slowAnimations.
Orientations are portrait, portrait_upside_down, landscape_left, and
landscape_right. Current run.cloud iPhone Simulator sessions do not render
portrait_upside_down; the API, CLI, SDK, and iframe return a non-retryable
unsupported_action acknowledgement with the supported orientations. Android
Emulator sessions support all four values.
Semantic keys
All key names are case-sensitive:- letters:
a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z; - digits:
0,1,2,3,4,5,6,7,8,9; - editing:
enter,escape,backspace,tab,space,insert,delete; - punctuation:
minus,equal,bracketLeft,bracketRight,backslash,semicolon,quote,backquote,comma,period,slash; - navigation:
home,end,pageUp,pageDown,arrowRight,arrowLeft,arrowDown,arrowUp; - system and function:
capsLock,f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,printScreen,scrollLock,pause,numLock; - number pad:
numpadDivide,numpadMultiply,numpadSubtract,numpadAdd,numpadEnter,numpad0,numpad1,numpad2,numpad3,numpad4,numpad5,numpad6,numpad7,numpad8,numpad9,numpadDecimal.
unsupported_action for the lock-state keys
capsLock, numLock, and scrollLock. Other listed semantic keys are
available on both platforms.
Embedded viewer
The ReactRemoteControl handle exposes corresponding typed methods. The
acknowledged orientation and reload helpers are named setOrientation and
reloadApp to distinguish them from legacy fire-and-forget controls. It sends
each action through the signed iframe and resolves only when the matching
requestId result arrives:
type, requestId, and
timeoutMs:
type: "run-cloud:interaction-result", the matching
request id, platform, action, status, timing, and typed result or error fields.
Acknowledged results and failures always include valid acceptedAt,
completedAt, and durationMs timing. A browser-side timeout raised before any acknowledgement cannot
identify a platform. Verify both event.source and event.origin before
trusting a result. See
Embed a Simulator for a complete secure listener
and session lifecycle example. To stop pending work, post
{ type: "run-cloud:interaction-cancel", requestId, action } to the same exact
origin. Cancellation is best effort and cannot undo an action that completed.
Screenshot examples
The maintained examples build a small native app, create a session, install the app, capture a PNG, validate its dimensions, and release the session.screenshots/run-cloud-proof.png. Pass --open to open the signed
viewer while the example runs, or --app <path> to use a prebuilt artifact.
Building the iOS app requires macOS with Xcode. Building the Android app
requires JDK 17 or newer and Android SDK 35 or newer.
Source:
iOS screenshot example
and
Android screenshot example.