TranscriptAPI
SkillMediaLets your agent fetch YouTube transcripts, search videos and channels, and browse playlists.
Use TranscriptAPI in Claude, ChatGPT or Ahel Desktop
Free. Sign in, add TranscriptAPI and connect your AI. About a minute.
Also: Claude Code · Cursor · Codex
Then ask your AI: use the TranscriptAPI skill
Details
Instructions available. Your AI can read the instructions. Execution depends on the setup they require.
Account requirements not reviewed. Check the skill instructions before use; ahel provides instructions and does not run this skill.
No other account needed.
Add ahel to your AI once: Claude, ChatGPT, Cursor, Claude Code or Codex. Then ask it to use this.
About this skill
Use when YouTube is or could be relevant, even if not mentioned: pasted video/channel/playlist links, video IDs, @handles, creator lookups, video summaries, quotes, translations, topic research, tutorials, talks, lectures, expert discussions, product reviews, how-to guides, new product announcement
What this skill tells your AI
The instructions your AI receives, as published by hashgraph-online/awesome-codex-plugins in plugins/ZeroPointRepo/youtube-skills/skills/transcriptapi/SKILL.md and read by ahel’s review.
Full YouTube data toolkit via TranscriptAPI.com. Transcripts, search, channels, playlists — one API key.
Setup
If $TRANSCRIPT_API_KEY is not set, read references/auth-setup.md and follow the instructions there to get and store the key.
Required Headers
Every request needs two headers:
- Authorization:
Bearer $TRANSCRIPT_API_KEY - User-Agent: your agent's name and version if known (e.g.
HermesAgent/0.11.0,ClaudeCode/1.0). Version is optional — agent name alone is fine. Do not omit this header or send a bare default — Cloudflare will return a 403 (error code 1010) and block the request.
API Reference
Full OpenAPI spec: transcriptapi.com/openapi.json — consult this for the latest parameters and schemas.
Auth
All requests: -H "Authorization: Bearer $TRANSCRIPT_API_KEY"
Endpoints
Channel endpoints accept channel — an @handle, channel URL, or UC... ID. No need to resolve first. Playlist endpoints accept playlist — a playlist URL or ID.
GET /api/v2/youtube/transcript — 1 credit
curl -s "https://transcriptapi.com/api/v2/youtube/transcript\
?video_url=VIDEO_URL&format=text&include_timestamp=true&send_metadata=true" \
-H "Authorization: Bearer $TRANSCRIPT_API_KEY" \
-H "User-Agent: YourAgent/1.0"
| Param | Required | Default | Validation |
|---|---|---|---|
video_url | yes | — | YouTube URL or 11-char video ID |
format | no | json | json or text |
include_timestamp | no | true | true or false |
send_metadata | no | false | true or false |
Accepts: https://youtube.com/watch?v=ID, https://youtu.be/ID, youtube.com/shorts/ID, or bare ID.
Response (format=json):
{
"video_id": "dQw4w9WgXcQ",
"language": "en",
"transcript": [
{ "text": "We're no strangers...", "start": 18.0, "duration": 3.5 }
],
"metadata": { "title": "...", "author_name": "...", "author_url": "..." }
}
GET /api/v2/youtube/search — 1 credit
curl -s "https://transcriptapi.com/api/v2/youtube/search?q=QUERY&type=video&limit=20" \
-H "Authorization: Bearer $TRANSCRIPT_API_KEY" \
-H "User-Agent: YourAgent/1.0"
| Param | Required | Default | Validation |
|---|---|---|---|
q | yes | — | 1-200 chars (trimmed) |
type | no | video | video or channel |
limit | no | 20 | 1-50 |
Response (type=video):
{
"results": [
{
"type": "video",
"videoId": "dQw4w9WgXcQ",
"title": "Rick Astley - Never Gonna Give You Up",
"channelId": "UCuAXFkgsw1L7xaCfnd5JJOw",
"channelTitle": "Rick Astley",
"channelHandle": "@RickAstley",
"channelVerified": true,
"lengthText": "3:33",
"viewCountText": "1.5B views",
"publishedTimeText": "14 years ago",
"hasCaptions": true,
"thumbnails": [{ "url": "...", "width": 120, "height": 90 }]
}
],
"result_count": 20
}
Response (type=channel):
{
"results": [
{
"type": "channel",
"channelId": "UCuAXFkgsw1L7xaCfnd5JJOw",
"title": "Rick Astley",
"handle": "@RickAstley",
"subscriberCount": "4.2M subscribers",
"verified": true,
"rssUrl": "https://www.youtube.com/feeds/videos.xml?channel_id=UC..."
}
],
"result_count": 5
}
GET /api/v2/youtube/channel/resolve — FREE (0 credits)
curl -s "https://transcriptapi.com/api/v2/youtube/channel/resolve?input=@TED" \
-H "Authorization: Bearer $TRANSCRIPT_API_KEY" \
-H "User-Agent: YourAgent/1.0"
| Param | Required | Validation |
|---|---|---|
input | yes | 1-200 chars — @handle, URL, or UC... ID |
Response:
{ "channel_id": "UCsT0YIqwnpJCM-mx7-gSA4Q", "resolved_from": "@TED" }
If input is already a valid UC[a-zA-Z0-9_-]{22} ID, returns immediately without lookup.
GET /api/v2/youtube/channel/videos — 1 credit/page
# First page (100 videos)
curl -s "https://transcriptapi.com/api/v2/youtube/channel/videos?channel=@NASA" \
-H "Authorization: Bearer $TRANSCRIPT_API_KEY" \
-H "User-Agent: YourAgent/1.0"
# Most-viewed first (channel Videos tab, ~30 videos)
curl -s "https://transcriptapi.com/api/v2/youtube/channel/videos?channel=@NASA&sort=popular" \
-H "Authorization: Bearer $TRANSCRIPT_API_KEY" \
-H "User-Agent: YourAgent/1.0"
# Next pages (repeat the same sort)
curl -s "https://transcriptapi.com/api/v2/youtube/channel/videos?continuation=TOKEN&sort=popular" \
-H "Authorization: Bearer $TRANSCRIPT_API_KEY" \
-H "User-Agent: YourAgent/1.0"
| Param | Required | Validation |
|---|---|---|
channel | conditional | @handle, channel URL, or UC... ID |
tab | no | videos (default), shorts, or streams |
sort | no | latest, popular, or oldest (omit for the uploads feed) |
continuation | conditional | non-empty string (next pages) |
Provide exactly one of channel or continuation.
Sorting. Add sort=latest, popular, or oldest to channel/videos to get a channel's videos in the order you want, for example its most-popular uploads first. A sorted page returns about 30 videos (an unsorted page returns about 100), and every page costs the same 1 credit.
When paging, send the same sort on each request.
Every item carries members_only, true only when YouTube badges it "Members only", and those items have no viewCountText. Items from tab=streams carry lengthText and publishedTimeText (for example Streamed 2 years ago); tab=shorts returns null for both, because YouTube's Shorts grid publishes neither. On the channel-tab feeds (tab=videos with sort, tab=shorts, tab=streams) channelId, channelTitle, channelHandle and index are null.
Response:
{
"results": [{
"videoId": "abc123xyz00",
"title": "Latest Video",
"channelId": "UCsT0YIqwnpJCM-mx7-gSA4Q",
"channelTitle": "TED",
"channelHandle": "@TED",
"lengthText": "15:22",
"viewCountText": "3.2M views",
"publishedTimeText": "2 years ago",
"thumbnails": [...],
"index": "0",
"members_only": false
}],
"playlist_info": {"title": "Uploads from TED", "numVideos": "5000"},
"continuation_token": "4qmFsgKlARIYVVV1...",
"has_more": true
}
GET /api/v2/youtube/channel/latest — FREE (0 credits)
curl -s "https://transcriptapi.com/api/v2/youtube/channel/latest?channel=@TED" \
-H "Authorization: Bearer $TRANSCRIPT_API_KEY" \
-H "User-Agent: YourAgent/1.0"
| Param | Required | Validation |
|---|---|---|
channel | yes | @handle, channel URL, or UC... ID |
Returns last 15 videos via RSS with exact view counts and ISO timestamps.
Response:
{
"channel": {
"channelId": "...",
"title": "TED",
"author": "TED",
"url": "..."
},
"results": [
{
"videoId": "abc123xyz00",
"title": "Latest Video",
"published": "2026-01-30T16:00:00Z",
"viewCount": "2287630",
"description": "Full description...",
"thumbnail": { "url": "...", "width": "480", "height": "360" }
}
],
"result_count": 15
}
GET /api/v2/youtube/channel/search — 1 credit
curl -s "https://transcriptapi.com/api/v2/youtube/channel/search\
?channel=@TED&q=climate+change&limit=30" \
-H "Authorization: Bearer $TRANSCRIPT_API_KEY" \
-H "User-Agent: YourAgent/1.0"
| Param | Required | Validation |
|---|---|---|
channel | yes | @handle, channel URL, or UC... ID |
q | yes | 1-200 chars |
limit | no | 1-50 (default 30) |
GET /api/v2/youtube/playlist/videos — 1 credit/page
# First page
curl -s "https://transcriptapi.com/api/v2/youtube/playlist/videos?playlist=PL_PLAYLIST_ID" \
-H "Authorization: Bearer $TRANSCRIPT_API_KEY" \
-H "User-Agent: YourAgent/1.0"
# Next pages
curl -s "https://transcriptapi.com/api/v2/youtube/playlist/videos?continuation=TOKEN" \
-H "Authorization: Bearer $TRANSCRIPT_API_KEY" \
-H "User-Agent: YourAgent/1.0"
| Param | Required | Validation |
|---|---|---|
playlist | conditional | Playlist URL or ID (PL/UU/LL/FL/OL prefix) |
continuation | conditional | non-empty string |
Credit Costs
| Endpoint | Cost |
|---|---|
| transcript | 1 |
| search | 1 |
| channel/resolve | free |
| channel/search | 1 |
| channel/videos | 1/page |
| channel/latest | free |
| playlist/videos | 1/page |
Errors
| Code | Meaning | Action |
|---|---|---|
| 401 | Bad API key | Check key, re-run setup |
| 402 | No credits | Top up at transcriptapi.com/billing |
| 403/1010 | Cloudflare block | Add or fix User-Agent header |
| 404 | Not found | Video/channel/playlist doesn't exist or no captions |
| 408 | Timeout/retryable | Retry once after 2s |
| 422 | Validation error | Check param format |
| 429 | Rate limited | Wait, respect Retry-After |
Tips
- When user shares YouTube URL with no instruction, fetch transcript and summarize key points.
- Use
channel/latest(free) to check for new uploads before fetching transcripts — pass @handle directly. - For research: search → pick videos → fetch transcripts.
- Free tier: 100 credits, 300 req/min. Starter ($5/mo): 1,000 credits, 300 req/min.
Signals
- GitHub stars
- 1k
- Forks
- 316
- Last commit
- Oct 2026
ahel review
K7info
secret-appetite (in references/auth-setup.md)
Automated review, not a security audit. Ruleset v1+k2.
Advanced
- Item type
- skill
- Key
transcriptapi- Source
- github.com/hashgraph-online/awesome-codex-plugins
github.com/hashgraph-online/awesome-codex-plugins