Getting started5 min read

Reading the response

The four top-level fields, what each one carries, and how to read them in order.

A capture returns one JSON object. Most of it is not about the image. This page walks it in the order it is worth reading.

the full shape
{
  "source":    { "kind": "desktop", "display": ":1",
                 "x": 0, "y": 0, "width": 1920, "height": 1080 },
  "image":     { "width": 960, "height": 540,
                 "media_type": "image/jpeg", "format": "jpeg",
                 "byte_length": 14907, "encoding": "base64",
                 "quality": 75, "data": "/9j/4AAQSkZJRg..." },
  "transform": { "origin": "top-left",
                 "offset_x": 0, "offset_y": 0,
                 "scale_x": 2.0, "scale_y": 2.0 },
  "timing":    { "capture_us": 910, "resize_us": 620,
                 "encode_us": 3870, "base64_us": 330, "total_us": 5730 }
}

Four top-level fields, read in order

sourceobject

Where the pixels came from, in source coordinates — the real screen. Also says what kind of target it was: desktop, region, or window, plus the display or file it came from.

imageobject

The returned image: its own dimensions, format, byte length, and the base64 payload when you asked for one. Note that this width is not the same as source.width whenever you resized.

transformobject

How to map a point in the image back to a point on the screen. This is the field that makes the response actionable rather than merely descriptive, and it is covered in full on the next page.

timingobject

Where the microseconds went, stage by stage. Five fields rather than one, because how long and where are different questions and only the second one tells you what to fix.

The timing block, field by field

capture_usnumber

Time spent opening the display and reading pixels from the X server. Usually dominated by the connection handshake and the pixel transfer, not by arithmetic.

resize_usnumber

Time spent resizing the raw frame, before encoding. Zero when no resize was asked for.

encode_usnumber

Time spent in the PNG or JPEG encoder. On large images this is normally the largest term, and it is the one --compression and --format move.

base64_usnumber

Time spent base64-encoding the result. Nearly always negligible, and reported separately so you can confirm that rather than assume it.

total_usnumber

The whole pipeline. Watch the gap between this and the sum of the parts: a large gap means time is going somewhere the pipeline does not account for — process startup, most often.

How a program reads the fields in order

The useful pattern is to branch on source and transform before touching the image at all:

  1. Is this the target I asked for? source.kind and source.display answer that, and they answer it even when the capture was resized, because source geometry is never rewritten by a resize.
  2. How do I translate a click? transform — not the two widths, and not a ratio you compute yourself.
  3. Was this fresh enough to act on? The timing block, plus the frame identity when you are inside a session or an observation.

Timing means different things in different commands

A single capture reports one frame's pipeline. An observation reports totals across many samples, and separates the time spent waiting from the time spent working:

eensh wait_stable timing: elapsed=301ms captures=4 comparisons=3 \
capture=7810us compare=467us sleep=293275us encode=2518us

Read that as: four captures cost 7.8 ms in total, comparison cost 0.5 ms for the whole run, and 293 ms was deliberate waiting for the requested stability. Comparison is not the bottleneck; the cadence is.

Where errors appear

Every failure returns a nonzero exit status, a short message on stderr, and — with --json — a structured error with a stable code:

a structured failure
{
  "error": {
    "code": "display_unavailable",
    "message": "unable to connect to X11 display :1: ..."
  }
}

The code is the part to branch on; the message is for whoever reads the logs. The errors page covers the whole table and, more usefully, groups it by what you should do about each class.