API Reference
Everything the TranscriptLayer API can do — endpoints, parameters, response shapes, errors, and rate limits.
Getting Started
The API is served over HTTPS from a single base URL. All responses are JSON unless you request plain text.
https://api.transcriptlayer.com/v1
- Create an account and grab your API key from the dashboard.
- Pass the key as a Bearer token on every request (see Authentication).
- Call any endpoint — your first 100 credits are free, no card required.
Authentication
Authenticate with your API key in the Authorization header using the Bearer scheme:
Authorization: Bearer tl_live_xxxxxxxxxxxxxxxx
- Keep keys server-side — never ship them in client bundles or mobile apps.
- Rotate keys from the dashboard at any time; old keys revoke instantly.
- Use separate keys per environment so you can revoke one without downtime.
code field of invalid_api_key — check for it before retrying.
Get Transcript
Returns the transcript of a public video. Choose JSON segments (with or without timestamps) or a single plain-text block.
Query parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
video_url | string | Required | — | Full video URL, short URL, or bare 11-char video ID. |
format | string | Optional | json | json or text. Text returns one joined string. |
include_timestamp | boolean | Optional | true | When false, segments omit start/duration. |
send_metadata | boolean | Optional | false | Include title, channel, duration, and view count in the response. |
language | string | Optional | auto | ISO 639-1 code (e.g. en, es). Falls back to the default track when omitted. |
language on the first call — the response's language field tells you which track was used, and a 404 for a specific language lists the tracks that are available.
Example request
curl "https://api.transcriptlayer.com/v1/youtube/transcript?video_url=dQw4w9WgXcQ&send_metadata=true" \
-H "Authorization: Bearer $TL_API_KEY"import requests
r = requests.get(
"https://api.transcriptlayer.com/v1/youtube/transcript",
params={"video_url": "dQw4w9WgXcQ", "send_metadata": True},
headers={"Authorization": f"Bearer {API_KEY}"},
)
r.raise_for_status()
data = r.json()const res = await fetch(
"https://api.transcriptlayer.com/v1/youtube/transcript?" +
new URLSearchParams({ video_url: "dQw4w9WgXcQ", send_metadata: "true" }),
{ headers: { Authorization: `Bearer ${process.env.TL_API_KEY}` } }
);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();Example response
{
"video_id": "dQw4w9WgXcQ",
"language": "en",
"metadata": {
"title": "How We Built Our Home Studio",
"channel": "Creator Channel",
"duration_seconds": 213
},
"transcript": [
{ "text": "Welcome back to the channel", "start": 0.0, "duration": 3.4 },
{ "text": "today we're covering something special", "start": 3.4, "duration": 3.1 }
]
}{
"video_id": "dQw4w9WgXcQ",
"language": "en",
"transcript": [
{ "text": "Welcome back to the channel" },
{ "text": "today we're covering something special" }
]
}{
"video_id": "dQw4w9WgXcQ",
"language": "en",
"transcript": "Welcome back to the channel today we're covering something special ..."
}Video Info
Returns metadata for a video without fetching its transcript. Costs no credits — useful for validating URLs before spending a credit on the transcript.
Query parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
video_url | string | Required | — | Full video URL, short URL, or bare video ID. |
Example response
{
"video_id": "dQw4w9WgXcQ",
"title": "How We Built Our Home Studio",
"channel": "Creator Channel",
"duration_seconds": 213,
"view_count": 1600000000,
"has_transcript": true,
"available_languages": ["en", "es", "pt"]
}
Search YouTube
Searches all of YouTube for videos, channels, or playlists. Paginate with the returned continuation token.
Query parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
q | string | Required* | — | Search query. *Not required when passing continuation. |
type | string | Optional | video | video, channel, or playlist. |
continuation | string | Optional | — | Token from a previous response to fetch the next page. |
Example response
{
"results": [
{
"video_id": "5C_HPTJg5ek",
"title": "Rust in 100 Seconds",
"channel": "Fireship",
"duration_seconds": 156,
"view_count": 2400000,
"thumbnail": "https://i.ytimg.com/vi/5C_HPTJg5ek/hqdefault.jpg"
}
],
"continuation": "EpcDEg1ydXN0IGxhbmd1YWdl..."
}
q → 2. read continuation from the response → 3. call again passing only continuation → repeat until it returns null.
Resolve Channel
Turns any channel reference — @handle, custom URL, or full URL — into a canonical channel ID. Free, so resolve once and cache the ID.
Query parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
input | string | Required | — | Handle (@fireship), channel URL, or channel ID. |
Example response
{
"channel_id": "UCsBjURrPoezykLs9EqgamOA",
"handle": "@fireship",
"title": "Fireship",
"subscriber_count": 3100000
}
Channel Search
Searches for videos within a single channel. Same result shape as Search YouTube.
Query parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
channel | string | Required | — | Handle, channel URL, or channel ID. |
q | string | Required* | — | Search query. *Not required when passing continuation. |
continuation | string | Optional | — | Token for the next page of results. |
Channel Videos
Lists a channel's uploads, newest first, ~30 per page. Each page consumes one credit.
Query parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
channel | string | Required* | — | Handle, channel URL, or channel ID. *Not required when passing continuation. |
continuation | string | Optional | — | Token for the next page of uploads. |
Example response
{
"channel_id": "UCHnyfMqiRRG1u-2MsSQLbXA",
"videos": [
{
"video_id": "aX3jf9Qw1kE",
"title": "The Universe Is Weirder Than You Think",
"published": "3 days ago",
"duration_seconds": 1264,
"view_count": 1900000
}
],
"continuation": "4qmFsgKFARIYVUNIbnlmTXFpUlJH..."
}
Latest Uploads
Returns a channel's most recent uploads at zero credit cost. Designed for polling — diff the IDs against your store to detect new videos, then spend credits only on transcripts you actually need.
Query parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
channel | string | Required | — | Handle, channel URL, or channel ID. |
Playlist Videos
Expands a playlist into its ordered list of videos, ~100 per page.
Query parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
playlist | string | Required* | — | Playlist URL or ID. *Not required when passing continuation. |
continuation | string | Optional | — | Token for the next page. |
Example response
{
"playlist_id": "PLBmcuObd5An594-lZO6BvNU7cvz9CkQvI",
"title": "Intro to Machine Learning",
"videos": [
{ "position": 1, "video_id": "kfF04B6pDKY", "title": "Lesson 1: Getting Started" }
],
"continuation": null
}
Error Handling
Errors use conventional HTTP status codes with a consistent JSON body:
{
"detail": "Transcript not available in requested language 'fr'",
"code": "language_unavailable",
"available_languages": ["en", "es"]
}
| Status | Meaning | Retry? | What to do |
|---|---|---|---|
400 | Bad request | No | Fix the parameter named in detail. |
401 | Invalid or missing API key | No | Check the Authorization header and key validity. |
402 | Out of credits | No | Top up — the response includes a billing_url to your dashboard. |
404 | Video/channel/transcript not found | No | For language misses, pick from available_languages in the body. |
429 | Rate limit exceeded | Yes | Back off per Retry-After, then retry. |
500 | Server error | Yes | Retry with exponential backoff; contact us if persistent. |
503 | Upstream temporarily unavailable | Yes | Retry after a short delay — usually transient. |
Rate Limits
Default limit is 10 requests/second per API key (burst up to 20). Every response includes your current state:
| Header | Description |
|---|---|
X-RateLimit-Limit | Requests allowed per window. |
X-RateLimit-Remaining | Requests left in the current window. |
X-RateLimit-Reset | Unix time when the window resets. |
Retry-After | Seconds to wait (only on 429 responses). |
Best practices
- Honor
Retry-Afterinstead of hammering on 429s. - Use continuation tokens promptly — they expire after ~1 hour.
- Cache
channel/resolveresults; channel IDs never change. - Parallelize transcript fetches up to your rate limit, not beyond.
- Need a higher limit? Contact us — bumps are usually same-day.
MCP Server
The official MCP server exposes every endpoint above as tools your AI client can call natively.
claude mcp add transcriptlayer \
-e TL_API_KEY=tl_live_xxx \
-- npx @transcriptlayer/mcp{
"mcpServers": {
"transcriptlayer": {
"command": "npx",
"args": ["@transcriptlayer/mcp"],
"env": { "TL_API_KEY": "tl_live_xxx" }
}
}
}Tool calls made through MCP consume credits at the same rates as direct API calls.