# YouTube Thumbnail Downloader (`automation-lab/youtube-thumbnail-downloader`) Actor

Download public YouTube thumbnails in bulk with quality, image, and stored-asset metadata.

- **URL**: https://apify.com/automation-lab/youtube-thumbnail-downloader.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Videos, Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## YouTube Thumbnail Downloader

Download public **YouTube thumbnails** in bulk from video URLs or IDs.
The Actor stores each image in the run key-value store and returns structured metadata in the default dataset.
No YouTube Data API key, browser, login, or proxy configuration is required.

Use it for creative research, media archiving, content audits, design references, and automated asset pipelines.
Choose the best available image automatically or request a standard YouTube thumbnail quality.

### What does YouTube Thumbnail Downloader do?

For every unique supplied video, the Actor:

1. validates and extracts the canonical 11-character video ID;
2. constructs the public YouTube image URL;
3. downloads the requested thumbnail quality;
4. optionally falls back to a smaller standard quality;
5. stores the image in the run's default key-value store;
6. emits one typed dataset record with source and asset metadata.

Supported input forms include:

- `https://www.youtube.com/watch?v=...`
- `https://youtu.be/...`
- `https://www.youtube.com/shorts/...`
- `https://www.youtube.com/live/...`
- `https://www.youtube.com/embed/...`
- YouTube Music watch URLs
- raw 11-character video IDs

The Actor downloads thumbnails only.
It does not download videos, audio, captions, or private media.

### Who is this Actor for?

#### Creative researchers

Build a repeatable visual reference library without manually saving images one by one.
Compare thumbnail composition, color, typography, and framing across a supplied list of videos.

#### Content and channel teams

Archive the current public thumbnail assets associated with videos in a campaign or editorial calendar.
Keep the source video ID and canonical URL next to each stored file.

#### Data engineers

Feed normalized image metadata into Apify datasets, webhooks, Google Sheets, cloud storage, or downstream media processors.
Use stable `storageKey` and `assetUrl` fields instead of parsing logs.

#### Agencies and analysts

Process mixed watch, Shorts, embed, share, and ID inputs in one run.
Export file sizes and selected quality for audits and reporting.

### Why use this Actor?

- **Images and metadata together:** each result links the public source and the stored run asset.
- **Automatic quality fallback:** `best` checks standard YouTube variants from largest to smallest.
- **Bulk input:** submit up to 1,000 URLs or IDs per run.
- **Duplicate control:** the same video ID is downloaded once per run.
- **HTTP-only execution:** no browser startup or account session is needed.
- **Typed output:** quality, dimensions, content type, bytes, and storage fields are ready for integrations.
- **Fail-closed validation:** malformed or unsupported inputs stop before network processing.

### What data does it return?

| Field | Type | Meaning |
| --- | --- | --- |
| `videoId` | string | Canonical YouTube video ID |
| `input` | string | Original URL or ID supplied by the user |
| `videoUrl` | string | Canonical YouTube watch URL |
| `requestedQuality` | string | Requested mode or quality |
| `quality` | string | Quality actually downloaded |
| `fallbackUsed` | boolean | Whether a lower candidate was selected |
| `width` | integer | Standard width for the selected quality |
| `height` | integer | Standard height for the selected quality |
| `sourceUrl` | string | Public `i.ytimg.com` image URL |
| `contentType` | string | Returned image media type |
| `sizeBytes` | integer | Downloaded file size |
| `storageId` | string | Run key-value store ID |
| `storageKey` | string | Key of the stored image record |
| `assetUrl` | string | Apify API URL for the stored image |
| `downloadedAt` | string | ISO 8601 download timestamp |

The default dataset contains metadata.
The image bytes are kept separately in the default key-value store so dataset exports stay compact.

### Supported thumbnail qualities

