skip to content

Stack Anatomy

How an Appium run is assembled: the hop from a test process to the server, the driver it picks for Android or iOS, and the agent on the device. Interviewers use it to sort users from debuggers.

on this pageshow

explore

questions

page 1 of 2

In Appium 3, what must a POST /session request body contain to start a session?

level: juniorimportance: must knowfreq 74%

answer

  1. one envelope, not two
  2. the W3C new-session shape
  3. alwaysMatch and firstMatch live inside
  4. desiredCapabilities is no longer accepted

basics

~10 s

Appium 3 accepts a single top-level capabilities object holding alwaysMatch and firstMatch. The older desiredCapabilities and requiredCapabilities bodies are no longer accepted, and every Appium-specific key inside carries the appium: prefix.

solid answer

~50 s

A new Appium session is one HTTP request: `POST /session`, with a JSON body whose only top-level member is `capabilities`. Inside it, `alwaysMatch` is a single object of requirements and `firstMatch` an optional array of alternatives; combining them is the W3C protocol's job. Appium 3 dropped the pre-W3C `desiredCapabilities` and `requiredCapabilities` envelopes entirely, so a client binding that still posts a flat map gets nowhere. Within the object, only W3C standard names such as `platformName` travel bare — anything Appium-specific, from `appium:automationName` to `appium:newCommandTimeout`, carries the `appium:` prefix or is nested under `appium:options`. A birdwatching sightings suite therefore sends `platformName` plus `appium:automationName` and whatever names its app and device. On success the server answers with a session id and the capabilities it actually matched, and every later command in the run is addressed under that id.

code

json · 11 lines
json
{
  "capabilities": {
    "alwaysMatch": {
      "platformName": "Android",
      "appium:automationName": "UiAutomator2",
      "appium:app": "/builds/birdwatching-sightings.apk",
      "appium:newCommandTimeout": 120
    },
    "firstMatch": [{}]
  }
}

go deeper

for a junior

Be able to write the body from memory: one capabilities object, alwaysMatch inside it, W3C names bare and Appium keys prefixed. This is asked as a screening question of anyone who has run a suite.

for a middle

Explain why the envelope changed and what happens to a client that still posts desiredCapabilities. The repair is a client upgrade, not a server setting, and you should be able to say why.

for a senior

Show that you read new-session bodies in server logs during triage, comparing the capabilities the server matched against the ones the suite believed it sent before blaming anything downstream.

for a principal

Own where capability envelopes are assembled across a suite, so one lane cannot quietly send a different session shape than another without that difference being visible in the report.

