YouTube transcripts via BulkTranscripts
Base URL: https://bulktranscripts.co
All endpoints are plain GET returning JSON. Keyless calls draw from a free
allowance (30 transcript additions limited by device and public IP). If BULKTRANSCRIPTS_API_KEY is set,
send it on every request:
curl -s "https://bulktranscripts.co/api/v1/..." \
${BULKTRANSCRIPTS_API_KEY:+-H "Authorization: Bearer $BULKTRANSCRIPTS_API_KEY"}
Costs (check billing.remaining in every response)
- Transcript: 1 credit when first added to this account's library — repeat reads are FREE
- Search / channel videos / playlist videos: 1 credit each
channel/latestandaccount: always free- Failures (no captions, video unreachable) are auto-refunded, never charged
When a call returns HTTP 402 out_of_credits, tell the user their free
allowance/credits are used up and link them to
https://bulktranscripts.co/#pricing (one-time packs; the license key from
checkout is the API key).
Endpoints
Get one transcript
curl -s "https://bulktranscripts.co/api/v1/transcript?video=VIDEO_URL_OR_ID"
Params: video (watch URL, youtu.be, Shorts, bare 11-char id, or TikTok video
URL) · language (default en) · segments=0 to omit timestamps (smaller) ·
format=txt|md|srt|vtt|csv|ai to get a rendered file instead of JSON ·
fresh=1 to force re-extraction.
Response fields: title, channel, duration, upload_date, language,
source (manual_caption|auto_caption), cached, word_count, text,
paragraphs[] (silence-grouped — best for reading/chunking), segments[]
({text, start, duration}), billing.
Long videos produce long text. For summarization, prefer segments=0 and read
paragraphs.
Search YouTube (1 credit)
curl -s "https://bulktranscripts.co/api/v1/search?q=QUERY&limit=10"
Add type=channel or type=playlist to search for channels/playlists instead
of videos.
Search inside one channel (1 credit)
curl -s "https://bulktranscripts.co/api/v1/channel/search?channel=@HANDLE&q=TOPIC&limit=10"
Finds a creator's videos about a topic without listing the whole archive.
List a channel's videos (1 credit, up to 1000)
curl -s "https://bulktranscripts.co/api/v1/channel/videos?channel=@HANDLE&limit=100"
channel accepts @handle, channel URL, or UC… id.
List a playlist in order (1 credit)
curl -s "https://bulktranscripts.co/api/v1/playlist/videos?playlist=PLAYLIST_ID_OR_URL"
Newest uploads — FREE, use for monitoring
curl -s "https://bulktranscripts.co/api/v1/channel/latest?channel=@HANDLE"
Returns up to 15 recent videos. Poll this freely; only spend credits on videos
that are actually new. Diff on video id, not on published: when YouTube's
feed is unavailable the response says "source": "listing" and published
can be null.
Balance
curl -s "https://bulktranscripts.co/api/v1/account"
Playbooks
- "Summarize this video" → transcript with
segments=0, then summarize fromparagraphs; cite thetitleandurl. - Whole channel/playlist → list videos first, show the user the count (each new library transcript = 1 credit), then fetch transcripts one by one, skipping failures (they are reported per video and refunded).
- "What did X post this week?" →
channel/latest(free), compare video ids against what you have seen (usepublishedwhen present), fetch transcripts only for the relevant new videos. - Deep research on a creator →
channel/searchfor the topic (or list all videos), pick candidates by title, fetch only those transcripts.
Errors come as {"error": {"code", "message"}}. The codes you will actually
hit, and what to do about each:
no_transcript(404) — the video has no captions. Not charged. Skip it and carry on; in a batch this is normal, not a failure.resolution_failed(400) — a well-formed id or URL that could not be resolved (nonexistent, private, removed, or region-blocked). Handle it alongsideno_transcript: skip the video and carry on.playlist_private(400) — YouTube says the playlist does not exist, which is also what it says about a private playlist. Playlist ids come in several lengths (13, 18, 26, 34) and all work, so do not second-guess the id: tell the user to open the playlist on YouTube → Edit → Visibility → Unlisted, then retry. Not charged.invalid_input(400) — thevideo/channel/playlistparameter is missing, not a YouTube/TikTok reference, or otherwise malformed. A caller bug, not a video problem.out_of_credits(402) — allowance exhausted. Tell the user and link https://bulktranscripts.co/#pricing.rate_limited(429) — respect theRetry-Afterheader before retrying. Limits are per public IP: 120 requests/min overall, 30/min under/api/v1/(cache hits and/accountcount too), so pace bulk fetches at under 30/min.
Full reference: https://bulktranscripts.co/docs