How to scrape YouTube video transcript

Get YouTube video transcript as JSON with one request. Captions cost 1 credit.

Preview
The API is in early access. Ask for a key; the examples use api.socialscrape.io.

Before you start

  • An API key, sent in the x-api-key header. Keep it on your server.
  • For this endpoint you send one of url or id. The YouTube video transcript page lists every parameter.

Step 1: Send the request

GET /v1/youtube/video/transcript. Pick your language; each one reads the key from SOCIALSCRAPE_API_KEY.

curl
curl -G "https://api.socialscrape.io/v1/youtube/video/transcript" \
  -H "x-api-key: $SOCIALSCRAPE_API_KEY" \
  --data-urlencode 'id=dQw4w9WgXcQ' \
  --data-urlencode 'language=de'
Python
import os
import requests

params = {
    "id": "dQw4w9WgXcQ",
    "language": "de",
}
res = requests.get(
    "https://api.socialscrape.io/v1/youtube/video/transcript",
    headers={"x-api-key": os.environ["SOCIALSCRAPE_API_KEY"]},
    params=params,
    timeout=60,
)
body = res.json()

if body["ok"]:
    print(body["data"])
else:
    print(body["error"]["code"], body["error"]["message"])
JavaScript
const url = new URL("https://api.socialscrape.io/v1/youtube/video/transcript");
url.search = new URLSearchParams({
  id: "dQw4w9WgXcQ",
  language: "de",
}).toString();
const res = await fetch(url, {
  headers: { "x-api-key": process.env.SOCIALSCRAPE_API_KEY },
});
const body = await res.json();

if (body.ok) {
  console.log(body.data);
} else {
  console.error(body.error.code, body.error.message);
}
TypeScript
const url = new URL("https://api.socialscrape.io/v1/youtube/video/transcript");
url.search = new URLSearchParams({
  id: "dQw4w9WgXcQ",
  language: "de",
}).toString();
const res = await fetch(url, {
  headers: { "x-api-key": process.env.SOCIALSCRAPE_API_KEY! },
});
const body = await res.json();

if (body.ok) {
  console.log(body.data);
} else {
  console.error(body.error.code, body.error.message);
}
Go
package main

import (
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
)

func main() {
	q := url.Values{}
	q.Set("id", "dQw4w9WgXcQ")
	q.Set("language", "de")
	req, _ := http.NewRequest("GET", "https://api.socialscrape.io/v1/youtube/video/transcript" + "?" + q.Encode(), nil)
	req.Header.Set("x-api-key", os.Getenv("SOCIALSCRAPE_API_KEY"))
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)
	fmt.Println(res.StatusCode, string(body))
}
PHP
<?php
$query = http_build_query([
    'id' => 'dQw4w9WgXcQ',
    'language' => 'de',
]);
$ch = curl_init('https://api.socialscrape.io/v1/youtube/video/transcript' . "?" . $query);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["x-api-key: " . getenv("SOCIALSCRAPE_API_KEY")],
]);
$body = json_decode(curl_exec($ch), true);
curl_close($ch);

if ($body["ok"]) {
    print_r($body["data"]);
} else {
    echo $body["error"]["code"], " ", $body["error"]["message"], "\n";
}
Ruby
require "net/http"
require "json"

uri = URI('https://api.socialscrape.io/v1/youtube/video/transcript')
uri.query = URI.encode_www_form('id' => 'dQw4w9WgXcQ', 'language' => 'de')
req = Net::HTTP::Get.new(uri)
req["x-api-key"] = ENV.fetch("SOCIALSCRAPE_API_KEY")
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
body = JSON.parse(res.body)

if body["ok"]
  puts body["data"]
else
  puts body["error"]["code"], body["error"]["message"]
end
Java
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;

public class Main {
    public static void main(String[] args) throws Exception {
        String query = "id=" + URLEncoder.encode("dQw4w9WgXcQ", StandardCharsets.UTF_8) + "&language=" + URLEncoder.encode("de", StandardCharsets.UTF_8);
        HttpRequest req = HttpRequest.newBuilder()
            .uri(URI.create("https://api.socialscrape.io/v1/youtube/video/transcript" + "?" + query))
            .header("x-api-key", System.getenv("SOCIALSCRAPE_API_KEY"))
            .GET()
            .build();
        HttpResponse<String> res = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
        System.out.println(res.statusCode() + " " + res.body());
    }
}
C#
using System;
using System.Net.Http;

var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", Environment.GetEnvironmentVariable("SOCIALSCRAPE_API_KEY"));
var query = string.Join("&", new[] {
    "id=" + Uri.EscapeDataString("dQw4w9WgXcQ"),
    "language=" + Uri.EscapeDataString("de"),
});
var res = await client.GetAsync("https://api.socialscrape.io/v1/youtube/video/transcript" + "?" + query);
Console.WriteLine((int)res.StatusCode);
Console.WriteLine(await res.Content.ReadAsStringAsync());

Step 2: Read the response

The result is in data. Here is what the object gives you, from a recorded sample.

Python
print(body["data"]["text"])
JavaScript
console.log(body.data.text);
Fields printed aboveSample
{
  "text": "Uns beiden ist die Liebe nicht fremd Du kennst die Regeln genau wie ich Für mich zählst nur du Das kriegst du sonst von keinem hier Ich will dir sagen, wie i..."
}

A field the platform does not give comes back as null. The full field list is on the endpoint page.

Step 3: Handle errors

Check ok, then branch on error.code and error.retryable, never on the message.

Python
body = res.json()
if not body["ok"]:
    err = body["error"]
    if err["retryable"]:
        ...  # wait a moment and send the same request again
    else:
        raise RuntimeError(f'{err["code"]}: {err["message"]}')
JavaScript
const body = await res.json();
if (!body.ok) {
  const { code, message, retryable } = body.error;
  if (retryable) {
    // wait a moment and send the same request again
  } else {
    throw new Error(`${code}: ${message}`);
  }
}
CodeHTTPRetryMeaning
invalid_params400noA parameter is missing, unknown or has the wrong type.
unsupported_url400noThe URL is not one this endpoint accepts (wrong platform or form).
not_found404noThe platform says this profile, post or item does not exist.
transcript_unavailable404noNo captions exist and AI transcription is not possible for this media.

Other errors, such as unauthorized or rate_limited, are on the errors page.

With the SDK

The Python and TypeScript clients wrap all of this: typed errors, retries. They are in preview and not published yet.

Python
from socialscrape import SocialScrape

client = SocialScrape()  # reads SOCIALSCRAPE_API_KEY

res = client.youtube.video_transcript(id="dQw4w9WgXcQ", language="de")
print(res.data)
print(res.credits_charged, res.credits_remaining)
TypeScript
import { SocialScrape } from "socialscrape";

const client = new SocialScrape(); // reads SOCIALSCRAPE_API_KEY

const res = await client.youtube.videoTranscript({ id: "dQw4w9WgXcQ", language: "de" });
console.log(res.data);
console.log(res.credits_charged, res.credits_remaining);

What it costs

1 credit for captions; AI transcription 1 up to 2 minutes, then 1 per started minute. A failed request costs nothing. Add max_age_days to reuse a cached result for 0 credits. Results are kept 30 days.

Next

Questions

Which language should I use?

Any. It is plain HTTP and JSON, so every language with an HTTP client works. The tabs show the same request nine ways.

Get a key.

Early access keys go to developers and agent builders first.

Get early access