Use cases / YouTube API, Google Search API
YouTube transcripts for RAG
Last updated October 29, 2026. Response excerpts are recorded from the live API.
Who runs this, and what for
| Team | What they decide with it |
|---|---|
| AI product teams | Which videos to add to an assistant's knowledge, and how to cite the moment an answer came from. |
| Researchers and analysts | What experts, competitors, or executives said on a subject across many videos, without watching them. |
| Education and training | Which lectures cover a topic, and where in each video it starts. |
The calls, step by step
1. Find the videos
If you already have video links, skip this step: the transcript endpoint takes a link or an id. To start from a topic, search Google with site:youtube.com in front of the query. Each results page is one request and lists about ten videos in results[], and when Google shows its video carousel, videos[] adds more with title, channel, and duration.
GET /v1/google-search?q=albert+einstein&country=us&page=1 · videos
[ { "position": 1, "title": "Who Was Albert Einstein? Facts for Kids", "url": "https://www.youtube.com/watch?v=nEaFtXEYJn0", "platform": "YouTube", "channel": "Hey! Guess What", "date": "Oct 17, 2022", "duration": "8:47" } ]Recorded response. Live values differ. 2. Read each transcript
Call the transcript endpoint with the video id or link and the language you want. It returns the whole transcript as text, plus segments[] with start_ms and duration_ms for each caption line. kind tells you whose captions they are: manual for the uploader's, auto for YouTube's speech recognition. A video without captions in that language returns 404 with the languages it has, so a pipeline can skip it or ask for another.
GET /v1/youtube/transcript?video_id=jNQXAC9IVRw · transcript
{ "language": "en", "kind": "manual", "text": "All right, so here we are, in front of the elephants the cool thing about these guys is that they have really... really really long trunks and that's cool (baaaaaaaaaaahhh!!) and that's pretty much all there is to say", "segments": [ { "start_ms": 1200, "duration_ms": 2160, "text": "All right, so here we are, in front of the elephants" }, { "start_ms": 5318, "duration_ms": 2656, "text": "the cool thing about these guys is that they have really..." }, { "start_ms": 7974, "duration_ms": 4642, "text": "really really long trunks" }, { "start_ms": 12616, "duration_ms": 1751, "text": "and that's cool" }, { "start_ms": 14421, "duration_ms": 1312, "text": "(baaaaaaaaaaahhh!!)" }, { "start_ms": 16881, "duration_ms": 2000, "text": "and that's pretty much all there is to say" } ] }Recorded response. Live values differ. 3. Chunk with timestamps
Caption lines are a few words each, too short to embed on their own. Join consecutive segments until a chunk reaches the size your retriever works best with, a few hundred words, and keep the start_ms of its first line. A link ending in &t=<seconds>s then opens the video at the moment the chunk starts, so an answer can cite it.
GET /v1/youtube/transcript?video_id=jNQXAC9IVRw · transcript.segments
[ { "start_ms": 1200, "duration_ms": 2160, "text": "All right, so here we are, in front of the elephants" }, { "start_ms": 5318, "duration_ms": 2656, "text": "the cool thing about these guys is that they have really..." }, { "start_ms": 7974, "duration_ms": 4642, "text": "really really long trunks" }, { "start_ms": 12616, "duration_ms": 1751, "text": "and that's cool" }, { "start_ms": 14421, "duration_ms": 1312, "text": "(baaaaaaaaaaahhh!!)" }, { "start_ms": 16881, "duration_ms": 2000, "text": "and that's pretty much all there is to say" } ]Recorded response. Live values differ.
A script to start from
index_transcripts.py
# Index the transcripts of YouTube videos on a topic for retrieval.
# Finds videos through Google, reads each transcript, and writes chunks of
# about 200 words, each with a link to the second it starts at.
import json, os, re, requests
API = "https://api.clair.im"
HEADERS = {"Authorization": f"Bearer {os.environ['CLAIR_API_KEY']}"}
TOPIC = "transformer neural networks explained"
PAGES = 2 # each Google results page is one request, about ten videos
WORDS = 200
def get(path, **params):
r = requests.get(f"{API}{path}", headers=HEADERS, params=params, timeout=90)
r.raise_for_status()
return r.json()
videos = {}
for page in range(1, PAGES + 1):
body = get("/v1/google-search", q=f"site:youtube.com {TOPIC}",
country="us", language="en", page=page)
for hit in body["results"] + (body.get("videos") or []):
m = re.search(r"[?&]v=([\w-]{11})", hit["url"])
if m:
videos.setdefault(m.group(1), hit["title"])
def write(f, video_id, title, start_ms, lines):
f.write(json.dumps({
"video_id": video_id, "title": title, "start_ms": start_ms,
"url": f"https://www.youtube.com/watch?v={video_id}&t={start_ms // 1000}s",
"text": " ".join(lines),
}) + "\n")
with open("chunks.jsonl", "w") as f:
for video_id, title in videos.items():
try:
t = get("/v1/youtube/transcript", video_id=video_id, language="en")["transcript"]
except requests.HTTPError as e:
if e.response.status_code == 404:
continue # no English captions on this video
raise
lines, start = [], None
for seg in t["segments"]:
start = seg["start_ms"] if start is None else start
lines.append(seg["text"])
if sum(len(line.split()) for line in lines) >= WORDS:
write(f, video_id, title, start, lines)
lines, start = [], None
if lines:
write(f, video_id, title, start, lines)
Set CLAIR_API_KEY to your Clair key; one plan covers the YouTube API and Google Search API. Each call spends that API's rate from the plan's monthly balance.
What it costs per month
| Schedule | Requests | Plan | Per month | Per 1,000 |
|---|---|---|---|---|
| One topic, 200 videos20 Google results pages of about ten videos, then one transcript call per video. | 220 | Starter | $30 | $136.36 |
| 1,000 known videos, onceOne transcript call per video link you already have. | 1,000 | Starter | $30 | $30 |
| 50 new videos a day5 searches and 50 transcripts a day, over 30 days. | 1,650 | Starter | $30 | $18.18 |
| 500 new videos a day50 searches and 500 transcripts a day, over 30 days. | 16,500 | Standard | $100 | $6.06 |
Response times
| Google Search API | |
|---|---|
| Succeeded | 18 of 20 |
| Median response time | 6.2 s |
| 95th percentile | 25.2 s |
| Had knowledge graph | 28% |
| Had people also ask | 94% |
| Had related searches | 78% |
| Had local results | 11% |
| Had videos | 33% |
What to plan for
- Clair reads caption tracks; it does not transcribe audio. A video with neither uploaded nor automatic captions returns 404.
- Automatic captions come from speech recognition. They misspell names and technical terms and often lack punctuation, so retrieval over them works better than quoting them verbatim. Prefer kind manual when a video has both.
- The transcript response holds the captions only. Take the title and channel from the search result that found the video.
- Only videos anyone can watch signed out are available: not private, members-only, or age-restricted ones.
- There is no endpoint for a channel's or playlist's video list. Find videos through Google Search, or bring the links.
- A transcript is the creator's work. Index it for search and answers, link back to the video, and do not republish it as your own content.
Common questions
Why not use YouTube's official API?
The YouTube Data API downloads a caption track only for a video the signed-in user can edit. For anyone else's video it returns 403, so it cannot feed an index of public videos.
How long is a transcript?
Speech runs at roughly 130 to 160 words a minute, so a 20-minute talk is about 3,000 words. The transcript is one request whatever its length.
Can I get transcripts in other languages?
Yes, in the languages the video has captions for. Pass language, such as de or pt-BR; a language the video lacks returns 404 listing the ones it has.
Does a long video cost more?
No. One transcript is one request, for a one-minute short or a three-hour lecture.
Run it on your own products
$1 of usage a month free across every API, no card. Enough to run the pipeline on a short list before choosing a plan.

Glassdoor API
Crunchbase API
Instagram API
Bloomberg API
Associated Press API