BulkTranscripts logo BulkTranscripts
Developers & no-code builders · 30 free credits

Get YouTube transcripts into anything

One URL gives you the transcript of any YouTube video as text. Your AI assistant can call it, your scripts can call it, and tools like n8n or Google Sheets can call it. You do not need to be a developer to use this page — pick the path that sounds like you.

30free credits to startGoogle sign-in, no card
1,000videos per bulk joba whole channel or playlist
$0to read a video againyour library stays free
Nevercredits expireone-time packs, no subscription
Show

Start in 3 steps

About two minutes. Free — 30 credits, no card.

  1. 1

    Create a free API key

    Sign in with Google at bulktranscripts.co/app, open the MCP & API tab and press Create key. Copy the key — it starts with bt_ak_ and is shown only once.

    In plain words: an API key is a password that programs use on your behalf. Keep it private, and revoke it from the same place if it ever leaks.

    Open the app and create a key →
  2. 2

    Ask for one transcript

    Paste this into a terminal (Mac: Terminal; Windows: PowerShell) after replacing YOUR_API_KEY. No terminal? Use the playground right below instead — it does the same thing with a button.

    curl "https://bulktranscripts.co/api/v1/transcript?video=https://www.youtube.com/watch?v=jNQXAC9IVRw" \
      -H "Authorization: Bearer YOUR_API_KEY"

    In plain words: you are visiting a web address, and the second line shows your key so we know whose credits to use.

  3. 3

    Read the answer

    The reply is JSON — labelled fields, like a form. text is the whole transcript, segments are the timestamped lines, and billing.remaining is how many credits you have left.

    {
      "video_id": "jNQXAC9IVRw",
      "url": "https://www.youtube.com/watch?v=jNQXAC9IVRw",
      "title": "Me at the zoo",
      "channel": "jawed",
      "duration": 19,
      "duration_text": "0:19",
      "upload_date": "2005-04-23",
      "language": "en",
      "source": "auto_caption",
      "cached": true,
      "word_count": 43,
      "text": "All right, so here we are in front of the elephants...",
      "segments": [{"text": "All right, so here we are...", "start": 0.0, "duration": 5.4}],
      "billing": {"remaining": 29, "creditsCharged": 1, "freeLimit": 30}
    }

    Trimmed for reading — the full field list is in the reference.

Try it here — nothing to install

This calls the real API from your browser. Paste your key once (it stays in this browser only), pick what you want, press Send. The first fetch of a video costs 1 credit; fetching a video already in your library is free.

No key yet? Create one free, paste it above, press Send.
// The answer will appear here.

What you can ask for

Every request is a plain web address (a GET). Replace the parts in UPPERCASE. Full details for each are in the reference.

I want…Call thisCosts
The transcript of one video/api/v1/transcript?video=VIDEO_URL1 credit, free next time
The transcript as a file (SRT, TXT, Markdown…)/api/v1/transcript?video=VIDEO_URL&format=srtsame as above
Every video in a channel (to fetch them one by one)/api/v1/channel/videos?channel=@HANDLE1 credit for the list
Every video in a playlist/api/v1/playlist/videos?playlist=PLAYLIST_URL1 credit for the list
Videos about a topic/api/v1/search?q=WORDS1 credit
A video inside a specific channel/api/v1/channel/search?channel=@HANDLE&q=WORDS1 credit
To know when a channel posts something new/api/v1/channel/latest?channel=@HANDLEfree
To check my balance/api/v1/accountfree

Rule of thumb: getting a transcript costs 1 credit the first time, and reading it again from your library is free forever. Lists and searches cost 1 credit each. Checking your balance and watching for new uploads are always free. Anything that fails is not charged.

Words on this page, in plain English

API
A way for programs to ask our service for things. You "call" it by visiting a web address.
Endpoint
One specific address that does one job — /api/v1/transcript gets a transcript.
API key
Your password for programs. It starts with bt_ak_ and links calls to your credits.
Header
Extra information sent along with a request. Your key travels in the Authorization header.
JSON
The format of every answer: labelled fields in curly braces. Every language and no-code tool can read it.
curl
A tiny built-in command-line tool for visiting addresses. Already installed on Mac, Windows, and Linux.
Credit
One unit of work. 30 free to start; packs never expire.
MCP
The standard AI assistants use to plug in tools. Connect our server and Claude or ChatGPT can fetch transcripts itself.
Cache / library
Transcripts we have already extracted. Yours are free to re-read; everyone's come back instantly.

