# Set a default thumbnail for a video

Choose which frame Mux returns when a thumbnail is requested without an explicit time. Set `thumbnail_time` on an asset to control the default poster image.

When you request a thumbnail from `image.mux.com` without a `time` parameter, Mux picks a frame from the middle of the video. Set `thumbnail_time` on the asset to choose that frame yourself.

The value is a media time in seconds, and it applies to every default thumbnail request for the asset across all of its playback IDs. See the <ApiRefLink href="/docs/api-reference/video/assets/update-asset">Update Asset API reference</ApiRefLink> for the full endpoint specification.

<Callout type="info">
  `thumbnail_time` can only be set on an asset in the `ready` state, and cannot be set at asset creation time. Mux validates the value against the asset's duration, so the asset needs a known duration first.
</Callout>

## Set the thumbnail time

`PATCH` the asset with the media time you want, in seconds:

```bash
curl https://api.mux.com/video/v1/assets/${ASSET_ID} \
  -H "Content-Type: application/json" \
  -X PATCH \
  -d '{
    "thumbnail_time": 12.67
  }' \
  -u ${MUX_TOKEN_ID}:${MUX_TOKEN_SECRET}
```

The value must be at least `0` and less than the asset's duration. A negative value or a value at or past the end of the asset is rejected with a `400`.

Once set, `thumbnail_time` is included in the asset object. It is omitted entirely when no value is set:

```json
{
  "data": {
    "id": "YOUR_ASSET_ID",
    "status": "ready",
    "duration": 138.31,
    "thumbnail_time": 12.67
  }
}
```

Fetch it any time with <ApiRefLink href="/docs/api-reference/video/assets/get-asset">Get Asset</ApiRefLink>.

## Unset the thumbnail time

Because `0` is a valid thumbnail time, there's a dedicated endpoint for clearing the field rather than a sentinel value. Send a `DELETE` to return the asset to Mux's default frame selection:

```bash
curl https://api.mux.com/video/v1/assets/${ASSET_ID}/thumbnail-time \
  -X DELETE \
  -u ${MUX_TOKEN_ID}:${MUX_TOKEN_SECRET}
```

A successful request returns `204 No Content`, and `thumbnail_time` disappears from the asset object.

## What `thumbnail_time` affects

`thumbnail_time` is used only for thumbnail requests that don't already specify a frame:

```bash
# Uses thumbnail_time
https://image.mux.com/{PLAYBACK_ID}/thumbnail.jpg

# Ignores thumbnail_time, uses the requested frame
https://image.mux.com/{PLAYBACK_ID}/thumbnail.jpg?time=42
```

An explicit `time`, `program_time`, or `latest=true` in the request always wins. Other thumbnail parameters like `width`, `height`, and `fit_mode` work as usual and don't change which frame is selected. See [Get thumbnails and images from a video](/docs/guides/get-images-from-a-video) for the full set of image parameters.

Animated GIFs (`animated.gif`, `animated.webp`) and [storyboards](/docs/guides/create-timeline-hover-previews) are not affected by `thumbnail_time`.

## When the new thumbnail appears

Changing `thumbnail_time` does not instantly change the image every client sees. There are two layers of caching involved, and Mux only controls one of them.

**Mux's CDN cache is purged for you.** When you set or unset `thumbnail_time`, Mux purges the cached default thumbnails for that asset across all of its playback IDs. A request that reaches the CDN after the purge gets the new frame. Thumbnails requested with an explicit `time` are cached separately and are not purged, since their frame hasn't changed.

**Local caches are not purged.** Image responses are served with a long browser cache lifetime, so a browser, mobile app, proxy, or CDN of your own that already downloaded the old default thumbnail will keep serving it until its own cached copy expires. Mux has no way to invalidate those copies.

<Callout type="warning">
  A new thumbnail will appear for some clients sooner than others, depending on their local cache settings. If you're building a UI where users pick a thumbnail, plan for the change not to be visible immediately on every client that has already loaded the old one.
</Callout>

If you need the change reflected right away in your own application, request the thumbnail with an explicit `time` matching the value you just set:

```bash
https://image.mux.com/{PLAYBACK_ID}/thumbnail.jpg?time=12.67
```

That's a different URL, so no cache has an entry for it yet and the new frame shows up on the next load. This is what the Mux Dashboard does on the asset detail page after a thumbnail is set. Use it on screens where the user just made the change. Everywhere else, request the plain thumbnail URL, since a hard-coded `time` won't pick up future changes to `thumbnail_time`.

<Callout type="info">
  Mux Player builds its poster URL from the playback ID alone, so it picks up `thumbnail_time` without any extra configuration. It's subject to the same client-side caching described above.
</Callout>

## Set the thumbnail from Mux Robots

The [`find-best-thumbnails`](/docs/guides/robots-find-best-thumbnails) Robots workflow scores frames across an asset and returns the best candidates ranked best to worst. Set `update_asset_thumbnail` to `true` and the top-scoring frame's timestamp is written to the asset's `thumbnail_time` when the job completes, so the frame the model picked becomes the asset's default thumbnail with no follow-up call from you:

```bash
curl https://api.mux.com/robots/v0/jobs/find-best-thumbnails \
  -H "Content-Type: application/json" \
  -X POST \
  -d '{
    "parameters": {
      "asset_id": "YOUR_ASSET_ID",
      "max_thumbnails": 3,
      "update_asset_thumbnail": true
    }
  }' \
  -u ${MUX_TOKEN_ID}:${MUX_TOKEN_SECRET}
```

The parameter is off by default, and the write is best-effort: if it fails, the job still completes and returns its ranked candidates. The `timestamp_ms` values in `outputs.best_thumbnails` are unchanged either way, so you can always set `thumbnail_time` yourself from the job results, or present the candidates to a user and set whichever one they choose.

Because this write goes through the same API, the caching behavior above applies to it too. The thumbnail changes when the job completes, not when the job is created.

## FAQ

**Does setting `thumbnail_time` cost anything?**

No. It's asset metadata, with no additional charge for setting, reading, or clearing it.

**Can I set it when I create the asset?**

Not currently. Set it with a `PATCH` once the asset reaches the `ready` state.

**What happens to the thumbnail request limit?**

Nothing changes. The [per-asset thumbnail limits](/docs/guides/get-images-from-a-video) apply the same way whether the frame comes from `thumbnail_time` or an explicit `time` parameter.

**Can I set more than one thumbnail?**

Not currently. An asset has a single `thumbnail_time`. If you want to offer several options, keep the candidate timestamps in your own system and render each one with `?time=`.
