- Python 100%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| yt_dlp_thumbnail_scraper | ||
| .gitignore | ||
| LICENSE | ||
| pyproject.toml | ||
| README.md | ||
yt-dlp-thumbnail-scraper
A small command-line tool that uses yt-dlp under the hood to download YouTube thumbnails — without downloading any video data.
- Pass a video URL to grab that video's best thumbnail.
- Pass a channel,
@handle,user/,c/,channel/, or playlist URL to walk every video and download thumbnails for all of them. - Picks the highest-resolution thumbnail available, automatically skipping
YouTube's gray placeholder image when
maxresdefaultis missing. - Optional
--allmode grabs every thumbnail variant per video. --flatmode drops every thumbnail into one directory named after the video title;--templatelets you customize that filename.--limit Ncaps how many videos a channel/playlist scrape processes.- Resumable: existing thumbnails are skipped by default.
- Retries failed downloads and can sleep between videos to be polite to YouTube when scraping large channels.
Installation
The easiest way is to install directly from GitHub with pip:
pip install git+https://github.com/thesimonharms/yt-dlp-thumbnail-scraper.git
This works in any virtualenv, conda env, or system Python, and automatically
installs yt-dlp as a dependency.
Other install options
From a specific branch / tag / commit
pip install git+https://github.com/thesimonharms/[email protected]
pip install git+https://github.com/thesimonharms/yt-dlp-thumbnail-scraper.git@main
pip install git+https://github.com/thesimonharms/yt-dlp-thumbnail-scraper.git@<commit-sha>
Clone-and-install
git clone https://github.com/thesimonharms/yt-dlp-thumbnail-scraper.git
cd yt-dlp-thumbnail-scraper
pip install .
Editable / dev install
git clone https://github.com/thesimonharms/yt-dlp-thumbnail-scraper.git
cd yt-dlp-thumbnail-scraper
pip install -e .
Upgrade an existing install
pip install --upgrade --force-reinstall git+https://github.com/thesimonharms/yt-dlp-thumbnail-scraper.git
After installation, the yt-thumb command is on your PATH. You can also run
it as a Python module:
python -m yt_dlp_thumbnail_scraper <url>
Quick start
# Single video — saves the best thumbnail
yt-thumb https://www.youtube.com/watch?v=dQw4w9WgXcQ
# Whole channel
yt-thumb https://www.youtube.com/@SomeChannel
# Playlist
yt-thumb "https://www.youtube.com/playlist?list=PLxxxxxxxx"
Usage
Single video
yt-thumb https://www.youtube.com/watch?v=dQw4w9WgXcQ
thumbnails/
└── thumbnail.jpg
Also works with youtu.be/, embed/, and shorts/ URLs:
yt-thumb https://youtu.be/dQw4w9WgXcQ
yt-thumb https://www.youtube.com/shorts/abcdef12345
Channels
# @handle (modern)
yt-thumb https://www.youtube.com/@SomeChannel
# /channel/UCxxxxxxxx (legacy ID)
yt-thumb https://www.youtube.com/channel/UCxxxxxxxxxxxxxxxx
# /user/Name or /c/Name (legacy)
yt-thumb https://www.youtube.com/user/SomeUser
yt-thumb https://www.youtube.com/c/SomeChannel
Playlists
yt-thumb "https://www.youtube.com/playlist?list=PLxxxxxxxx"
URLs with shell metacharacters like ? and & should be quoted.
Save every thumbnail variant per video
By default only the best single thumbnail is saved per video. Use --all to
save every variant YouTube provides (maxres, sd, hq, mq, default, storyboards,
etc.):
yt-thumb --all https://www.youtube.com/@SomeChannel
Flat output: one directory, named by video title
Use --flat to discard the per-video subdirectory layout and write every
thumbnail directly into the output directory, named after the video title:
yt-thumb --flat https://www.youtube.com/@SomeChannel
# drop them in the current working directory:
yt-thumb --flat -o . https://www.youtube.com/@SomeChannel
thumbnails/
├── <video title>.jpg
├── <another video title>.jpg
└── ...
Collisions are handled automatically: if two videos share a title, the second
one is written as <title> [<video id>].jpg. Re-runs reuse the previously
written file (and skip the download) thanks to --skip-existing.
With --all --flat, each video's variants are written as
<title>_00.<ext>, <title>_01.<ext>, ...
Custom filename template (--template)
--template selects your own filename in flat mode (it implies --flat).
Available placeholders:
| Placeholder | Meaning |
|---|---|
{title} |
Video title |
{id} |
Video id |
{uploader} |
The video's uploader |
{channel} |
Channel (or uploader) of the source page |
{playlist} |
Channel or playlist display name |
{idx} |
1-based index of the video within this scrape |
Standard str.format format specs work, e.g. {idx:03d}.
yt-thumb --template "{idx:03d} - {title}" https://www.youtube.com/@SomeChannel
yt-thumb --template "{uploader} - {title} [{id}]" "https://www.youtube.com/playlist?list=PLxxxx"
Limit how many videos are scraped
--limit N stops after processing N videos from a channel or playlist —
handy for sampling a large channel or quickly testing a setup:
yt-thumb --limit 10 https://www.youtube.com/@SomeChannel
Custom output directory
yt-thumb --output ./my-thumbs https://www.youtube.com/@SomeChannel
# or short form:
yt-thumb -o ./my-thumbs https://www.youtube.com/@SomeChannel
Force re-download of existing thumbnails
By default already-downloaded thumbnails are skipped. Disable with:
yt-thumb --no-skip-existing https://www.youtube.com/@SomeChannel
Be polite on large channels
Sleep N seconds between videos:
yt-thumb --sleep 0.5 https://www.youtube.com/@SomeChannel
Quiet mode (no progress output)
yt-thumb --quiet https://www.youtube.com/@SomeChannel
# or: yt-thumb -q ...
Adjust retries
Per-thumbnail download retries (default 3):
yt-thumb --retries 5 https://www.youtube.com/@SomeChannel
Combine options
# Nested layout with every variant, polite throttling
yt-thumb \
--output ./out \
--all \
--sleep 0.25 \
--retries 5 \
https://www.youtube.com/@SomeChannel
# Flat layout, custom names, sample of 50 videos
yt-thumb \
--output ./out \
--flat --template "{idx:03d} - {title}" \
--limit 50 \
https://www.youtube.com/@SomeChannel
Command reference
yt-thumb [-h] [-o OUTPUT] [-a] [-f] [--template TEMPLATE] [--limit N]
[--no-skip-existing] [-q] [--retries RETRIES] [--sleep SLEEP]
[--version] url
positional arguments:
url YouTube video, channel, or playlist URL
options:
-h, --help show this help message and exit
-o, --output DIR Output directory (default: ./thumbnails)
-a, --all Download every available thumbnail per video,
not just the best one
-f, --flat Save every thumbnail directly inside the output
directory, named after the video title
--template TEMPLATE Custom filename template in --flat mode (implies
--flat). Placeholders: {title}, {id}, {uploader},
{channel}, {playlist}, {idx}
--limit N Process at most N videos when scraping a
channel/playlist
--no-skip-existing Re-download thumbnails that already exist on disk
-q, --quiet Suppress progress output
--retries N Number of download retries per thumbnail (default: 3)
--sleep SECONDS Seconds to sleep between videos when scraping a
channel (default: 0)
--version show program's version number and exit
Two console commands are installed and are identical:
yt-thumb(short)yt-dlp-thumbnails(long)
Both can be invoked with the options above.
Output layout
Single video
thumbnails/
└── thumbnail.jpg
Channel or playlist
thumbnails/
└── <channel or playlist name>/
├── <video title> [<video id>]/
│ └── thumbnail.jpg
├── <uploader>/ # only present for playlists mixing uploaders
│ └── <video title> [<video id>]/
│ └── thumbnail.jpg
└── ...
With --all, each video directory contains multiple files:
<video title> [<video id>]/
├── thumbnail_00.jpg
├── thumbnail_01.webp
├── thumbnail_02.jpg
└── ...
Flat mode (--flat / --template)
thumbnails/
├── <video title>.jpg
├── <another video title>.jpg
└── ...
Collisions are disambiguated with the video id (e.g. <title> [dQw4w9WgXcQ].jpg).
With --all --flat, variants become <title>_00.jpg, <title>_01.webp, ...
How it works
- The tool calls
yt_dlp.YoutubeDL.extract_info(url, download=False)withextract_flat=True, which quickly returns video IDs and their thumbnail URLs without downloading any media. - For each video the candidate thumbnails are ranked by resolution and YouTube
id preference (
maxresdefault>sddefault>hqdefault>mqdefault>default). Candidates are fetched best-first. - YouTube serves a tiny gray placeholder image with HTTP 200 when a higher resolution variant does not actually exist for a video — the scraper detects this (file size below ~2 KB) and automatically falls back to the next candidate.
- Each thumbnail is downloaded with Python's
urlliband written to disk. No video streams are ever requested.
Uninstall
pip uninstall yt-dlp-thumbnail-scraper
This leaves the auto-installed yt-dlp dependency in place; remove it with
pip uninstall yt-dlp if you no longer need it.
Requirements
- Python 3.9+
yt-dlp(installed automatically as a dependency)
License
MIT