Answers
Is there one API to track a brand across TikTok, YouTube and X?
Short answer
Yes: okdata searches TikTok ($0.002 a page), YouTube ($0.004 a page) and X ($0.006 a page) with one key, and returns posts in the same shape on all three. A weekly brand sweep of about 120 TikTok videos, 40 YouTube videos with their top comments and 200 X posts costs $0.156.
Every Monday a brand manager wants one sheet: what got posted about the product last week on TikTok, YouTube and X, sorted by reach. Doing that by hand means three apps and a lot of copying. With three official APIs it means three developer accounts, three auth schemes and three data formats. Here it is one key and one shape. Every result is a post with url, text, published_at, author and metrics, whichever platform it came from.
The endpoints
- TikTok video search: videos with plays, likes, comments and shares.
- YouTube video search: videos with views, channel and published time; YouTube comments for what viewers say under the big ones.
- X post search: posts with views, likes, replies and reposts, latest first.
The weekly sweep
| Step | Calls | Cost |
|---|---|---|
| TikTok search, 4 pages (about 120 videos) | 4 | $0.008 |
| YouTube search, 2 pages (about 40 videos) | 2 | $0.008 |
| Comments on the 10 biggest YouTube videos, 2 pages each | 20 | $0.08 |
| X search, 10 pages (about 200 posts) | 10 | $0.06 |
| Total | 36 | {{cost:tiktok.videos.search4+youtube.videos.search2+youtube.videos.comments.list20+x.posts.search10}} |
One loop, three platforms
import csv, os, requests
API = "https://api.okdata.online/v1"
H = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}
BRAND = "glowlab serum"
def search(path, query, pages, **extra):
cursor, out = None, []
for _ in range(pages):
params = {"query": query, **extra, **({"cursor": cursor} if cursor else {})}
body = requests.get(f"{API}/{path}", headers=H, params=params, timeout=60).json()
if body["code"] != "ok":
raise RuntimeError(f"{path}: {body['code']} {body['message']}")
out += body["data"]["items"]
if not body["page"]["has_more"]:
break
cursor = body["page"]["next_cursor"]
return out
rows = []
for platform, path, pages, extra in [("tiktok", "tiktok/videos/search", 4, {}),
("youtube", "youtube/videos/search", 2, {}),
("x", "x/posts/search", 10, {"sort": "latest"})]:
for p in search(path, BRAND, pages, **extra):
m = p["metrics"]
rows.append([platform, p["url"], p["published_at"], p["author"]["username"], m["views"], m["likes"], (p["title"] or p["text"])[:120]])
rows.sort(key=lambda r: r[4] or 0, reverse=True)
csv.writer(open("weekly-sweep.csv", "w", newline="", encoding="utf-8")).writerows(rows)
What differs between the three
- YouTube search results carry views but no like or comment counts; those fields are null and named in
meta.unavailable. Call video detail for the handful you care about. - TikTok and YouTube search rank by relevance, so a latest sort is not strict date order. Filter on
published_atto keep last week only. - X search takes X's operators, so
-from:yourbrandkeeps your own posts out. - Comments come back top-level with a reply count, on both TikTok and YouTube.
When a listening suite is the better buy
If the team wants dashboards, alerts, sentiment scoring and years of history without writing code, a social listening product is worth its subscription. If you would rather own the data, feed it to your own model or keep the bill per call, this sweep does the core job. Sentiment and topic tagging on top are covered in the word-of-mouth guide, and every field is described on the post object page.
Updated