YouTube Transcript API: Get Video Transcripts in Python

by Simon Balfe·

A YouTube transcript API accepts a public video URL and returns the spoken text as JSON. With CreatorCrawl, one request returns the full transcript, detected language, and timestamped segments:

curl --get "https://app.creatorcrawl.com/api/youtube/video/transcript" \
  --data-urlencode "url=https://www.youtube.com/watch?v=dQw4w9WgXcQ" \
  -H "x-api-key: YOUR_API_KEY"

Use the free YouTube transcript generator if you need one transcript in the browser. The API is for bulk processing, applications, agents, and automated research.

#Does the official YouTube API return transcripts?

Not as a simple public transcript endpoint.

Google's captions.list method returns metadata about caption tracks, but the response does not contain the caption text. Listing tracks requires OAuth 2.0 authorization. Downloading a track uses captions.download, which also requires an OAuth-authorized request.

That official workflow is useful when your application manages captions for authorized channels. It is awkward when you need the transcript from an arbitrary public video URL.

You have three common options:

MethodBest forMain limitation
YouTube Data API captions methodsManaging captions for authorized channelsOAuth and no transcript text in captions.list
Open-source transcript librarySmall scripts and local experimentsYou manage blocking, updates, proxies, and failures
Managed YouTube transcript APIProduction applications and bulk public URLsPaid after the free allowance

#YouTube transcript API response

CreatorCrawl returns a normalized response envelope:

{
  "data": {
    "language": "en",
    "text": "Full transcript text...",
    "segments": [
      {
        "start_seconds": 1.2,
        "end_seconds": 4.8,
        "text": "First spoken segment"
      }
    ]
  },
  "meta": {
    "platform": "youtube",
    "fetched_at": "2026-07-31T12:00:00.000Z"
  }
}

Use data.text when you need plain text for summarization, semantic search, or storage. Use data.segments when timing matters for subtitles, citations, video navigation, or clip generation.

#Get a YouTube transcript in Python

Install requests if your project does not already use it:

pip install requests

Then call the transcript endpoint:

import requests

API_KEY = "your_api_key"
VIDEO_URL = "https://www.youtube.com/watch?v=dQw4w9WgXcQ"

response = requests.get(
    "https://app.creatorcrawl.com/api/youtube/video/transcript",
    params={"url": VIDEO_URL},
    headers={"x-api-key": API_KEY},
    timeout=30,
)
response.raise_for_status()

payload = response.json()
transcript = payload["data"]

print(transcript["language"])
print(transcript["text"])

for segment in transcript.get("segments", []):
    print(
        f"{segment['start_seconds']:.1f}s-"
        f"{segment['end_seconds']:.1f}s: "
        f"{segment['text']}"
    )

The params argument URL-encodes the video URL correctly. Avoid building the query string manually, especially when the source URL contains &, playlist parameters, or a timestamp.

#Request a specific transcript language

Pass a two-letter language code when you want a specific available track:

response = requests.get(
    "https://app.creatorcrawl.com/api/youtube/video/transcript",
    params={
        "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
        "language": "es",
    },
    headers={"x-api-key": API_KEY},
    timeout=30,
)
response.raise_for_status()

spanish_transcript = response.json()["data"]["text"]

Language availability depends on the caption tracks attached to the video. Your application should handle a missing requested language without assuming every public video has translations.

#Get a YouTube transcript in JavaScript

This example works in modern Node.js runtimes with built-in fetch:

const endpoint = new URL(
  'https://app.creatorcrawl.com/api/youtube/video/transcript',
)
endpoint.searchParams.set(
  'url',
  'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
)

const response = await fetch(endpoint, {
  headers: {
    'x-api-key': process.env.CREATORCRAWL_API_KEY,
  },
})

if (!response.ok) {
  throw new Error(`Transcript request failed: ${response.status}`)
}

const { data, meta } = await response.json()

console.log(`Language: ${data.language ?? 'unknown'}`)
console.log(`Fetched: ${meta.fetched_at}`)
console.log(data.text)

#Save timestamped segments as JSON

For a transcript database or RAG pipeline, keep the timing data:

import json

with open("transcript.json", "w", encoding="utf-8") as output:
    json.dump(
        {
            "video_url": VIDEO_URL,
            "language": transcript["language"],
            "text": transcript["text"],
            "segments": transcript.get("segments", []),
        },
        output,
        ensure_ascii=False,
        indent=2,
    )

