YouTube transcripts are valuable input for summarization models, RAG pipelines, content analysis, and accessibility tools. YouTube's official data API does not expose transcripts directly — developers typically resort to parsing auto-generated captions from internal endpoints, which break without notice. The Scavio transcript endpoint accepts a video_id and returns the transcript as one string (or timed srt cues when you ask for them). This tutorial shows how to call the endpoint, handle the response, and reassemble the text for downstream processing. The transcript endpoint returns one string under data.content, not a list of timed segments - pass format "srt" if you need cue timings.
Prerequisites
- Python 3.8 or higher installed
- requests library installed
- A Scavio API key
- A YouTube video ID to test with (e.g. dQw4w9WgXcQ)
Walkthrough
Step 1: Identify the video ID
The video ID is the 11-character string after v= in a YouTube URL. For https://youtube.com/watch?v=dQw4w9WgXcQ the ID is dQw4w9WgXcQ.
from urllib.parse import urlparse, parse_qs
def extract_video_id(url: str) -> str:
parsed = urlparse(url)
return parse_qs(parsed.query).get("v", [url])[0]Step 2: Call the transcript endpoint
POST the video id (or the watch URL) to /api/v1/youtube/transcript. Add format "srt" when you want timed cues instead of plain text.
import requests
response = requests.post(
"https://api.scavio.dev/api/v1/youtube/transcript",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"video_id": "dQw4w9WgXcQ"}
)
data = response.json()["data"]Step 3: Read the transcript text
data.content holds the whole transcript as one string, alongside language_code and format.
full_text = data.get("content", "")
print(data.get("language_code"), data.get("format"))
print(full_text[:500])Step 4: Save to file for downstream use
Write the transcript to disk so it can be ingested by a vector store or summarization model.
with open("transcript.txt", "w", encoding="utf-8") as f:
f.write(full_text)
print(f"Saved {len(full_text)} characters")Python Example
import os
import requests
API_KEY = os.environ.get("SCAVIO_API_KEY", "your_scavio_api_key")
ENDPOINT = "https://api.scavio.dev/api/v1/youtube/transcript"
def get_transcript(video_id: str, fmt: str = "text") -> str:
response = requests.post(
ENDPOINT,
headers={"Authorization": f"Bearer {API_KEY}"},
json={"video_id": video_id, "format": fmt}
)
response.raise_for_status()
# The payload is wrapped in `data`; the transcript itself is data.content.
return response.json()["data"].get("content", "")
def main():
text = get_transcript("dQw4w9WgXcQ")
print(f"Transcript: {len(text)} chars")
print(text[:300])
if __name__ == "__main__":
main()JavaScript Example
const API_KEY = process.env.SCAVIO_API_KEY || "your_scavio_api_key";
const ENDPOINT = "https://api.scavio.dev/api/v1/youtube/transcript";
async function getTranscript(videoId, format = "text") {
const response = await fetch(ENDPOINT, {
method: "POST",
headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ video_id: videoId, format })
});
if (!response.ok) throw new Error(`HTTP ${response.status}`);
// The payload is wrapped in `data`; the transcript itself is data.content.
const { data } = await response.json();
return data.content || "";
}
async function main() {
const text = await getTranscript("dQw4w9WgXcQ");
console.log(`${text.length} chars`);
console.log(text.slice(0, 300));
}
main().catch(console.error);Expected Output
{
"data": {
"video_id": "dQw4w9WgXcQ",
"language_code": "en",
"language_name": "English",
"format": "txt",
"content": "We're no strangers to love You know the rules and so do I A full commitment's what I'm thinking of ..."
},
"response_time": 1633,
"credits_used": 8,
"credits_remaining": 4747
}