skip to content

Build-Time Runs

What changes when nobody is watching the run: the server has to come up already configured, and whatever the session saw has to be captured while it happens, because nobody will reproduce it.

on this pageshow

explore

questions

8

In Appium, which request captures a still screenshot on Android and on iOS?

level: juniorimportance: must knowfreq 74%

answer

  1. inherited from the protocol, not invented
  2. same call, both drivers
  3. base64, not bytes
  4. whole screen, no element tree
  5. GET /session/:sessionId/screenshot

basics

~10 s

Both platforms answer the same W3C request, GET /session/:sessionId/screenshot, and return the whole screen as a base64-encoded PNG. Appium's UiAutomator2 driver on Android and its XCUITest driver on Apple platforms behave identically here.

solid answer

~40 s

The still screenshot is inherited from the W3C WebDriver protocol, so it is the one capture command that does **not** diverge: `GET /session/:sessionId/screenshot` returns a base64-encoded PNG of the whole screen on an Android UiAutomator2 session and on an Apple XCUITest session alike. Everything around it does diverge. The UiAutomator2 driver declares extras in its own execute-method map, including `mobile: screenshots` and `mobile: viewportScreenshot`; XCUITest's settings reference declares `screenshotQuality`, `screenshotOrientation` and `webScreenshotMode`. Video is a different command on each platform again. So a cross-platform harness for a cattle-auction bidding app can attach a failure image with one shared call, but must branch the moment it wants anything richer than a still.

code

python · 13 lines
python
from appium import webdriver
from appium.options.android import UiAutomator2Options

options = UiAutomator2Options()
options.automation_name = "UiAutomator2"
options.app = "/builds/cattle-auction.apk"

driver = webdriver.Remote("http://127.0.0.1:4723", options=options)
try:
    driver.find_element("accessibility id", "place-bid").click()
    driver.get_screenshot_as_file("cattle-auction-bid.png")
finally:
    driver.quit()

go deeper

for a junior

Be ready to name the request and its payload without hedging: GET /session/:sessionId/screenshot, base64-encoded PNG, whole screen, identical on Android and Apple sessions.

for a middle

Explain why this one command is portable while recording is not: the still comes from the W3C protocol, the recorders come from each driver's own execute-method map.

for a senior

Show how a failure handler captures safely in production: inside the live session, decoded before writing, and budgeted rather than fired after every single step in a wide parallel run.

for a principal

Own the tradeoff between artefact richness and run cost across a fleet, and be clear that a still is the cheapest evidence available while video and streaming carry per-platform mechanisms and per-platform failure modes.

## The still image is the one thing that does not diverge Appium is a W3C WebDriver server, so the screenshot command is inherited from the protocol rather than invented per platform. A test issues `GET /session/:sessionId/screenshot` and the server answers with a JSON body whose `value` is a **base64-encoded PNG** of the whole screen. That holds for an Android session driven by the UiAutomator2 driver and for an Apple session driven by the XCUITest driver: same route, same encoding, same response shape. Language clients wrap it in a helper, but underneath every one of them issues that request. This matters because almost nothing else about evidence capture in Appium is portable. Video, live streaming and audio are each answered by a **different execute method on a different driver**, and any helper that captures them has to branch on `platformName`. The still screenshot is the exception, and it is why a cross-platform suite for a cattle-auction bidding app can attach a "what the run saw" image on both platforms from one line of shared code. ## What the call actually returns - The payload is the **whole screen**, not just the application window: status bars, notification shades and any system dialog drawn over the auction lot list all appear in it. - It is a **PNG**, base64-encoded inside the JSON envelope, so a large device screen becomes a sizeable string; capturing after every step is real bytes over the wire. - It is a snapshot of the display, so an in-flight animation or a half-drawn bid list is captured mid-flight. - It carries **no element metadata**. If you need the tree, that is `GET /session/:sessionId/source`, a different command. - Appium's route tables spell the session placeholder `:sessionId`. `/session/:id/screenshot` is not the form the server documents. ## What each driver adds on top The common call is the floor, not the ceiling. Each driver declares extras in its own execute-method map or settings reference, and those are **not** shared: | Concern | Android (UiAutomator2 / the Android drivers) | Apple (XCUITest) | |---|---|---| | Standard still | `GET /session/:sessionId/screenshot` | `GET /session/:sessionId/screenshot` | | Extra still commands | `mobile: screenshots`, `mobile: viewportScreenshot` | `mobile: source` for the tree, not the image | | Named tuning settings | `mjpegServerScreenshotQuality`, `mjpegBilinearFiltering` | `screenshotQuality`, `screenshotOrientation`, `webScreenshotMode` | | Video | `mobile: startMediaProjectionRecording` | `mobile: startXCTestScreenRecording`, `mobile: startScreenRecording` | `mobile: screenshots` and `mobile: viewportScreenshot` are declared in the **UiAutomator2 driver's own** execute-method map, alongside `mobile: viewportRect`; they let an Android session ask for per-display images or for the viewport region rather than the whole display. XCUITest's settings reference declares `screenshotQuality` and `screenshotOrientation`, which change how the still is produced on Apple platforms. Attributing one of these to the wrong driver is the classic mistake here, and no spell-check catches it because every identifier involved is real. ## Where the still stops being enough A single PNG answers "what was on screen when the assertion failed". It does not answer: 1. What happened in the three seconds before the failure — that needs a recording. 2. Whether the element existed but sat off-screen — that needs the page source. 3. Why a tap landed on the wrong auction lot — that usually needs the element tree and a video together. That is why a serious Appium harness pairs the screenshot with a platform-specific recording, and why "we take screenshots" should be read as the beginning of an evidence story rather than the whole of it. ## Failure modes worth recognising - Calling the command **after** the session ends. `DELETE /session/:sessionId` invalidates the id, so the capture has to happen inside the failure handler while the session is still alive. - Writing the base64 string straight to disk without decoding it, producing a "corrupt" PNG that is really a text file. - Capturing on every step across a large parallel run and being surprised by the artefact volume; the encoding cost is paid per call. - Treating the image as proof of visibility. On Apple platforms an element can be present in the tree and rendered under another view; the picture shows the composite, not the hierarchy. - Expecting two runs of the same screen to produce byte-identical images. A clock and a battery indicator differ every time, which is why comparing images is a separate discipline from capturing them. The summary a junior should be able to give: one request, both platforms, base64 PNG of the whole screen — and everything richer than that is per driver.

  • The image comes back as a base64 string. What does a harness have to do before it is a usable artefact?
    Decode it. The JSON `value` is base64 text, so the harness must base64-decode it and write the resulting bytes as a binary file. Most language clients expose a helper that does the decode and the write for you; skipping the decode is how teams end up with PNG files that no viewer will open.
  • Why can the screenshot succeed while a video capture on the same Android session returns nothing?
    They are different mechanisms. The still is a W3C command the driver answers directly; the Android video is produced by the `io.appium.settings` helper application through media projection, and its payload only comes back from `mobile: stopMediaProjectionRecording`. A working screenshot therefore proves the session is alive, not that recording is wired up.

