Build · task-based recipes

Copy a recipe, get real data.

Eight end-to-end tasks with curl, Python requests and a realistic (truncated) response for each. Every snippet targets the same origin, needs no API key, and links back to the matching reference card in the docs.

Resolved API base: …

Recipes

Jump straight to a task. Each panel has copy buttons on every code block.

GET

/api/profile/{u}

docs ↗ try it ↗

Resolve a creator's identity and lifetime counters, then add per-video averages and the follow ratio via /api/profile/{u}/analytics.

curl

bash
curl -s "$BASE/api/profile/charlidamelio" | jq
curl -s "$BASE/api/profile/charlidamelio/analytics" | jq '.metrics'

Python

python · requests
import os, requests

BASE = os.environ.get("TS_API_BASE", "https://tiktokscope.120319.xyz")
user = "charlidamelio"

profile = requests.get(f"{BASE}/api/profile/{user}", timeout=30).json()
analytics = requests.get(f"{BASE}/api/profile/{user}/analytics", timeout=30).json()

m = analytics["metrics"]
print(profile["nickname"], profile["followers"])
print("likes/video:", m["likes_per_video"], "follow ratio:", m["following_ratio"])
print("growth/day:", analytics["growth"]["deltas"]["followers_per_day"])

Response · truncated

json · 200
{
  "profile": {
    "username": "charlidamelio",
    "nickname": "charli d'amelio",
    "verified": true,
    "followers": 155400000,
    "following": 1200,
    "likes": 11500000000,
    "videos": 2400
  },
  "metrics": {
    "followers": 155400000,
    "following": 1200,
    "likes": 11500000000,
    "videos": 2400,
    "likes_per_video": 4791666.6667,
    "followers_per_video": 64750.0,
    "following_ratio": 0.0
  },
  "growth": {
    "points": [
      { "t": 1759990000, "followers": 155380000, "likes": 11498000000, "videos": 2400 },
      { "t": 1760000000, "followers": 155400000, "likes": 11500000000, "videos": 2400 }
    ],
    "deltas": { "followers_per_day": 17280.0, "likes_per_day": 1728000000.0, "videos_per_day": 0.0 }
  },
  "snapshots": 2,
  "tracked": false
}
GET

/api/followers/{u}/export

docs ↗ try it ↗

Stream a creator's followers as a downloadable CSV. The server pages upstream at 50 rows per request and sleeps between pages, so allow a generous timeout for large limit (max 5000, default 500).

curl

bash
curl -s "$BASE/api/followers/charlidamelio/export?limit=500" \
  -o charli-followers.csv

wc -l charli-followers.csv

Python

python · requests
import os, requests

BASE = os.environ.get("TS_API_BASE", "https://tiktokscope.120319.xyz")

r = requests.get(
    f"{BASE}/api/followers/charlidamelio/export",
    params={"limit": 500},
    timeout=180,
    stream=True,
)
r.raise_for_status()
with open("charli-followers.csv", "wb") as fh:
    for chunk in r.iter_content(chunk_size=8192):
        fh.write(chunk)

print("saved:", r.headers.get("content-disposition"))

Response · text/csv · truncated

csv
user_id,username,nickname,sec_uid,bio,verified,private,followers,following,likes,videos
6901234567890123456,somefan,Some Fan,MS4wLjABAAAA...,fan account,False,False,1234,321,5678,42
6901234567890123457,anotherfan,Another Fan,MS4wLjABAAAA...,,False,True,88,120,301,7
...
GET

/api/video

docs ↗ try it ↗

Fetch a full video record (author, stats, media, hashtags) with derived metrics, then pull the parsed caption lines from /api/video/subtitles.

curl

bash
VIDEO="https://www.tiktok.com/@charlidamelio/video/7300000000000000000"

curl -s "$BASE/api/video?url=$VIDEO" | jq '{desc, stats, metrics}'
curl -s "$BASE/api/video/subtitles?url=$VIDEO&lang=eng-US" | jq '.lines'

Python

python · requests
import os, requests

BASE = os.environ.get("TS_API_BASE", "https://tiktokscope.120319.xyz")
url = "https://www.tiktok.com/@charlidamelio/video/7300000000000000000"

video = requests.get(f"{BASE}/api/video", params={"url": url}, timeout=30).json()
subs = requests.get(
    f"{BASE}/api/video/subtitles",
    params={"url": url, "lang": "eng-US"},
    timeout=30,
).json()

print(video["desc"], video["stats"])
print(video["metrics"]["engagement_rate"])
print("\n".join(subs["lines"]))

Response · /api/video · truncated

json · 200
{
  "id": "7300000000000000000",
  "desc": "day in the life #fyp",
  "duration": 15,
  "author": { "username": "charlidamelio", "nickname": "charli d'amelio" },
  "stats": { "plays": 2500000, "likes": 340000, "comments": 4200, "shares": 18000, "collects": 9600 },
  "metrics": {
    "engagement_rate": 0.1449,
    "save_rate": 0.0038,
    "share_rate": 0.0072,
    "like_per_1k": 136.0,
    "est_watch_proxy": 2.1735
  },
  "music": "original sound",
  "challenges": ["fyp", "dayinthelife"]
}

Response · /api/video/subtitles · truncated

json · 200
{
  "lines": ["hey guys", "welcome back to my channel", "today we are doing something fun"],
  "text": "hey guys\nwelcome back to my channel\ntoday we are doing something fun"
}
GET

/api/sound/{music_id}

docs ↗ try it ↗

Find the videos using a sound. Each item is a full video record with metrics; the response also carries an optional meta block describing the track itself.

