Skip to content

Thumbnail URL API

The thumbnail API is a set of URL shapes served from the apex domain vumbnail.com. There is no JSON API and no key — the path encodes the request and the response is an image.

A user takes a video and rewrites its URL as a Vumbnail path:

  • YouTube https://www.youtube.com/watch?v=zFJ3yNVQ3v4https://vumbnail.com/zFJ3yNVQ3v4.jpg
  • Vimeo https://vimeo.com/637615910https://vumbnail.com/637615910.jpg

The Worker parses the path into a provider, video ID, optional password, and optional size, resolves the poster frame, and returns it as image/jpeg. The same path is stable and cacheable, so it can be dropped into an <img> tag, an Open Graph tag, or any client that fetches a URL.

PathMeaning
/<id>.jpg, /<id>.jpeg, /<id>Default thumbnail (extension optional, case-insensitive)
/<id>_<size>.jpgA specific size variant, e.g. /zFJ3yNVQ3v4_hqdefault.jpg
/<numericId>.jpgVimeo (all-numeric IDs route to Vimeo; alphanumeric route to YouTube)
/<id>:<password>.jpgPassword-protected Vimeo video
/playlist?list=<playlistId>.jpgThe first video of a YouTube playlist
  • Provider detection is by ID shape: all-numeric → Vimeo, otherwise YouTube.
  • Default size: YouTube resolves to hqdefault unless a size is given.
  • ID canonicalization: a trailing numeric suffix is treated as a size hint and stripped for the cache key (1101804103_123456.jpg and 1101804103_.jpg both cache as 1101804103). Non-numeric suffixes are preserved.

Inputs (all from the HTTP request — there is no request body):

  • Path — encodes provider, video ID, optional :password, optional _size, optional .jpg/.jpeg extension.
  • Query?list= for playlists; legacy ?h=<password> for Vimeo (see Redirects & compatibility); ?key=<apiKey> for paid bypass; ?debug / ?_debug for diagnostic headers.
  • HeadersReferer (drives the watermark decision), CF-Connecting-IP, User-Agent, and an optional X-Vumbnail-Key header for paid bypass.

Outputs:

  • A 200 image/jpeg body — the clean or watermarked poster frame.
  • Content-Disposition: inline with a filename hint.
  • Cache-Control headers tuned per variant (clean vs. watermarked vs. fallback).
  • Redirects (302/307) for the compatibility cases in Redirects & compatibility.
  • In debug mode, a set of X-Thumbnail-* headers describing the decision.
  • Unknown / deleted video — resolves to the shared error.jpg fallback, served 200 so the <img> never breaks; the failure is negatively cached.
  • Password-protected Vimeo — if the password is supplied and valid, the poster is returned; otherwise a shared locked.jpg graphic is served with a restriction header.
  • Playlist — known playlists are redirected to a mapped video ID; unknown playlists are resolved to their first video via oEmbed or an external resolver (see Redirects & compatibility).
  • Unsupported but thumbnail-shaped path (8+ char id + optional suffix, .jpg/.jpeg) — routed to an error.jpg fallback rather than a 404.
  • Non-thumbnail path — passed through to the marketing site service binding (astro.vumbnail.com), or returns a 404 text response (debug JSON if ?debug is set).
  • Provider slow / rate-limiting — served from cache if warm; otherwise the Vimeo relay or negative cache absorbs the failure. The viewer never waits on a hung upstream beyond the resolver timeout.

The parsed request that the rest of the pipeline operates on:

type ThumbnailRequest = {
provider: "youtube" | "vimeo"
videoId: string // canonical id used for the cache key
password?: string // Vimeo password, from ":pw" path or legacy ?h=
size?: string // e.g. "hqdefault", "sddefault"; provider default if absent
extension: "jpg" | "jpeg" | ""
playlistId?: string // present for /playlist?list=... requests
}
// What the client ultimately receives:
type ThumbnailResponse = {
status: 200 | 302 | 307 | 404
contentType: "image/jpeg" | "text/plain"
variant: "clean" | "wm" | "fallback-error" | "fallback-locked"
body: ArrayBuffer // the JPEG bytes
}
  • Animated and non-JPEG output. Short animated previews exist behind a flag (see Animated thumbnails); WebP/AVIF output is not currently offered. Whether to expose them through the same path shape (e.g. .gif, .webp) is undecided.
  • Explicit size vocabulary. The set of accepted _size tokens per provider is provider-derived rather than a documented, stable list. A published size vocabulary is not yet committed to.
  • See the global Open questions page for cross-cutting items.