> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mobilerun.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# ADB

> Run your local adb or Frida client against a Mobilerun cloud device through a WebSocket tunnel.

Mobilerun can expose each device over WebSocket endpoints that speak the `adb` transport protocol and, on supported devices, the Frida transport. Bridge your local client to the tunnel and you can use familiar workflows against a cloud device, without installing anything on the device itself:

* `adb shell`, `adb install`, `adb push`, `adb pull`, `adb forward` over the adb tunnel.
* `frida`, `frida-ps`, `frida-trace`, and any Frida-based tooling over the Frida tunnel.

The adb tunnel is **command-filtered**: an in-line proxy inspects every adb service request and only permits the families needed for ordinary debugging. Full, unfiltered access (including root) can be granted on request. The Frida tunnel is a raw byte pipe that carries the Frida transport verbatim to the device's Frida server.

## Requirements

<Note>
  adb and Frida access are only available on request. Contact Mobilerun support at [contact@mobilerun.ai](mailto:contact@mobilerun.ai) to have them enabled for your account.
</Note>

* A Mobilerun [API key](/api-keys) (`dr_sk_...`)
* A device in the `ready` state (see [Devices](/devices))
* `adb` installed locally (Android SDK platform-tools) for the adb tunnel
* Frida installed locally (`frida-tools`) for the Frida tunnel, on a device whose `capabilities.frida` is `true`
* A WebSocket-to-TCP bridge such as [`websocat`](https://github.com/vi/websocat)

Check whether a device supports Frida before opening the Frida tunnel:

```bash theme={null}
curl -H "Authorization: Bearer $MOBILERUN_API_KEY" \
  https://api.mobilerun.ai/v1/devices/$DEVICE_ID/capabilities
```

`capabilities.frida` is `true` for devices created in a Frida-enabled pool and `false` otherwise. The value is frozen at device creation, so toggling the pool setting later does not change existing devices.

## Endpoints

```
wss://api.mobilerun.ai/v1/devices/{deviceId}/adb
wss://api.mobilerun.ai/v1/devices/{deviceId}/frida
```

| Parameter  | Description                                                                |
| ---------- | -------------------------------------------------------------------------- |
| `deviceId` | UUID of a device you own. List devices with `GET /v1/devices?state=ready`. |

Authenticate with the same `Authorization: Bearer dr_sk_...` header you use for the REST API. You must own the device and it must be in the `ready` state, or the upgrade is rejected before the WebSocket opens. The Frida endpoint additionally requires `capabilities.frida` to be `true`.

## Connect your local adb client

The adb endpoint speaks the raw adb transport, so your local `adb` daemon needs a TCP socket on the other end. The simplest setup pipes the WebSocket through `websocat` to a local port, then attaches `adb` to that port.

```bash theme={null}
# 1. Bridge the WebSocket to localhost:5037-style TCP
websocat \
  --binary tcp-listen:127.0.0.1:7777 \
  "wss://api.mobilerun.ai/v1/devices/$DEVICE_ID/adb" \
  -H "Authorization: Bearer $MOBILERUN_API_KEY"

# 2. In another terminal, attach adb and use it normally
adb connect 127.0.0.1:7777
adb -s 127.0.0.1:7777 shell getprop ro.product.model
adb -s 127.0.0.1:7777 install ./app-release.apk
adb -s 127.0.0.1:7777 push ./data.bin /sdcard/Download/
```

<Tip>
  Each WebSocket connection carries a single adb transport. Open one tunnel per device, and let `adb` multiplex shells, file transfers, and forwards over it.
</Tip>

## Connect your local Frida client

Frida's client speaks its own transport over TCP. Bridge the WebSocket to a local port, then point Frida at that port with `-H`.

```bash theme={null}
# 1. Bridge the WebSocket to a local TCP port
websocat \
  --binary tcp-listen:127.0.0.1:27042 \
  "wss://api.mobilerun.ai/v1/devices/$DEVICE_ID/frida" \
  -H "Authorization: Bearer $MOBILERUN_API_KEY"

# 2. In another terminal, run Frida against the local bridge
frida-ps -H 127.0.0.1:27042
frida -H 127.0.0.1:27042 -n com.example.app
frida-trace -H 127.0.0.1:27042 -i "open" com.example.app
```

<Tip>
  Each WebSocket connection carries a single Frida session transport. Open one tunnel per device and let Frida multiplex scripts and RPC calls over it.
</Tip>

## Access policy

By default, the adb tunnel is filtered so that everyday debugging workflows (shells, installs, file transfers, port forwards, app debugging, screenshots) pass through, while requests that would restart `adbd`, take the device offline, or mutate global device state are refused. Blocked requests fail with an in-stream error visible to your `adb` client.

Full, unfiltered access — including `adb root` — can be granted per-account on request. Contact [contact@mobilerun.ai](mailto:contact@mobilerun.ai) if you need it.

## Troubleshooting

* **`400 Bad Request` on the Frida upgrade** — The device does not support Frida (`capabilities.frida` is `false`). Provision a device in a Frida-enabled pool.
* **`401 Unauthorized` on upgrade** — Check your `Authorization` header and that the API key has access to the device.
* **`409` or `412` on upgrade** — The device is not in the `ready` state. List devices with `?state=ready` and pick one that is available.
* **`adb` reports `closed`** — The service you tried to open is denied by the policy. Look at the bridge's stderr for the plaintext reason; switch to an allowed family (e.g. use `adb shell svc` instead of `adb root`).
* **Nested adb is refused** — Forwarding to port `5555` or to the device's own adb port is intentionally blocked. Use the outer tunnel directly.
* **Frida reports the server is unreachable** — The device's Frida server did not start. Confirm `capabilities.frida` is `true` on the device and retry, or contact support.
