> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# iOS environment setup

Midscene connects to and controls iOS devices through WebDriverAgent (WDA), supporting UI automation across native apps, hybrid apps, and system interfaces.

This guide prepares the iOS environment: build and start WDA, then make it reachable from the computer that runs Midscene. Playground, Midscene Test, and the JavaScript SDK all use this connection.

## Connect the device through WDA {#connect-device}

Midscene communicates with iOS physical devices and simulators through a running WebDriverAgent (WDA) service. If WDA is already running and reachable from your computer, skip directly to [Verify the WDA service status](#verify-wda-status).

### Build and start WebDriverAgent

Before you begin, prepare the following iOS development environment:

- macOS (required for iOS development and device debugging)
- Xcode and Xcode Command Line Tools
- An iOS Simulator or physical iOS device

:::info Version requirement

WebDriverAgent version must be **>= 7.0.0**.

:::

Follow the official Appium documentation to build and start WebDriverAgent (WDA):

- **Simulator setup**: [Run Prebuilt WDA](https://appium.github.io/appium-xcuitest-driver/latest/guides/run-prebuilt-wda/)
- **Physical device setup**: [Real Device Configuration](https://appium.github.io/appium-xcuitest-driver/latest/getting-started/device-setup/)

### Configure a physical device and forward the port

iOS Simulators expose WDA directly on `localhost` and do not require port forwarding—if you are using a simulator or a remote WDA service, skip to [Verify the WDA service status](#verify-wda-status).

When using a physical iOS device:

1. Connect the device to your Mac via USB and tap **Trust This Computer** when prompted on the device.
2. Enable **Developer Mode** (**Settings > Privacy & Security > Developer Mode**) and **UI Automation** (**Settings > Developer > Enable UI Automation**) on the device.
3. After signing and starting WDA on the device, use `iproxy` (installable via `brew install libimobiledevice`) to forward the WDA port (`8100` by default) from the device to your Mac:

```bash
iproxy 8100 8100 YOUR_DEVICE_ID
```

Replace `YOUR_DEVICE_ID` with your device's UDID, and keep both WDA and `iproxy` running. When connecting multiple devices or using custom ports, forward each device to a distinct local port and use that port in Playground or your project configuration.

### Verify the WDA service status {#verify-wda-status}

Open the WDA `/status` endpoint in your browser or terminal from the computer running Midscene:

- **Default local URL**: `http://localhost:8100/status` (if using a custom port, remote host, or gateway, use the actual service address)
- **Expected JSON response**:

```json
{
  "value": {
    "build": {
      "version": "10.1.1",
      "time": "Sep 24 2025 18:56:41",
      "productBundleIdentifier": "com.facebook.WebDriverAgentRunner"
    },
    "os": {
      "testmanagerdVersion": 65535,
      "name": "iOS",
      "sdkVersion": "26.0",
      "version": "26.0"
    },
    "device": "iphone",
    "ios": {
      "ip": "10.91.115.63"
    },
    "message": "WebDriverAgent is ready to accept commands",
    "state": "success",
    "ready": true
  },
  "sessionId": "BCAD9603-F714-447C-A9E6-07D58267966B"
}
```

A JSON response containing `"ready": true` confirms that WDA is ready to accept commands. Note the WDA host and port (or gateway base URL) so you can use the same connection settings in Playground and your project.

## Verify {#verify}

When the WDA `/status` endpoint returns `"ready": true`, verify the environment in Playground. Open [Get started](/get-started.md?platform=ios\&scene=playground), where iOS and Playground are already selected, choose how to connect a model, and follow the steps to run one `aiAct` action and one `aiAssert` assertion. A passing assertion confirms that WDA, screen capture, touch input, and model calls work together.

## FAQ {#faq}

### Why can't I control my physical device even though WebDriverAgent is connected?

Check the following settings on your iOS device:

1. **Developer Mode**: Make sure **Settings > Privacy & Security > Developer Mode** is enabled and the device has been restarted.
2. **UI Automation**: Make sure **Settings > Developer > Enable UI Automation** is turned on.
3. **Computer Trust**: Reconnect the USB cable and make sure you have tapped **Trust This Computer** on the device prompt.

### What are the differences between iOS Simulators and physical devices?

| Feature              | Physical Device                             | iOS Simulator                                |
| -------------------- | ------------------------------------------- | -------------------------------------------- |
| Port forwarding      | Requires `iproxy`                           | Not required (listens on localhost directly) |
| Developer Mode       | Must be enabled manually                    | Enabled by default                           |
| UI Automation toggle | Must be enabled in **Settings > Developer** | Enabled by default                           |
| Performance          | Real hardware performance                   | Depends on host Mac performance              |
| Hardware sensors     | Real sensors                                | Simulated data                               |

### How do I customize the WebDriverAgent port and host?

See the [iOS JavaScript SDK guide](/sdk/ios.md#how-do-i-customize-the-webdriveragent-port-and-host).

### How do I get a smoother live screen preview in Playground?

iOS Playground supports two screen preview modes:

- **Polling mode** (default): Captures screenshots sequentially via the WDA screenshot endpoint at roughly 5–10 fps.
- **Native MJPEG stream** (recommended): Connects directly to WDA's built-in MJPEG server for higher frame rates and lower latency.

To enable the native MJPEG stream on a physical device, forward WDA's MJPEG port (`9100` by default) to your Mac (not required for Simulators):

```bash
iproxy 9100 9100 YOUR_DEVICE_ID
```

Playground automatically probes local port `9100` on startup: if available, the terminal logs `MJPEG: streaming via native WDA MJPEG server`; otherwise, it falls back to polling mode automatically.
