API Reference
v1Extract the highest-quality cover image from YouTube videos via a simple REST API.
Base URL
# Production (Cloudflare Workers)
https://your-worker.your-domain.workers.dev
# Local development
http://localhost:8787Authentication
No authentication required. The API is currently open.
POST /v1/resolve
Resolve the best cover image for a given URL. Returns the highest-quality candidate along with all alternatives.
Request Body
| Field | Type | Default | Description |
|---|---|---|---|
| Top-level | |||
| url | string | required | YouTube video URL (youtube.com/watch?v=, youtu.be/, /shorts/, /embed/) |
| options | object | optional | Resolve options (see below) |
| options | |||
| options.prefer | enum | "balanced" | "largest" | "balanced" | "fastest" |
| options.min_width | number | 0 | Minimum width filter (pixels) |
| options.min_height | number | 0 | Minimum height filter (pixels) |
| options.refresh | boolean | false | Skip cache, always re-fetch |
| options.debug | boolean | false | Include detailed trace info in response |
Example Request
curl -X POST https://your-api.workers.dev/v1/resolve \
-H "Content-Type: application/json" \
-d '{
"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}'Response
| Field | Type | Description | |
|---|---|---|---|
| request_id | string | — | Unique request identifier |
| canonical | object | — | { platform, resource_type, resource_id, canonical_url } |
| best | ImageCandidate | — | Highest-scored candidate image |
| candidates | ImageCandidate[] | — | All candidates sorted by score (maxres, sd, hq, mq, default) |
| cache | object | — | { hit: boolean, ttl_seconds: number } |
| trace | object | — | Pipeline execution trace (steps, timings) |
| meta | object? | — | Page metadata (title, author, etc.) |
| warnings | array? | — | Non-fatal issues encountered |
| errors | array? | — | Errors encountered during resolve |
ImageCandidate Object
| Field | Type | Description | |
|---|---|---|---|
| url | string | — | Direct image URL (e.g. i.ytimg.com/vi/.../maxresdefault.jpg) |
| width | number|null | — | Image width in pixels (from HTTP probe) |
| height | number|null | — | Image height in pixels (from HTTP probe) |
| format | enum | — | "jpg" | "png" | "webp" | "avif" | "gif" | "unknown" |
| quality_tier | enum | — | "max" | "high" | "medium" | "low" | "unknown" |
| score | number|null | — | Composite score (tier bonus + pixel bonus) |
| source_method | enum | — | "rule" | "api" | "og" | "oembed" | ... |
| availability | object | — | { status: "ok"|"missing"|"blocked"|"error", http_status? } |
Example Response
{
"request_id": "mme7othw-i1eau49ph",
"canonical": {
"platform": "youtube",
"resource_type": "video",
"resource_id": { "videoId": "dQw4w9WgXcQ" },
"canonical_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
},
"best": {
"url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg",
"width": 1280,
"height": 720,
"format": "jpg",
"quality_tier": "max",
"score": 129.8,
"source_method": "rule",
"availability": { "status": "ok", "http_status": 200 }
},
"candidates": [ "...5 candidates from maxres to default..." ],
"cache": { "hit": false, "ttl_seconds": 86400 },
"trace": { "timings": { "total_ms": 789 } }
}Error Codes
| HTTP | Code | Description |
|---|---|---|
| 400 | INVALID_JSON | Request body is not valid JSON |
| 400 | VALIDATION_ERROR | Request doesn't match schema (missing url, invalid options) |
| 500 | RESOLVE_ERROR | Pipeline execution failed |
GET /health
Simple health check endpoint. Returns 200 when the service is running.
{ "ok": true }YouTube Quality Tiers
For YouTube videos, the API probes 5 thumbnail quality tiers and returns the best available:
| Tier | URL Pattern | Typical Size |
|---|---|---|
| max | i.ytimg.com/vi/ID/maxresdefault.jpg | 1280x720 |
| high | i.ytimg.com/vi/ID/sddefault.jpg | 640x480 |
| medium | i.ytimg.com/vi/ID/hqdefault.jpg | 480x360 |
| low | i.ytimg.com/vi/ID/mqdefault.jpg | 320x180 |
| low | i.ytimg.com/vi/ID/default.jpg | 120x90 |
Playground
Try the API directly from your browser. Edit the request body and click send.
Request Body
POSTResponse
Click "Send Request" to try the API