An iOS simulator session catches Appium setup problems before the same test reaches physical-device signing or CI. The first run should prove that the local Appium server can load XCUITest, select the intended Simulator, and launch one app under WebDriver control.

The XCUITest driver coordinates Appium, Xcode simulator tooling, and WebDriverAgent. A simulator app session needs platformName set to iOS, appium:automationName set to XCUITest, a simulator name and runtime, and either appium:app or appium:bundleId so the driver knows what to open.

Use one booted simulator and one app bundle built for the simulator runtime. A .app built for the iOS simulator is not interchangeable with an .ipa signed for a real device, and a stale /wd/hub client URL fails against current Appium servers unless the server was started with that legacy base path.

Steps to run an Appium session on an iOS simulator:

  1. Confirm that the XCUITest driver is installed.
    $ appium driver list --installed
    - Listing installed drivers (rerun with --verbose for more info)
    - xcuitest@11.11.2 [installed (npm)]

    The exact driver version changes over time. Install xcuitest before creating an iOS session if this list does not show it.
    Related: How to install the Appium iOS driver

  2. List the available iOS simulators.
    $ xcrun simctl list devices available
    == Devices ==
    -- iOS 17.5 --
        iPhone 15 (4D99D8D8-6E31-44F0-9A7A-4B6D7E2C3A10) (Shutdown)
    ##### snipped #####

    Use a simulator name and iOS runtime that exist on this Mac. Set appium:platformVersion in the client script when the same device name appears under multiple runtimes.

  3. Boot the selected simulator.
    $ xcrun simctl boot "iPhone 15"

    Skip this command if the simulator already shows Booted in the simctl list output.

  4. Wait for the simulator to finish booting.
    $ xcrun simctl bootstatus "iPhone 15" -b
    Monitoring boot status for iPhone 15 (4D99D8D8-6E31-44F0-9A7A-4B6D7E2C3A10).
    Device booted in 12.45 seconds
  5. Check that the Appium server is ready.
    $ curl --silent http://127.0.0.1:4723/status
    {"value":{"ready":true,"message":"Appium is ready"}}

    Start the server first if this endpoint does not respond. Current Appium servers use http://127.0.0.1:4723 by default, not /wd/hub.
    Related: How to start the Appium server

  6. Create the Python iOS simulator smoke test.
    $ cat > ios_simulator_session.py <<'PY'
    from appium import webdriver
    from appium.options.ios import XCUITestOptions
     
    APPIUM_SERVER = "http://127.0.0.1:4723"
    APP_PATH = "/Users/developer/Builds/MyApp.app"
    APP_BUNDLE_ID = "com.example.MyApp"
     
    options = XCUITestOptions().load_capabilities({
        "platformName": "iOS",
        "appium:automationName": "XCUITest",
        "appium:deviceName": "iPhone 15",
        "appium:platformVersion": "17.5",
        "appium:app": APP_PATH,
    })
     
    driver = webdriver.Remote(APPIUM_SERVER, options=options)
     
    try:
        state = driver.execute_script(
            "mobile: queryAppState",
            {"bundleId": APP_BUNDLE_ID},
        )
        print(f"session={driver.session_id}")
        print(f"context={driver.current_context}")
        print(f"app_state={state}")
    finally:
        driver.quit()
    PY

    Replace APP_PATH with a .app bundle built for the simulator and replace APP_BUNDLE_ID with that app's bundle identifier. Install the Python client first if the appium import is missing: python3 -m pip install Appium-Python-Client.
    Related: How to install an app for an Appium session
    Related: How to configure Appium capabilities

  7. Run the smoke test.
    $ python3 ios_simulator_session.py
    session=91b4d3a0-6c19-4d44-8e0f-f42b2f30a611
    context=NATIVE_APP
    app_state=4

    app_state=4 means the queried bundle is running in the foreground according to XCTest. A failure before this output usually points to the simulator name, iOS runtime, app path, XCUITest driver, or server URL.

  8. Check the Appium server terminal for the session success lines.
    [XCUITest] WebDriverAgent successfully started after 14286ms
    [HTTP] <-- POST /session 200 15194 ms - 921

    The WebDriverAgent line confirms that the simulator-side runner started, and the HTTP 200 line confirms that the new-session request returned successfully.

  9. Remove the one-off smoke test when the session check is complete.
    $ rm ios_simulator_session.py