Documentation
One REST API, CLI, and MCP server over the same four operations — search, metadata, transcripts, and summaries. Every example below is copy-paste runnable against production.
- Base URL
- https://api.youtubesearch.dev
- Auth
- Authorization: Bearer ys_live_… — required on every call
- Formats
- JSON · Markdown · plain text
- Interfaces
- REST · MCP · CLI
On this page
First call in under a minute
Every call needs a free API key — 1,000 credits a month, no card.
Get a free key, then pass it as a bearer token:
curl -s "https://api.youtubesearch.dev/v1/videos/zjkBMFhNj_g/summary" \-H "Authorization: Bearer ys_live_YOUR_KEY"
Replace ys_live_YOUR_KEY with your key.
Omit the header and every call returns a typed 401 — this is the envelope, verbatim:
curl -s "https://api.youtubesearch.dev/v1/videos/xJ8dLd9M4qE/transcript"
{"error": "KEY_REQUIRED","message": "An API key is required — get a free key (1,000 credits/month, no card) at https://youtubesearch.dev/login."}
One header, required everywhere
Send Authorization: Bearer ys_live_… on every call — there is no keyless tier.
A key is ys_live_followed by 32 random characters. It’s shown once when you mint it in the dashboard (from a magic link), then stored only as a hash — save it then. Rotating a key revokes the old one and mints a new one in a single step, keeping your tier and your monthly balance.
Tiers
| Tier | Rate | Credits / mo |
|---|---|---|
free | 10 req/s | 1,000 |
pro | 10 req/s | 20,000 |
Same speed, same data quality for everyone — pro buys more credits, not more access.
Credits & metering
Each metered response carries X-Credits-Charged and X-Credits-Remaining headers. Charges settle only after a successful response — failed calls are never billed. Per-call costs are listed with each endpoint. Running out returns OUT_OF_CREDITS (402); exceeding your rate returns RATE_LIMITED (429). Errors are typed JSON — see §07 Errors.
GET /v1/credits
Your key’s balance. Takes no parameters.
Request
curl -s "https://api.youtubesearch.dev/v1/credits" \-H "Authorization: Bearer ys_live_YOUR_KEY"
Response
{"tier": "free","monthly_allowance": 1000,"used_this_month": 137,"remaining": 863}
CREDITS 0 · unmetered — this call emits no X-Credits-* headers
POST /v1/search
Search YouTube and get ranked, agent-ready results — one query, or up to five in a single batch.
JSON body
| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | One of | A single search query. Provide exactly one of query or queries. |
queries | string[] | One of | Up to 5 queries in one batch. A query that fails returns a typed error in its own slot without dropping the others. |
limit | integer | Optional | Results per query, 1–20. Default 10. |
filters | object | Optional | duration (short <4m · medium 4–20m · long >20m), recency (hour · day · week · month · year), and channel (case-insensitive substring of the channel name or id). |
Request
curl -s -X POST https://api.youtubesearch.dev/v1/search \-H "Authorization: Bearer ys_live_YOUR_KEY" \-H "Content-Type: application/json" \-d '{"query": "intro to large language models", "limit": 3}'
Response
{"query": "intro to large language models","videos": [{"youtube_id": "zjkBMFhNj_g","title": "[1hr Talk] Intro to Large Language Models","channel": "Andrej Karpathy","channel_id": "UCXUPKJO5MZQN11PqgIvyuvQ","duration_s": 3588,"view_count": 3835399,"published": "2 years ago","thumbnail_url": "https://i.ytimg.com/vi/zjkBMFhNj_g/hqdefault.jpg","description_snippet": "This is a 1 hour general-audience introduction to Large Language Models...","summary": "Large Language Models (LLMs) are fundamentally computational artifacts, best understood not as simple chatbots, but as the kernel process of an emerging operating system…"}]}
A single query returns { query, videos }. A batch returns { results: [...] } — one entry per query, each either { query, videos } or { query, error, message }.
CREDITS 1 per query · a batch charges 1 × the queries that succeeded
ERRORS INVALID_REQUEST, RATE_LIMITED, OUT_OF_CREDITS, SEARCH_UNAVAILABLE — see §07.
GET /v1/videos/{video_id}
Full native metadata for one video — the cheap look before an expensive extract.
Path parameter
| Parameter | Type | Required | Description |
|---|---|---|---|
video_id | string | Required | The 11-character YouTube id. Must match ^[A-Za-z0-9_-]{11}$. |
Request
curl -s "https://api.youtubesearch.dev/v1/videos/zjkBMFhNj_g" \-H "Authorization: Bearer ys_live_YOUR_KEY"
Response
{"youtube_id": "zjkBMFhNj_g","title": "[1hr Talk] Intro to Large Language Models","channel": "Andrej Karpathy","channel_id": "UCXUPKJO5MZQN11PqgIvyuvQ","duration_s": 3588,"view_count": 3835399,"published_at": "2 years ago","description": "This is a 1 hour general-audience introduction to Large Language Models...","chapters": [{"title": "Intro: Large Language Model (LLM) talk","start_s": 0},{"title": "LLM Inference","start_s": 34},{"title": "LLM Training","start_s": 126}],"cached": true}
Returns youtube_id, title, channel, channel_id, duration_s, published_at, view_count, description, chapters (when the video has them), and cached. The cache refreshes when older than 7 days.
CREDITS 1
ERRORS INVALID_VIDEO_ID, KEY_REQUIRED, VIDEO_UNAVAILABLE, AGE_RESTRICTED, METADATA_* — see §07.
GET /v1/videos/{video_id}/transcript
The timestamped transcript. Sourced from captions when present; when they're absent, ASR transcribes the audio. A genuinely unextractable video returns a typed error saying exactly why.
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
format | string | Optional | markdown · json · plain. Default markdown. json returns segments [{ text, offset_ms, duration_ms }]; the others return a string. |
start, end | float | Optional | Seconds, decimals allowed (e.g. 1663.5). Clip the transcript to this window. start greater than end is rejected. |
max_tokens | integer | Optional | Cap the returned text to fit a context budget. Minimum 1. |
Request
curl -s "https://api.youtubesearch.dev/v1/videos/zjkBMFhNj_g/transcript?start=1663&end=2012" \-H "Authorization: Bearer ys_live_YOUR_KEY"
Response
{"youtube_id": "zjkBMFhNj_g","source": "caption","language": "en","format": "markdown","cached": true,"truncated": false,"transcript": "So the way we train these models is we take a large chunk of the internet — roughly 10 terabytes of text — and a big cluster of GPUs…"}
source is caption or asr. transcript is a string, or a segment array when format=json. truncated reflects max_tokens.
CREDITS 1 cached · 2 cold · 10 when ASR transcribes the audio
ERRORS KEY_REQUIRED, TRANSCRIPTS_DISABLED, NO_TRANSCRIPT_FOUND, AGE_RESTRICTED, the 502 caption family — see §07.
GET /v1/videos/{video_id}/summary
The fewest-tokens way to understand a video — one narrative summary.
Request
curl -s "https://api.youtubesearch.dev/v1/videos/zjkBMFhNj_g/summary" \-H "Authorization: Bearer ys_live_YOUR_KEY"
Response
{"youtube_id": "zjkBMFhNj_g","summary": "Large Language Models (LLMs) are fundamentally computational artifacts, best understood not as simple chatbots, but as the kernel process of an emerging operating system…"}
summaryis the video’s full narrative summary — a cold call also queues an async premium upgrade that improves it in place.
CREDITS 1 cached · 5 cold
ERRORS KEY_REQUIRED, SUMMARY_UNAVAILABLE, SUMMARY_GENERATION_FAILED, the transcript family it reads from — see §07.
Typed, never silent
Every error is the same envelope — a machine-readable code your agent branches on, plus a human message. This is a live 402:
{"error": "OUT_OF_CREDITS","message": "Monthly credit allowance (1000) is insufficient for this operation. Credits reset at the start of next month. Need more now? See Pro plans at https://youtubesearch.dev/dashboard/billing."}
| Status | Code | Retry | Trigger |
|---|---|---|---|
400 | INVALID_REQUEST | No | Bad or empty query, start > end, unknown summary sections, failed validation. |
400 | INVALID_VIDEO_ID | No | id doesn't match ^[A-Za-z0-9_-]{11}$. |
401 | INVALID_KEY | No | Malformed, unknown, or revoked bearer token. |
401 | KEY_REQUIRED | No | No Authorization header was sent. |
402 | OUT_OF_CREDITS | No | Monthly allowance exhausted. No Retry-After — resets next month. |
403 | AGE_RESTRICTED, VIDEO_UNPLAYABLE, TRANSCRIPTS_DISABLED | No | The video's state forbids the operation. |
404 | VIDEO_UNAVAILABLE, NO_TRANSCRIPT_FOUND | No | Video removed or private; no caption track exists. |
429 | RATE_LIMITED | Yes | Rate exceeded. Retry-After (seconds) is set. |
429 | IP_BLOCKED, REQUEST_BLOCKED, AUDIO_DOWNLOAD_BLOCKED | Varies | Upstream block. Back off; AUDIO_DOWNLOAD_BLOCKED carries no Retry-After. |
500 | INTERNAL_ERROR | No | Unhandled server error. Retry once, then report it. |
502 | PO_TOKEN_REQUIRED, YOUTUBE_REQUEST_FAILED, TRANSCRIPT_FETCH_FAILED, METADATA_FETCH_FAILED, ASR_FAILED, SUMMARY_GENERATION_FAILED, and related | Varies | An upstream fetch or pipeline step failed. Most are transient — retry with backoff. |
503 | SEARCH_UNAVAILABLE, ASR_UNAVAILABLE, SUMMARY_UNAVAILABLE, METADATA_QUOTA_EXCEEDED, AUTH_UNAVAILABLE, and related | Varies | A dependency is unavailable or over quota. Retry later; an unconfigured provider won't clear on retry. |
Retry-After (seconds) is set on RATE_LIMITED 429 responses — honor it. OUT_OF_CREDITS 402 never carries Retry-After(credits reset monthly; it isn’t retryable now). When a 429 or 5xx arrives without one, back off exponentially. Failed calls are never billed. All 401s also carry WWW-Authenticate: Bearer.
Wire it into Claude Code
A remote Streamable HTTP server (youtubesearch-mcp) — stateless JSON, a thin client of this API that forwards your Authorization header per request.
It exposes the four operations as read-only tools: search_videos, get_video, get_transcript, and get_summary— same parameters as the endpoints above. There’s no credits tool; check your balance over REST or the CLI.
claude mcp add --transport http \youtubesearch \https://mcp.youtubesearch.dev/mcp \--header "Authorization: Bearer ys_live_YOUR_KEY"
Every call needs the header — omit it and you get KEY_REQUIRED. Errors surface verbatim as { error, message }, with “(retry after Ns)” appended when Retry-After is present.
The same four operations, from a shell
No install — npx runs the latest version. Log in once with your key.
Commands: search, video, transcript, summary, and auth login / auth status. Pass --json for raw output. The key lives in YOUTUBESEARCH_API_KEY (or the stored config); YOUTUBESEARCH_API_BASE overrides the base URL.
npx @youtubesearch/cli auth login # paste your key once, stored 0600npx @youtubesearch/cli search "intro to large language models" --limit 5npx @youtubesearch/cli video zjkBMFhNj_gnpx @youtubesearch/cli transcript zjkBMFhNj_g --start 1663 --end 2012npx @youtubesearch/cli summary zjkBMFhNj_g
Exit codes: 0 success · 1 API/network · 2 usage · 3 auth. On failure, --json writes { error, message, retryAfter? } to stderr.
View the package on npm.
The machine-readable contract
Every endpoint, parameter, and response shape above is specified in the OpenAPI document — feed it to a generator or an agent.
OpenAPI
https://api.youtubesearch.dev/v1/openapi.json
For agents
Read /llms-full.txt — this entire reference as one plain-markdown file — or the shorter /llms.txt index.
Health
Liveness at GET /health, readiness (with a DB probe) at GET /health/ready — both outside /v1. The MCP server lives at https://mcp.youtubesearch.dev/mcp.