> ## 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.

# Port Forwarding

> Reach arbitrary TCP services on a Mobilerun device through a WebSocket tunnel or an HTTP reverse proxy.

Mobilerun exposes a per-device port-forwarding endpoint that bridges to any TCP service listening on the device. You can connect with either a raw WebSocket tunnel (for arbitrary TCP traffic) or a transparent HTTP reverse proxy (for HTTP services), without managing your own ADB forwards.

Use this when you want to talk to an app, web server, debugger, or other service running on the device — for example, a local HTTP server inside a test build, an Appium endpoint, or a custom inspector.

## Endpoints

Both endpoints are scoped to a device and a target port on the device.

**WebSocket tunnel** — binary frames are forwarded to and from the device TCP port:

```text theme={null}
wss://api.mobilerun.ai/v1/devices/{deviceId}/ports/{port}
```

**HTTP reverse proxy** — preserves method, path, and body and streams the response back:

```text theme={null}
https://api.mobilerun.ai/v1/devices/{deviceId}/ports/{port}/{path}
```

### Authentication

Pass your Mobilerun API key as a request header:

```text theme={null}
Authorization: Bearer dr_sk_YOUR_API_KEY
```

<Warning>
  Always send credentials as headers. The proxy strips `Authorization` and `X-Device-Token` from forwarded HTTP requests so your key is never sent to the on-device service.
</Warning>

### Requirements

* The device must be in the `ready` state. See [Devices](/devices) for state details.
* The target service must be listening on the chosen TCP port on the device.
* You need a Mobilerun [API key](/api-keys).

## HTTP reverse proxy

Send any HTTP request to the device. Method, path, query string, headers (minus auth), and body are preserved. Redirects are not followed — you receive the device's response as-is.

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

The device sees a request to `GET /api/status` on its local port `8080`.

<Note>
  Request bodies are capped at 10 MB. Larger payloads are rejected before they reach the device.
</Note>

## WebSocket tunnel

Open a WebSocket and exchange binary frames with the device port. Each frame is written to the underlying TCP connection in order; bytes coming back from the device are delivered as binary frames.

```js theme={null}
import WebSocket from 'ws';

const ws = new WebSocket(
  `wss://api.mobilerun.ai/v1/devices/${deviceId}/ports/8080`,
  {
    headers: {
      Authorization: `Bearer ${process.env.MOBILERUN_API_KEY}`,
    },
  }
);

ws.on('open', () => ws.send(Buffer.from('hello\n')));
ws.on('message', (data) => console.log('from device:', data));
```

<Note>
  Individual WebSocket frames are capped at 10 MB. Chunk larger payloads across multiple frames.
</Note>

## Blocked ports

Forwarding to ports used by Mobilerun's own on-device agents is denied with `403 Forbidden`. The default blocklist covers adb, the device streaming bridge, the agent runtime, and the Frida server. Requests to other ports are passed through.

## Limitations

* **TCP only.** UDP services are not exposed.
* **Ready devices only.** Requests against devices in other states return an error before the tunnel is opened.
* **No redirect following.** The HTTP proxy returns the device's `3xx` response so your client can decide what to do.
