TikTok offers no sound API to businesses. TikTok's Display API returns the videos of a user who signs in to your app. Its Research API can search videos by music_id, but only approved researchers get access, not creators, advertisers or other commercial users. Our TikTok API reads a sound's public page: how many videos use it, and the videos that lead it, up to 30 a call.
What TikTok's APIs are for
TikTok's Display API has video.list, which reads the public videos of the user whose token you hold, so it covers accounts that signed in to your app, not a sound. The Research API queries public videos by fields that include music_id, but its FAQ answers no to creators, advertisers and commercial users asking for access. Neither is open to a brand or a label tracking a sound.
Sound data with ToolzerHub
We make ToolzerHub. Our TikTok API returns public TikTok profiles, videos, comments and sounds as JSON with one API key. These routes do the job here:
/v2/tiktok/app/music: one sound's details, includinguser_count, the number of videos using it, 2 credits/v1/tiktok/music_videos: the videos that use a sound, up to 30 a page, 1 credit; takes a sound link or its ID/v2/tiktok/app/music/chart: a chart of 50 sounds with their video counts, 2 credits
export TOOLZERHUB_API_KEY=your_key
curl -H "x-api-key: $TOOLZERHUB_API_KEY" \
"https://api.toolzerhub.com/v1/tiktok/music_videos?music_id_or_url=https://www.tiktok.com/music/Housewife-7697010651306838068"
The first video in data.entries, trimmed:
{
"id": "7697301244750073102",
"create_time": 1792167638,
"author": {"unique_id": "tatemcrae", "nickname": "tate mcrae", "verified": true},
"stats": {"play_count": 22300000, "digg_count": 3300000, "comment_count": 8579, "share_count": 59400},
"video": {"duration": 12},
"music": {"id": "7697010651306838068", "title": "Housewife", "author_name": "Tate McRae"}
}
digg_count is likes. Plays and likes come rounded, the way TikTok shows them. The list is in TikTok's order for the sound page, not sorted by plays, and next_cursor gives the next page; pages held 24 to 30 videos in our checks.
Track how a sound is used
The script takes sound links (the full tiktok.com/music/ link) or sound IDs, reads the sound's details and the pages of videos you ask for, keeps only videos tagged with that sound and writes one row per video with its author, plays, likes, comments, shares and saves. For each sound it prints the video count, the median plays of the videos it read and how many came from verified accounts. Install requests (pip install requests) and save it as tiktok_sound.py.
import csv
import os
import re
import statistics
import sys
import time
from datetime import datetime, timezone
import requests
API = "https://api.toolzerhub.com"
HEADERS = {"x-api-key": os.environ.get("TOOLZERHUB_API_KEY", "")}
FIELDS = ["sound", "sound_id", "rank", "video_id", "posted_at", "author", "verified", "plays", "likes",
"comments", "shares", "saves", "duration_s", "url"]
def get(path, params, tries=3):
# Retry rate limits, server errors and dropped connections.
for attempt in range(tries):
last = attempt == tries - 1
try:
r = requests.get(f"{API}{path}", headers=HEADERS, params=params, timeout=120)
except requests.RequestException:
if last:
raise
time.sleep(5 * (attempt + 1))
continue
if r.status_code in (429, 500, 502, 503, 504) and not last:
time.sleep(5 * (attempt + 1))
continue
r.raise_for_status()
return r.json()["data"]
def main(sounds, pages="2", out="tiktok_sound_videos.csv"):
with open(out, "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=FIELDS)
writer.writeheader()
for ref in filter(None, (s.strip() for s in sounds.split(","))):
# A sound link ends in the numeric sound ID.
sound_id = re.findall(r"\d{15,}", ref)[-1]
info = get("/v2/tiktok/app/music", {"music_id": sound_id})["music_info"]
videos, seen, cursor = [], set(), 0
for _ in range(int(pages)):
data = get("/v1/tiktok/music_videos", {"music_id_or_url": sound_id, "cursor": cursor})
for v in data.get("entries") or []:
# Keep only videos whose sound is this one.
if v["id"] not in seen and str((v.get("music") or {}).get("id")) == sound_id:
seen.add(v["id"])
videos.append(v)
if not data.get("has_more"):
break
cursor = data["next_cursor"]
for rank, v in enumerate(videos, 1):
s = v.get("stats") or {}
writer.writerow({
"sound": info["title"], "sound_id": sound_id, "rank": rank, "video_id": v["id"],
"posted_at": datetime.fromtimestamp(v["create_time"], timezone.utc).isoformat(),
"author": v["author"]["unique_id"], "verified": v["author"].get("verified"),
"plays": s.get("play_count"), "likes": s.get("digg_count"), "comments": s.get("comment_count"),
"shares": s.get("share_count"), "saves": (v.get("stats_v2") or {}).get("collectCount"),
"duration_s": (v.get("video") or {}).get("duration"),
"url": f"https://www.tiktok.com/@{v['author']['unique_id']}/video/{v['id']}",
})
plays = [(v.get("stats") or {}).get("play_count") or 0 for v in videos]
print(f"{info['title']} by {info['author']}: used in {info['user_count']:,} videos; "
f"first {len(videos)} videos, median {statistics.median(plays or [0]):,.0f} plays, "
f"{sum(bool(v['author'].get('verified')) for v in videos)} by verified accounts")
if __name__ == "__main__":
if len(sys.argv) < 2:
sys.exit("usage: python tiktok_sound.py <sound links or ids, comma-separated> [pages] [out.csv]")
if not HEADERS["x-api-key"]:
sys.exit("set TOOLZERHUB_API_KEY first")
main(*sys.argv[1:])
What four chart sounds showed
Two pages each for four sounds from the music chart made 12 calls in 35 seconds and saved 227 videos:
python tiktok_sound.py "https://www.tiktok.com/music/Housewife-7697010651306838068,https://www.tiktok.com/music/Coming-Up-Roses-7613798254214187009,https://www.tiktok.com/music/Nicole-Kidman-7680715246777501713,https://www.tiktok.com/music/DEATHMETAL-7140421880682383362" 2
| Sound | Videos using it | Videos read | Median plays | 1 million plays or more | From verified accounts | Median age of videos |
|---|---|---|---|---|---|---|
| Housewife, Tate McRae | 520,036 | 60 | 1,100,000 | 34 | 5 | 9.8 days |
| Coming Up Roses, Harry Styles | 221,942 | 54 | 4,250,000 | 54 | 3 | 184.6 days |
| Nicole Kidman, ADÉLA | 199,090 | 57 | 4,200,000 | 57 | 18 | 49 days |
| D>E>A>T>H>M>E>T>A>L, Panchiko | 126,568 | 56 | 1,950,000 | 56 | 0 | 118.6 days |
Housewife is the newest of the four, with no video older than 19 days, and more videos use it than any of the other three. Tate McRae's own post leads its page at 22,300,000 plays. On the older sounds every video read had at least a million plays, so the sound page leads with proven hits, not the latest uses. Verified accounts were rare except on Nicole Kidman, where they posted 18 of 57 videos, among them LE SSERAFIM, Lizzo and Nicole Kidman herself.
What it costs
A sound is 4 credits at two pages: 2 for its details and 1 per page of up to 30 videos. The 100 free credits a month cover 25 sounds at that depth; $19 buys 10,000 credits that never expire, and plans for higher volume cover daily tracking of a release. Set your key and the first sound is a CSV in under a minute.
For videos under a hashtag, see the TikTok hashtag API, and for the follower counts of the creators who used a sound, the TikTok user info API. For one creator's uploads, see TikTok API get user videos, and for the same songs on Instagram, the Instagram music API.
We are not affiliated with TikTok or ByteDance.