ScreenshotNeo

BlogHow-to

How to Download a YouTube Thumbnail from a URL

Extract a YouTube video ID, build its thumbnail URL, download the best available size, and automate the process with Python, Node.js, or cURL.

By the ScreenshotNeo team1 October 20266 min read

Short answer: extract the YouTube video ID, then open https://img.youtube.com/vi/VIDEO_ID/maxresdefault.jpg. Replace VIDEO_ID with the ID from the video URL and save the image. If the largest file is unavailable, try sddefault.jpg, hqdefault.jpg, mqdefault.jpg, or default.jpg.

YouTube thumbnail URLs use the video ID rather than the complete watch URL.

URL form Where to find the ID
youtube.com/watch?v=VIDEO_ID Value after v=
youtu.be/VIDEO_ID First path segment
youtube.com/shorts/VIDEO_ID Segment after /shorts/
youtube.com/embed/VIDEO_ID Segment after /embed/
https://img.youtube.com/vi/VIDEO_ID/maxresdefault.jpg

You can also use the commonly used i.ytimg.com host:

https://i.ytimg.com/vi/VIDEO_ID/maxresdefault.jpg

Open the resulting address in a browser, right-click the image, and choose Save image as. This downloads the thumbnail without downloading the video.

2. Choose the best available variant

Filename Typical use Availability
maxresdefault.jpg Largest standard variant, up to 1280×720 Only some videos
sddefault.jpg Standard-size fallback Not guaranteed
hqdefault.jpg High-quality fallback Common
mqdefault.jpg Medium-quality fallback Common
default.jpg Small default image, typically 120×90 Common
0.jpg, 1.jpg, 2.jpg, 3.jpg Generated frame variants Depends on the video

Google’s YouTube thumbnails documentation names the API sizes default, medium, high, standard, and maxres. Max-resolution thumbnails exist only for some videos, and dimensions can vary by resource.

3. Manual download

  1. Copy the YouTube video URL.
  2. Extract the ID from v=, youtu.be/, /shorts/, or /embed/.
  3. Insert it into the img.youtube.com template.
  4. Open the image URL and confirm it is correct.
  5. Save the image from your browser.
  6. If maxresdefault.jpg fails, try the fallback filenames in order.

This is the simplest approach for a one-off download.

4. Automate the download

Python

from urllib.parse import urlparse, parse_qs
import requests

variants = ['maxresdefault', 'sddefault', 'hqdefault', 'mqdefault', 'default']

def get_video_id(link):
    parsed = urlparse(link)
    host = parsed.netloc.lower().split(':')[0]
    parts = [p for p in parsed.path.split('/') if p]
    if host.endswith('youtu.be'):
        return parts[0] if parts else None
    if parts and parts[0] in {'shorts', 'embed', 'live'}:
        return parts[1] if len(parts) > 1 else None
    return parse_qs(parsed.query).get('v', [None])[0]

link = input('YouTube URL: ').strip()
video_id = get_video_id(link)
if not video_id:
    raise SystemExit('Could not find a video ID')

for variant in variants:
    url = f'https://img.youtube.com/vi/{video_id}/{variant}.jpg'
    response = requests.get(url, timeout=30)
    if response.ok and response.headers.get('content-type', '').startswith('image/'):
        with open(f'{video_id}-{variant}.jpg', 'wb') as file:
            file.write(response.content)
        print(f'Saved {variant}: {url}')
        break
else:
    raise SystemExit('No thumbnail variant was available')

Node.js 18+

import { writeFile } from 'node:fs/promises';

const input = process.argv[2];
if (!input) throw new Error('Usage: node thumb.mjs YOUTUBE_URL');
const url = new URL(input);
const host = url.hostname.toLowerCase();
const parts = url.pathname.split('/').filter(Boolean);
let id;
if (host.endsWith('youtu.be')) id = parts[0];
else if (['shorts', 'embed', 'live'].includes(parts[0])) id = parts[1];
else id = url.searchParams.get('v');
if (!id) throw new Error('Could not find a video ID');

