InsightSocial API
Recipes

Video transcription

One transcribe() function that returns the spoken words of a video on YouTube, TikTok, Instagram, Facebook, X, Reddit or LinkedIn. 30 credits on YouTube, 100 on the others.

You will build one transcribe(url) function that returns what was said in a social video, whichever of seven platforms it lives on. Every transcript endpoint answers in the same shape, so the only platform-specific part is choosing the endpoint.

Cost per run

30 credits for a YouTube video, 100 credits for a video on any of the other six platforms. You make exactly one call per video. A video with no captions or no speech is not charged. Transcribing the same URL again is charged again, so store the transcript.

How do you turn a social video into text?

Pass the video URL to that platform's transcript endpoint. Each one returns the spoken content as text. Transcripts are the densest signal in social video: captions and thumbnails are written to get the click, while the spoken words are what the creator actually said.

What you need

EndpointCoversCredits
GET /v1/youtube/video/transcriptYouTube videos and Shorts30
GET /v1/tiktok/post/transcriptTikTok videos100
GET /v1/instagram/media/transcriptInstagram reels and videos up to 2 minutes100
GET /v1/facebook/post/transcriptFacebook video posts100
GET /v1/twitter/tweet/transcriptVideos attached to X posts100
GET /v1/reddit/post/transcriptReddit video posts100
GET /v1/linkedin/post/transcriptVideos in LinkedIn posts100

Every one takes a url parameter.

When there is nothing to transcribe

  • YouTube, Instagram and LinkedIn answer 404 when a video has no captions or no speech, and name the reason (for example no_captions or no_speech). That is an expected outcome, not a failure, and it is not charged.
  • Reddit answers with a transcript whose text is null when Reddit publishes no captions for the video, and lists transcript.text in unavailable.
  • TikTok reads the video's captions. Add use_ai_as_fallback=true to fall back to AI transcription when there are none.

One shape on every platform

Every transcript endpoint returns data.transcript with three fields:

  • text: the whole transcript as one string, or null when there is none.
  • language: the language tag the platform gives, such as en, or null.
  • segments: timed cues, each { text, start_seconds, duration_seconds }, or null when the platform has no timings. YouTube has them; most of the others return the text only.

See Transcript for the full schema.

The code

Python
# transcribe.py
# Returns the transcript of a social video URL on any of seven platforms.
# Run with: INSIGHTSOCIAL_API_KEY=isk_live_... python transcribe.py
import os
from urllib.parse import urlparse

import requests

KEY = os.environ["INSIGHTSOCIAL_API_KEY"]
BASE = "https://api.insightsocial.app/v1"

ENDPOINT = {
    "youtube":   "youtube/video/transcript",
    "tiktok":    "tiktok/post/transcript",
    "instagram": "instagram/media/transcript",
    "facebook":  "facebook/post/transcript",
    "twitter":   "twitter/tweet/transcript",
    "reddit":    "reddit/post/transcript",
    "linkedin":  "linkedin/post/transcript",
}
HOSTS = {"youtube.com": "youtube", "youtu.be": "youtube", "tiktok.com": "tiktok",
         "instagram.com": "instagram", "facebook.com": "facebook", "fb.watch": "facebook",
         "x.com": "twitter", "twitter.com": "twitter", "reddit.com": "reddit",
         "v.redd.it": "reddit", "linkedin.com": "linkedin"}

def platform_of(url):
    host = urlparse(url).netloc.lower().removeprefix("www.").removeprefix("m.")
    for suffix, platform in HOSTS.items():
        if host == suffix or host.endswith("." + suffix):
            return platform
    raise ValueError(f"unsupported host: {host}")

def extract_text(data):
    # The same on all seven platforms. `text` is null when there is no transcript.
    return data["transcript"]["text"] or ""

def transcribe(url):
    platform = platform_of(url)
    res = requests.get(f"{BASE}/{ENDPOINT[platform]}", params={"url": url},
                       headers={"x-api-key": KEY}, timeout=120)
    body = res.json()
    if not body["success"]:
        # A 404 here usually means "no captions" or "no speech", and costs nothing.
        return {"platform": platform, "text": None, "error": body["error"]["type"],
                "credits_used": body["credits_used"]}
    return {"platform": platform, "text": extract_text(body["data"]),
            "language": body["data"]["transcript"]["language"],
            "segments": body["data"]["transcript"]["segments"],
            "credits_used": body["credits_used"]}

# Any public video URL on the seven platforms works; add your own to the list.
for url in [
    "https://www.youtube.com/watch?v=dQw4w9WgXcQ",
]:
    t = transcribe(url)
    if t["text"] is None:
        print(f"[{t['platform']}] no transcript ({t['error']}), {t['credits_used']} credits")
    else:
        print(f"[{t['platform']}] {len(t['text'])} chars, {t['credits_used']} credits")
        print(t["text"][:200], "...")

What you get back

Response (YouTube, trimmed)
{
  "success": true,
  "platform": "youtube",
  "endpoint": "/v1/youtube/video/transcript",
  "schema_version": "2",
  "data": {
    "transcript": {
      "language": "en",
      "text": "[♪♪♪] ♪ We're no strangers to love ♪ ♪ You know the rules and so do I ♪ ...",
      "segments": [
        { "text": "[♪♪♪]", "start_seconds": 1.36, "duration_seconds": 1.68 },
        { "text": "♪ We're no strangers to love ♪", "start_seconds": 18.64, "duration_seconds": 3.24 }
      ]
    }
  },
  "unavailable": [],
  "credits_used": 30,
  "credits_remaining": 9940,
  "request_id": "req_1a2b3c4d5e6f",
  "cached": false,
  "idempotent_replay": false,
  "charge_reason": "miss",
  "free_call": false
}

On another platform the same call returns the same keys. Where the platform has no timings, segments is null and text carries the whole transcript.

What to change

  • Cheaper YouTube. If you can parse caption files yourself, GET /v1/youtube/video/subtitles (10 credits, beta) returns the caption tracks with download URLs instead.
  • Find a moment instead of reading everything. Where segments is filled, search it for a phrase and read start_seconds to jump to that point in the video, for example to find a discount code or a sponsor mention.
  • Pick a language. YouTube, TikTok and Reddit take language, a two-letter code.
  • Ads too. GET /v1/facebook/adlibrary/ad/transcript (100 credits) returns what a Facebook Ad Library video ad says out loud. Pass the ad id or its library URL.

On this page