| Input value | Standard YouTube dimensions | Behavior |
| --- | ---: | --- |
| `best` | up to 1280×720 | Tries all standard qualities from largest to smallest |
| `maxresdefault` | 1280×720 | Requests maximum resolution first |
| `sddefault` | 640×480 | Requests standard definition first |
| `hqdefault` | 480×360 | Requests high quality first |
| `mqdefault` | 320×180 | Requests medium quality first |
| `default` | 120×90 | Requests the smallest default image |

Not every YouTube video has every quality.
Keep `fallbackToLowerQuality` enabled when your workflow values a usable image over one exact resolution.

### How much does it cost to download YouTube thumbnails?

Pricing uses one `start` event per run plus one `item` event per successfully stored thumbnail.
Failed, invalid, duplicate, and unavailable images are not charged as items.

The start fee is **$0.005 per run**.
At the BRONZE tier, each downloaded thumbnail costs **$0.008**.
The FREE tier item price is **$0.0092**, and higher subscription tiers receive lower per-item prices.

BRONZE examples:

| Successful thumbnails | Estimated charge |
| ---: | ---: |
| 1 | $0.013 |
| 10 | $0.085 |
| 25 | $0.205 |
| 100 | $0.805 |

The estimate is `start + successful items × item price`.
Your applicable Apify subscription tier determines the exact item price shown in Console.

### How to use the Actor

1. Open the Actor in Apify Console.
2. Add one YouTube video URL or ID per line.
3. Select `best` or an exact quality.
4. Decide whether lower-quality fallback is allowed.
5. Set `maxItems` to cap stored results.
6. Click **Start**.
7. Open the **Thumbnail metadata** output for structured records.
8. Open **Downloaded images** or follow `assetUrl` to retrieve files.

For the first run, the prefilled two-video example is a useful smoke test.

### Input parameters

#### `videoInputs`

Required array of one to 1,000 public YouTube video URLs or IDs.
Whitespace is trimmed.
Duplicate IDs are processed once while preserving the first original input value.

#### `quality`

Optional quality selection.
Defaults to `best`.
Use an exact quality when consistent dimensions matter more than coverage.

#### `fallbackToLowerQuality`

Optional boolean.
Defaults to `true`.
For `best`, the Actor already evaluates all quality candidates from largest to smallest.
For an exact selection, this option controls whether smaller variants may be used.

#### `maxItems`

Optional integer from 1 to 1,000.
Defaults to 100.
Processing stops as soon as this many unique images have been stored and emitted.

### Input example

```json
{
  "videoInputs": [
    "https://youtu.be/dQw4w9WgXcQ",
    "jNQXAC9IVRw",
    "https://www.youtube.com/embed/9bZkp7q19f0"
  ],
  "quality": "best",
  "fallbackToLowerQuality": true,
  "maxItems": 3
}
```

### Output example

```json
{
  "videoId": "dQw4w9WgXcQ",
  "input": "https://youtu.be/dQw4w9WgXcQ",
  "videoUrl": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
  "requestedQuality": "best",
  "quality": "maxresdefault",
  "fallbackUsed": false,
  "width": 1280,
  "height": 720,
  "sourceUrl": "https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg",
  "contentType": "image/jpeg",
  "sizeBytes": 65324,
  "storageId": "YOUR_RUN_STORE_ID",
  "storageKey": "thumbnail-dQw4w9WgXcQ-maxresdefault",
  "assetUrl": "https://api.apify.com/v2/key-value-stores/YOUR_RUN_STORE_ID/records/thumbnail-dQw4w9WgXcQ-maxresdefault",
  "downloadedAt": "2025-01-15T12:00:00.000Z"
}
```

`storageId` and `assetUrl` vary for every run.
The downloaded image remains subject to the retention rules of your Apify storage plan.

### Downloading the stored images

Use `assetUrl` directly with an authenticated Apify request when the store is private:

```bash
curl -L \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  "https://api.apify.com/v2/key-value-stores/STORE_ID/records/thumbnail-VIDEO_ID-maxresdefault" \
  --output thumbnail.jpg
```