saying these in an interview costs you the question

  • Says the screenshot endpoint differs between Android and iOS
  • Expects raw PNG bytes rather than a base64-encoded string
  • Thinks the driver saves the image to device storage and returns a path
  • Assumes the capture is limited to the app window, excluding system bars
  • Attributes mobile: viewportScreenshot to the XCUITest driver
  • Believes a screenshot proves an element was visible and hittable
open as a page

In Appium, what must each `--allow-insecure` value carry, and what happens without it?

level: middleimportance: must knowfreq 52%

basics

~10 s

Every value needs a scope prefix — the driver that owns the feature, or a star for a server-wide one. An unscoped name is fatal at startup, so Android's adb_shell must be written uiautomator2:adb_shell.

open as a page

In Appium, which execute method starts a screen recording on Android, and which on iOS?

level: juniorimportance: should knowfreq 58%

basics

~10 s

Android sessions call mobile: startMediaProjectionRecording, declared by the Android drivers and captured by the io.appium.settings helper app. Apple sessions call XCUITest's mobile: startXCTestScreenRecording. The names, the mechanisms and the outputs are all platform-specific.

open as a page

What do Appium's `--port` and `--base-path` server flags change about the running server?

level: juniorimportance: should knowfreq 58%

basics

~20 s

The port flag sets the TCP port the Appium server listens on, 4723 by default. The base path flag sets the prefix every WebDriver route is mounted under, so a new session is posted to that prefix plus slash session.

open as a page

In Appium, how does the live MJPEG screen stream differ on Android and iOS?

level: middleimportance: should knowfreq 38%

basics

~20 s

Both the UiAutomator2 and XCUITest drivers declare appium:mjpegServerPort, but it names two different mechanisms: on Android it is a host-forwarded port onto the device-side server, and on Apple platforms it is WebDriverAgent's own broadcast port.

open as a page

Your Appium cattle-auction suite records video on iOS but returns nothing on Android — why?

level: seniorimportance: should knowfreq 42%

basics

~20 s

The recorders are different products. Apple's video comes from XCTest inside WebDriverAgent; Android's is produced by the io.appium.settings helper application, so a missing helper, an ungranted media projection, or a skipped stop call returns nothing.

open as a page

Which Appium server flags would you pin on an unattended box running an allotment watering-rota suite?

level: seniorimportance: should knowfreq 40%

basics

~20 s

Pin the interface, port and base path; pin the box's own facts with default capabilities; decide one session at a time or many; and grant the narrowest scoped insecure feature the lane needs instead of relaxing security wholesale.

open as a page

In Appium, what does the `--session-override` server flag do when a session is already open?

level: middleimportance: nice to knowfreq 28%

basics

~20 s

With that flag set, a new session request first deletes every session the Appium server is already holding, then starts the requested one. Without it, the older session stays alive beside it and keeps its device busy.

open as a page