Screenshots.live
Team
How to Automate App Store Screenshots with Fastlane and a REST API
Learn how to build a fully automated screenshot pipeline using Screenshots.live REST API and Fastlane, eliminating days of manual work from every release cycle.
The Manual Screenshot Problem
If you have ever shipped a mobile app, you know the pain. Every release cycle, you open Figma or Sketch, manually update screenshots for every device size, every language, every screen. For a single app supporting iPhone, iPad, and Android across 10 localizations, you could be looking at hundreds of individual assets to produce, export, and upload.
Most teams spend anywhere from one to three full days on this process per release. And the worst part? It is almost entirely repetitive. The design template stays the same. The device frames stay the same. Only the screenshot content and text change.
There is a better way.
The Automated Alternative: Screenshots.live + Fastlane
In this guide, we will walk through setting up a fully automated screenshot pipeline using Screenshots.live and Fastlane. By the end, your CI/CD pipeline will generate, localize, and upload all your app store screenshots without any manual intervention.
Here is what the workflow looks like:
- You design your screenshot templates once in the Screenshots.live visual editor.
- You define variables (headline text, screenshot image, background color) in each template.
- Your Fastlane pipeline calls the Screenshots.live REST API, swapping in localized text and fresh screenshots.
- Fastlane uploads the finished images directly to App Store Connect or Google Play.
Prerequisites
Before we start, make sure you have the following:
- A Screenshots.live account with at least one template created.
- An API key from your Screenshots.live dashboard (Settings > API Keys).
- Fastlane installed and configured for your project.
- Ruby 2.7+ (for Fastlane).
- A CI/CD environment such as GitHub Actions, GitLab CI, or Bitrise.
Step 1: Design Your Templates
Log in to Screenshots.live and open the visual editor. Create a template for each screenshot slot you need. For most apps, that is 4 to 8 templates covering your key features.
The key concept is dynamic variables. When you design your template, you insert variable placeholders instead of hardcoding text or images:
{{headline}}for the marketing text overlay{{screenshot}}for the actual device screenshot{{background_color}}for theme customization
Each template automatically supports every device size: iPhone 6.7", iPhone 6.5", iPad Pro, and all standard Android resolutions. You design once, and Screenshots.live renders to every required dimension.
Step 2: Get Your API Credentials
Navigate to your dashboard and generate an API key. You will need two values:
- Your API key (a bearer token for authentication)
- Your template IDs (visible in the template editor URL or via the API)
Store your API key as an environment variable. Never commit it to your repository:
export SCREENSHOTS_LIVE_API_KEY="sk_live_your_api_key_here"Step 3: Test the API Directly
Before integrating with Fastlane, verify the API works with a simple cURL request:
curl -X POST https://api.screenshots.live/v1/render \
-H "Authorization: Bearer $SCREENSHOTS_LIVE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"templateId": "tpl_abc123",
"variables": {
"headline": "Track your habits effortlessly",
"screenshot": "https://your-bucket.s3.amazonaws.com/screen1.png"
},
"deviceFrames": ["iphone_6.7", "iphone_6.5", "ipad_pro"]
}'The API returns a JSON response with download URLs for each rendered image. You can also request a synchronous render that returns the image data directly.
Step 4: Create Your Localization Config
Create a YAML file that maps each locale to its translated text. This is the single source of truth for all your screenshot copy:
# screenshots.yml
locales:
en:
screenshots:
- template: tpl_abc123
variables:
headline: "Track your habits effortlessly"
screenshot: screens/en/home.png
- template: tpl_def456
variables:
headline: "Beautiful charts and insights"
screenshot: screens/en/stats.png
- template: tpl_ghi789
variables:
headline: "Set reminders that work"
screenshot: screens/en/reminders.png
de:
screenshots:
- template: tpl_abc123
variables:
headline: "Verfolge deine Gewohnheiten muhelos"
screenshot: screens/de/home.png
- template: tpl_def456
variables:
headline: "Anschauliche Diagramme und Einblicke"
screenshot: screens/de/stats.png
- template: tpl_ghi789
variables:
headline: "Erinnerungen, die funktionieren"
screenshot: screens/de/reminders.png
es:
screenshots:
- template: tpl_abc123
variables:
headline: "Rastrea tus habitos sin esfuerzo"
screenshot: screens/es/home.png
device_frames:
ios:
- iphone_6.7
- iphone_6.5
- ipad_pro_12_9
android:
- phone
- tablet_7
- tablet_10Step 5: Write the Fastlane Integration
Now create a custom Fastlane action or lane that reads your YAML config, calls the Screenshots.live API for each locale and template, and saves the results to the correct directory structure.
Add this to your Fastfile:
require 'yaml'
require 'net/http'
require 'json'
require 'fileutils'
platform :ios do
desc "Generate and upload localized screenshots"
lane :screenshots do
generate_screenshots
upload_to_app_store(
skip_binary_upload: true,
skip_metadata: true,
screenshots_path: "./fastlane/screenshots"
)
end
end
platform :android do
desc "Generate and upload localized screenshots"
lane :screenshots do
generate_screenshots(platform: "android")
upload_to_play_store(
skip_upload_apk: true,
skip_upload_aab: true,
skip_upload_metadata: true,
skip_upload_changelogs: true,
images_path: "./fastlane/android_screenshots"
)
end
end
private_lane :generate_screenshots do |options|
platform = options[:platform] || "ios"
config = YAML.load_file("screenshots.yml")
api_key = ENV["SCREENSHOTS_LIVE_API_KEY"]
device_frames = config["device_frames"][platform]
config["locales"].each do |locale, data|
data["screenshots"].each_with_index do |entry, index|
UI.message("Rendering #{locale} screenshot #{index + 1}...")
uri = URI("https://api.screenshots.live/v1/render")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{api_key}"
request["Content-Type"] = "application/json"
request.body = {
templateId: entry["template"],
variables: entry["variables"],
deviceFrames: device_frames
}.to_json
response = http.request(request)
result = JSON.parse(response.body)
result["images"].each do |image|
output_dir = "./fastlane/screenshots/#{locale}"
FileUtils.mkdir_p(output_dir)
File.write(
"#{output_dir}/#{image['device']}_#{index}.png",
Net::HTTP.get(URI(image["url"]))
)
end
end
end
endStep 6: Integrate with CI/CD
The final step is wiring this into your CI/CD pipeline. Here is a GitHub Actions example:
# .github/workflows/screenshots.yml
name: Generate App Store Screenshots
on:
push:
branches: [main]
paths:
- 'screenshots.yml'
- 'screens/**'
workflow_dispatch:
jobs:
generate:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.2'
bundler-cache: true
- name: Install Fastlane
run: bundle install
- name: Generate and upload screenshots
env:
SCREENSHOTS_LIVE_API_KEY: ${{ secrets.SCREENSHOTS_LIVE_API_KEY }}
APP_STORE_CONNECT_API_KEY: ${{ secrets.ASC_API_KEY }}
run: |
bundle exec fastlane ios screenshots
bundle exec fastlane android screenshotsNow every time you push a change to your screenshot config or source screens, the pipeline automatically regenerates and uploads all assets.
Before and After: The Real Impact
Before: The Manual Workflow
- Designer opens Figma, manually places new screenshots into 6 templates.
- Exports for 3 device sizes per platform = 36 images per language.
- With 10 languages: 360 images to export and organize.
- Uploads manually through App Store Connect and Google Play Console.
- Time: 2 to 3 days per release cycle.
- Error rate: high. Wrong screenshot in wrong locale happens constantly.
After: The Automated Pipeline
- Developer updates
screenshots.ymlwith new text or screenshots. - Pushes to main. CI/CD runs automatically.
- All 360+ images generated and uploaded in under 15 minutes.
- Zero manual intervention. Zero misplaced assets.
- Time saved per release: 2+ days.
Advanced: Dynamic A/B Testing
Once your pipeline is automated, you can take it further. Use the Screenshots.live API to generate multiple variants of each screenshot with different headlines, colors, or layouts. Feed these into your ASO A/B testing tool and let data decide which converts best.
# Generate A/B variants
variants:
- name: "control"
variables:
headline: "Track your habits effortlessly"
background_color: "#1a1a2e"
- name: "variant_b"
variables:
headline: "Build better habits today"
background_color: "#0f3460"Since rendering is API-driven, generating 10 variants costs you seconds, not days.
Troubleshooting Common Issues
API Rate Limits
If you are generating hundreds of images in a tight loop, you may hit rate limits. Add a small delay between requests or use the batch endpoint to render multiple templates in a single call.
Image Quality
Always provide source screenshots at the highest resolution available. Screenshots.live will downscale as needed but cannot upscale without quality loss.
Fastlane Upload Failures
Ensure your output directory structure matches what Fastlane expects. For iOS, images must be in locale-named subdirectories. For Android, follow the Play Store image type conventions.
Conclusion
Automating your app store screenshots is one of the highest-leverage improvements you can make to your release process. With Screenshots.live handling the rendering and Fastlane handling the upload, you eliminate days of manual work and reduce errors to zero.
The initial setup takes about an hour. After that, every release ships with perfect, localized screenshots automatically. Get started with Screenshots.live and reclaim your release days.