TikTokAnswer

TikTok sound API: videos using a sound, with plays

TikTok's own APIs can't list the videos that use a sound outside research access. Our API returns a sound's video count and top videos, up to 30 a call.

5 min read

Short answer

  • TikTok's Display API reads a signed-in user's own videos, and only its Research API can search videos by music_id, for approved researchers.
  • A sound's page shows how many videos use it and which ones lead, which is what labels, marketers and creators track.
  • Our TikTok API returns a sound's details with its video count at 2 credits, and the videos that use it, up to 30 a call at 1 credit.
On this page

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, including user_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
bash
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:

json
{
  "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.

python
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:

bash
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.

Get this data from your own code

The TikTok API returns it as JSON with one x-api-key header. 100 free credits monthly.