Skip to main content
This guide covers the one-time setup required to automate physical iOS devices connected via USB using WebDriverAgent (WDA).
Looking for other options? Check out the Local Quickstart for Android/iOS simulators or Cloud Mobile Quickstart for zero-setup cloud devices.
Make sure you’ve completed the Installation steps before proceeding.

What You’ll Need

macOS with Xcode

Required for code signing and building WDA

Physical iOS Device

iPhone or iPad connected via USB cable

Node.js & npm

For installing Appium and drivers

Apple Developer Account

Free account works - needed for code signing

One-Time Setup

1

Install Appium

Install Appium globally via npm:
npm install -g appium
2

Install XCUITest Driver

Install the XCUITest driver which includes WebDriverAgent:
appium driver install xcuitest
This installs WebDriverAgent at: ~/.appium/node_modules/appium-xcuitest-driver/node_modules/appium-webdriveragent/.
3

Configure Code Signing

WebDriverAgent must be code-signed to run on physical devices. This is a one-time setup.
# Open the WebDriverAgent project in Xcode
open ~/.appium/node_modules/appium-xcuitest-driver/node_modules/appium-webdriveragent/WebDriverAgent.xcodeproj
In Xcode:
  1. Open the Project Navigator (panel on the left), then select the WebDriverAgent project at the top.
  2. Select the WebDriverAgentRunner target (top-left dropdown)
  3. Go to Signing & Capabilities tab
  4. Check β€œAutomatically manage signing”
  5. Select your Team (your Apple ID)
  6. Change the iOS Bundle Identifier to something unique:
    • Example: com.yourname.WebDriverAgentRunner
    • Must be unique across all Apple apps
    Don’t forget: Repeat the same steps for the WebDriverAgentLib and IntegrationApp targets.
  7. Select your physical device as the run destination in Xcode, then build the IntegrationApp target once. This will trigger the code-signing process and install the required provisioning profile on your device.

    Option B: Using CLI (Advanced)

If you prefer command-line signing:
# Set your development team ID
TEAM_ID="YOUR_TEAM_ID"

# Navigate to WDA directory
cd ~/.appium/node_modules/appium-xcuitest-driver/node_modules/appium-webdriveragent/

# Update Bundle ID and Team in the project
sed -i '' "s/PRODUCT_BUNDLE_IDENTIFIER = .*/PRODUCT_BUNDLE_IDENTIFIER = com.yourname.WebDriverAgentRunner;/" WebDriverAgent.xcodeproj/project.pbxproj
sed -i '' "s/DEVELOPMENT_TEAM = .*/DEVELOPMENT_TEAM = $TEAM_ID;/" WebDriverAgent.xcodeproj/project.pbxproj
You’ll still need to get your Team ID from Xcode or your Apple Developer account.
4

Trust Developer Certificate on Device

After the first WDA build, trust the developer certificate on your iOS device:
  1. On your device: Settings β†’ General β†’ VPN & Device Management
  2. Tap on your developer certificate (your Apple ID)
  3. Tap Trust
You only need to do this once per developer certificate.

Using Your Physical iOS Device

After the one-time setup, mobile-use handles everything automatically:
  • βœ… Starts iproxy for USB port forwarding
  • βœ… Builds and runs WebDriverAgent via xcodebuild
  • βœ… Connects to WDA and waits for it to be ready
  • βœ… Cleans up processes when your script exits

Basic Example

physical_device_demo.py
import asyncio
from minitap.mobile_use.sdk import Agent

async def main():
    # Create agent - automatically detects connected iOS device
    agent = Agent()
    
    # Initialize - WDA, iproxy, and xcodebuild start automatically
    await agent.init()
    
    # Run tasks on your physical device
    result = await agent.run_task(
        goal="Open Safari and search for 'mobile automation'",
    )
    
    print(f"Task completed: {result.status}")

if __name__ == "__main__":
    asyncio.run(main())
The agent automatically detects your connected iOS device. No UDID needed unless you have multiple devices connected!

Multiple Devices

If you have multiple devices connected, specify which one to use:
multiple_devices.py
from minitap.mobile_use.sdk import Agent
from minitap.mobile_use.sdk.builders import Builders

