Appium iOS Setup: XCUITest, Real-Device Signing and Python

Set up an iPhone test with the XCUITest driver, connect Python to the Appium server, troubleshoot WebDriverAgent signing and inspect hybrid WebViews.

Understand the four components

A test client sends WebDriver commands to the Appium server. The XCUITest driver uses WebDriverAgent (WDA) on the simulator or device to control the app. Appium Inspector helps inspect elements; it does not replace the driver or WDA signing.

The older source notes used uiautomator2 for iOS and set automationName to Chromium. Those are incorrect for a current XCUITest session, so this guide follows the official driver documentation.

Swipe the table sideways to see every column →

ComponentRoleTypical address or choice
Appium serverAccepts test sessionsUsually localhost:4723
XCUITest driveriOS automationInstall xcuitest
WebDriverAgentDevice-side bridge8100 is not the usual Appium endpoint
Appium InspectorInspects UI elementsCannot fix signing

Install and prove a simulator session first

Install compatible Node.js, Appium and Xcode versions according to the current official guide. The commands below install XCUITest, confirm it is present and start the server. Confirm driver requirements for the versions you actually install.

Use a working iOS Simulator, a test app and its bundle ID before moving to a real iPhone. Set platformName=iOS, appium:automationName=XCUITest and appium:bundleId; add appium:udid when device selection is ambiguous.

npm install -g appium
appium driver install xcuitest
appium driver list --installed
appium

Create a modern Python session

Install an Appium Python Client version compatible with your server and driver. Use XCUITestOptions and webdriver.Remote with options=options. Replace the example bundle ID and accessibility ID with your test app values; install that app before running the script.

from appium import webdriver
from appium.options.ios import XCUITestOptions
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support.ui import WebDriverWait

options = XCUITestOptions()
options.set_capability("appium:bundleId", "com.example.TestApp")
# If several devices are available:
# options.set_capability("appium:udid", "YOUR_DEVICE_UDID")

driver = webdriver.Remote("http://127.0.0.1:4723", options=options)
try:
    button = WebDriverWait(driver, 10).until(
        lambda d: d.find_element(AppiumBy.ACCESSIBILITY_ID, "start-button")
    )
    button.click()
    driver.save_screenshot("after-tap.png")
finally:
    driver.quit()

Swipe the table sideways to see every column →

Old noteCurrent approach
Positional desired_capsXCUITestOptions and options=options
find_element_by_nameExplicit AppiumBy locator
Device port 8100Appium server port 4723 for ordinary sessions
A wait object as a sleepWait for a specific condition
  1. Set appium:bundleId and, if needed, appium:udid.
  2. Connect to the Appium server, not directly to WDA's port 8100.
  3. Wait for a known element with WebDriverWait and an explicit AppiumBy locator.
  4. Call driver.quit() in finally even when an assertion fails.

Diagnose real-device WDA failures

A real iPhone needs a development team, valid signing and a trusted test device. Follow the XCUITest provisioning guide for xcodeOrgId, xcodeSigningId or an appropriate provisioning profile. Keep UDIDs, certificates and internal bundle IDs out of public logs.

Separate a build error from signing, device trust, missing app and network forwarding failures. Save the first actionable Appium and Xcode error and fix the failing layer before changing unrelated capabilities.

Find a hybrid app's WEBVIEW

Native controls are in NATIVE_APP. Web content is available only when the XCUITest driver can expose the relevant WEBVIEW context. Check that the app has an inspectable WKWebView and that the official Safari Web Inspector prerequisites are met; wait for the context, then switch. Do not change the iOS session's automationName to Chromium.

If only NATIVE_APP appears, check page load, inspection settings and permissions. Switch back to NATIVE_APP before interacting with native controls. Prefer the app's own Back button when relevant instead of generalizing one app's driver.back() behavior to all iOS apps.

Make the test reproducible

Keep one small case: cold-start the app, wait for a known element, tap it, capture a screenshot and end the session. Record Appium, driver, Python client, Xcode, iOS and app versions. Sources checked November 6, 2026. This guide adapts an older author's note and does not claim a fresh test on the reader's device.

Sources checked

Related Apple guides

Editorial note

We review the primary sources linked above and distinguish documented steps from our own measurements. Features, model support, and menu labels can change; confirm the current guidance for your device before making a change.