Automated App Store Screenshots
Set up Fastlane Snapshot to automatically capture App Store screenshots across multiple devices and languages.
Pre-flight Checks
- Fastlane installed: !
fastlane --version 2>/dev/null | grep "fastlane " | head -1 || echo "✗ Not installed - run: brew install fastlane" - Fastfile exists: !
ls fastlane/Fastfile 2>/dev/null && echo "✓ Found" || echo "✗ Not found - run /setup-fastlane first" - Existing Snapfile: !
ls fastlane/Snapfile 2>/dev/null && echo "✓ Already configured" || echo "○ Not configured yet" - UI Test target: !
find . -maxdepth 3 -name "*UITests*" -type d 2>/dev/null | head -1 || echo "○ No UI test target found" - Simulators available: !
xcrun simctl list devices available | grep -E "iPhone|iPad" | head -3
Arguments: ${ARGUMENTS:-setup}
Why Automate Screenshots?
App Store requires screenshots for multiple device sizes. Manual capture means:
- 5+ device sizes × 5+ screenshots × N languages = hours of work
- Risk of inconsistency between screenshots
- Repeat everything for each app update
Snapshot automates this: run once, get all screenshots.
Step 1: Initialize Snapshot
fastlane snapshot init
This creates:
fastlane/Snapfile- Configuration filefastlane/SnapshotHelper.swift- Helper for UI tests
Step 2: Configure Snapfile
Edit fastlane/Snapfile:
# Devices to capture (App Store requirements)
devices([
"iPhone 15 Pro Max", # 6.7" display (required)
"iPhone 15 Pro", # 6.1" display
"iPhone SE (3rd generation)", # 4.7" display (if supporting older phones)
"iPad Pro 13-inch (M4)", # iPad screenshots (if universal app)
])
# Languages to capture
languages([
"en-US",
# "ja", # Japanese
# "de-DE", # German
# "fr-FR", # French
# "es-ES", # Spanish
])
# UI Test scheme
scheme("YourAppUITests")
# Output directory
output_directory("./fastlane/screenshots")
# Clear old screenshots before capture
clear_previous_screenshots(true)
# Stop on first error (set false to continue despite failures)
stop_after_first_error(true)
# Dark mode variants (iOS 13+)
# dark_mode(true)
# Workspace or project (uncomment one)
# workspace("YourApp.xcworkspace")
# project("YourApp.xcodeproj")
Step 3: Add SnapshotHelper to UI Tests
-
Add SnapshotHelper.swift to your UI test target:
- Drag
fastlane/SnapshotHelper.swiftinto Xcode - Ensure it's added to your UITests target (not main app)
- Drag
-
Import and configure in your UI test file:
import XCTest
class ScreenshotTests: XCTestCase {
override func setUpWithError() throws {
continueAfterFailure = false
let app = XCUIApplication()
setupSnapshot(app) // Initialize snapshot
app.launch()
}
func testTakeScreenshots() throws {
let app = XCUIApplication()
// Screenshot 1: Home screen
snapshot("01_HomeScreen")
// Navigate to feature and capture
app.buttons["Feature"].tap()
snapshot("02_FeatureScreen")
// Screenshot with content
app.textFields["Search"].tap()
app.textFields["Search"].typeText("Example")
snapshot("03_SearchResults")
// Settings screen
app.buttons["Settings"].tap()
snapshot("04_Settings")
// Any additional screens...
snapshot("05_DetailView")
}
}
Step 4: Run Snapshot
# Capture all screenshots
fastlane snapshot
# Specific device only
fastlane snapshot --devices "iPhone 15 Pro Max"
# Specific language only
fastlane snapshot --languages "en-US"
# Skip launch (use existing simulator state)
fastlane snapshot --skip_open_summary
Screenshots are saved to fastlane/screenshots/{language}/{device}/.
Step 5: Upload to App Store Connect
After capturing, upload with deliver:
# Upload screenshots only (no binary)
fastlane deliver --skip_binary_upload --skip_metadata
# Or use the screenshots lane from setup-fastlane
fastlane ios screenshots
App Store Screenshot Requirements (2024)
Required Device Sizes
| Display Size | Example Devices | Dimensions | |-------------|-----------------|------------| | 6.7" | iPhone 15 Pro Max, 14 Pro Max | 1290 × 2796 | | 6.5" | iPhone 15 Plus, 14 Plus, 11 Pro Max | 1284 × 2778 | | 5.5" | iPhone 8 Plus (legacy) | 1242 × 2208 | | 12.9" iPad | iPad Pro 12.9" | 2048 × 2732 |
Minimum: You need at least 6.7" or 6.5" iPhone screenshots. Other sizes can be auto-generated by App Store Connect.
Screenshot Count
- Minimum: 1 per device size
- Maximum: 10 per device size
- Recommended: 5-6 highlighting key features
Optional: Frame Screenshots with Device Bezels
Add device frames around screenshots using frameit:
# Install frameit
brew install imagemagick
# Frame screenshots
fastlane frameit
# Silver device frames
fastlane frameit silver
Create fastlane/screenshots/Framefile.json for custom titles:
{
"default": {
"title": {
"font": "./fonts/MyFont.ttf",
"color": "#000000"
},
"background": "#FFFFFF",
"padding": 50,
"show_complete_frame": true
}
}
Troubleshooting
"SnapshotHelper.swift not found"
Re-run fastlane snapshot init and add the helper to your UI test target.
"Unable to boot simulator"
Reset the simulator:
xcrun simctl shutdown all
xcrun simctl erase all
Screenshots are black/blank
- Ensure
setupSnapshot(app)is called beforeapp.launch() - Add small delays if content loads asynchronously:
sleep(1) // Wait for content
snapshot("01_HomeScreen")
"No matching device found"
Check available simulators:
xcrun simctl list devices available
Update Snapfile device names to match exactly.
UI test fails to find element
Use accessibility identifiers:
// In your app code
button.accessibilityIdentifier = "settingsButton"
// In UI test
app.buttons["settingsButton"].tap()
Integrate with Fastfile
Add a dedicated lane for screenshots:
lane :screenshots do
snapshot(
scheme: "YourAppUITests",
devices: ["iPhone 15 Pro Max", "iPad Pro 13-inch (M4)"],
languages: ["en-US"]
)
# Optional: frame screenshots
# frameit(white: true)
end
lane :upload_screenshots do
deliver(
skip_binary_upload: true,
skip_metadata: true,
overwrite_screenshots: true
)
end
Best Practices
- Use sample data: Pre-populate app with attractive demo content
- Consistent state: Reset app state before each test run
- Accessibility IDs: More reliable than text matching
- Handle async: Add waits for network content to load
- Dark mode: Capture both light and dark variants
- Localization: Test with actual translations, not placeholders
- Landscape: Include landscape screenshots for iPad if relevant
Files Created
fastlane/
├── Snapfile # Snapshot configuration
├── SnapshotHelper.swift # Helper for UI tests (copy to test target)
└── screenshots/
├── en-US/
│ ├── iPhone 15 Pro Max/
│ │ ├── 01_HomeScreen.png
│ │ ├── 02_FeatureScreen.png
│ │ └── ...
│ └── iPad Pro 13-inch (M4)/
│ └── ...
└── ja/
└── ...
Complete Workflow
# 1. Set up snapshot
fastlane snapshot init
# 2. Write UI tests with snapshot() calls
# 3. Capture screenshots
fastlane snapshot
# 4. Review screenshots in fastlane/screenshots/
# 5. Optional: add device frames
fastlane frameit
# 6. Upload to App Store Connect
fastlane deliver --skip_binary_upload --skip_metadata