For a long-lived archive, copy the image into storage you control before the run store expires.
Do not assume a public source thumbnail or temporary Actor run store is permanent.

### Run from the Apify API with cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~youtube-thumbnail-downloader/runs" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "videoInputs": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"],
    "quality": "best",
    "fallbackToLowerQuality": true,
    "maxItems": 1
  }'
```

Wait for the run to finish, then read its default dataset and key-value store IDs from the run object.

### Run from JavaScript

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/youtube-thumbnail-downloader').call({
    videoInputs: ['https://youtu.be/dQw4w9WgXcQ'],
    quality: 'best',
    fallbackToLowerQuality: true,
    maxItems: 1,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].assetUrl);
```

The returned `assetUrl` identifies the image in `run.defaultKeyValueStoreId`.

### Run from Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/youtube-thumbnail-downloader').call(run_input={
    'videoInputs': ['jNQXAC9IVRw'],
    'quality': 'hqdefault',
    'fallbackToLowerQuality': False,
    'maxItems': 1,
})

items = client.dataset(run['defaultDatasetId']).list_items().items
print(items[0]['assetUrl'])
```

### Use with Apify MCP

Add the Actor to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/youtube-thumbnail-downloader"
```

#### Claude Desktop

Add this server object to Claude Desktop's MCP configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/youtube-thumbnail-downloader"
    }
  }
}
```

#### Cursor

Open **Settings → MCP**, add a remote server named `apify`, and use:

`https://mcp.apify.com?tools=automation-lab/youtube-thumbnail-downloader`

#### VS Code

Add the same remote HTTP URL to your workspace MCP server configuration and name the server `apify`.

Example prompts:

- "Download the best available thumbnails for these YouTube watch URLs."
- "Store HQ thumbnails for these video IDs and return their file sizes."
- "Create a thumbnail archive from this list and give me the stored asset links."

### Integration workflows

#### Google Sheets or Excel

Export the default dataset as CSV or XLSX.
Keep `videoId`, `quality`, `sizeBytes`, and `assetUrl` as an asset manifest.

#### Webhooks

Attach an Actor run succeeded webhook.
Pass dataset rows to a downstream media-copy or image-analysis service.

#### Scheduled archives

Create an Apify Task with a maintained list of video URLs and run it on a schedule.
Copy the assets out of the run store if you need retention beyond your Apify plan.

#### Creative analysis

Use `sourceUrl` or `assetUrl` as input to a vision model, color extractor, or similarity workflow.
The Actor does not perform image interpretation itself.

### Tips for reliable runs

- Prefer video IDs when upstream systems already provide them.
- Use `best` for broad archives where availability matters.
- Use `hqdefault` or another exact quality when consistent dimensions matter.
- Keep fallback enabled unless lower qualities would invalidate your workflow.
- Split very large operational lists into bounded Tasks when you need separate run histories.
- Copy valuable assets to durable storage before Apify retention removes the run store.

### Limits and failure behavior

- Only public YouTube thumbnail image URLs are supported.
- Private, deleted, unavailable, or malformed videos may have no usable image.
- Standard filename dimensions describe YouTube's quality variant; the Actor does not decode image pixels.
- Input validation rejects the entire run if any supplied value is not a supported URL or valid ID.
- A missing image for one valid video is logged and skipped.
- The run fails when no supplied video produces an image.
- YouTube can change its public image behavior without notice.
- The Actor does not monitor channel feeds or discover video IDs.

### Responsible use and legality

Thumbnails may be copyrighted and may include trademarks, people, or other protected material.
Use downloaded files only when you have a lawful purpose and the rights required for storage, analysis, publication, or redistribution.
Respect YouTube's terms, applicable law, privacy rights, and your organization's retention policy.

This Actor accesses public image URLs and does not bypass login controls.
Public availability does not grant ownership or permission to republish an image.

### Troubleshooting

#### Why did I receive a lower quality than requested?

