Skip to main content

Capturing Screenshots

Capture App Store screenshots directly from iOS/iPadOS simulators using UI tests. Replaces fastlane snapshot.

Quick start

ascelerate screenshot init                  # Create config and helper in ascelerate/
ascelerate screenshot # Capture screenshots

Commands

Run

ascelerate screenshot                       # Capture screenshots
ascelerate screenshot run # Same as above

Always uses ascelerate/screenshot.yml in the current directory.

Init

ascelerate screenshot init

Creates both ascelerate/screenshot.yml and ascelerate/ScreenshotHelper.swift in the ascelerate/ directory. Prompts for confirmation before writing. Won't overwrite existing files.

Create helper

ascelerate screenshot create-helper         # Generates ScreenshotHelper.swift
ascelerate screenshot create-helper -o CustomHelper.swift

Frame

ascelerate screenshot frame                    # Frame screenshots with device bezels

Frames captured screenshots using device bezel images. Uses the frameDevice and deviceBezel settings from the config. Can be run independently after capturing screenshots.

Doctor

ascelerate screenshot doctor                   # Check config and environment

Validates the screenshot configuration and environment: checks config file, project/workspace existence, xcodebuild and simctl availability, simulator devices, helper file version, device bezel files, and output directories. Shows a checklist with pass/fail/warning indicators.

Config (ascelerate/screenshot.yml)

workspace: MyApp.xcworkspace
# project: MyApp.xcodeproj # Use project instead of workspace
scheme: AppUITests
devices:
- simulator: iPhone 17 Pro Max
# frameDevice: true
# deviceBezel: ./bezels/iPhone 17 Pro Max.png
- simulator: iPad Pro 13-inch (M5)
# frameDevice: true
# deviceBezel: ./bezels/iPad Pro 13-inch (M5).png
languages:
- en-US
- de-DE
outputDirectory: ./screenshots
# framedOutputDirectory: ./screenshots/framed
clearPreviousScreenshots: true
eraseSimulator: false
localizeSimulator: true
overrideStatusBar: true
darkMode: false
disableAnimations: true
waitAfterBoot: 0
# waitAfterEraseAndReboot: 30 # Extra wait for first-run system alerts (e.g. Apple Intelligence)
# statusBarArguments: "--time '9:41' --dataNetwork wifi"
# testWithoutBuilding: true # Skip build, use existing xctestrun
# cleanBuild: false
# headless: false # Don't open Simulator.app
# helperPath: AppUITests/ScreenshotHelper.swift
# launchArguments:
# - -ui_testing
# configuration: Debug # Build configuration
# testplan: MyTestPlan # Xcode test plan name
# numberOfRetries: 0 # Retry failed languages (erase + reboot simulator)
# stopAfterFirstError: false # Stop all devices on first failure
# reinstallApp: false # Delete and reinstall app before tests
# xcargs: SWIFT_ACTIVE_COMPILATION_CONDITIONS=SCREENSHOTS

UITest usage

Add ScreenshotHelper.swift to your UITest target:

override func setUp() {
setupScreenshots(app)
app.launch()
}

func testScreenshots() {
screenshot("01-home")
app.buttons["Settings"].tap()
screenshot("02-settings")
}

Your app can detect screenshot mode via:

if ProcessInfo.processInfo.arguments.contains("-ASC_SCREENSHOT") {
// Show demo data, hide debug UI, etc.
}

The helper also provides disableAnimationsIfNeeded() to turn off animations when disableAnimations is enabled in the config:

override func setUp() {
setupScreenshots(app)
disableAnimationsIfNeeded()
app.launch()
}

How it works

  1. Builds once with build-for-testing (or skips if testWithoutBuilding: true)
  2. For each language: boots all simulators, localizes, overrides status bar
  3. Runs tests concurrently across devices
  4. If numberOfRetries is set and any device fails: erases failed simulators, re-localizes, reboots, and retries
  5. Collects screenshots from per-device cache to output directory
  6. Frames screenshots with device bezels (if frameDevice is enabled)
  7. Errors skip and continue — error logs saved to output

Output

screenshots/
├── en-US/
│ ├── iPhone 17 Pro Max-01-home.png
│ ├── iPhone 17 Pro Max-02-settings.png
│ └── iPad Pro 13-inch (M5)-01-home.png
└── de-DE/
└── ...

Device framing

Frame captured screenshots with Apple device bezels.

info

Device bezels are not included with ascelerate — download them from Apple Product Bezels (requires an Apple Developer account). The download is a DMG file containing PNG bezels for all current devices.

Setup

  1. Download the Product Bezels DMG from Apple Design Resources
  2. Extract the bezel PNG files to a folder in your project (e.g. ./bezels/)
  3. Enable framing per device in the config:
devices:
- simulator: iPhone 17 Pro Max
frameDevice: true
deviceBezel: ./bezels/iPhone 17 Pro Max.png
- simulator: iPad Pro 13-inch (M5)
frameDevice: false

Output

Framed screenshots are saved to framedOutputDirectory (defaults to {outputDirectory}/framed):

screenshots/framed/
├── en-US/
│ └── iPhone 17 Pro Max-01-home.png
└── de-DE/
└── ...

Only devices with frameDevice: true are framed. Framing runs automatically after each language during screenshot run, or standalone via screenshot frame.

Options

OptionDescription
clearPreviousScreenshotsClear language folder before collecting (only if all devices succeed)
eraseSimulatorErase simulator before each language
localizeSimulatorSet simulator language/locale per language
overrideStatusBarOverride status bar (9:41, full bars, Wi-Fi)
statusBarArgumentsCustom xcrun simctl status_bar arguments
darkModeEnable dark mode on simulators
disableAnimationsDisable animations during tests
waitAfterBootSeconds to wait after simulator boot (default: 0)
waitAfterEraseAndRebootExtra seconds to wait when the simulator is in a fresh state — first language of the run, or any time the simulator was erased (via eraseSimulator: true or a retry). Gives first-run system alerts (e.g. "Apple Intelligence is ready") time to appear before screenshots.
testWithoutBuildingSkip build, use existing xctestrun file
cleanBuildRun clean before building
headlessDon't open Simulator.app
helperPathPath to ScreenshotHelper.swift for version checking
launchArgumentsExtra launch arguments passed to the app
configurationBuild configuration (e.g. Debug, Release)
testplanXcode test plan name
numberOfRetriesNumber of times to retry failed languages — erases the simulator, re-localizes, reboots, and reruns tests. Only retries failed devices. Retried results are marked in the summary table.
stopAfterFirstErrorStop all devices after the first failure
reinstallAppDelete and reinstall the app before running tests
xcargsExtra arguments passed to xcodebuild
frameDeviceEnable device bezel framing for this device (per-device)
deviceBezelPath to the device bezel PNG file (per-device)
framedOutputDirectoryOutput directory for framed screenshots (default: {outputDirectory}/framed)