Skip to main content
Mobilerun can inspect a device’s network traffic and stream decoded HTTP/1.1, HTTP/2, HTTP/3, and application WebSocket events to your local machine. The stream is live-only and does not require adb or direct access to the device. Unlike the ADB and Frida tunnels, network inspection is session-based. You start a session with the REST API, connect to the returned WebSocket with either your API key or the device’s existing stream token, and stop the session when you are finished.

Requirements

Network inspection must be enabled for the device’s hosting pool. Contact Mobilerun support at contact@mobilerun.ai if you need access.
Set the API key and device ID in your shell:
Check whether the device supports network inspection:
The value must be true. The capability is granted when a device is placed in an enabled pool. Disabling inspection for that pool also prevents new sessions and stops active sessions.

Endpoints

Use your Mobilerun API key for the REST endpoints. Non-browser WebSocket clients also authenticate with that API key. Browser clients, which cannot set an Authorization header on WebSocket, use the existing device stream token returned in stream.token as a token query parameter. Always start with the returned stream.url instead of constructing the path yourself.

Start an inspection session

Create a session with a unique Idempotency-Key so retrying the same request does not start another session:
Only one session can be starting, active, or stopping for a device at a time. Starting another returns 409 TRAFFIC_ALREADY_ACTIVE.

Wait until the session is active

Starting inspection is asynchronous. Poll the status endpoint until the device producer is ready:
While the session is starting or active, the status response returns the device’s existing stream token. This is the same device-bound credential used by other device WebSocket endpoints; it is not a traffic-specific or session-scoped viewer token. It is revoked when the device is terminated and rotates when device ownership changes. Treat it as a secret and do not log URLs containing it.

Stream events with websocat

Open the returned WebSocket URL with your Mobilerun API key and the required subprotocol:
Do not send stream.token as a Bearer token. For non-browser clients, the Bearer credential is your dr_sk_... API key. The websocat options keep large JSON events intact when piping them into jq, including on macOS.

Browser WebSocket clients

The browser WebSocket API cannot set an Authorization header. Add the returned device stream token to the returned URL instead:
The edge authenticates the query token against the device before forwarding the WebSocket upgrade. Devices API then verifies that the traffic session belongs to the same device owner and is still starting or active. Exercise the app on the device while this command is running. Each line is a JSON event. The first event is hello; subsequent event types are:

Event schema

Stream hello

The gateway sends a hello message immediately after the WebSocket opens. This message uses camelCase fields and is separate from the device event envelope:

Device event envelope

All subsequent device events use snake_case fields: The ingest boundary rejects undeclared or duplicate fields, malformed Base64, negative numeric values, and payloads that exceed the session body limit. A ready event has no additional fields:

Flow events

A flow event adds a flow object. Only id and decryption_status are always present; other fields can be omitted or null when an interception fails before that information is available.
There is no combined url field. Construct one from scheme, host, optional port, and path if your parser needs it. A null body field means that no body bytes were captured. Use the corresponding *_body_bytes and *_body_truncated fields to distinguish an empty body from one clipped by the session limit.

WebSocket message events

Application WebSocket messages refer back to their HTTP upgrade flow by flow_id:

Gap events

A gap event reports that the device queue dropped one or more events:
dropped_events is a required positive integer. The event does not identify which flows or messages were dropped. For example, decode response bodies with jq:
Inspected headers and bodies can contain credentials, personal data, and other secrets. Mobilerun does not retain session events, but anything you print, pipe, or redirect locally may be stored on your machine.

Interception behavior

Inspection is transparent at the device-networking layer. You do not need to configure an HTTP proxy in the app or Android settings. Starting a session temporarily installs the capture CA and reconfigures the device’s existing TUN routing; stopping the session restores the previous routing and trust-store mounts. Android’s global http_proxy setting is neither required nor modified. Certificate pinning is not bypassed. A pinned app can reject the inspection certificate before an HTTP request is available, causing the connection to fail without a decoded flow. If the failure reaches the HTTP flow pipeline, the stream reports decryption_status: "failed" with an error, but clients should not assume every rejected TLS handshake produces an event. Keep using an authorized Frida pinning bypass, or equivalent instrumentation for a native or custom trust store, when inspecting pinned apps.

Stop the session

Stop inspection when you are finished so the device can restore its normal routing and temporary trust changes:
The request returns 202 Accepted while cleanup runs. Repeating it is safe. Sessions also stop automatically when they expire.

Troubleshooting

  • TRAFFIC_NOT_SUPPORTED — The device image does not support network inspection.
  • TRAFFIC_NOT_ENTITLEDcapabilities.trafficInspection is false; create a device in an enabled pool or contact support.
  • TRAFFIC_ALREADY_ACTIVE — Another session is starting, active, or stopping. Use the session ID in details.sessionId, or list sessions with GET /devices/{deviceId}/traffic/sessions.
  • TRAFFIC_DEVICE_NOT_READY — Wait until the device reaches the ready state and retry with the same idempotency key.
  • 401 Unauthorized on the WebSocket — For CLI clients, send your dr_sk_... API key as Authorization: Bearer .... For browsers, append the returned stream.token as the URL’s token query parameter. Do not send stream.token as a Bearer token.
  • WebSocket subprotocol error — Send Sec-WebSocket-Protocol: mobilerun.traffic.v1 with either authentication method.
  • Incoming message too long or a jq parse error — Increase websocat’s message buffer with -B; do not use -S, because strict mode drops oversized inspection events. Use --no-async-stdio when piping large messages on macOS.
  • The socket closed with 1013 — Reconnect with the same authentication method. Read the session status again first if the device may have been transferred or replaced. Missed events are not replayed.