The requested file was unavailable and `fallbackToLowerQuality` was enabled.
Check `quality` and `fallbackUsed` in the result.
Disable fallback if the run should accept only one exact quality.

#### Why is there no result for a valid video ID?

The video may be private, deleted, regionally unavailable, recently uploaded, or missing the requested image variants.
Try `best` with fallback enabled.
The run log lists IDs for which no candidate was available.

#### Why does `assetUrl` require authentication?

Actor run key-value stores are normally private.
Send your Apify API token in the `Authorization` header, or use an Apify client authenticated with that token.

#### Why are there fewer results than inputs?

Duplicate video IDs are processed once, processing stops at `maxItems`, and videos with no usable image are skipped.
The final log reports submitted, unique, and saved counts.

### FAQ

#### Does it need a YouTube API key?

No.
It downloads from YouTube's public thumbnail image surface.

#### Does it download YouTube videos or audio?

No.
It stores only thumbnail images and related metadata.

#### Can it process Shorts?

Yes.
Supply a Shorts URL or its video ID.

#### Can it search YouTube or scrape a channel?

No.
Supply the exact video URLs or IDs you want to process.
For discovery, use a separate YouTube search or channel Actor first, then pass its video IDs here.

#### Are images kept forever?

Not automatically.
They follow your Apify key-value store retention policy.
Copy assets into durable storage when permanence matters.

#### Is each quality returned as a separate result?

No.
The Actor stores one selected thumbnail per unique video per run.
Run separate Tasks when you need multiple qualities for the same video.

### Related automation-lab Actors

- [YouTube Channel Videos Scraper](https://apify.com/automation-lab/youtube-channel-videos-scraper) — discover video IDs from a channel before downloading their thumbnails.
- [YouTube Channel Search Scraper](https://apify.com/automation-lab/youtube-channel-search-scraper) — find channels and videos for research workflows.
- [YouTube Comments Scraper](https://apify.com/automation-lab/youtube-comments-scraper) — add audience feedback to a video research dataset.
- [YouTube Shorts Scraper](https://apify.com/automation-lab/youtube-shorts-scraper) — collect Shorts records that can feed thumbnail downloads.

Combine discovery Actors with this downloader through Apify Tasks, schedules, API calls, or dataset-to-dataset automation.

# Actor input Schema

## `videoInputs` (type: `array`):

One public YouTube watch, Shorts, live, embed, youtu.be, or YouTube Music URL—or an 11-character video ID—per line.

## `quality` (type: `string`):

Choose best available quality automatically, or request one YouTube thumbnail filename/resolution.

## `fallbackToLowerQuality` (type: `boolean`):

When a specifically requested quality is unavailable, try progressively smaller standard YouTube thumbnails.

## `maxItems` (type: `integer`):

Maximum number of unique thumbnail images to store and return.

## Actor input object example

```json
{
  "videoInputs": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "jNQXAC9IVRw"
  ],
  "quality": "best",
  "fallbackToLowerQuality": true,
  "maxItems": 3
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset containing one record per downloaded thumbnail.

## `files` (type: `string`):

Key-value store containing the image assets.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "videoInputs": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "jNQXAC9IVRw"
    ],
    "quality": "best",
    "fallbackToLowerQuality": true,
    "maxItems": 3
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/youtube-thumbnail-downloader").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "videoInputs": [
        "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "jNQXAC9IVRw",
    ],
    "quality": "best",
    "fallbackToLowerQuality": True,
    "maxItems": 3,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/youtube-thumbnail-downloader").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "videoInputs": [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
    "jNQXAC9IVRw"
  ],
  "quality": "best",
  "fallbackToLowerQuality": true,
  "maxItems": 3
}' |
apify call automation-lab/youtube-thumbnail-downloader --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/youtube-thumbnail-downloader"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/DwIo12RfKefHd3Xn7/builds/EqDj27phCqvzebTn3/openapi.json
