# Thumbnails

> A still frame of every live stream, once a minute. Always visible to you; public only when you turn it on.

While a stream is live, JustOnAir takes **one frame a minute** from it: the first about 10 seconds after the publisher starts, then every 60 seconds. You always see the newest one; viewers and the public see it only if you make it public.

## Where you see it

`thumbnail` on [the stream](/api-reference#get-a-stream):

```json
"thumbnail": {
  "public": false,
  "url": "https://live.joacdn.com/bcdn_token=…/_rec/str_e1bzk3dxw9z9allei6n7/thumbs/1791115200/thumb.jpg",
  "captured_at": "2026-10-04T12:00:00.000Z",
  "public_url": null
}
```

- `url` is a signed link to the newest frame, a 640-pixel-wide JPEG (360 pixels high for 16:9). It works for about an hour and opens that one frame only. Read the stream again for a fresh link; while nothing changes the link stays the same, so browsers can cache the image.
- `captured_at` is when the frame was taken. Both are `null` until the first frame.
- `GET /v1/streams` carries the same object on every stream, so one call gives you a picture for each row of your own stream list. The [dashboard](https://app.justonair.com) shows it in the stream list, as the poster of the live preview, and as the last frame of an ended stream.

## Make it public

Off by default. Turn it on when you create the stream or later:

```bash
curl -X PATCH https://api.justonair.com/v1/streams/str_e1bzk3dxw9z9allei6n7 \
  -H "Authorization: Bearer $JOA_API_KEY" -H "Content-Type: application/json" \
  -d '{"thumbnail": {"public": true}}'
```

Or with **Public thumbnail** in the dashboard's Stream settings. While it is on:

- **The [hosted player](/player) uses it.** The newest frame is the video's poster before playback starts, and a blurred backdrop behind "Going live" and "Stream ended".
- **`public_url` works for anyone:**

```text
https://play.joacdn.com/api/embed/str_e1bzk3dxw9z9allei6n7/thumbnail.jpg
```

It never changes; it redirects to the newest frame, or to the JustOnAir placeholder before the first one, so an `<img>` always has something to show. Use it for link previews (`og:image`), event pages, or your own list of live streams. It is cached for 30 seconds.

```html
<img src="https://play.joacdn.com/api/embed/str_e1bzk3dxw9z9allei6n7/thumbnail.jpg"
  alt="Live now" width="640" height="360">
```

Turned off, the player shows no frame and `public_url` answers `404`. The setting is separate from `player.enabled`: switching the hosted player off hides the poster, but the public thumbnail keeps working while it is on.

## How long frames are kept

Frames are stored with the stream's [recording](/recordings) and deleted with it: when the recording reaches its `delete_at`, when you delete it, or, for a stream created with `"record": false`, a few minutes after the stream ends. Once they are gone `url` and `captured_at` are `null`, and a public thumbnail falls back to the placeholder.

## Things to know

- **Leave it off for private streams.** A public thumbnail shows what is on screen to anyone who has the stream id, which is in every playback URL and embed code. For paid or members-only streams keep it off; you still see the frames yourself.
- **Up to a minute old.** It is a preview, not a live view. For live video use the player or `playback_url`.
- **Cost.** Taking and storing frames is free. Each time one is shown it counts as delivery like video, but a frame is about 15 KB: 10,000 views are 0.15 GB, under half a cent.
