Labels, artist teams and music marketers all ask the same question about a song on TikTok: who used it, and which of those videos took off? This guide answers it with about 60 lines of Python and one endpoint.
You will fetch one page of videos for a sound, then follow the cursor through the whole list without missing or double-counting a video, and finally save a CSV sorted by views. The responses shown are real, trimmed with … where they run long.
Before you start
- A ScrapingBot API key. Create a free account for 100 credits, enough for 100 pages of videos. No card needed.
- Python 3.9 or newer and
pip install requests. - A sound ID. This guide uses
7682907287056337667, the original sound behind a lo-fi house clip by@aetherrr.flp.
Find the sound ID
Open the sound on TikTok. Its page URL has the form tiktok.com/music/<sound-name>-<id>, and the number at the end is the sound ID. You can also send the whole sound URL as url instead of music_id.
If all you have is a video, fetch it with the / endpoint and read data.music_info. For a NASA video the sound block looked like this:
"music_info": {
"id": "7692161536332253965",
"title": "original sound - NASA",
"author": "NASA",
"duration": 136,
"original": false
}
Fetch one page of videos
Every TikTok call is a POST to https://scrapingbot.io/api/v1/tiktok with the endpoint name and its parameters in the body:
curl -X POST https://scrapingbot.io/api/v1/tiktok \
-H "x-api-key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"endpoint": "/music/posts", "params": {"music_id": "7682907287056337667", "count": 30}}'
The response holds a page of videos, a cursor for the next page and a hasMore flag:
{
"success": true,
"data": {
"videos": [
{
"video_id": "7682907275505224982",
"title": "luna eterna #lofihouse #electronicmusic #club #fyp #2000smusic",
"play_count": 353558,
"digg_count": 53947,
"comment_count": 741,
"create_time": 1788816252,
"play": "https://v19.tiktokcdn.com/…",
"author": { "id": "7002179649582711813", "unique_id": "aetherrr.flp", "nickname": "aether" }
},
…
],
"cursor": 12,
"hasMore": 1
},
"processed_time": 1.9064,
"duration": "1.91",
"statusCode": 200,
"creditsUsed": 1
}
Three fields matter for paging. videos is this page. cursor goes back unchanged in the next request. hasMore is 1 while there are more pages and 0 at the end. digg_count is TikTok's name for likes, and create_time is a Unix timestamp.
The full script
Save this as sound_videos.py. It wraps the API call with retries, walks every page, keeps the first copy of each video and writes a CSV.
import csv
import time
from datetime import datetime, timezone
import requests
API = "https://scrapingbot.io/api/v1/tiktok"
HEADERS = {"x-api-key": "YOUR_API_KEY"}
def call(endpoint, params, tries=3):
"""One API call. Failed calls are refunded, so a retry costs nothing extra."""
for attempt in range(tries):
res = requests.post(API, headers=HEADERS, timeout=60,
json={"endpoint": endpoint, "params": params})
body = res.json()
if body.get("success"):
return body["data"]
if res.status_code in (400, 401, 402): # bad input, bad key, no credits
raise RuntimeError(body.get("error"))
time.sleep(2 ** attempt) # 408, 429 or 5xx: wait and try again
raise RuntimeError(f"{endpoint} kept failing: {body.get('error')}")
def videos_for_sound(music_id, max_pages=100):
videos, cursor = {}, None
for page in range(1, max_pages + 1):
params = {"music_id": music_id, "count": 30}
if cursor is not None:
params["cursor"] = cursor
data = call("/music/posts", params)
for v in data.get("videos", []):
videos.setdefault(v["video_id"], v) # the same video can appear twice
print(f"page {page}: {len(data.get('videos', []))} videos, "
f"{len(videos)} unique, hasMore={data.get('hasMore')}")
if not data.get("hasMore"): # only 0 / false ends the list
break
cursor = data["cursor"]
return list(videos.values())
FIELDS = ["video_id", "url", "creator", "posted", "views", "likes", "comments", "caption"]
def row(v):
handle = v["author"]["unique_id"]
return {
"video_id": v["video_id"],
"url": f"https://www.tiktok.com/@{handle}/video/{v['video_id']}",
"creator": handle,
"posted": datetime.fromtimestamp(v["create_time"], timezone.utc).date().isoformat(),
"views": v.get("play_count", 0),
"likes": v.get("digg_count", 0),
"comments": v.get("comment_count", 0),
"caption": v.get("title", ""),
}
if __name__ == "__main__":
import sys
sound_id = sys.argv[1] if len(sys.argv) > 1 else "7682907287056337667"
max_pages = int(sys.argv[2]) if len(sys.argv) > 2 else 100
rows = sorted(map(row, videos_for_sound(sound_id, max_pages)),
key=lambda r: r["views"], reverse=True)
path = f"sound_{sound_id}.csv"
with open(path, "w", newline="", encoding="utf-8") as f:
writer = csv.DictWriter(f, fieldnames=FIELDS)
writer.writeheader()
writer.writerows(rows)
print(f"saved {len(rows)} videos to {path}")
A few choices in that code are deliberate:
- It stops on
hasMore, never on page size. TikTok often returns about 10 videos even when you ask for 30, and a short page in the middle of the list is normal. - It keys videos on
video_id. Pages can overlap, so a dictionary keeps one copy of each. Usevideo_idrather thanaweme_id, which can be empty. - It retries only what can succeed later. A
400(bad input),401(bad key) or402(out of credits) will fail the same way again, so it raises. Timeouts,429and server errors get up to three tries with a growing pause. Failed calls are refunded, so retries cost nothing. max_pagescaps the spend. Each page is 1 credit, so the default of 100 can never cost more than 100 credits per sound.
Run it
export SOUND=7682907287056337667
python sound_videos.py $SOUND
The script prints one line per page and then the file name. The first row of the CSV, from the response above:
video_id,url,creator,posted,views,likes,comments,caption
7682907275505224982,https://www.tiktok.com/@aetherrr.flp/video/7682907275505224982,aetherrr.flp,2026-09-07,353558,53947,741,luna eterna #lofihouse #electronicmusic #club #fyp #2000smusic
…
Open it in a spreadsheet and the creators whose videos did best are at the top. That list is often the most useful output for a music marketer: they already chose the song once, and their audience responded.
Add the sound's own details
/music/info returns the title, author, duration, an audio URL and how many videos use the sound. It is one more credit and tells you how big the export will be before you start. For another sound, 7683546066251827217:
{
"success": true,
"data": {
"id": "7683546066251827217",
"title": "Hoe Craft",
"author": "MC",
"album": "Hoe Craft",
"duration": 60,
"original": false,
"video_count": 218,
"play": "https://sf16.tiktokcdn-us.com/…",
"cover": "https://p16-common.tiktokcdn-us.com/…"
},
"processed_time": 0.1327,
"duration": "0.13",
"statusCode": 200,
"creditsUsed": 1
}
With 218 videos at roughly 10 per page, exporting that sound takes about 22 calls: 22 credits, or about four-tenths of a cent on the Starter plan ($49.99 for 275,000 credits).
info = call("/music/info", {"music_id": "7683546066251827217"})
print(info["title"], "by", info["author"], "-", info["video_count"], "videos")
# Hoe Craft by MC - 218 videos
Fields you get for each video
| Field | What it is |
|---|---|
video_id | The video's ID. Build the link as tiktok.com/@<unique_id>/video/<video_id>. |
title | The caption, including hashtags. |
play_count | Views. |
digg_count | Likes. |
comment_count | Comments. |
create_time | When it was posted, as a Unix timestamp in seconds. |
author.unique_id | The creator's handle; author.id is their numeric ID, which you need for /user/followers. |
play | A playable video URL. It is signed and expires, so download soon if you need the file. |
Where to go from here
- Run the export every day and compare: the daily sound tracker in Node.js stores snapshots in SQLite and reports new videos and view growth.
- Size up the creators who used the sound with follower and like counts.
- The TikTok sound API page and the /music/posts reference list every parameter.
- Comparing providers? See the best TikTok data APIs in 2026.
Common questions
How do I get all the videos that use a TikTok sound?
Call the /music/posts endpoint with the sound ID, then send the cursor from each response back with the next request until hasMore is 0. De-duplicate on video_id, because the same video can show up on two pages.
Where do I find a TikTok sound ID?
It is the number at the end of the sound page URL (tiktok.com/music/<name>-<id>). If you only have a video, fetch it with the / endpoint and read data.music_info.id.
How many videos come back per page?
Around 10, whatever count says. Page sizes vary from page to page, so never treat a short page as the end of the list; only hasMore: 0 means you are done.
What does it cost to export a sound?
Each page is one call and costs 1 credit, so a sound with 218 videos takes about 22 calls. On the Starter plan that is well under a cent. Failed calls are refunded.
Can I get the audio file of the sound?
Yes. /music/info returns a play URL for the audio along with the title, author, duration and the number of videos that use the sound. Media URLs are signed and expire, so download what you need soon after the call.