Authentication — where the key goes

Every /api/v1/* request, including the free ones, needs a credential. The normal one is your API key, sent as a Bearer token:

curl "https://bulktranscripts.co/api/v1/transcript?video=VIDEO_ID" \
  -H "Authorization: Bearer bt_ak_YOUR_KEY"
Pythonheaders={"Authorization": "Bearer bt_ak_…"}
Node / fetchheaders: { Authorization: "Bearer bt_ak_…" }
n8n / Make / ZapierHTTP module → Headers → name Authorization, value Bearer bt_ak_…
Postman / InsomniaAuth tab → Bearer Token → paste the key
Google SheetsApps Script — see the no-code section
Any tool with an "API key" fieldHeader name X-API-Key works too

A license key from checkout or an MCP OAuth token (bt_at_…) works as the Bearer value too. No credential → 401 missing_api_key; wrong one → 401 invalid_api_key. Credits belong to your Google account, so buying a pack tops up the same balance and the key never changes.

Credits

Credits are one-time purchases that never expire — no subscription, 30 free to start.

  • 1 credit: a transcript's first addition to your library, a search, or a channel/playlist listing.
  • Free: re-reading your library, checking your balance, watching for new uploads, and any failure.
  • Every response carries a billing block with creditsCharged and remaining.
  • $4.99 · 200
  • $14.99 · 1,200
  • $29 · 5,000
  • $99 · 25,000
  • $499 · 200,000

See pricing

REST API reference

Base URL https://bulktranscripts.co. Every endpoint returns JSON, and all but the bulk-job start are plain GET requests (machine-readable spec: /openapi.json). Each block shows the same request in cURL, Python and Node, plus a real response; the table under it lists every option.

GET/api/v1/transcript 1 credit first time · your repeats are free

Full transcript of one YouTube video with metadata, clean paragraph text, and timestamped segments.

curl "https://bulktranscripts.co/api/v1/transcript?video=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DaircAruvnKk&segments=0" \
  -H "Authorization: Bearer YOUR_API_KEY"
ParameterTypeDefaultDescription
videostringrequired—YouTube URL, youtu.be link, Shorts URL, or bare 11-char video id.
languagestringoptionalenPreferred caption language(s), comma-separated. Falls back to whatever the video has.
formatenumoptionaljsonjson, or txt, md, srt, vtt, csv, ai to get the rendered file instead of JSON.
segments0 | 1optional10 omits the segment array from JSON (smaller responses).
timestamps0 | 1optional01 includes timestamps in txt/md output.
fresh0 | 1optional01 bypasses the cache and re-extracts. Always charges a credit, even for a video already in your library.
GET/api/v1/channel/videos 1 credit

List a channel's videos — up to 1,000 — without fetching transcripts. Feed the ids into the transcript endpoint (ids already in your library stay free). There is no pagination: raise limit instead. has_more is true whenever the result reached limit.

curl "https://bulktranscripts.co/api/v1/channel/videos?channel=%40TED&limit=100" \
  -H "Authorization: Bearer YOUR_API_KEY"
ParameterTypeDefaultDescription
channelstringrequired—@handle, channel URL, or UC… channel id.
limitintegeroptional100Max videos, 1–1,000.
GET/api/v1/channel/latest free

A channel's newest uploads (up to 15). Free because it costs us nearly nothing — poll it for monitoring and only spend credits on what's new. When YouTube's feed is unavailable the response falls back to a direct listing and carries "source": "listing"; published can then be null, so diff on video id, not on date.

curl "https://bulktranscripts.co/api/v1/channel/latest?channel=%40TED" \
  -H "Authorization: Bearer YOUR_API_KEY"
ParameterTypeDefaultDescription
channelstringrequired—@handle, channel URL, or UC… channel id.
GET/api/v1/playlist/videos 1 credit

Every video in a playlist, in playlist order — courses stay in sequence. No pagination; has_more is true whenever the result reached limit.

curl "https://bulktranscripts.co/api/v1/playlist/videos?playlist=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi" \
  -H "Authorization: Bearer YOUR_API_KEY"
ParameterTypeDefaultDescription
playliststringrequired—Playlist URL or bare id (the list= value). Ids are 13, 18, 26 or 34 characters; public and unlisted playlists only — a private one reads as nonexistent (playlist_private).
limitintegeroptional100Max videos, 1–1,000.
GET/api/v1/account free

The credit balance for the key making the call. Returns the same billing block every credited response carries.

curl "https://bulktranscripts.co/api/v1/account" \
  -H "Authorization: Bearer YOUR_API_KEY"
POST/api/v1/bulk listing free · 1 credit per new transcript

Start a background job that fetches every transcript of a channel, playlist or video URL into your library (up to 1,000 videos). Returns 202 with a run_id straight away; small sources are listed within the call so videos_found is filled, larger ones report it on the first status poll. Cache hits and repeats are free, failures are never charged, and a job that runs out of credits keeps what it fetched and says how many videos it did not attempt. Two jobs per account at a time.

curl -X POST "https://bulktranscripts.co/api/v1/bulk" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://www.youtube.com/playlist?list=PLZHQObOWTQDNU6R1_67000Dx_ZCJB-3pi", "max_videos": 200}'
ParameterTypeDefaultDescription
urlstringrequired—Channel (@handle or URL), playlist URL or id, or a single video URL. JSON body field.
max_videosintegeroptional100Cap on videos to process, 1 to 1,000. JSON body field.
languagestringoptionalenPreferred caption language(s), comma-separated. JSON body field.
GET/api/v1/bulk/{run_id} free

Progress of a bulk job. status is running, completed, stopped (interrupted by a server restart; start it again, everything already fetched is free) or failed. Wait at least check_again_in_seconds between polls; it is 0 once the job has finished.

curl "https://bulktranscripts.co/api/v1/bulk/{run_id}" \
  -H "Authorization: Bearer YOUR_API_KEY"
ParameterTypeDefaultDescription
run_idstringrequired—The run_id from the start call, in the path.
GET/api/v1/bulk/{run_id}/results free

One page of per-video outcomes for a job, in source order: id, title, channel, duration, word count and status (ok, cached, or error with a code). Transcript text is not included — every video listed as ok or cached is already in your library, so /transcript returns it without spending a credit.

curl "https://bulktranscripts.co/api/v1/bulk/{run_id}/results?limit=2" \
  -H "Authorization: Bearer YOUR_API_KEY"
ParameterTypeDefaultDescription
run_idstringrequired—The run_id from the start call, in the path.
cursorintegeroptional—next_cursor from the previous page; omit for the first page.
limitintegeroptional50Items per page, 1 to 100.

MCP server — YouTube for your AI assistant

Connect https://bulktranscripts.co/mcp once and Claude, ChatGPT, Cursor, VS Code, and 20+ other MCP clients can fetch transcripts, search YouTube, list channels and playlists, and track new uploads — inside the conversation. One sign-in (Google or license key) includes 30 free credits, no card.

Example · once connected, just ask

Set it up in your client

  1. Settings → Connectors → Add custom connector
  2. Name BulkTranscripts, URL https://bulktranscripts.co/mcp → Connect
  3. On the page that opens, continue with Google (or paste a license key)

Step-by-step guides: Claude Code · Codex · Cursor · ChatGPT · VS Code · n8n · Make

The ten tools

Generated from the same tool schema the server sends to your client, so what you see here is exactly what Claude, Cursor or ChatGPT sees.

ToolParametersReturnsCost
get_transcript
Get YouTube video transcript
  • video string · required
    YouTube video URL or 11-character video id.
  • language string · optional
    Preferred caption language code, e.g. 'en' or 'de'. Defaults to 'en', falling back to whatever exists.
  • include_segments boolean · optional
    Include the timestamped segment list. Default false — the plain text is usually what you want.
  • fresh boolean · optional
    Bypass the cache and re-extract (costs a credit). Default false.
Title, channel, duration, upload date, language, clean paragraph text, word count and (on request) timed segments for one video.1 credit on first library addition · repeat reads free
get_transcripts
Get many transcripts at once
  • videos array of string · required
    Up to 20 YouTube video URLs or ids.
  • language string · optional
    Preferred caption language code. Default 'en'.
Up to 20 transcripts in one call, fetched in parallel; the call returns within about 40 seconds and anything still fetching comes back on the next call, free. Videos without captions are reported per item and do not fail the batch. One call is one request against the rate limit.1 credit per new transcript · repeats free
search_youtube
Search YouTube
  • query string · required
    Search terms, e.g. 'claude code tutorial'.
  • type video | channel | playlist · optional
    What to search for. Default video.
  • limit integer · optional
    Max results, default 10.
Videos, channels or playlists matching a query: id, title, channel, duration, URL and view count.1 credit
search_channel
Search inside a channel
  • channel string · required
    Channel @handle, URL, or UC… id.
  • query string · required
    Topic to search for within the channel.
  • limit integer · optional
    Max results, default 10.
Videos inside one channel that match a topic, same fields as search.1 credit
get_channel_videos
List a channel's videos
  • channel string · required
    Channel @handle, URL, or UC… id.
  • limit integer · optional
    Max videos to list, default 100.
A channel's video list (id, title, duration, URL), up to 1,000, ready to feed into get_transcripts.1 credit
get_playlist_videos
List a playlist's videos
  • playlist string · required
    Playlist URL or id (the list= value).
  • limit integer · optional
    Max videos to list, default 100.
Every video in a playlist, in playlist order.1 credit
get_latest_videos
Track new uploads (free)
  • channel string · required
    Channel @handle, URL, or UC… id.
A channel's newest uploads (up to 15) with publish dates and views.Free — always
start_bulk_extract
Start a bulk extraction job
  • url string · required
    Channel (@handle or URL), playlist URL/id, or a single video URL.
  • max_videos integer · optional
    Cap on videos to process, default 100.
  • language string · optional
    Preferred caption language code. Default 'en'.
A run_id straight away, plus videos_found once the listing is done (small sources list within the call). The server then fetches every transcript into this account's library in the background.Listing free · 1 credit per new transcript
get_bulk_status
Check a bulk job
  • run_id string · required
    The run_id from start_bulk_extract.
status, total, completed, failed, skipped, quota, remaining and check_again_in_seconds for a job.Free
list_bulk_results
List a bulk job's results
  • run_id string · required
    The run_id from start_bulk_extract.
  • cursor integer · optional
    next_cursor from the previous page; omit for the first page.
  • limit integer · optional
    Items per page, default 50.
A page of per-video outcomes (id, title, channel, duration, word count, status, error code) with next_cursor. No transcript text.Free
Which tool the agent picks, prompts that work, troubleshooting

Which tool does the agent reach for?

You never call these by name — the assistant picks from the descriptions. This is the mapping it lands on, so you know what a request will cost before you ask.

You say…Tool usedCredits
"Summarize this video: [URL]"get_transcript1 (0 if it is already in your library)
"Compare what these four talks say about X"get_transcripts1 per new video
"Find the best explainers on Y"search_youtube, then get_transcripts for the picks1 + 1 per transcript
"What has @creator said about Z?"search_channel, then get_transcripts1 + 1 per transcript
"Turn this course playlist into study notes"get_playlist_videos, then get_transcripts in batches of 201 + 1 per lecture
"Audit this channel's whole archive"get_channel_videos (up to 1,000), then selective get_transcripts1 + 1 per transcript read
"Did @creator post anything this week?"get_latest_videos0

Prompts that work on day one

One video

“Summarize this talk with the three strongest quotes and timestamps: https://youtube.com/watch?v=…”

“Pull the transcript and turn it into a LinkedIn post in my voice.”

Several videos

“Here are five interviews with the same founder. Where do their stories contradict each other?”

“Compare how these two channels explain the same concept. Which is clearer for a beginner?”

Research a topic

“Find the most-watched videos about intermittent fasting and tell me where the experts disagree.”

“What has @hubermanlab said about caffeine timing? Cite the episodes.”

Courses & playlists

“Read every lecture in this Stanford playlist and build a study guide with one section per lecture.”

“Which videos in this playlist mention gradient descent?”

Monitoring

“Check @TED, @veritasium and @3blue1brown for new uploads and brief me on anything about AI.”

“Every morning: new videos from these channels, one line each.” (free — uses get_latest_videos)

Whole channels

“List everything @mkbhd has published this year, then read the ten most-viewed and tell me his recurring complaints about phones.”

Troubleshooting

The connector shows “Needs authentication” or never finishes connecting
Open the sign-in your client offers (Claude Code: /mcp → Authenticate; Claude web: Settings → Connectors → the connector's menu → Reconnect; Cursor: Settings → MCP → Login). The sign-in page is served by BulkTranscripts and accepts Google or a license key. If the page never opens, the client is probably an older build without MCP OAuth: use the key-in-URL form https://bulktranscripts.co/mcp?key=YOUR_LICENSE_KEY instead.
I get 401 right after buying a pack
The key is issued at checkout but the payment webhook that activates it can land a few seconds later. Wait a moment and retry; nothing is charged for the failed call.
The assistant answers from memory instead of calling the tool
Paste the full YouTube URL (not just the title) and say “use BulkTranscripts” or “fetch the transcript” once. Check the connector is enabled for the current chat; ChatGPT and Claude web both have a per-conversation toggle.
out_of_credits in the middle of a batch
The transcripts already fetched are returned with partial: true and a stopped count, and the error carries a purchase link. Credits are added to the same account you signed in with, so nothing needs reconnecting afterwards.
no_transcript for a video that clearly has captions
Some videos only have captions in one language; ask for that language explicitly (“get the German transcript”). Live streams and members-only videos expose no captions. Never charged.
Long videos (2h+) take a while or the client times out
Extraction usually finishes in a few seconds, but the first read of a long, uncached video can take longer than a strict client timeout. Ask again: the second request returns instantly from the cache and the credit is not charged twice.
Something else
Every error has a stable code listed in the error table. Still stuck? Email hello@bulktranscripts.co with the tool name and the code.

Agent skill (Claude Code, Codex, OpenClaw & friends)

Prefer a skill over a server? One command installs a skill that teaches your agent the whole API. Create a free API key first at /app → MCP & API:

mkdir -p ~/.claude/skills/youtube-transcripts
curl -fsSL https://bulktranscripts.co/skill.md -o ~/.claude/skills/youtube-transcripts/SKILL.md

OpenClaw users install it from ClawHub instead: openclaw skills install @pratie/bulktranscripts-youtube (listing: clawhub.ai/pratie/skills/bulktranscripts-youtube).

Set BULKTRANSCRIPTS_API_KEY in your environment to your bt_ak_… key (a license key works too). The skill source lives at /skill.md and on GitHub; capabilities, example prompts, and per-agent notes are on the agent skill page.

No-code tools: n8n, Make, Zapier, Google Sheets

Anything with an "HTTP request" step can use the API. Method GET, the URL from the table above, and one header: Authorization = Bearer bt_ak_…. Then read text from the JSON reply.

  • n8n — HTTP Request node. Step-by-step: n8n guide.
  • Make — HTTP → Make a request. Step-by-step: Make guide.
  • Zapier — Webhooks by Zapier → GET, add the header under "Headers".
  • Google Sheets — Extensions → Apps Script, paste this, then use =TRANSCRIPT(A2) in a cell:
const KEY = "bt_ak_YOUR_KEY";
function TRANSCRIPT(video) {
  const url = "https://bulktranscripts.co/api/v1/transcript?segments=0&video=" + encodeURIComponent(video);
  const res = UrlFetchApp.fetch(url, {headers: {Authorization: "Bearer " + KEY}, muteHttpExceptions: true});
  const data = JSON.parse(res.getContentText());
  return data.text || (data.error && data.error.message) || "";
}

Sheets recalculates formulas on every edit; each recalculation of a video already in your library is free, so the cost is one credit per new video.

Questions people ask

Do I need to know how to code?

No. The web app needs nothing, the MCP server is a one-time connect inside your AI assistant, and the no-code tools only need a URL and a header. The code samples are for people who want them.

Is it really free to start?

Yes — 30 credits with a Google sign-in, no card. That is 30 transcripts, searches or listings. Re-reading a transcript you already fetched is free forever.

Where do I find my API key later?

You can't — it is shown once when created. Open MCP & API, revoke the old one, create a new one. Keys are free and you can have five.

What happens when I run out?

The request returns 402 out_of_credits with a purchase link. Buy a pack while signed in with the same Google account and your existing key keeps working — nothing to reconnect.

Can I get a whole channel at once?

Yes, up to 1,000 videos per job. Over the API: POST /api/v1/bulk with the channel or playlist URL, then poll /api/v1/bulk/{run_id}. Over MCP: start_bulk_extract, then get_bulk_status. The server keeps fetching after the call returns; each new transcript costs 1 credit and lands in your library. With zero code, the web app does the whole channel and zips the files.

Why did a video come back with "no_transcript"?

It has no captions at all — not even auto-generated ones. You are not charged. Try another language first; if that fails, the video simply has none.

Is my key safe in the playground?

It is stored only in your own browser's local storage, sent only to bulktranscripts.co, and never logged. Clear the field to forget it.

Errors

Every error is JSON with a stable code and a message that says what to do next:

{
  "error": {"code": "no_transcript", "message": "No captions available for this video..."}
}
HTTPCodeMeaningRetry?
400invalid_inputMissing or malformed video / channel / playlist / q parameter, or an unknown format. A caller bug.No — fix the request.
400resolution_failedA well-formed id or URL that could not be resolved (private, removed, region-locked, nonexistent). Not charged.No.
400empty_sourceThe channel or playlist resolved but contains no videos.No.
400playlist_privateYouTube reports the playlist as nonexistent — which is also what it says about a private playlist. Ask the owner to set Visibility to Unlisted or Public, then retry. Not charged.After the visibility change.
400private_video / members_only / age_restrictedYouTube will not serve this video's captions without a viewer login. Not charged; in a bulk job it counts as skipped.No.
401missing_api_keyNo credential on the request. Sign in at /app and create a key. The error object carries setup_url and docs_url.No — add the key.
401invalid_api_keyThe Bearer credential is not a valid API key or license key.No — check the key.
401invalid_tokenThe OAuth access token is expired or revoked — refresh or reconnect.After refreshing or reconnecting.
402out_of_creditsBalance empty. The error object also carries purchase_url, setup_url, and reconnect_steps so an agent can guide the user.After topping up.
403access_blockedThe caller has been blocked for abuse.No.
404no_transcriptThe video has no captions at all. Not charged.No — try another language first.
404not_foundUnknown /api/v1 path.No.
429rate_limitedToo many requests. Wait the number of seconds in the Retry-After header, then retry.Yes, after Retry-After seconds.
429too_many_runsThis account already has 2 bulk jobs running. Let one finish, then start the next.Yes, after Retry-After seconds.
500internal_errorSomething broke on our side. Retry once, then report it.Yes, once.
503restartingThe server is restarting for an update; back within a minute.Yes, in a minute.
504still_fetchingThe transcript is still being fetched and took longer than the request allows. It keeps going in the background.Yes — the same request returns it, usually within a minute.

Over MCP the same codes arrive as a tool result with isError: true and the identical error.code. A get_transcripts batch that runs out of credits part-way returns the transcripts it completed plus partial: true and a stopped count, so nothing already paid for is lost.

Rate limits

Per public IP, shared between REST and MCP traffic from that IP: 120 requests/minute overall, and 30 requests/minute for anything under /api/v1/ — including /account and cache hits — plus any MCP tool call. Exceeding either returns 429 rate_limited with a Retry-After header in seconds. Bulk jobs have their own budget: 12 starts per 10 minutes per IP, and 2 running at once per account. The REST API fetches one transcript per request; for batches, pace at under 30 per minute or use the MCP get_transcripts tool, which fetches up to 20 videos in parallel and counts as a single request. If you are building something high-volume (100k+ transcripts/month), email us for a custom pack.

Stuck anywhere on this page? Email hello@bulktranscripts.co with what you tried and what you see. A person answers, usually within a day.

Updated