# karagoz screenshot

Saves the screen as a PNG at full device resolution, never scaled, and prints where it went with the metadata needed to measure against it.

- Android emulator Done
- Android device Done
- iOS simulator Done
- iOS device Done

## Usage

```console title="~/app"
karagoz screenshot [--out <path>] [--device <id>]
```

## Before you start

- On an iOS simulator: Xcode, opened once, and a booted simulator (on Xcode 27, `xcrun simctl boot <name>`; on older ones, `open -a Simulator`).
- On an iPhone: paired with the Mac, Developer Mode on (Settings > Privacy & Security > Developer Mode), and Xcode 27 or newer, opened once: Xcode 26’s `devicectl` has no `device capture screenshot`.

## Options

| Option          | Default                                                               | Meaning                                                         |
| --------------- | --------------------------------------------------------------------- | --------------------------------------------------------------- |
| `--out <path>`  | a new file under the temp directory                                   | Where to write the PNG; must end in `.png`, in any letter case. |
| `--device <id>` | see [Device selection](https://karagozmcp.com/docs/device-selection/) | An adb serial, a simulator’s or iPhone’s UDID, or a name.       |

## Examples

### Save to a file

```console title="~/app"
$ karagoz screenshot --out home.png
{"path":"/Users/me/home.png","device":"emulator-5554","pixels":{"width":1080,"height":2400},"logical":{"width":411.42857142857144,"height":914.2857142857143},"scale":2.625,"safeArea":{"top":63,"right":0,"bottom":63,"left":0},"rotation":0}
```

## Output

An iPhone 17 simulator (macOS, Xcode 27), without `--out`:

```json
{
  "path": "/var/folders/.../T/karagoz/27024DC1-EDB0-4BF2-8010-08FE3936BAB6-20261012T182033769Z.png",
  "device": "27024DC1-EDB0-4BF2-8010-08FE3936BAB6",
  "pixels": { "width": 1206, "height": 2622 },
  "logical": { "width": 402, "height": 874 },
  "scale": 3,
  "safeArea": null,
  "rotation": 0
}
```

- `path` string: Absolute path of the PNG.
- `device` string: The adb serial, or the simulator's or iPhone's UDID.
- `pixels` object: Size of the PNG, read from the file itself.
- `pixels.width` number: Size of the PNG, read from the file itself.
- `pixels.height` number: Size of the PNG, read from the file itself.
- `logical` object: `pixels / scale`, not rounded.
- `logical.width` number: `pixels / scale`, not rounded.
- `logical.height` number: `pixels / scale`, not rounded.
- `scale` number: Physical pixels per density-independent pixel on Android, per point on iOS ([Coordinates](https://karagozmcp.com/docs/output/#coordinates)). See below.
- `safeArea` object or null: Pixels of this PNG covered by the status bar, navigation bar, caption bar or display cutout. `null` on iOS. See below.
- `safeArea.top` number: Pixels of this PNG covered by the status bar, navigation bar, caption bar or display cutout.
- `safeArea.right` number: Pixels of this PNG covered by the status bar, navigation bar, caption bar or display cutout.
- `safeArea.bottom` number: Pixels of this PNG covered by the status bar, navigation bar, caption bar or display cutout.
- `safeArea.left` number: Pixels of this PNG covered by the status bar, navigation bar, caption bar or display cutout.
- `rotation` number or null: Screen rotation in degrees: `0`, `90`, `180` or `270`. `null` on Xcode 26 and earlier, or when `devicectl` fails. See below.

How `scale` is read:

- Android: density / 160, using the override density if one is set (`adb shell wm density`).
- Simulator: its `SIMULATOR_MAINSCREEN_SCALE`.
- iPhone: the `pointScale` that `devicectl device info displays` reports for the primary display.
- On both iOS targets a 1080x2340 or 2340x1080 PNG (iPhone 12 mini, 13 mini) gets `2.88` (1080 / 375): the simulator reports 3 there, but apps lay out 375 points wide.

In `safeArea` a hidden bar counts as 0, and the keyboard and gesture areas are not included. It is `null` on iOS: only the app itself can read its safe area, and neither the simulator nor `devicectl` exposes another source.

On iOS with Xcode 27, `rotation` is the interface orientation from `devicectl`, in Android’s meaning: turned counter-clockwise (landscape left) is `90`.

On iOS the PNG is exactly what simctl or devicectl wrote; Karagöz does not rotate or re-encode it.

- On a simulator with Xcode 27, the PNG follows the interface orientation. With Xcode 26 it is the panel in portrait, and a landscape app’s UI is drawn sideways in it.
- A simulator’s PNG has square corners, not rounded ones, and the Dynamic Island area is black pixels.
- An iPhone’s PNG follows the interface orientation and has 16 bits per channel and a Display P3 color profile.

## File location

- Without `--out`: `<temp dir>/karagoz/<device id>-<UTC timestamp>.png`, for example `/var/folders/.../T/karagoz/emulator-5554-20260926T101530123Z.png`.

  - The device id is a UDID on iOS. Characters other than letters, digits, `.`, `_` and `-` in it become `_`.
  - The temp directory follows `TMPDIR`.
  - The `karagoz` directory is created private to your user (mode 0700) and must be a real directory you own.
  - The file is created with mode 0600 and never overwrites.

- With `--out`: relative paths resolve against the current directory, missing parent directories are created, and an existing `.png` is overwritten.

- Karagöz never deletes screenshots. The size of one capture:

  - about 1.4 MB at 1080x2400
  - about 2.9 MB from a 1206x2622 simulator
  - 1 to 5 MB from a 1290x2796 iPhone, depending on what is on screen

## Errors

| Code                                                                              | When                                                                                                                                                                                            |
| --------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`CAPTURE_FAILED`](https://karagozmcp.com/docs/error-codes/#capture-failed)       | On Android: screencap returned something other than a whole PNG. Its message is included.                                                                                                       |
| [`CAPTURE_FAILED`](https://karagozmcp.com/docs/error-codes/#capture-failed)       | On Android: the density, display size, rotation or insets could not be read (`cannot read <value> from <command>`).                                                                             |
| [`CAPTURE_FAILED`](https://karagozmcp.com/docs/error-codes/#capture-failed)       | On Android: the screen rotated or resized during the capture (`display is WxH but the screenshot is WxH`).                                                                                      |
| [`CAPTURE_FAILED`](https://karagozmcp.com/docs/error-codes/#capture-failed)       | On Android with more than one display: screencap's warning comes back as this error.                                                                                                            |
| [`CAPTURE_FAILED`](https://karagozmcp.com/docs/error-codes/#capture-failed)       | On a simulator: simctl printed something other than a whole PNG (its text, or `simctl returned no image data`).                                                                                 |
| [`CAPTURE_FAILED`](https://karagozmcp.com/docs/error-codes/#capture-failed)       | On a simulator: the scale could not be read (`cannot read scale from 'simctl getenv' (got '<value>')`).                                                                                         |
| [`CAPTURE_FAILED`](https://karagozmcp.com/docs/error-codes/#capture-failed)       | On an iPhone: `devicectl returned no image data`, or `cannot read scale from 'devicectl device info displays'`.                                                                                 |
| [`CAPTURE_FAILED`](https://karagozmcp.com/docs/error-codes/#capture-failed)       | On an iPhone: `the screen rotated during the capture (rotation <r>, screenshot <w>x<h>)` when the phone turned between the capture and the display read.                                        |
| [`SIMCTL_FAILED`](https://karagozmcp.com/docs/error-codes/#simctl-failed)         | On iOS the capture failed; the message is simctl's text. The first capture right after a boot can fail with `Error creating the image`.                                                         |
| [`SIMCTL_TIMEOUT`](https://karagozmcp.com/docs/error-codes/#simctl-timeout)       | After 30 s.                                                                                                                                                                                     |
| [`SIMCTL_NOT_FOUND`](https://karagozmcp.com/docs/error-codes/#simctl-not-found)   | Without Xcode.                                                                                                                                                                                  |
| [`DEVICE_NOT_READY`](https://karagozmcp.com/docs/error-codes/#device-not-ready)   | On an iPhone that is `unpaired` or `pairingInProgress`, before any capture.                                                                                                                     |
| [`DEVICE_NOT_READY`](https://karagozmcp.com/docs/error-codes/#device-not-ready)   | On an iPhone, from the capture: Developer Mode is off, the phone is no longer paired with this Mac, or it is locked since it restarted. In both cases the message says what to do on the phone. |
| [`NOT_SUPPORTED`](https://karagozmcp.com/docs/error-codes/#not-supported)         | On an iPhone, when this Mac's `devicectl` predates Xcode 27.                                                                                                                                    |
| [`DEVICECTL_TIMEOUT`](https://karagozmcp.com/docs/error-codes/#devicectl-timeout) | On an iPhone, after 30 s.                                                                                                                                                                       |
| [`DEVICECTL_FAILED`](https://karagozmcp.com/docs/error-codes/#devicectl-failed)   | On an iPhone, with devicectl's text for any other failure.                                                                                                                                      |
| [`WRITE_FAILED`](https://karagozmcp.com/docs/error-codes/#write-failed)           | The file could not be written, or the default directory is not yours (`pass --out`). Two captures of one device in the same millisecond without `--out`: the second fails.                      |
| [`INVALID_ARGS`](https://karagozmcp.com/docs/error-codes/#invalid-args)           | `'<absolute path>' is not a .png file` for an `--out` that does not end in `.png`, before any device call.                                                                                      |

Plus the [device selection errors](https://karagozmcp.com/docs/device-selection/#errors), the other [`INVALID_ARGS`](https://karagozmcp.com/docs/error-codes/#invalid-args) cases and the adb errors.

## Notes

- A capture takes about:

  - 1 s on the emulator
  - 0.5 s on a phone over USB
  - 0.6 s on a simulator
  - 0.9 s on an iPhone over USB. The first call after the iPhone was plugged in or sat idle takes a few seconds more while devicectl connects to it.

- A screen that is off, or an app that sets `FLAG_SECURE`, gives a black PNG and exit `0`; so does a locked iPhone with its screen off.

- Some Android 14 builds refuse the capture instead while a `FLAG_SECURE` window or the lock screen’s PIN pad is showing: [`CAPTURE_FAILED`](https://karagozmcp.com/docs/error-codes/#capture-failed) with `screencap returned no data`.

- If the density changes during a capture, `scale` and `safeArea` can disagree for that one capture.

## MCP equivalent

MCP equivalent `screenshot {"out":"home.png"}` [MCP tools](https://karagozmcp.com/docs/mcp/#tools)

Arguments: `out`, `inline`, `device`. The names are the CLI's option and positional names.
