# Youtube Transcripts

> Fetch YouTube video transcripts, search YouTube, list channel or playlist videos, and track new uploads via the BulkTranscripts API. Use when the user shares a YouTube link, asks to summarize/analyze/quote a video, wants transcripts for a whole channel or playlist, needs YouTube research, or asks what a channel posted recently. Works immediately with no API key (free tier); set BULKTRANSCRIPTS_API_KEY for purchased credits.

- Skill: `pratie/youtube-transcripts` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add pratie/youtube-transcripts`
- Raw SKILL.md: https://api.skillmd.com/api/skills/pratie/youtube-transcripts/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Research & Search
- License: Proprietary API; this skill file is freely redistributable.
- Author: pratie (https://skillmd.com/u/pratie)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/pratie/youtube-transcripts

---


# 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:

```bash
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/latest` and `account`: 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
```bash
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)
```bash
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)
```bash
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)
```bash
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)
```bash
curl -s "https://bulktranscripts.co/api/v1/playlist/videos?playlist=PLAYLIST_ID_OR_URL"
```

### Newest uploads — FREE, use for monitoring
```bash
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
```bash
curl -s "https://bulktranscripts.co/api/v1/account"
```

## Playbooks

- **"Summarize this video"** → transcript with `segments=0`, then summarize
  from `paragraphs`; cite the `title` and `url`.
- **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 (use `published` when present), fetch
  transcripts only for the relevant new videos.
- **Deep research on a creator** → `channel/search` for 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
  alongside `no_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) — the `video` / `channel` / `playlist` parameter 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 the `Retry-After` header before retrying.
  Limits are per public IP: 120 requests/min overall, 30/min under `/api/v1/`
  (cache hits and `/account` count too), so pace bulk fetches at under 30/min.

Full reference: https://bulktranscripts.co/docs