Timestamped chunks make it possible to link a search result or AI citation back to the relevant moment in the video.

#Handle videos without a transcript

Not every video has usable captions. Videos can fail because:

  • The creator disabled or removed captions.
  • The video contains no speech.
  • The requested language is unavailable.
  • The video is private, restricted, deleted, or region-blocked.
  • YouTube temporarily changed the underlying caption response.

Treat a missing transcript as a normal data condition:

try:
    response.raise_for_status()
    data = response.json()["data"]
except requests.HTTPError as error:
    status = error.response.status_code

    if status == 502:
        print("Transcript unavailable from the upstream source")
    elif status == 401:
        print("Check the CreatorCrawl API key")
    else:
        raise
else:
    if not data["text"]:
        print("The video returned an empty transcript")

For bulk jobs, store the status for each URL and retry only temporary failures. Do not let one unavailable video stop the full batch.

#Process multiple YouTube videos

The simplest batch workflow is a loop with explicit per-video error handling:

video_urls = [
    "https://www.youtube.com/watch?v=VIDEO_ID_1",
    "https://www.youtube.com/watch?v=VIDEO_ID_2",
    "https://www.youtube.com/shorts/VIDEO_ID_3",
]

results = []

for video_url in video_urls:
    response = requests.get(
        "https://app.creatorcrawl.com/api/youtube/video/transcript",
        params={"url": video_url},
        headers={"x-api-key": API_KEY},
        timeout=30,
    )

    if not response.ok:
        results.append(
            {
                "url": video_url,
                "status": "failed",
                "http_status": response.status_code,
            }
        )
        continue

    results.append(
        {
            "url": video_url,
            "status": "complete",
            "transcript": response.json()["data"],
        }
    )

Add controlled concurrency when you need more throughput. Keep timeouts, retries, and result logging so failed URLs can be inspected without repeating the successful work.

#Common YouTube transcript API uses

#Video summarization

Send data.text to an LLM with a structured prompt for a summary, chapter outline, action items, or key claims.

#Semantic search and RAG

Chunk the timestamped segments, create embeddings, and store the source video URL with each chunk. Search results can then link back to the exact moment in the video.

#Content and competitor research

Collect transcripts from channels in a niche, then compare hooks, recurring topics, calls to action, product mentions, and audience questions.

#Accessibility and localization

Use available transcript tracks as the starting point for searchable text, captions, translations, and accessible content workflows. Review the source video's rights before republishing transcript text.

#AI agents

CreatorCrawl also exposes the transcript operation through its social media MCP server. Claude, Cursor, and other MCP clients can retrieve a video transcript as a tool call instead of custom HTTP code.

#YouTube transcript API pricing

Each CreatorCrawl transcript request costs one credit.

PackCreditsPriceEffective cost per 1,000 calls
Free50$0Testing
Starter5,000$29$5.80
Pro20,000$99$4.95
Scale100,000$299$2.99

Credits do not expire. The same balance works across YouTube, TikTok, Instagram, LinkedIn, X, and Reddit endpoints.

#Frequently asked questions

#Can I get a YouTube transcript without an API key?

Yes, for individual videos. Use the free YouTube transcript generator. Programmatic requests require a CreatorCrawl API key.

#Does the API work with YouTube Shorts?

Yes. Pass a standard YouTube URL or Shorts URL. The video still needs an available transcript or caption track.

#Does the response include timestamps?

Yes. The normalized response includes a full text string and an optional segments array with start_seconds, end_seconds, and segment text.

#Can the official YouTube Data API download captions?

The official API can list and download caption tracks through its captions methods, but those requests require OAuth authorization. The list response contains track metadata rather than the transcript text.

#Can I translate a YouTube transcript?

You can request an available language with the language parameter, then translate the returned text in your own application. Availability depends on the video's caption tracks.

#Start with one video

Test the workflow in the free transcript generator, review the broader YouTube API, or create an API key and run the Python example above.

Explore CreatorCrawl

Try the free social media tools

Test transcripts, comments, profiles, channels, and tweets in your browser before moving to bulk API access.

More from the Blog

Takes 60 seconds

Add one line to your
MCP config. Ship today.

50 free credits. No card. Works with Claude, Cursor, Zed, and any MCP client.