skip to content

In Appium, which ports must a second simultaneous session change on Android and on iOS?

level: middleimportance: should knowfreq 50%

answer

  1. two lists, almost no shared vocabulary
  2. the agent channel on each platform
  3. one Apple entry is a directory
  4. only the stream port shares a name

basics

~10 s

On Android each concurrent session needs its own appium:systemPort, plus appium:chromedriverPort for web views. On iOS it needs its own appium:wdaLocalPort and appium:derivedDataPath. Only appium:mjpegServerPort is spelled the same on both platforms.

solid answer

~40 s

The two platforms allocate almost nothing in common. An Android session driven by UiAutomator2 needs its own `appium:systemPort` — the host port the driver reaches its on-device agent on — plus `appium:chromedriverPort` when it drives a web view, and `appium:adbPort` when a second adb server is in play. An Apple-platform session driven by XCUITest needs its own `appium:wdaLocalPort` for WebDriverAgent and its own `appium:derivedDataPath`, so two concurrent `xcodebuild` runs do not write the same directory; `appium:wdaRemotePort`, `appium:wdaBindingIP` and `appium:webDriverAgentUrl` complete that family. The one capability spelled identically on both is `appium:mjpegServerPort`, and even that is two mechanisms: a forwarded host port on Android, WebDriverAgent's own broadcast port on Apple platforms. Because the names barely overlap, a fleet's port helper branches on `platformName` first.

go deeper

for a junior

Learn the two headline names and which platform owns each: appium:systemPort on Android, appium:wdaLocalPort on Apple platforms. Knowing they are different names for the same job is most of the answer.

for a middle

Be able to lay out both lists and explain why each entry exists — agent channel, web-view process, screenshot stream, build directory — and why appium:mjpegServerPort shares a name without sharing a mechanism.

for a senior

Talk about how you verify the allocation on a live host: logging resolved values per session, checking what is actually bound before blaming a locator, and clearing leftovers from a killed run.

for a principal

Argue for one allocation scheme that branches per platform rather than a single shared map, and for keeping the two lanes' bands disjoint so a mixed fleet cannot cross-book a number.

## Two lists that barely overlap Running two Appium sessions at once on one machine is not a matter of flipping a parallel switch. Each driver opens host-side channels of its own, and each of those channels is a number only one session can hold. The catch is that the Android set and the Apple set were named independently, so almost nothing carries across. | Concern | Android, UiAutomator2 | Apple platforms, XCUITest | |---|---|---| | Channel to the on-device agent | `appium:systemPort` | `appium:wdaLocalPort` | | Web-view automation | `appium:chromedriverPort` | no port capability of its own | | Build output directory | not applicable | `appium:derivedDataPath` | | Screenshot stream | `appium:mjpegServerPort` | `appium:mjpegServerPort` | | Rest of the family | `appium:adbPort`, `appium:remoteAdbHost` | `appium:wdaRemotePort`, `appium:wdaBindingIP`, `appium:webDriverAgentUrl` | ## The Android side The UiAutomator2 driver pushes a helper server onto the device and speaks HTTP to it. `appium:systemPort` is the host-side port for that conversation and is the one capability a parallel Android lane cannot skip. If the session also drives Chrome or a web view, a Chromedriver process is started for it, and `appium:chromedriverPort` gives that process a port nobody else holds. `appium:mjpegServerPort` covers the screenshot stream when a session uses one. `appium:adbPort` and `appium:remoteAdbHost` address adb itself, and only matter when a host runs more than one adb server or reaches a device through another machine. ## The Apple side The XCUITest driver's agent is WebDriverAgent, and `appium:wdaLocalPort` is the host-side port the driver reaches it on — the same role `appium:systemPort` plays on Android, under a name that shares nothing with it. `appium:wdaRemotePort` names the port the agent listens on at the device end, `appium:wdaBindingIP` the address it binds, and `appium:webDriverAgentUrl` points a session at an agent that is already running instead of standing one up. The Apple lane also carries a per-session value that is not a port at all. `appium:derivedDataPath` is the directory `xcodebuild` writes into, and two concurrent sessions aimed at one derived-data directory interfere over files rather than over sockets. It belongs on the same checklist because the symptom is identical: a second session that either refuses to start or behaves as though it were the first. Nothing in either list is negotiated on your behalf. Every one of these values is supplied by the client in the `capabilities` body of `POST /session`, carrying the `appium:` vendor prefix, and the driver uses what it is given. There is no mode in which a session notices that another session already holds a number and quietly steps aside. ## The one shared name, and why it is not really shared `appium:mjpegServerPort` is declared by both drivers, and both parallel-run guides list it as a value each worker needs of its own. Even here the mechanism differs: on Android it is a host-forwarded port, and on Apple platforms it is WebDriverAgent's own broadcast port. `appium:mjpegScreenshotUrl` is shared in the same shape. The honest sentence is *the same capability name, two different mechanisms* — never *the same thing on both platforms*. ## What this does to configuration code - Do not write one list of port capabilities and apply it to every session; branch on `platformName` before allocating. - Keep one allocation function per platform, each returning only the names that platform actually declares. - Set only the ports a session really uses: a native-only Android session has no Chromedriver, so a per-worker `appium:chromedriverPort` buys nothing there. - Treat `appium:derivedDataPath` as part of the Apple allocation even though it names a directory rather than a socket. - Log every resolved value next to the session id, so a failed run can be read rather than reproduced. ## The failure the checklist prevents A stage-crew call-sheet suite that is green on one worker and starts shedding assertions at three usually has one of two shapes. On Android, two workers share `appium:systemPort` and a single device answers for both. On an Apple lane, two sessions share `appium:wdaLocalPort` or one derived-data directory, and the second session either refuses to start or drives the first device. Neither produces a message with the word port in it, which is why the allocation is worth pinning up front instead of discovering by bisecting the suite. ## What to remember 1. Android needs `appium:systemPort` always, `appium:chromedriverPort` for web views, `appium:mjpegServerPort` for the stream. 2. Apple platforms need `appium:wdaLocalPort` always, `appium:derivedDataPath` per session, `appium:mjpegServerPort` for the stream. 3. The only name on both lists is `appium:mjpegServerPort`, and it is two mechanisms wearing one name.

  • Why does appium:derivedDataPath belong on a port checklist when it names a directory?
    Because it is allocated for the same reason. Two concurrent Apple sessions that share one derived-data directory collide over `xcodebuild` output the way two sessions sharing a port collide over a socket. The symptom is the same — a second session that fails to start or behaves as the first — so it is allocated per session alongside `appium:wdaLocalPort`.
  • Does a native-only Android session still need appium:chromedriverPort set per worker?
    No. Chromedriver is started only when the session drives Chrome or a web view, so a purely native call-sheet session never binds that port. Allocate it for the lanes that use web views and leave it out elsewhere; reserving a value per worker for a process that never starts adds bookkeeping without removing a collision.

saying these in an interview costs you the question

  • Says the same port capabilities apply on Android and Apple platforms
  • Thinks appium:mjpegServerPort is the same mechanism on both platforms
  • Forgets appium:derivedDataPath when two Apple sessions run at once
  • Assumes only the Appium server's own port has to be unique
  • Believes a distinct appium:udid alone separates two sessions