How do you capture clean iOS Simulator screenshots?
Published
Short answer
Boot a 6.9-inch class simulator — iPhone 17 Pro Max, iPhone 16 Pro Max or iPhone Air — so xcrun simctl io booted screenshot writes pixels that already match an accepted App Store size, with no resampling. Before capturing, override the status bar with xcrun simctl status_bar booted override so every screenshot shows the same time, full signal and full battery, instead of whatever the clock read when you tapped. Resizing the Simulator window never changes the pixels a screenshot captures — capture reads the device framebuffer, not the on-screen window. Batch the sequence per device, per appearance and per locale, then clear the override.
Key points
- Match the device to the display class:
iPhone 17 Pro MaxandiPhone 16 Pro Maxcapture natively at 1320 × 2868, andiPhone Airat 1260 × 27362 (source 2)3 (source 3) — both are accepted 6.9-inch App Store sizes, so nothing needs resampling before upload. xcrun simctl status_bar <device> overridesets a fixed time, battery level and signal state in one call — flags include--time,--batteryLevel,--batteryState,--cellularBarsand--wifiBars6 (source 6).- A resized Simulator window is a display convenience, not a resample.
simctl io screenshotreads the device’s rendering directly, so a window shrunk to fit your monitor still produces a full-resolution file. - Status bar overrides are undocumented outside
--helpoutput and have had version-dependent glitches on past Xcode releases, by report on Apple’s own developer forums7 (source 7). Verify one screenshot from a fresh capture run before batching the rest. - The simulator is not the device: it has no real camera, no access to your photo library, and does not run every GPU path a physical phone does. Camera previews, AR and some Metal-heavy screens still need a hardware capture.
Choosing the right simulator
Pick a simulator whose native pixel size already lands on an accepted App Store size1 (source 1) — see the accepted size table for the full list. Get this right and every raw capture is upload-ready at full resolution; get it wrong and you are resizing images before you have even opened a design tool.
| Simulator device | Native portrait capture size | App Store display class |
|---|---|---|
| iPhone 17 Pro Max | 1320 × 28682 (source 2) | 6.9″, accepted |
| iPhone 16 Pro Max | 1320 × 2868 | 6.9″, accepted |
| iPhone Air | 1260 × 27363 (source 3) | 6.9″, accepted |
| iPhone 15 Pro Max / iPhone 14 Pro Max | 1290 × 27964 (source 4) | 6.9″, accepted |
Confirm what is actually installed before you plan a shoot — device availability depends on which Simulator runtimes your Xcode has downloaded:
xcrun simctl list devices available— every booted or bootable device, grouped by iOS runtime.xcrun simctl list devicetypes— every device model Xcode knows how to create, including ones with no runtime installed yet.
Cleaning the status bar before you capture
A raw simulator screenshot carries whatever the clock read when you tapped, plus a battery level and signal state that changes between runs. A marketing set built from ten screenshots with ten different times and battery levels looks assembled, not designed. Fix all three before you capture anything.
There is no public Apple web page for simctl status_bar; the flags below come straight from xcrun simctl status_bar booted override --help on a current Xcode install. A worked example using the same flags is documented independently by developer Jesse Squires6 (source 6).
xcrun simctl status_bar booted override --time "9:41" --batteryState charged --batteryLevel 100 --cellularMode active --cellularBars 4 --wifiMode active --wifiBars 3- Capture as many screenshots as you need — the override holds until you clear it or shut the device down.
xcrun simctl status_bar booted listto confirm the override is actually active, if a screenshot still looks wrong.xcrun simctl status_bar booted clearwhen you are done, so your own day-to-day testing on that simulator is not stuck on a 9:41 clock and a full battery.
Capturing at native resolution
Dragging the Simulator window smaller does not shrink what a screenshot captures. xcrun simctl io booted screenshot reads the booted device’s own framebuffer and writes it out at full size — it has no concept of the host window’s zoom level, because the window is just a viewer onto that framebuffer, not the source of it.
xcrun simctl bootstatus "iPhone 17 Pro Max" -b— boots the device if needed and blocks until it has finished booting.xcrun simctl launch booted com.example.yourapp— launch your app, then navigate to the screen you want.xcrun simctl status_bar booted override --time "9:41" --batteryState charged --batteryLevel 100 --cellularMode active --cellularBars 4 --wifiMode active --wifiBars 3xcrun simctl io booted screenshot 01-onboarding.pngxcrun simctl status_bar booted clearbefore you shut down or move to the next screen, unless you are about to capture another shot that wants the same override.xcrun simctl shutdown bootedonce a device is done, so a stray booted simulator does not answer tobootedon your next run.
Dark mode, light mode and locale variants
If you ship more than one appearance or language, capture every variant from the same script rather than by hand — it is the only way the set stays consistent when a screen changes six months later.
- Appearance:
xcrun simctl ui booted appearance darkorxcrun simctl ui booted appearance lightswitches the whole device immediately — no reboot, no relaunch required. - Locale: relaunch with
-AppleLanguagesand-AppleLocaleas launch arguments, e.g.xcrun simctl launch booted com.example.yourapp -AppleLanguages "(de)" -AppleLocale "de_DE". Apple documents these two flags as the standard way to force a language and region without changing the simulator’s system settings5 (source 5).
Name files so the variant is legible from the filename alone, before you have opened a single one: device, appearance, locale, then an ordered screen number and a short slug — iphone17promax-dark-de-01-onboarding.png. A batch script that loops devices × appearances × locales and writes files in that pattern is worth the half hour it takes to write the first time.
What the simulator can’t show you
The Simulator is a device model running on your Mac’s hardware, not an emulated iPhone. Two consequences matter for a screenshot set: there is no camera, so any screen behind a live camera preview shows either a black frame or a static placeholder image instead of what a customer sees; and rendering runs through your Mac’s GPU rather than the phone’s, so a small number of Metal-heavy effects and some AR content do not look the same as they do on hardware.
For those screens, capture from a real device instead — the device’s own screenshot gesture (side button and volume up, on current hardware) — and drop the resulting file into the same batch alongside your simulator captures. Everything else in this guide still applies: same target resolution, same status bar convention, same naming pattern.
Once the raw set is clean and at the right resolution, the next step is turning it into an actual marketing set — see building the marketing set. Shotluma is a free, MIT-licensed, browser-based tool built for exactly that handoff — it takes raw captures like these and turns them into an editable, store-ready set, exporting at 1290 × 2796 and 1242 × 2688.
Frequently asked questions
Do I need a full Xcode install, or does the standalone Command Line Tools package work?
A full Xcode install. xcrun simctl needs the Simulator runtimes that ship inside Xcode itself, not the smaller Command Line Tools package. If xcrun simctl list devices comes back empty, check xcode-select -p and point it at a full Xcode.app with xcode-select -s if it is not already.
Can I capture landscape screenshots the same way?
io screenshot saves whatever orientation the device is currently rendering — there is no separate landscape flag. Rotate the device first, in the Simulator app or from your own UI test code, then run the same screenshot command.
Does a status bar override risk getting an App Store submission rejected?
No. The override only changes what the simulator renders locally, before you take the screenshot. App Store Connect receives a plain image file and has no way to know it came from an overridden status bar rather than a lucky, fully-charged moment on a real phone.
What if the device I need isn’t in `xcrun simctl list devices`?
The device type exists but its runtime is not installed. Open Xcode’s Settings, go to the Platforms tab, and download the matching iOS Simulator runtime — then re-run xcrun simctl list devicetypes to confirm it is available before you try to boot it.
Can I script walking through every screen instead of navigating by hand?
simctl captures pixels; it does not know your app’s navigation. xcrun simctl openurl booted "yourapp://screen-name" opens a deep link if your app supports one, which is usually the fastest way to jump straight to a screen for a batch script. Full walkthroughs are better handled by an XCUITest that stops and shells out to the screenshot command at each screen.
Sources
- 1Screenshot specifications — App Store Connect Help — Apple Developer, iPhone 6.9-inch display class, accepted portrait sizes. Read .
- 2iPhone 17 Pro Max - Tech Specs — Apple Support, Display section, resolution figure. Read .
- 3iPhone Air - Tech Specs — Apple Support, Display section, resolution figure. Read .
- 4iPhone 15 Pro Max - Tech Specs — Apple Support, Display section, resolution figure. Read .
- 5Testing Your Internationalized App — Apple Developer, -AppleLanguages and -AppleLocale launch argument syntax. Read .
- 6Overriding status bar display settings in the iOS simulator — Jesse Squires, Worked `simctl status_bar override` example command. Read .
- 7Simulator not reflecting simctl override --time command as expected — Apple Developer Forums, Thread replies describing version-dependent regressions. Read .