## The one request the whole run hangs on Every Appium run opens with a single HTTP request: `POST /session`, sent to the server's base path — for a server running locally that is `http://127.0.0.1:4723/session`. Nothing else can happen until it succeeds, because the response is what hands back the **session id** that every later command is addressed under. Getting the body's shape wrong is not a subtle bug: there is no session at all, and a birdwatching sightings suite dies before it has seen one screen of the app. ## The envelope Appium 3 accepts The body has exactly one top-level member, `capabilities`. Inside it sit two optional members: - **`alwaysMatch`** — one object of requirements the created session must satisfy. - **`firstMatch`** — an array of alternative objects, any one of which may satisfy the remainder. Both are W3C WebDriver negotiation inputs, and the rules for combining them belong to the protocol rather than to Appium. What belongs to Appium is what it no longer takes: **`desiredCapabilities` and `requiredCapabilities` are gone.** Appium 3 accepts `capabilities` and nothing else. A client binding old enough to post a flat `desiredCapabilities` map is not negotiating badly — it is sending a body with no member the server recognises as the request, and the repair belongs in the client library, not in a server flag that restores the old shape. ## Two vocabularies inside one object | Kind of key | How it is written | Birdwatching example | |---|---|---| | W3C standard names | bare | `platformName: "Android"` | | Everything Appium-specific | `appium:` prefixed | `appium:automationName: "UiAutomator2"` | Only the W3C standard names — `platformName`, `browserName`, `timeouts`, `webSocketUrl` and the rest of that short set — may travel unprefixed. Every vendor key carries `appium:` or is nested under `appium:options`, and that includes keys that feel like core Appium concepts rather than extensions: `appium:app`, `appium:udid`, `appium:newCommandTimeout`. ## The same envelope, two platform families The shape of the request does not change between platforms; only the values do. - **Android**: `platformName` is `Android`, and `appium:automationName` names an Android driver such as `UiAutomator2` or `Espresso`. - **Apple platforms**: `platformName` names the Apple target you mean, and `appium:automationName` is `XCUITest`. That symmetry is worth saying out loud, because it is close to the last thing about a session that is symmetric. Once the request lands, what the driver has to do on the device diverges sharply: the Android drivers push a helper server onto the device, while the XCUITest driver has to have WebDriverAgent built, installed and running before it will answer a command. The request looks the same on both; the seconds it takes do not. ## What comes back A successful `POST /session` answers with the session id and the set of capabilities the server actually matched. Log the matched set. It is what the driver ran with, and it is not guaranteed to be key-for-key what you sent, because which keys mean anything depends on which driver answered — `appium:deviceName`, for instance, is declared by the Android drivers and by the XCUITest driver rather than by Appium's core. The session id itself is minted for this session and is meaningless afterwards: it is not a device identifier, not a run identifier, and not stable between runs. ## Where a birdwatching suite gets this wrong 1. **Sending `desiredCapabilities`.** Almost always an unupgraded client binding rather than hand-written JSON, and the symptom is total: no session is created, on any device. 2. **Hoisting `alwaysMatch` or `firstMatch` to the top level.** They live inside `capabilities`, not beside it. 3. **Dropping the `appium:` prefix on a vendor key.** The server does not quietly accept an unprefixed vendor name and carry on regardless. 4. **Assuming the response echoes the request.** It reports what was matched, which is the more useful of the two things to read. 5. **Hand-rolling the request when a client binding exists.** The bindings build this envelope for you; the value in knowing its shape is that you can read a rejected new-session request in a server log and see immediately which half is wrong. ## Why the shape matters beyond the first request The new-session body is the only place a run gets to say what it wants. There is no later negotiation and no second chance to add a key: everything the session does afterwards — which driver answers, which device it drives, how long it may sit idle before the server ends it — was fixed by this one object. So triage of a strange run starts here rather than at the failing command. If the capabilities the server logged are not the capabilities you believed the suite sent, nothing downstream will make sense, and the fastest way to find that out is to compare the two before reading another line of the log.

  • A client still posts desiredCapabilities to an Appium 3 server. What do you change?
    The client. Appium 3 accepts only a `capabilities` object, so a binding that sends the older flat map has no path to a session at all. Upgrade the client library rather than hunting for a server flag that restores the old envelope — there is not one.
  • Does the new-session body look different for an Android session and an Apple-platform one?
    No. The envelope is identical: one `capabilities` object with `alwaysMatch` inside it. Only the values change — `platformName`, and the driver named by `appium:automationName`. What differs between the two platform families is what the driver does on the device after the request lands, not the request itself.

saying these in an interview costs you the question

  • Says Appium still accepts desiredCapabilities alongside capabilities
  • Puts alwaysMatch and firstMatch at the top level of the body
  • Thinks every capability may be sent without the appium: prefix
  • Believes the response simply echoes the capabilities that were sent
  • Treats the session id as a stable device or run identifier
open as a page

In Appium, what is WebDriverAgent and why does an XCUITest session need it?

level: juniorimportance: must knowfreq 70%

basics

~20 s

WebDriverAgent is the on-device XCTest runner that Appium's XCUITest driver builds, signs, installs and launches. It holds Apple's automation APIs, so the driver never touches the app itself — it forwards every command to that agent over HTTP.

open as a page

In Appium, what does a session add on top of the W3C WebDriver protocol?

level: juniorimportance: must knowfreq 72%

basics

~20 s

Appium speaks W3C WebDriver unchanged and adds four things: the appium: capability prefix, per-driver mobile: and flutter: execute methods, its own web-view context routes, and, in Appium 3, the deletion of many old /appium/ routes.

open as a page

Why does a freshly installed Appium server automate nothing until you install a driver?

level: middleimportance: must knowfreq 72%

basics

~20 s

Appium 2 turned drivers into separately installed extensions, so the server package ships only the protocol layer and the extension machinery. Until you install a driver - UiAutomator2 for Android, XCUITest for Apple platforms - no session can start.

open as a page

In Appium, what does the official Flutter driver attach to in order to drive a Flutter app?

level: middleimportance: must knowfreq 50%

basics

~10 s

