A YouTube transcript is the video's caption track as text: the lines people see as subtitles, each with a start time. Most videos have one, written by the uploader or generated automatically. This guide fetches transcripts from Python through a YouTube transcript API, one HTTP call per batch of videos, collects the video links for a whole channel or topic, and summarizes each transcript with a model on the same API key. For a single video, the free YouTube transcript generator needs no code.
How the transcript API works
The YouTube transcript tool takes a list of video links and returns one transcript per video. You call it like every other data tool: POST https://lovelyrouter.com/v1/tools/youtube-transcript/run with an input object and a max_results cap.
startUrls is a list of youtube.com/watch?v=… or youtu.be/… links. lang is a caption language code such as en, es, de or pt-BR. Leave it empty for the video's default track.
Each item has inputSource (the link you sent), id, selected (the track you got, for example English (auto-generated)) and transcript, a list of segments with text, startTime (like "0:18") and dur in seconds.
You pay per transcript returned. Starting a run holds its maximum cost, the per-result fee times max_results, and the run settles to what it delivered. A run that fails pays only for the transcripts it delivered first.
Most runs finish in 5 to 60 seconds. If one takes longer than the wait window (60 seconds by default), you get 202 and poll until it finishes, as Run a tool describes.
Get a transcript in Python
You need an API key in LOVELY_API_KEY and requests. This helper starts a run, polls while it returns 202, and gives you the items:
import os
import requests
BASE = "https://lovelyrouter.com/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['LOVELY_API_KEY']}"}
def run_tool(tool, tool_input, max_results):
res = requests.post(
f"{BASE}/tools/{tool}/run",
headers=HEADERS,
json={"input": tool_input, "max_results": max_results},
timeout=90,
)
run = res.json()
if not res.ok:
raise RuntimeError(run["error"]["message"])
# 202 = still running: poll, letting the server wait up to 60 s per request.
while res.status_code == 202:
res = requests.get(f"{BASE}/tools/runs/{run['id']}", headers=HEADERS, params={"wait": 60}, timeout=90)
res.raise_for_status()
run = res.json()
print(f"{tool}: {run['status']}, {run['results']} results, charged {run['charge_usd']} USD")
if run["error"]:
print(" error:", run["error"])
return run["items"] or []
items = run_tool(
"youtube-transcript",
{"startUrls": ["https://www.youtube.com/watch?v=dQw4w9WgXcQ"], "lang": "en"},
max_results=1,
)
video = items[0]
print(video["selected"]["title"])
for seg in video["transcript"][:5]:
print(seg["startTime"], seg["text"])A 200 means the run finished, not that it succeeded, so the helper prints status and error. On failed or timed_out, items still holds what the run delivered.
Transcripts for a whole channel or topic
To cover a channel, list its videos with YouTube channel videos, then send the links to the transcript tool. For a topic, YouTube search does the same from keywords. Both return items with url, title, duration in seconds and publishDate.
# Up to 30 videos from a channel (a handle, or a channel URL in startUrls).
videos = run_tool("youtube-channel", {"youtubeHandles": ["@MrBeast"]}, max_results=30)
# Or long videos about a topic uploaded this year.
# videos = run_tool("youtube-search", {"keywords": ["espresso tutorial"], "duration": "l", "uploadDate": "y"}, max_results=30)
urls = [v["url"] for v in videos if "/watch?v=" in v.get("url", "")]
def transcripts(urls, lang="en"):
out = []
for i in range(0, len(urls), 50): # the tool takes up to 50 links per run
batch = urls[i : i + 50]
out += run_tool("youtube-transcript", {"startUrls": batch, "lang": lang}, max_results=len(batch))
return out
found = transcripts(urls)
missing = set(urls) - {t["inputSource"] for t in found if t.get("transcript")}
print(f"{len(urls) - len(missing)} transcripts, {len(missing)} videos without one")max_results caps each tool's own count field, so you don't need to set maxItems as well. Keep the link filter: the transcript tool doesn't take Shorts, live or playlist links. To start from a playlist, pass its URL to youtube-search in startUrls and use the video links it returns.
Summarize transcripts with a model
The same key calls Claude, GPT and Gemini. Point the Anthropic SDK at https://lovelyrouter.com and send the transcript with its timestamps, so the summary can say where each point is made:
import anthropic
llm = anthropic.Anthropic(base_url="https://lovelyrouter.com", api_key=os.environ["LOVELY_API_KEY"])
def summarize(item):
text = "\n".join(f"[{s['startTime']}] {s['text']}" for s in item["transcript"])
message = llm.messages.create(
model="claude-haiku-5.5",
max_tokens=1024,
messages=[{
"role": "user",
"content": "Summarize this video transcript in five bullet points. "
"Start each bullet with the timestamp where the point is made.\n\n" + text,
}],
)
return message.content[0].text
for item in found:
if item.get("transcript"):
print(item["inputSource"])
print(summarize(item), "\n")claude-haiku-5.5 keeps batch summaries cheap; switch to claude-sonnet-5.5 for dense technical talks. With the OpenAI SDK, set base_url="https://lovelyrouter.com/v1" and call client.chat.completions.create(model="gpt-6.1-sol", …). Every text model accepts Chat Completions, so you can switch vendors by changing the model id. See Anthropic Messages for streaming and long outputs.
What it costs
A job like the one above has three parts: the per-video fee for listing the channel or search, the per-transcript fee for each transcript, and the model's tokens. The transcript is the prompt, so input tokens grow with video length. Today's prices:
YouTube 動画の字幕全文(タイムスタンプ付き):動画リンクごとに 1 件、動画にあれば指定した言語で。
YouTube チャンネルの動画(@MrBeast のようなハンドルまたはチャンネル URL):タイトル、再生数、高評価、コメント数、長さ、日付。
キーワード検索、または YouTube のリンク(検索結果・チャンネル・再生リスト・動画の URL)から YouTube 動画を取得:タイトル、再生数、高評価、コメント数、長さ、チャンネル、日付。
| モデル | コンテキスト | 入力 | 出力 | キャッシュ読み取り |
|---|---|---|---|---|
| Claude Fable 5.1 claude-fable-5.1 | 1M | $10.00 | $50.00 | $0.25 |
| Claude Opus 5.5 claude-opus-5.5 | 1M | $4.00 | $20.00 | $0.20 |
| Claude Sonnet 5.5 claude-sonnet-5.5 | 1M | $2.00 | $10.00 | $0.10 |
| Claude Haiku 5.5 claude-haiku-5.5 | 1M | $0.10 | $0.50 | $0.01 |
| Claude Fable 5 claude-fable-5 | 1M | $10.00 | $50.00 | $1.00 |
| Claude Opus 5 claude-opus-5 | 1M | $5.00 | $25.00 | $0.50 |
| Claude Sonnet 5 claude-sonnet-5 | 1M | $2.00 | $10.00 | $0.20 |
| Claude Opus 4.8 claude-opus-4.8 | 1M | $5.00 | $25.00 | $0.50 |
| Claude Opus 4.7 claude-opus-4.7 | 1M | $5.00 | $25.00 | $0.50 |
| Claude Opus 4.6 claude-opus-4.6 | 1M | $5.00 | $25.00 | $0.50 |
| Claude Sonnet 4.6 claude-sonnet-4.6 | 1M | $3.00 | $15.00 | $0.30 |
| Claude Opus 4.5 claude-opus-4.5 | 200K | $5.00 | $25.00 | $0.50 |
| Claude Sonnet 4.5 claude-sonnet-4.5 | 1M | $3.00 | $15.00 | $0.30 |
| Claude Haiku 4.5 claude-haiku-4.5 | 200K | $1.00 | $5.00 | $0.10 |
100 万トークンあたりの米ドル価格(カタログからリアルタイム表示)。
Everything comes out of one prepaid balance, with no subscription. The pricing page lists every tool and model.
Pitfalls
A video with captions turned off has no track to read. Check transcript on every item and compare inputSource with the links you sent, as the missing set above does.
lang asks for a track; auto-generated captions count. When a video has no track in that language, check selected.languageCode before you trust the text. A model can translate while it summarizes, so you can ask for the default track and summarize in English.
A run takes up to 50 links. A list longer than max_results is cut to max_results entries, so set max_results to the batch length.
Your account can have 10 runs in progress. An 11th returns 429; start it again when one finishes.
startTime is a clock string like "3:26" and dur is seconds as a string, like "5.039". Convert them before you do arithmetic.
Frequently asked questions
Can I get a transcript of a YouTube video that has no captions?+
No. The tool reads the video's caption tracks, including auto-generated ones. When a video has no caption track, there is no transcript to return, so check each item before you use it.
How do I get transcripts for every video on a channel?+
List the channel's videos with the youtube-channel tool, keep the watch links, and send them to the youtube-transcript tool in batches of up to 50 links per run.
Can I choose the transcript language?+
Yes. Set lang to a caption language code such as en, es or pt-BR, and auto-generated captions count. Leave it empty to get the video's default track, and read selected to see which track you got.
Do I need a separate API key for the model that summarizes?+
No. The key that runs the transcript tool also calls Claude, GPT and Gemini, and both come out of the same prepaid balance. Point the Anthropic SDK at the base URL, or the OpenAI SDK at the base URL with /v1.
Can an AI agent fetch transcripts on its own?+
Yes. Connect the MCP server to Claude Code, Cursor or another MCP client, and the agent can run the youtube-transcript tool with run_tool and read the results itself.
Next, see the other YouTube tools, the research agents use case for combining transcripts with web search, and the MCP server to let an agent do all of this from a prompt.