YouTube Storyboard Images
Looking for the cover image, not the seek-bar stills? Paste a link above to grab every thumbnail size in one click. Want the hover-preview frames? Read on, they work very differently.
Looking for the cover image, not the seek-bar stills? Paste a link above to grab every thumbnail size in one click. Want the hover-preview frames? Read on, they work very differently.
Hover the progress bar on a YouTube video, or drag the scrubber on your phone, and a strip of tiny preview stills follows your finger. Those are storyboard images. They are not the video's thumbnail, and they do not live at the same tidy address, so the trick that grabs a thumbnail in one request does not work on them. This page explains what storyboards are, why you cannot build one's URL from a video ID the way you can a thumbnail, and the one reliable way to download them. If you actually want the cover image, the YouTube thumbnail grabber returns every size in one click.
They are two different image types that people mix up because both are "pictures of the video."
| Thumbnail | Storyboard | |
|---|---|---|
| What it is | The single cover image | A grid of many small stills sampled across the runtime |
| Where it is used | Search, the sidebar, the watch page | The hover and scrub preview on the progress bar only |
| Host path | i.ytimg.com/vi/<ID>/ | i.ytimg.com/sb/<ID>/ |
| URL | Public, buildable from the video ID | Signed with sqp and sigh, not buildable from the ID |
| How to get it | One HTTP request, or the grabber above | Read the signed spec, or let yt-dlp do it |
So if you came here wanting the picture that represents the video, that is the thumbnail: the YouTube thumbnail URL guide lists every file and address for it. The rest of this page is about the seek-preview stills.
A storyboard sheet is served from the /sb/ path, and the address carries query parameters you cannot invent:
https://i.ytimg.com/sb/<VIDEO_ID>/storyboard3_L2/M0.jpg?sqp=...&sigh=...
Reading it left to right: /sb/ instead of /vi/, then a detail level (L0, L1, L2), then which sheet in the sequence (M0, M1...). The two query parameters are the catch. sqp is a protobuf-encoded block of parameters, and sigh is a cryptographic signature tied to that video, that level, and a time window. Strip them or guess them and the request returns a 403. That is the whole difference from a thumbnail: a thumbnail URL is complete once you know the 11-character ID, and a storyboard URL is not.
YouTube ships the storyboard recipe inside the watch page itself, in the player response, at storyboards.playerStoryboardSpecRenderer.spec on the ytInitialPlayerResponse object. On a watch page you can read it straight from the console:
const pr = window.ytInitialPlayerResponse; // present on a watch page
const spec = pr?.storyboards?.playerStoryboardSpecRenderer?.spec;
console.log(spec);
// A single pipe-delimited string (shape varies):
// "https://i.ytimg.com/sb/VIDEO_ID/storyboard3_L$L/$N.jpg?sqp=...
// |48#27#100#10#10#0#default#...sigh...
// |80#45#...sigh...
// |160#90#...sigh..."
The first segment is a base URL with $L and $N placeholders; each segment after it describes one detail level: tile width, tile height, total number of stills, columns and rows per sheet, the interval between stills, and that level's own sigh token. Code that shows storyboards, whether a custom player or an archiver, parses this string and fills in the placeholders per level and per sheet; it never guesses the signature. Because the grammar can change, parse it defensively rather than assuming a fixed field order.
You do not have to parse the spec by hand. yt-dlp already understands storyboards and reads the signed spec for you. List the available sheets first:
yt-dlp -F "https://www.youtube.com/watch?v=VIDEO_ID"
Among the audio and video rows you will see the storyboard formats, in mhtml, at a few resolutions:
ID EXT RESOLUTION
sb0 mhtml 159x90
sb1 mhtml 79x45
sb2 mhtml 48x27
sb0 is the highest-resolution level and sb2 the coarsest. Grab the sharpest one without pulling the video itself:
yt-dlp -f sb0 --skip-download "https://www.youtube.com/watch?v=VIDEO_ID"
The result is an .mhtml web-archive file that bundles the sprite sheets together; open it in a browser or extract the embedded images. This is the reliable route precisely because yt-dlp resolves the current sigh for you. For the ordinary cover image on the command line, the same tool with --write-thumbnail is covered in the command-line thumbnail download guide.
Each sheet is a grid, so one still is a single cell at the tile size -F reported (for example 159x90 for sb0). Crop the cells with any image tool, ffmpeg or Pillow, using the tile width and height and the columns-per-row from the spec. In Python, once you have a sheet saved:
from PIL import Image
sheet = Image.open("storyboard_sb0.jpg")
tile_w, tile_h, cols, rows = 159, 90, 5, 5 # read these from the -F row / spec
for i in range(cols * rows): # rows also comes from the spec
x = (i % cols) * tile_w
y = (i // cols) * tile_h
sheet.crop((x, y, x + tile_w, y + tile_h)).save(f"frame_{i:03}.jpg")
If what you actually wanted was one clean frame from the video rather than the low-resolution preview grid, that is a screenshot, not a storyboard: see how to screenshot a YouTube video for the sharp way to capture an exact moment.
If you are a developer who wanted YouTube's storyboards to power a hover preview in your own video player, do not point at YouTube's sheets: the sigh tokens expire and the frames are the creator's. Generate your own instead. Standard players such as Video.js and Plyr read a WebVTT thumbnails track, a sprite sheet you build with ffmpeg plus a .vtt file mapping each timestamp to a region of it. That is the same pattern YouTube uses, on an asset you control and can serve without a signature.
403 later.sb0 through sb2 always exist.They are storyboard images, sometimes called seek-preview thumbnails. YouTube samples stills across the whole runtime and packs them into a sprite sheet, a grid of tiny frames, then shows the frame nearest your cursor as you move along the progress bar. They are a separate image type from the video's thumbnail, which is the single cover picture.
No. A thumbnail lives at a predictable public address you can build from the 11-character video ID, such as i.ytimg.com/vi/VIDEO_ID/maxresdefault.jpg. A storyboard is served from an /sb/ path whose URL carries a protobuf sqp parameter and a cryptographic sigh signature, so you cannot construct a working link from the video ID alone. Let yt-dlp read the signed spec and download the sheets for you.
Inside the watch page's player response, at storyboards.playerStoryboardSpecRenderer.spec on the ytInitialPlayerResponse object. The spec is a single pipe-delimited string: a base URL followed by one segment per detail level giving the tile width and height, the columns and rows per sheet, the total number of stills, the interval between them, and that level's sigh token.
No. The thumbnail is the one cover image a video shows in search and on the watch page, stored at the /vi/ path and downloadable in seconds. A storyboard is the grid of small stills used only for the hover and scrub preview, stored at the /sb/ path behind a signed URL. If you want the cover image, use the thumbnail grabber, not the storyboard.
Run yt-dlp -F on the watch URL to list the storyboard formats sb0, sb1, and sb2, then run yt-dlp -f sb0 --skip-download on the same URL to save the highest-resolution sheet. The output is an .mhtml file that bundles the sprite sheets; open it in a browser or extract the embedded images to get the individual frames.
The sigh signature on a storyboard URL is time-limited, so a link that loads now returns a 403 later. That is why saving the files with yt-dlp beats hotlinking the signed URLs. For your own video player, generate a fresh sprite sheet and a WebVTT thumbnails track rather than pointing at YouTube's expiring links.
Not reliably, because the signed URLs expire and the sheets are the creator's frames. The standard approach is to generate your own: build a sprite sheet with ffmpeg and a WebVTT thumbnails file that maps timestamps to regions of it. Players such as Video.js and Plyr read that WebVTT track to show a scrub preview, which is the same pattern YouTube uses, on an asset you control.
Just need the cover image? Paste any link into the YouTube thumbnail grabber and download every size in one click.