async def main():
    config = (
        Builders.AgentConfig
        .for_device("YOUR_DEVICE_UDID", platform="ios")
        .build()
    )
    
    agent = Agent(config=config)
    await agent.init()
    
    # Your automation here
# Option 1: Using idevice_id
idevice_id -l

# Option 2: Using Xcode
# Window β†’ Devices and Simulators β†’ Select your device
# The UDID is shown in the device info

Advanced Configuration

Managing WDA Externally

For debugging or custom setups, you can disable auto-start and manage iproxy/WDA manually:
manual_wda_setup.py
from minitap.mobile_use.sdk import Agent
from minitap.mobile_use.sdk.builders import Builders
from minitap.mobile_use.clients.ios_client_config import IosClientConfig, WdaClientConfig

async def main():
    # Create config to disable auto-starting
    ios_config = IosClientConfig(
        wda=WdaClientConfig(
            auto_start_iproxy=False,  # Don't auto-start iproxy
            auto_start_wda=False,      # Don't auto-start WDA
            wda_url="http://localhost:8100"
        )
    )

    config = (
        Builders.AgentConfig
        .for_device("YOUR_DEVICE_UDID", platform="ios")
        .with_ios_client_config(ios_config)
        .build()
    )

    agent = Agent(config=config)
    await agent.init()
    
    # Your automation here
When auto-start is disabled, manually start the required processes:
# Start USB port forwarding
iproxy 8100 8100 -u YOUR_DEVICE_UDID
OptionTypeDefaultDescription
auto_start_iproxyboolTrueAuto-start USB port forwarding
auto_start_wdaboolTrueAuto-build and run WDA via xcodebuild
wda_urlstr"http://localhost:8100"WDA server URL
wda_project_pathstr | NoneNoneCustom path to WebDriverAgent.xcodeproj
wda_startup_timeoutfloat120.0Max seconds to wait for WDA startup

How It Works

1

iproxy Port Forwarding

iproxy forwards USB traffic from device port 8100 to localhost:8100
2

WDA Build & Deploy

xcodebuild builds WDA (if needed) and deploys it to your device
3

WDA Server Running

WDA server runs on the device, listening on port 8100
4

Python Client Connection

Python client connects to localhost:8100 via iproxy
The WDA wrapper automatically manages iproxy and xcodebuild processes, cleaning them up when your script exits.

Getting Your Device UDID

# List connected devices
idevice_id -l

# Or use Xcode
# Window β†’ Devices and Simulators β†’ Select your device

Troubleshooting

Solution: Trust the developer certificate on your device
  1. Go to Settings β†’ General β†’ VPN & Device Management
  2. Tap on your developer certificate
  3. Tap Trust
Possible causes:
  • No Team selected in Xcode
  • Bundle Identifier conflict
  • Device not registered in Apple Developer account
Solutions:
  1. Open the WDA project in Xcode
  2. Verify a Team is selected for both targets
  3. Try a different Bundle Identifier (e.g., com.yourname.WebDriverAgentRunner)
  4. Check device registration in your Apple Developer account
Solution: Keep your device unlocked
  • Unlock your device before running automation
  • Keep it unlocked during the initial WDA build
  • Consider disabling auto-lock temporarily: Settings β†’ Display & Brightness β†’ Auto-Lock β†’ Never
Debugging steps:
  1. First build takes time: Initial builds can take 1-2 minutes
  2. Check Xcode: Open the project in Xcode for detailed error messages
  3. Verify signing: Ensure code signing is configured for both WebDriverAgentRunner and WebDriverAgentLib targets
  4. Clean build: In Xcode, go to Product β†’ Clean Build Folder
  5. Update Xcode: Make sure you’re running the latest version
Troubleshooting:
  1. Verify WDA is running on device (you should see the WDA screen)
  2. Check iproxy is running: ps aux | grep iproxy
  3. Test WDA manually: curl http://localhost:8100/status
  4. Restart your device and try again
  5. Increase timeout in config: wda_startup_timeout=180.0
For more troubleshooting help, check the Troubleshooting Guide or join our Discord community.

Next Steps