for (const variant of ['maxresdefault', 'sddefault', 'hqdefault', 'mqdefault', 'default']) {
  const thumbnail = `https://img.youtube.com/vi/${id}/${variant}.jpg`;
  const response = await fetch(thumbnail);
  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 ${variant}: ${thumbnail}`);
    break;
  }
}

cURL

curl -fL 'https://img.youtube.com/vi/VIDEO_ID/maxresdefault.jpg' -o thumbnail.jpg

Use a fallback by changing the final filename:

curl -fL 'https://img.youtube.com/vi/VIDEO_ID/hqdefault.jpg' -o thumbnail.jpg

5. Use the YouTube Data API when dimensions matter

The direct URL method guesses filenames. For a catalog or batch pipeline, the YouTube Data API returns the available snippet.thumbnails entries, including URL, width, and height when supplied. Select the largest available entry instead of assuming maxres exists.

curl -G 'https://www.googleapis.com/youtube/v3/videos' \
  --data-urlencode 'part=snippet' \
  --data-urlencode 'id=VIDEO_ID' \
  --data-urlencode 'key=YOUR_YOUTUBE_API_KEY'

In application code, inspect the returned keys and sort available images by width * height. The Data API has its own credentials and quota requirements.

6. Edge cases

  • Playlist links: use the v parameter from watch?v=ID&list=....
  • Tracking parameters: ignore everything except the video ID.
  • Mobile URLs: m.youtube.com/watch?v=ID uses the same rule.
  • Live streams: use the ID in the watch URL; available sizes can differ while a stream is live.
  • Private, removed, or invalid videos: a normal thumbnail may not be available.
  • Older uploads: max-resolution files may not have been generated.
  • Dimensions: documented sizes are typical values, not guarantees for every upload.

7. Troubleshooting

Problem Cause Fix
404 or failed download Wrong ID or unavailable variant Re-extract the ID and try sddefault, hqdefault, and smaller fallbacks.
Image is unexpectedly small A low-resolution filename was selected Try maxresdefault.jpg first, then sddefault.jpg.
Wrong video A playlist or tracking value was copied Use only the video ID from v or the path.
HTML saved as JPG Redirect or non-image response Follow redirects and validate the Content-Type header.
API returns no item Private, removed, or invalid video Verify that the video opens and check the ID and API key.
API quota error Google Cloud quota or credentials Use a direct image URL for simple jobs or resolve the project quota and key settings.

8. Performance, reliability, and cost

  • For one image, constructing the direct URL is fastest.
  • For batches, parse IDs once, try variants in order, validate the content type, and record the successful variant.
  • Cache files by video ID and variant to avoid repeated downloads.
  • Retry transient network errors with a short backoff, but stop retrying a variant that is genuinely unavailable.
  • Use API metadata when exact dimensions are important.
  • Direct thumbnail URLs avoid downloading the video. The Data API uses its own quota model.

9. Or skip the browser setup

ScreenshotNeo can capture a URL with one GET request when you need a normalized PNG, JPEG, WebP, or PDF response. It removes cookie and consent banners, newsletter popups, and chat widgets before capture. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing state. Its MCP server lets Claude, Cursor, and other MCP clients take screenshots.

See the ScreenshotNeo API documentation for configuration options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://img.youtube.com/vi/VIDEO_ID/maxresdefault.jpg -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://img.youtube.com/vi/VIDEO_ID/maxresdefault.jpg"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://img.youtube.com/vi/VIDEO_ID/maxresdefault.jpg' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

The free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 screenshots. Create a free ScreenshotNeo account.

10. Check reuse rights before publishing

Downloading an image does not grant permission to republish it. Obtain the creator’s permission or confirm an applicable license or other lawful basis before using a thumbnail on a website, in an application, or in marketing. Review YouTube’s thumbnail policy as well.

11. FAQ

What is the maxresdefault URL?

https://img.youtube.com/vi/VIDEO_ID/maxresdefault.jpg, with the actual video ID substituted. It is the largest standard variant when available.

Can I download a thumbnail without the API?

Yes. Direct image URLs work for manual downloads and scripts. The API is useful when you need the available URLs and dimensions returned programmatically.

Why does maxresdefault fail?

Max-resolution thumbnails exist only for some videos. Try sddefault, hqdefault, mqdefault, or default.

Can I publish the downloaded image?

Only if you have permission, a suitable license, or another lawful reuse basis.