Screenshots captured from an Appium session preserve the device screen at the moment a mobile test reaches a checkpoint or fails. Saving the image from the active driver session keeps visual evidence with the test run instead of depending on a manual emulator or simulator capture after the state has changed.
The WebDriver screenshot command returns a base64-encoded PNG from the current browsing context. In the Appium Python Client, the inherited Selenium method save_screenshot() calls that endpoint and writes the image to a local file on the machine running the test.
Screenshot capture needs a live session and a screen that the platform allows Appium to read. Android screens protected by FLAG_SECURE can return a blank or blocked image, and parallel jobs should write unique filenames so one test worker does not overwrite another worker's artifact.
$ curl --silent http://127.0.0.1:4723/status {"value":{"ready":true,"message":"Appium is ready"}}
Start the server first if the status endpoint does not respond.
Related: How to start the Appium server
$ mkdir -p screenshots
Keep screenshots under the test report or CI artifact directory when the suite runs in automation.
$ vi capture_appium_screenshot.py
import struct from pathlib import Path from appium import webdriver from appium.options.android import UiAutomator2Options APPIUM_SERVER = "http://127.0.0.1:4723" SCREENSHOT = Path("screenshots/settings-home.png") capabilities = { "platformName": "Android", "automationName": "UiAutomator2", "deviceName": "Android Emulator", "appPackage": "com.android.settings", "appActivity": ".Settings", "language": "en", "locale": "US", } def png_size(path: Path) -> tuple[int, int]: data = path.read_bytes() if not data.startswith(b"\x89PNG\r\n\x1a\n"): raise RuntimeError(f"{path} is not a PNG screenshot") return struct.unpack(">II", data[16:24]) SCREENSHOT.parent.mkdir(exist_ok=True) driver = webdriver.Remote( APPIUM_SERVER, options=UiAutomator2Options().load_capabilities(capabilities), ) try: if not driver.save_screenshot(str(SCREENSHOT)): raise RuntimeError("Appium did not save the screenshot") width, height = png_size(SCREENSHOT) print(f"session={driver.session_id}") print(f"saved={SCREENSHOT}") print("format=PNG") print(f"size={width}x{height}") finally: driver.quit()
Replace the package, activity, device name, and target filename with values from the app under test. The Appium Python Client adds the appium: vendor prefix for Appium-specific capability names when UiAutomator2Options sends the session request.
Related: How to configure Appium capabilities
$ python3 capture_appium_screenshot.py session=2e5f6d4c-9f1b-4d52-8e65-4cf2f8d96a15 saved=screenshots/settings-home.png format=PNG size=360x800
The session line confirms the script used an active Appium driver session. The PNG and size lines confirm that the saved file is an image rather than an empty artifact or error page.
from datetime import datetime, timezone from pathlib import Path stamp = datetime.now(timezone.utc).strftime("%Y%m%d-%H%M%S") SCREENSHOT = Path(f"screenshots/{stamp}-settings-home.png")
A fixed filename such as settings-home.png is fine for a single smoke test, but parallel CI jobs can overwrite it before the report uploader collects the file.
For local debugging, open screenshots/settings-home.png after the run. For CI, publish the whole screenshots directory with the same job that stores logs and test reports.