control_url,
and send DCP frames. This is the same socket the
SDK uses — here you speak to it directly.
The examples use Python’s websockets library, but nothing is Python-specific.
Any WebSocket client works.
Before you start
- An API key — create one in API Keys. See Authentication.
- A dedicated phone ID — choose an idle phone in
Phones or run
axilio phones list. - A WebSocket client. For the examples:
pip install axilio websockets.
1. Get a phone and its control URL
Allocate a phone through the REST API or the SDK. The allocation returns acontrol_url — a WebSocket scoped to this one session:
The
control_url is self-contained and embeds its credential, so you can
connect without extra headers. Pass it directly to your WebSocket client.
Never put it in logs, shell history, tickets, or chat, and do not cache it
across sessions. It stops working when the session ends.2. Open the socket and handshake
SendProtocol.handshake
first. It returns the phone’s protocol version, device descriptor, and the exact
set of methods it supports — gate your code on that instead of assuming:
3. Send a command
Commands are{ "id", "method", "params" }; the phone replies with
{ "id", "result" } on success or { "id", "error" } on failure. Tap a pixel:
4. Read the screen
Screen.observe returns the on-screen text and icons with their bounding
boxes — enough to decide where to tap next:
Correlating replies
Responses can arrive in any order, so match a reply to its command byid
instead of assuming the next frame is the answer. A frame with no id is a
notification, not a response. A small pattern: keep an outstanding-id map,
increment a counter per command, and resolve each reply against it. The
SDK does exactly this for you.
The idempotencyKey is separate from the request id. Generate one UUID per
logical Touch.* or Keyboard.* command. Reuse that key only if you must
resend the same command after a dropped connection. See
Reconnect and resume.
Next steps
Message reference
Every method, its params, its result, and the error shape.
Reconnect and resume
Handle close codes, cursors, replay, and safe resends.
Live telemetry
Stream the session’s Telemetry frames on a second socket.
Use the SDK instead
Selectors, waiting, and retries over DCP.