curl

bash
curl -s "$BASE/api/sound/7000000000000000000?count=20" \
  | jq '{total, has_more, first: .items[0].stats}'

Python

python · requests
import os, requests

BASE = os.environ.get("TS_API_BASE", "https://tiktokscope.120319.xyz")
music_id = "7000000000000000000"

page = requests.get(
    f"{BASE}/api/sound/{music_id}",
    params={"cursor": 0, "count": 20},
    timeout=30,
).json()

for v in page["items"]:
    print(v["id"], v["author"]["username"], v["stats"]["plays"])

print("more:", page["has_more"], "next:", page["next_cursor"])

Response · truncated

json · 200
{
  "items": [
    {
      "id": "7300000000000000000",
      "desc": "day in the life #fyp",
      "author": { "username": "charlidamelio", "nickname": "charli d'amelio" },
      "stats": { "plays": 2500000, "likes": 340000, "comments": 4200, "shares": 18000, "collects": 9600 },
      "metrics": { "engagement_rate": 0.1449 },
      "music_id": "7000000000000000000"
    }
    // …more videos
  ],
  "has_more": true,
  "next_cursor": 20,
  "total": 125000,
  "meta": { "id": "7000000000000000000", "title": "original sound", "author": "charlidamelio", "duration": 24 }
}
GET

/api/benchmark

docs ↗ try it ↗

Compare up to four creators side by side on followers, average engagement, average plays, plays-per-follower and posting cadence. Rows are sorted by follower count.

curl

bash
curl -s "$BASE/api/benchmark?users=charlidamelio,khaby.lame,addisonre&videos=4" \
  | jq '.rows[] | {username, avg_engagement_rate, plays_per_follower}'

Python

python · requests
import os, requests

BASE = os.environ.get("TS_API_BASE", "https://tiktokscope.120319.xyz")

data = requests.get(
    f"{BASE}/api/benchmark",
    params={"users": "charlidamelio,khaby.lame,addisonre", "videos": 4},
    timeout=90,
).json()

for row in data["rows"]:
    print(row["username"], row["followers"], row["avg_engagement_rate"])

Response · truncated

json · 200
{
  "rows": [
    {
      "username": "khaby.lame",
      "nickname": "Khabane lame",
      "followers": 162800000,
      "likes_total": 2400000000,
      "videos_total": 1100,
      "sampled_videos": 4,
      "avg_engagement_rate": 0.0871,
      "avg_plays": 24500000,
      "plays_per_follower": 0.151,
      "posts_last_30d": 6,
      "avg_days_between_posts": 4.5
    },
    {
      "username": "charlidamelio",
      "nickname": "charli d'amelio",
      "followers": 155400000,
      "likes_total": 11500000000,
      "videos_total": 2400,
      "sampled_videos": 4,
      "avg_engagement_rate": 0.121,
      "avg_plays": 1800000,
      "plays_per_follower": 0.012,
      "posts_last_30d": 9,
      "avg_days_between_posts": 3.1
    }
  ]
}
GET

/api/profile/{u}/card

docs ↗ try it ↗

Get oEmbed-style metadata and ready-to-paste html for a profile card. For a rendered widget with no work, point an <iframe> at /embed?user=charlidamelio.

curl

bash
curl -s "$BASE/api/profile/charlidamelio/card" | jq '{title, html, thumbnail_url}'

# Ready-made HTML widget:
open "$BASE/embed?user=charlidamelio"

Python

python · requests
import os, requests

BASE = os.environ.get("TS_API_BASE", "https://tiktokscope.120319.xyz")

card = requests.get(f"{BASE}/api/profile/charlidamelio/card", timeout=30).json()
print(card["title"])
print(card["html"])

# Embed the hosted widget instead:
widget = f'<iframe src="{BASE}/embed?user=charlidamelio" width="400" height="220"></iframe>'
print(widget)

Response · truncated

json · 200
{
  "type": "rich",
  "version": "1.0",
  "provider_name": "TikTokScope",
  "provider_url": "https://tiktokscope.120319.xyz",
  "title": "@charlidamelio on TikTok",
  "author_name": "charli d'amelio",
  "thumbnail_url": "https://p16-sign.tiktokcdn-us.com/...",
  "width": 400,
  "height": 220,
  "html": "<blockquote class=\"tiktokscope-card\"><a href=\"https://www.tiktok.com/@charlidamelio\">@charlidamelio</a> — 155400000 followers, 11500000000 likes.</blockquote>",
  "profile": { "username": "charlidamelio", "followers": 155400000 }
}
GET

/api/video/transcript

docs ↗ try it ↗

Translate a video's native description and subtitles. TikTok currently accepts lang=es (Spanish) only; the response carries the translated description and subtitle text.

curl

bash
curl -s "$BASE/api/video/transcript?url=https://www.tiktok.com/@charlidamelio/video/7300000000000000000&lang=es" \
  | jq '{target, description, subtitle}'

Python

python · requests
import os, requests

BASE = os.environ.get("TS_API_BASE", "https://tiktokscope.120319.xyz")
url = "https://www.tiktok.com/@charlidamelio/video/7300000000000000000"

data = requests.get(
    f"{BASE}/api/video/transcript",
    params={"url": url, "lang": "es"},
    timeout=30,
).json()

print(data["description"])
print(data["subtitle"])

Response · truncated

json · 200
{
  "id": "7300000000000000000",
  "target": "es",
  "description": "un día en la vida #fyp",
  "subtitle": "hola chicos, bienvenidos de nuevo a mi canal, hoy vamos a hacer algo divertido"
}