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. 60 credits on YouTube, 200 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. Your application code stays platform-agnostic. A short adapter absorbs the differences.

Cost per run

60 credits for a YouTube video, 200 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, and transcribing the same URL again within 6 hours is free.

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 Shorts60
GET /v1/tiktok/post/transcriptTikTok videos200
GET /v1/instagram/media/transcriptInstagram reels and videos up to 2 minutes200
GET /v1/facebook/post/transcriptFacebook video posts200
GET /v1/twitter/tweet/transcriptVideos attached to X posts200
GET /v1/reddit/post/transcriptReddit video posts200
GET /v1/linkedin/post/transcriptVideos in LinkedIn posts200

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 returns an empty transcript with a flag rather than an error when Reddit publishes no captions for the video.
  • TikTok reads the video's captions. Add use_ai_as_fallback=true to fall back to AI transcription when there are none.

The response shapes differ

Each endpoint keeps the platform's own transcript shape, so you do not lose platform-specific fields. Three shapes to expect:

  • YouTube: data.transcript is an array of timed segments, data.transcript_only_text is the full text as one string, and data.language is the language.
  • TikTok: data.transcript is the full text as a string.
  • Instagram: data.transcripts (plural) is an array of { id, shortcode, text }.

For Facebook, X, Reddit and LinkedIn, inspect the first response you get and extend the adapter below if you want a platform-specific field.

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(platform, data):
    if platform == "youtube":
        return data.get("transcript_only_text") or ""
    if platform == "instagram":
        return " ".join(t.get("text", "") for t in data.get("transcripts") or [])
    t = data.get("transcript")
    if isinstance(t, str):
        return t
    # Other shapes: fall back to any plain-text field; inspect your first response.
    return data.get("transcript_only_text") or data.get("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(platform, body["data"]),
            "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",
  "data": {
    "transcript": [
      { "text": "...", "startMs": "80", "endMs": "4000", "startTimeText": "0:00" }
    ],
    "transcript_only_text": "...",
    "language": "en"
  },
  "credits_used": 60,
  "credits_remaining": 9940,
  "request_id": "req_1a2b3c4d5e6f",
  "cached": false,
  "idempotent_replay": false,
  "charge_reason": "miss",
  "free_call": false
}

What to change

  • Cheaper YouTube. If you can parse caption files yourself, GET /v1/youtube/video/subtitles (20 credits) returns the caption tracks with download URLs instead.
  • Find a moment instead of reading everything. The YouTube and TikTok transcript endpoints take q, a question about the video (for example q=what discount code do they give), and moments, a list of moment kinds such as sponsor_read or call_to_action. The matching stretches come back on data.moments with their timestamps.
  • Pick a language. YouTube, TikTok and Reddit take language, a two-letter code.
  • Ads too. GET /v1/facebook/adlibrary/ad/transcript (200 credits) returns what a Facebook Ad Library video ad says out loud. Pass the ad id or its library URL.

On this page