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.
…
Recipes
Jump straight to a task. Each panel has copy buttons on every code block.
Keyword search across public TikTok videos. Pass q, plus optional
cursor and count (1–50). Results include derived
metrics on each video.
curl
curl -s "$BASE/api/search?q=gamergirl&count=18" | jq '.videos[0]'
Python
import os, requests
BASE = os.environ.get("TS_API_BASE", "https://tiktokscope.120319.xyz")
r = requests.get(
f"{BASE}/api/search",
params={"q": "gamergirl", "count": 18},
timeout=30,
)
r.raise_for_status()
data = r.json()
for v in data["videos"]:
stats = v.get("stats", {})
print(v["id"], stats.get("plays"), v.get("metrics", {}).get("engagement_rate"))
Response · truncated
{
"query": "gamergirl",
"cursor": 18,
"has_more": true,
"videos": [
{
"id": "7300000000000000000",
"desc": "#fyp Fortnite gameplay clips",
"author": { "username": "proplayer", "nickname": "Pro Player" },
"stats": { "plays": 49400, "likes": 6100, "comments": 142, "shares": 390, "collects": 220 },
"metrics": { "engagement_rate": 0.1343, "like_per_1k": 123.5 }
}
// …more videos
]
}
Resolve a creator's identity and lifetime counters, then add per-video averages and the
follow ratio via /api/profile/{u}/analytics.
curl
curl -s "$BASE/api/profile/charlidamelio" | jq
curl -s "$BASE/api/profile/charlidamelio/analytics" | jq '.metrics'
Python
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
{
"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
}
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
curl -s "$BASE/api/followers/charlidamelio/export?limit=500" \
-o charli-followers.csv
wc -l charli-followers.csv
Python
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
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
...
Fetch a full video record (author, stats, media, hashtags) with derived
metrics, then pull the parsed caption lines from
/api/video/subtitles.
curl
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
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
{
"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
{
"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"
}
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
curl -s "$BASE/api/sound/7000000000000000000?count=20" \
| jq '{total, has_more, first: .items[0].stats}'
Python
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
{
"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 }
}
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
curl -s "$BASE/api/benchmark?users=charlidamelio,khaby.lame,addisonre&videos=4" \
| jq '.rows[] | {username, avg_engagement_rate, plays_per_follower}'
Python
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
{
"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 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
curl -s "$BASE/api/profile/charlidamelio/card" | jq '{title, html, thumbnail_url}'
# Ready-made HTML widget:
open "$BASE/embed?user=charlidamelio"
Python
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
{
"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 }
}
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
curl -s "$BASE/api/video/transcript?url=https://www.tiktok.com/@charlidamelio/video/7300000000000000000&lang=es" \
| jq '{target, description, subtitle}'
Python
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
{
"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"
}