skip to content

Protocol Lineage

The request path from a test process to a device: who speaks HTTP to whom, what Appium inherited from WebDriver and what it added on top, and how one session is opened and torn down.

on this pageshow

explore

questions

12

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 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

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 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 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 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

After an Appium 3 upgrade, which /appium/... routes stop answering and what replaces them?

level: seniorimportance: should knowfreq 46%

basics

~20 s

Appium 3 removed most of the old /appium/... routes, moving that work into per-driver mobile: execute methods: app reset became mobile: clearApp, and press_keycode became mobile: pressKey on the Android drivers. Some routes only moved, not vanished.

open as a page

In Appium, when is it worth leaving the W3C command set for a driver's mobile: method?

level: principalimportance: should knowfreq 37%

basics

~20 s

Stay on the inherited W3C commands for what a suite does constantly, because they port across drivers; reach for a driver's mobile: method when the standard surface cannot express the intent, and keep that per-driver name behind one call site.

open as a page

In Appium, does every driver have to install an agent on the device?

level: middleimportance: nice to knowfreq 38%

basics

~20 s

No. Android's UiAutomator2 driver installs and starts a helper server, Apple's XCUITest driver deploys WebDriverAgent, and Android's Espresso driver installs a test package, but the official Flutter driver installs nothing and attaches to the app's running Dart VM Service.

open as a page