To get the thumbnail already attached to a YouTube video, copy its video ID and place it in https://i.ytimg.com/vi/VIDEO_ID/maxresdefault.jpg. Replace VIDEO_ID with the value from the YouTube URL, open the completed address, then save the image. Because maxresdefault.jpg is optional, try hqdefault.jpg, mqdefault.jpg, or default.jpg if the largest version is unavailable.
This method downloads YouTube’s existing associated thumbnail. It does not design a new thumbnail or extract an arbitrary frame from the video.
1. Get the thumbnail with a browser and one URL
- Copy the YouTube link.
- Find the video ID in the link.
- Insert that ID into a thumbnail URL.
- Open the URL and save the image.
Find the video ID
For a normal watch link, the ID is the value after v=. For a short link, it is the path segment after youtu.be/. For a Shorts link, it is the segment after youtube.com/shorts/. Stop the ID at the next query-string character such as & or ?.
| Link form | Example | Video ID to copy |
|---|---|---|
| Watch page | https://www.youtube.com/watch?v=dQw4w9WgXcQ |
dQw4w9WgXcQ |
| Short link | https://youtu.be/dQw4w9WgXcQ |
dQw4w9WgXcQ |
| Shorts | https://www.youtube.com/shorts/dQw4w9WgXcQ |
dQw4w9WgXcQ |
Tracking parameters do not belong in the thumbnail address. For example, from https://www.youtube.com/watch?v=dQw4w9WgXcQ&t=30s, use only dQw4w9WgXcQ.
Recommended Free Tools
#1 Best Overall
- Simple, accessible and beginner-friendly app
- Select suitable dimensions for thumbnail or banner
- Different categories of attractive backgrounds
- Customization by adding text, overlay, and stickers
- Different brands to make thumbnail more attractive
Build the direct thumbnail URL
Use this pattern:
https://i.ytimg.com/vi/VIDEO_ID/maxresdefault.jpg
With the public sample ID dQw4w9WgXcQ, the finished address is:
https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg
Paste that address into a browser. On a computer, right-click the image and choose Save image as. On a phone, press and hold the image and choose the browser’s save or download option. Rename the file if needed; the extension shown in the URL is .jpg.
2. Choose the largest thumbnail that actually exists
maxresdefault.jpg is a best-case request, not a guarantee. If it does not load, replace only the filename with one of the documented alternatives:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
| Variant | Documented dimensions | When to use it |
|---|---|---|
maxresdefault.jpg |
1280×720 for some videos | Try first when you need the largest available image. |
hqdefault.jpg |
High-quality variant; dimensions are not fixed in the supplied specification | First fallback when the max-resolution file is unavailable. |
mqdefault.jpg |
Medium-quality variant; dimensions are not fixed in the supplied specification | Use when a smaller, widely available image is sufficient. |
default.jpg |
120×90 | Last-resort small thumbnail. |
The YouTube Data API documents these named objects and also lists medium (320×180), high (480×360), and standard (640×480) where available. YouTube can omit a size or its width and height, so treat maxres as optional rather than assuming every video has it.
A simple fallback sequence
- Try
maxresdefault.jpg. - If it is unavailable, try
hqdefault.jpg. - Then try
mqdefault.jpg. - Use
default.jpgif you only need a small preview.
3. Download from the command line
cURL
Replace the ID in this command, then run it in a terminal:
curl -L "https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg" -o thumbnail.jpg
If the first file is unavailable, repeat with hqdefault.jpg, mqdefault.jpg, or default.jpg. The -L option follows redirects.
Rank #2
Python with automatic fallback
This script accepts a watch, youtu.be, or Shorts link, extracts the ID, tries the four variants, and writes the first successful image.
Quick wins for a faster PC:
Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repair Windows errors before they cause bigger problemsFix Now →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →import sys
from urllib.parse import urlparse, parse_qs
import requests
def video_id(link):
parsed = urlparse(link)
host = parsed.netloc.lower().split(":")[0]
if host in {"youtu.be", "www.youtu.be"}:
return parsed.path.strip("/").split("/")[0]
query_id = parse_qs(parsed.query).get("v")
if query_id:
return query_id[0]
parts = [part for part in parsed.path.split("/") if part]
for marker in ("shorts", "embed", "live"):
if marker in parts:
index = parts.index(marker)
if index + 1 < len(parts):
return parts[index + 1]
raise ValueError("No YouTube video ID found")
if len(sys.argv) != 2:
raise SystemExit("Usage: python thumb.py YOUTUBE_URL")
vid = video_id(sys.argv[1])
for variant in ("maxresdefault", "hqdefault", "mqdefault", "default"):
image_url = f"https://i.ytimg.com/vi/{vid}/{variant}.jpg"
response = requests.get(image_url, timeout=30)
if response.ok and response.headers.get("content-type", "").startswith("image/"):
with open(f"{vid}-{variant}.jpg", "wb") as output:
output.write(response.content)
print(f"Saved {vid}-{variant}.jpg")
break
else:
raise SystemExit("No thumbnail variant was available")
Install the only dependency with python -m pip install requests. The script deliberately checks the response content type so an error page is not saved as a JPEG.
Node.js
In Node.js 18 or newer, the built-in fetch is sufficient:
import { writeFile } from "node:fs/promises";
const link = process.argv[2];
if (!link) throw new Error("Usage: node thumb.mjs YOUTUBE_URL");
const parsed = new URL(link);
let id = parsed.searchParams.get("v");
if (!id) {
const parts = parsed.pathname.split("/").filter(Boolean);
const host = parsed.hostname.toLowerCase();
if (host === "youtu.be" || host === "www.youtu.be") id = parts[0];
else {
for (const marker of ["shorts", "embed", "live"]) {
const index = parts.indexOf(marker);
if (index >= 0 && parts[index + 1]) { id = parts[index + 1]; break; }
}
}
}
if (!id) throw new Error("No YouTube video ID found");
for (const variant of ["maxresdefault", "hqdefault", "mqdefault", "default"]) {
const response = await fetch(`https://i.ytimg.com/vi/${id}/${variant}.jpg`);
const type = response.headers.get("content-type") || "";
if (response.ok && type.startsWith("image/")) {
await writeFile(`${id}-${variant}.jpg`, Buffer.from(await response.arrayBuffer()));
console.log(`Saved ${id}-${variant}.jpg`);
break;
}
}
4. Use the official YouTube Data API for applications
The direct URL is convenient for a one-off download. An application that processes many links should request the video’s snippet resource through the YouTube Data API and read its snippet.thumbnails object. Each returned thumbnail object can include a URL, width, and height. The documented keys are default, medium, high, standard, and maxres; standard and maxres are available only for some videos.
The API requires project setup, an API key, and quota management. Select the first available key in descending quality instead of assuming maxres is present.
API request with cURL
curl "https://www.googleapis.com/youtube/v3/videos?part=snippet&id=dQw4w9WgXcQ&key=YOUR_API_KEY"
API request with Python
import requests
video_id = "dQw4w9WgXcQ"
api_key = "YOUR_API_KEY"
response = requests.get(
"https://www.googleapis.com/youtube/v3/videos",
params={"part": "snippet", "id": video_id, "key": api_key},
timeout=30,
)
response.raise_for_status()
items = response.json().get("items", [])
if not items:
raise SystemExit("The API returned no video item")
thumbnails = items[0]["snippet"].get("thumbnails", {})
for name in ("maxres", "standard", "high", "medium", "default"):
thumbnail = thumbnails.get(name)
if thumbnail and thumbnail.get("url"):
print(name, thumbnail["url"], thumbnail.get("width"), thumbnail.get("height"))
break
else:
raise SystemExit("No thumbnail URL was returned")
API request with Node.js
const id = "dQw4w9WgXcQ";
const key = "YOUR_API_KEY";
const endpoint = new URL("https://www.googleapis.com/youtube/v3/videos");
endpoint.search = new URLSearchParams({ part: "snippet", id, key });
const response = await fetch(endpoint);
if (!response.ok) throw new Error(`YouTube API failed: ${response.status}`);
const data = await response.json();
const thumbnails = data.items?.[0]?.snippet?.thumbnails || {};
for (const name of ["maxres", "standard", "high", "medium", "default"]) {
const item = thumbnails[name];
if (item?.url) {
console.log(name, item.url, item.width ?? "width not returned", item.height ?? "height not returned");
break;
}
}
5. Know what this method does—and does not do
It retrieves the associated image
The URL points to the thumbnail YouTube associates with the video. It does not generate a custom design, add text, change colors, or select a random frame from the video. To create a new design, download the associated image and edit it in an image editor, or capture and edit a frame separately.
File dimensions are not a promise
A URL naming maxresdefault does not guarantee a 1280×720 response. The API’s returned width and height are the dependable way to know what a particular resource provides, and even those fields may be omitted.
Rank #3
Downloading is not permission to republish
Saving a file does not by itself establish that you may reuse it. Check the creator’s and rights holder’s permission for the intended publication, advertising, social post, or commercial use.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.6. Troubleshoot a missing or incorrect thumbnail
The large URL does not load
Cause: that video does not expose the optional maximum-resolution variant.
Fix: try hqdefault.jpg, then mqdefault.jpg, then default.jpg. For an application, use the API response and select the highest key that was actually returned.
You copied the whole link instead of the ID
Cause: the thumbnail path contains only the ID, not https://, watch?v=, or tracking parameters.
Fix: from a watch URL, copy only the value after v= and stop before &. From a short or Shorts URL, copy the relevant path segment.
The downloaded file is not an image
Cause: a script saved an error response without checking it.
Fix: require a successful HTTP response and an image/* content type, as the Python and Node examples do, then try the next variant.
Rank #4
- 1. Pick a background from GALLERY, COLOR PALLETE or TRANSPARENT.
- 2. You can add Text and stickers.
- 3. You can apply filters
- 4. You can change canvas size
The API returns no item
Cause: the ID is wrong, the request is not authorized, or the API project has a quota or configuration problem.
Fix: test the ID with the direct URL first, verify the API key and enabled YouTube Data API, and inspect the HTTP status and response body before retrying.
The image looks different from the video
Cause: YouTube’s associated thumbnail is a selected promotional image, not a guaranteed video frame.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Fix: use a frame-capture workflow if you need a specific moment; the thumbnail URL method cannot choose arbitrary frames.
7. Or skip the browser setup
If you need a rendered capture of a thumbnail URL or a YouTube page in an automated workflow, ScreenshotNeo is a website screenshot API and MCP server. It can remove cookie-consent banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, timeouts, failed loads, and cache hits are not billed as clean shots. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
Pass the completed thumbnail URL to the API (this captures the rendered image; it does not invent a new YouTube thumbnail):
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://i.ytimg.com/vi/VIDEO_ID/maxresdefault.jpg -o shot.webp
See the ScreenshotNeo API documentation for options such as full-page capture, CSS selectors, device presets, retina scale, custom JavaScript, waiting rules, request blocking, cookies, headers, caching, signed links, asynchronous jobs, bulk capture, and usage reporting. The response identifies the page verdict and billing status in X-Page-Verdict and X-Billed headers.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesPython:
import requests; r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://i.ytimg.com/vi/VIDEO_ID/maxresdefault.jpg"}, timeout=90); open("shot.webp", "wb").write(r.content)
Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://i.ytimg.com/vi/VIDEO_ID/maxresdefault.jpg' }); const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
Every feature is included on every plan. The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for the free ScreenshotNeo plan.
Frequently Asked Questions
Can I use the same ID in more than one thumbnail URL?
Yes. Keep the video ID unchanged and swap only the variant filename, such as maxresdefault.jpg or hqdefault.jpg.
Why might the API omit width or height?
Google notes that thumbnail dimensions can vary by resource and that width and height are not always returned, so client code should treat those fields as optional.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




