For AI

How-to guides

How to get YouTube video transcripts from a keyword search

Search with YouTube video search, then fetch each chosen video's captions with YouTube video transcript. The worked example is 6 calls and costs at most $0.024; a failed call is not charged, and a video without captions comes back not_found at no charge.

Updated

The job: you want to know what the popular videos on a topic actually say, not just their titles. Search YouTube, keep the videos worth reading, and pull their transcripts. You end with one JSON Lines file: per video, its title, channel, views, the language of the track you got, the full text for a model to read, and timed segments for quoting with a timestamp.

No Google API key, OAuth consent or proxy is involved. Each call is an HTTPS request with your key.

Step by step

Step 1: find the videos

Call YouTube video search with query. sort takes relevance (the default), latest or most_viewed. One call returns about 20 videos for $0.004, each with the 11-character id, title, url, published_at, the channel in author and metrics.views. Add view=full and each video carries ext.length_s, its length in seconds, which helps you skip Shorts when you want long explanations.

curl -G "https://api.okdata.online/v1/youtube/videos/search" \
  -H "Authorization: Bearer $OKDATA_API_KEY" \
  --data-urlencode 'query=sourdough starter' \
  -d sort=most_viewed -d view=full

Search results leave text empty and metrics.likes and metrics.comments null; YouTube video detail has them if you need them. published_at is worked out from labels such as "3 weeks ago", so treat it as approximate.

Step 2: fetch each transcript

Pass a video's id to YouTube video transcript. One call returns one transcript for $0.004.

  • lang is your preferred language, such as en, es or ja. It is a preference: the transcript's own lang field says which track came back, and it is und when the track's language cannot be told. Check it before you file the text under a language.
  • segments is the list of timed pieces, each with start and end in seconds and its text. Use it for quotes, chapter notes, subtitles or links that jump to a moment (&t= plus the start in whole seconds).
  • text is all segments joined into plain text. Hand this to a model when you want a summary.
curl -G "https://api.okdata.online/v1/youtube/videos/transcript/get" \
  -H "Authorization: Bearer $OKDATA_API_KEY" \
  -d id=Qm7rT2vXa9c -d lang=en

A video without captions returns not_found, which is free, so the bill is lower for every captionless video in your batch.

Step 3: put it together in Python

import json
import os
import requests

API = "https://api.okdata.online"
HEADERS = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}
PICK = 5  # transcripts to fetch; each is one call


def get(path, **params):
    return requests.get(API + path, headers=HEADERS, params=params, timeout=90).json()


found = get("/v1/youtube/videos/search", query="sourdough starter", sort="most_viewed", view="full")
if found["code"] != "ok":
    raise RuntimeError(f"{found['code']}: {found['message']}")
videos = sorted(found["data"]["items"], key=lambda v: v["ext"]["length_s"] or 0, reverse=True)[:PICK]

with open("transcripts.jsonl", "w", encoding="utf-8") as out:
    for v in videos:
        body = get("/v1/youtube/videos/transcript/get", id=v["id"], lang="en")
        if body["code"] == "not_found":
            print(v["id"], "no captions, not charged")
            continue
        if body["code"] != "ok":
            print(v["id"], body["code"], body["message"])
            continue
        t = body["data"]["item"]
        out.write(json.dumps({
            "id": v["id"], "title": v["title"], "channel": v["author"]["name"], "views": v["metrics"]["views"],
            "lang": t["lang"], "text": t["text"], "segments": t["segments"],
        }, ensure_ascii=False) + "\n")

A failed transcript is printed and skipped rather than stopping the run, because the other videos are still worth having.

Good to know

  • No captions, no transcript. The endpoint reads caption tracks; it does not run speech-to-text. For a captionless video, use Whisper or another speech model on audio you are allowed to use. New uploads sometimes get automatic captions a day later.
  • One language per call. Asking for a second language is a second charged call. Ask once, check lang, and translate segment by segment yourself if needed; the timings stay valid.
  • Automatic or typed captions. The response does not say which kind of track it is. Treat automatic captions with care when you quote.
  • The official API. YouTube's captions.download costs 200 quota units per call and requires permission to edit the video, so it serves your own channel, not other people's videos.
  • Retries without paying twice. Send an Idempotency-Key header, such as transcript- plus the video ID. A repeated request with the same key within 24 hours returns the stored answer with no new charge.

If a library such as youtube-transcript-api tells you transcripts are disabled, see what TranscriptsDisabled means. For hundreds of videos at once, see bulk YouTube transcripts.

What the example costs

One page of the most viewed YouTube videos about sourdough starters, then the English transcripts of the five longest

EndpointCallsPriceSubtotal
YouTube video search1$0.004$0.004
YouTube video transcript5$0.004$0.02
Total6$0.024

Prices in force when this page was built. A failed call costs nothing.

In your AI (MCP)

Connect the MCP server once, then say what you want. The agent finds these endpoints, reads their prices and calls them on your balance.

SaySearch YouTube for sourdough starter, most viewed, one page. Take the five longest videos, get their English transcripts and summarise what each one recommends, with a timestamp for each point.

What the agent sends to the call tool first
{
  "endpoint": "youtube.videos.search",
  "params": {
    "query": "claude code tutorial"
  },
  "idempotency_key": "<a new UUID>"
}

Set up the MCP server →

Sources

  1. YouTube Data API: Captions: downloaddevelopers.google.com · read

Connect once, then just ask.

Every new key comes with $0.10 to try it. One sentence connects your agent.

Start free
Connect your AI

Paste this into your agent

Read https://okdata.online/agents.md and set up okdata for me; my key is in the OKDATA_API_KEY environment variable.

Claude Code, Cursor, Codex and other agents that can open a link set themselves up from it.

MCP serverhttps://api.okdata.online/mcp