Appium's official appium-flutter-driver attaches over a WebSocket to the Dart VM Service that a running Flutter build publishes, and drives widgets through the ext.flutter.driver service extension registered by Flutter's test package.

open as a page

In Appium, what does the XCUITest driver do with xcodebuild before an iOS session runs?

level: middleimportance: must knowfreq 62%

basics

~20 s

Before the first command, Appium's XCUITest driver compiles WebDriverAgent with xcodebuild on the macOS host, signs it, installs it on the simulator or device, launches it under XCTest, and waits for its HTTP server to answer.

open as a page

In Appium, which four tiers sit between a test's findElement call and the app under test?

level: middleimportance: must knowfreq 74%

basics

~10 s

Four tiers carry every Appium command: a thin language client in the test process, the Appium server, the driver that appium:automationName selects, and the device-side agent or debug channel that driver drives.

open as a page

Why does Appium send its mobile: commands through execute/sync instead of new endpoints?

level: middleimportance: must knowfreq 58%

basics

~10 s

W3C fixes WebDriver's route table, so Appium exposes driver-specific commands through one standard endpoint instead: POST /session/:sessionId/execute/sync carries the command name in script and a single parameter object in args.

open as a page

In Appium, which commands does the UiAutomator2 driver declare itself, and which does it inherit?

level: seniorimportance: must knowfreq 45%

basics

~20 s

Appium's UiAutomator2 driver declares only gesture, scroll, window, viewport, clipboard and device-info commands of its own on Android. The rest of its Android surface, roughly sixty methods, is inherited from appium-android-driver, the shared base the Espresso driver also extends.

open as a page

In Appium, a driver adds a mobile: command your java-client version predates — what must you upgrade?

level: seniorimportance: must knowfreq 57%

basics

~20 s

Usually nothing on the client side. A driver's new mobile: command is reachable from any client version, because the client sends the name as a plain string; what must be current is the driver installed on the Appium server.

open as a page

When would you pick Appium's Espresso driver over its UiAutomator2 driver on Android?

level: seniorimportance: must knowfreq 55%

basics

~20 s

Pick Appium's Espresso driver when you own the Android app and its build and need in-process reach: registered idling resources, backdoor calls, matcher-based finds. Pick UiAutomator2 when the journey leaves the app or you cannot re-sign it.

open as a page

Why can't Appium's official Flutter driver automate the release build of a courier proof-of-delivery app?

level: seniorimportance: must knowfreq 44%

basics

~20 s

Appium's official Flutter driver reaches an app through the ext.flutter.driver extension, which exists only when the build imports Flutter's test package. Its README says such a build cannot be released as-is, so a store build exposes nothing to attach to.

open as a page

Which locator strategies does Appium's UiAutomator2 driver declare on Android?

level: juniorimportance: should knowfreq 62%

basics

~10 s

Six: xpath, id, class name, accessibility id, css selector, and -android uiautomator. The Android base driver declares five of them; css selector is the web-context strategy the UiAutomator2 driver adds on top.

open as a page

In Appium, what work does a language client such as java-client actually do?

level: juniorimportance: should knowfreq 66%

basics

~20 s

An Appium language client only encodes your calls as HTTP requests to the Appium server and decodes the replies. All device work happens in the server's driver, so the client stays thin and is versioned on its own.

open as a page

In Appium, what does the Espresso driver build and install on Android at session start?

level: juniorimportance: should knowfreq 60%

basics

~10 s

Appium's Espresso driver compiles an Android instrumentation server with Gradle against the app under test, signs it to match that app, and installs it so the server runs inside the app's own process.

open as a page

In Appium, which capability decides which driver handles a session?

level: juniorimportance: should knowfreq 62%

basics

~20 s

The appium:automationName capability names the driver, such as UiAutomator2, XCUITest, Espresso or Flutter. The Appium server reads it when the session is created and hands the session to that installed driver; platformName says which platform, not which driver.

open as a page

In Appium, what does the UiAutomator2 driver install on an Android device before a session?

level: middleimportance: should knowfreq 55%

basics

~20 s

Appium's UiAutomator2 driver puts its own helper applications on the Android device: the io.appium.uiautomator2.server app with its companion instrumentation package, and the io.appium.settings helper. The driver then proxies WebDriver commands to that on-device server over HTTP.

open as a page

In Appium on Android, how do appium:systemPort and UiAutomator2's serverPort setting differ?

level: middleimportance: should knowfreq 38%

