# Observe

Source: https://phonebox.dev/docs/api-reference/observe

> Read the screen as numbered elements or compact text, and take screenshots with their scale.



Both endpoints read the phone's screen, so the phone must be `ready`, and both count as activity that keeps the phone from idling, unless the key is Read-only. [Observe the screen](/docs/using-phones/observe) explains every field, which elements are listed, and the text form.

## Observe the screen [#observe-the-screen]

`GET /v1/phones/{id}/observe` needs the `phones:read` scope.

Reads the screen and stores its element list as a snapshot for 15 minutes, so that actions can target elements by `ref` together with the `snapshot_id`.

| Parameter    | Type    | Default            | Rules                                                          |
| ------------ | ------- | ------------------ | -------------------------------------------------------------- |
| `screenshot` | string  | `none`             | `none`, `jpeg` or `png`. Adds a screenshot to the JSON.        |
| `max_width`  | integer | The screen's width | From 160 to 2000. The widest the screenshot may be, in pixels. |
| `format`     | string  | `json`             | `json`, or `text` for the text form alone.                     |

```bash
curl "https://phonebox.dev/v1/phones/ph_7kx2m6q4v3ta/observe?screenshot=jpeg&max_width=720" \
  -H "Authorization: Bearer $PHONEBOX_API_KEY"
```

The JSON answer is an observation. This one is shortened: `data` holds the image in base64.

```json title="Response: observation"
{
  "snapshot_id": "snp_4f2k7m3q6z3a",
  "taken_at": "2026-09-29T10:01:05.662Z",
  "app": { "package": "com.android.launcher3", "activity": null },
  "keyboard": { "visible": false, "focused_editable": false },
  "screen": { "width": 1080, "height": 2400 },
  "elements": [
    {
      "ref": 1, "type": "EditText", "text": "Search apps", "desc": null, "id": "com.android.launcher3:id/search",
      "bounds": [60, 200, 1020, 300], "center": [540, 250], "state": ["clickable", "editable"]
    },
    {
      "ref": 2, "type": "TextView", "text": "Chrome", "desc": null, "id": "com.android.launcher3:id/icon",
      "bounds": [100, 1800, 300, 2000], "center": [200, 1900], "state": ["clickable"]
    }
  ],
  "truncated": false,
  "text": "app com.android.launcher3\nkeyboard hidden\nscreen 1080x2400\n[1] EditText \"Search apps\" #search clickable editable (540,250)\n[2] TextView \"Chrome\" #icon clickable (200,1900)",
  "screenshot": { "format": "jpeg", "width": 720, "height": 1600, "scale": 0.666667, "data": "/9j/4AAQSkZJRgABAQAAAQABAAD…" }
}
```

`screenshot` is present only when you ask for one. Element coordinates are always device pixels, and `screenshot.scale` is the image's width divided by the screen's. The whole answer stays under 4 MB, so Phonebox shrinks a screenshot further when it has to.

With `format=text`, the answer is `text/plain; charset=utf-8`, holding the `text` field alone, and its `X-Snapshot-Id` header carries the snapshot ID. The text form never includes a screenshot.

| Error                   | When                                             |
| ----------------------- | ------------------------------------------------ |
| `400 validation_failed` | A parameter is outside its range or given twice. |

The readiness and phone-service errors in [Common errors](/docs/api-reference#common-errors) apply too.

## Take a screenshot [#take-a-screenshot]

`GET /v1/phones/{id}/screenshot` needs the `phones:read` scope.

Returns the screen as an image, not JSON.

| Parameter   | Type    | Default            | Rules                                                     |
| ----------- | ------- | ------------------ | --------------------------------------------------------- |
| `format`    | string  | `png`              | `png` or `jpeg`.                                          |
| `max_width` | integer | The screen's width | From 160 to 2000. The widest the image may be, in pixels. |
| `quality`   | integer | 70                 | From 30 to 95. JPEG quality. A PNG ignores it.            |

```bash
curl -o screen.jpg "https://phonebox.dev/v1/phones/ph_7kx2m6q4v3ta/screenshot?format=jpeg&max_width=720" \
  -H "Authorization: Bearer $PHONEBOX_API_KEY"
```

The answer is `image/png` or `image/jpeg`, always under 4 MB. Phonebox makes the image narrower when it would be larger. Three headers describe it:

| Header            | Meaning                                                                                                                   |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------- |
| `X-Screen-Width`  | The screen's width in device pixels.                                                                                      |
| `X-Screen-Height` | The screen's height in device pixels.                                                                                     |
| `X-Screen-Scale`  | The image's width divided by the screen's, to six decimal places. Divide a point on the image by it to get device pixels. |

| Error                   | When                                             |
| ----------------------- | ------------------------------------------------ |
| `400 validation_failed` | A parameter is outside its range or given twice. |

The readiness and phone-service errors in [Common errors](/docs/api-reference#common-errors) apply too.