basics

~20 s

They sit on opposite ends of the same connection. appium:systemPort is the port the driver reaches the UiAutomator2 server on from the host, while UiAutomator2's serverPort setting is the port the server binds on the Android device itself.

open as a page

In Appium, how does a test call a driver's mobile: command through java-client or the Python client?

level: middleimportance: should knowfreq 61%

basics

~10 s

Through the client's script-execution call - executeScript in Java, execute_script in Python - passing the command name as the script string and exactly one parameter map as the single argument the driver reads.

open as a page

What do appium:espressoBuildConfig and appium:forceEspressoRebuild control in an Android Espresso session?

level: middleimportance: should knowfreq 42%

basics

~10 s

In Appium's Android Espresso driver, appium:espressoBuildConfig supplies the configuration used when the driver generates and compiles its own on-device server, and appium:forceEspressoRebuild discards the cached server so that build runs again.

open as a page

In Appium's Android Espresso driver, what does mobile: registerIdlingResources buy a test?

level: middleimportance: should knowfreq 45%

basics

~10 s

It hands Appium's in-process Android Espresso server the idling resources the app already exposes, so the driver's own commands respect the app's declared-busy state instead of inferring it from outside the process.

open as a page

In Appium, why must you pass --use-plugins at server start when --use-drivers is optional?

level: middleimportance: should knowfreq 44%

basics

~20 s

Installing an Appium extension and activating it are different steps. Every installed driver is active by default, so --use-drivers only narrows the set; no plugin runs unless --use-plugins names it, because a plugin sits in every session's command path.

open as a page

In Appium, what happens on the device between POST /session and the first command?

level: middleimportance: should knowfreq 60%

basics

~20 s

The driver gets its own agent running on the device. On Android the UiAutomator2 driver pushes and starts a helper server; on Apple platforms the XCUITest driver builds WebDriverAgent with xcodebuild, installs it and launches it.

open as a page

In Appium, what do appium:usePreinstalledWDA and appium:webDriverAgentUrl change about an iOS session?

level: middleimportance: should knowfreq 52%

basics

~10 s

Both skip part of the WebDriverAgent sequence. appium:usePreinstalledWDA reuses an agent already installed on the target instead of compiling one; appium:webDriverAgentUrl points the driver at an agent already running, skipping build, install and launch.

open as a page

In Appium, how does the XCUITest driver reach WebDriverAgent on a simulator versus a real iPhone?

level: middleimportance: should knowfreq 44%

basics

~20 s

Appium's XCUITest driver speaks the same HTTP either way. For a simulator it uses simctl on the macOS host and reaches the agent there; for a real iPhone it uses devicectl and crosses the device link.

open as a page

Your Appium library loan-renewal suite needs an unreleased driver fix - how do you install that build?

level: seniorimportance: should knowfreq 37%

basics

~20 s

Install the build from where it lives: appium driver install with --source=github or --source=git plus --package, or --source=local for a checkout. It lands in APPIUM_HOME like any driver, but a branch pins nothing - treat it as temporary.

open as a page

How can Appium drive a release Flutter build on Android and iOS with no Flutter driver?

level: seniorimportance: should knowfreq 38%

basics

~20 s

Set SemanticsProperties.identifier on the Flutter widgets a suite needs: it surfaces as resource-id on Android and as accessibilityIdentifier on iOS, so a UiAutomator2 or XCUITest session can drive the shipped release build with no test package in it.

open as a page

In Appium, what does DELETE /session/:sessionId actually tear down on the device?

level: seniorimportance: should knowfreq 52%

basics

~20 s

It ends the driver's own session: the conversation with the device-side agent, the per-session host plumbing, and the server slot the session held. It does not uninstall the app or undo device state the run changed.

open as a page

In an Appium run, what is the difference between deleting a session and letting the server reap it?

level: seniorimportance: should knowfreq 45%

basics

~10 s

The device-side teardown is identical. What differs is who decided and what the client knows: a reaped session is ended silently, so the client finds out only when its next command fails.

open as a page

In Appium, what does driver proxy mode change about which tier answers a command?

level: seniorimportance: should knowfreq 44%

basics

~20 s

In proxy mode the driver forwards the request to its device-side agent, which answers it; only routes on the driver's proxy-avoid list run in the driver's own code. So driver source can understate what a session accepts.

open as a page

showing 1–30 of 38