TikTokHow-to

TikTok API get video: stats and MP4 link from a URL

Get a TikTok video's plays, likes, saves, length and MP4 link from its URL for 2 credits. TikTok's Display API reads only signed-in users' videos.

4 min read

Short answer

  • TikTok's Display API returns video details by ID only for the videos of users who sign in to your app.
  • Our video route takes the ID from a tiktok.com video URL and returns the post time, plays, likes, comments, shares, saves, length and MP4 links.
  • Each video is 2 credits, so the 100 free credits a month cover 50 videos; the script below writes a list of URLs to CSV.
On this page

Take the number after /video/ in a TikTok URL, send it to /v2/tiktok/app/video, and you get the video's post time, stats, length and MP4 links for 2 credits. TikTok's own Display API returns video details only for the videos of users who sign in to your app.

What TikTok's Display API returns

TikTok's Display API has three calls: user info, video list and video query. They read the videos of users who sign in to your app, and /v2/video/query/ returns that user's videos filtered by ID.

What one call returns

One call returns a video's author, post time, stats, length and playback links. We make ToolzerHub. Our TikTok API reads public TikTok data with one API key. /v2/tiktok/app/video takes aweme_id, the video ID, and costs 2 credits.

bash
curl "https://api.toolzerhub.com/v2/tiktok/app/video?aweme_id=7701302261489700148" \
  -H "x-api-key: $TOOLZERHUB_API_KEY"

One video, trimmed:

json
{
  "data": {
    "aweme_detail": {
      "aweme_id": "7701302261489700148",
      "desc": "Funny,raw,unfiltered…😅Updated skincare routine🫶 telling you ",
      "create_time": 1793099174,
      "author": {
        "unique_id": "_d_vine"
      },
      "statistics": {
        "play_count": 871810,
        "digg_count": 165685,
        "comment_count": 747,
        "share_count": 913,
        "collect_count": 10706
      },
      "video": {
        "duration": 488934,
        "width": 576,
        "height": 1024,
        "play_addr": {
          "url_list": [
            "https://v19.tiktokcdn-us.com/5beeca2d4510dcc391ceaf9e958fa51..."
          ]
        }
      }
    }
  }
}

create_time is a Unix timestamp, video.duration is in milliseconds and digg_count is likes. The link in play_addr served the MP4 itself: 28.8 MB for this 8-minute video. If you only need plays, likes, comments and shares, /v1/tiktok/video returns them for 1 credit from the author's username and the video_id, without the post time or file links.

Get many videos to CSV

The script takes tiktok.com/@user/video/<id> URLs or bare IDs, pulls the ID out of each, and writes one row per video with the post time, length and stats.

python
import csv
import os
import re
import sys
import time
from datetime import datetime, timezone

import requests

API = "https://api.toolzerhub.com/v2/tiktok/app/video"
HEADERS = {"x-api-key": os.environ.get("TOOLZERHUB_API_KEY", "")}
FIELDS = ["video_id", "author", "posted", "seconds", "plays", "likes", "comments", "shares",
          "saves", "description", "url"]


def cell(value):
    # A leading = + - or @ would run as a formula when the CSV opens in a spreadsheet.
    return "'" + value if isinstance(value, str) and value[:1] in ("=", "+", "-", "@") else value


def get(video_id, tries=4):
    # 429 and 503 are worth a retry; the body or the Retry-After header says how long to wait.
    for attempt in range(tries):
        r = requests.get(API, params={"aweme_id": video_id}, headers=HEADERS, timeout=120)
        if r.status_code in (429, 503) and attempt < tries - 1:
            wait = int(((r.json().get("error") or {}).get("details") or {}).get("retryAfter") or r.headers.get("Retry-After") or 5 * (attempt + 1))
            time.sleep(min(wait, 60))
            continue
        r.raise_for_status()
        return (r.json().get("data") or {}).get("aweme_detail")


def row(v):
    stats, author = v.get("statistics") or {}, v.get("author") or {}
    posted = v.get("create_time")
    return {
        "video_id": v["aweme_id"], "author": author.get("unique_id"),
        "posted": datetime.fromtimestamp(posted, timezone.utc).isoformat() if posted else "",
        "seconds": round((v.get("video") or {}).get("duration", 0) / 1000, 1),
        "plays": stats.get("play_count"), "likes": stats.get("digg_count"),
        "comments": stats.get("comment_count"), "shares": stats.get("share_count"),
        "saves": stats.get("collect_count"),
        "description": cell((v.get("desc") or "").replace("\n", " ")),
        "url": f"https://www.tiktok.com/@{author.get('unique_id')}/video/{v['aweme_id']}",
    }


def main(links, out="tiktok_videos.csv"):
    # A video ID is the number after /video/ in the URL; a bare ID works too.
    ids = [m.group(1) for s in links.split(",")
           if (m := re.search(r"/video/(\d+)", s) or re.fullmatch(r"\s*(\d{15,25})\s*", s))]
    if not ids:
        sys.exit("no video ID found: pass tiktok.com/@user/video/<id> URLs or the IDs themselves")
    saved = 0
    with open(out, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=FIELDS)
        writer.writeheader()
        for video_id in ids:
            v = get(video_id)
            if not v:
                print(video_id, "-> not available")
                continue
            writer.writerow(row(v))
            saved += 1
            print(video_id, "->", (v.get("statistics") or {}).get("play_count"), "plays")
    print(f"saved {saved} of {len(ids)} videos to {out}")


if __name__ == "__main__":
    if not HEADERS["x-api-key"] or len(sys.argv) < 2:
        sys.exit("usage: TOOLZERHUB_API_KEY=... python tiktok_videos.py URL_OR_ID[,URL_OR_ID] [file.csv]")
    main(*sys.argv[1:])
bash
export TOOLZERHUB_API_KEY=your_key
python tiktok_videos.py "https://www.tiktok.com/@musiced13/video/7701640406185889046,https://www.tiktok.com/@codingwithalexz/video/7691531865009704223,https://www.tiktok.com/@foodreviewclub/video/7702446687217798422,https://www.tiktok.com/@jessreadsalott/video/7702389725012790548,https://www.tiktok.com/@alexaaliftss/video/7666151163787611406,7700297051380174093"
text
7701640406185889046 -> 628073 plays
7691531865009704223 -> 3451 plays
7702446687217798422 -> 88895 plays
7702389725012790548 -> 10505 plays
7666151163787611406 -> 8336 plays
7700297051380174093 -> 3531735 plays
saved 6 of 6 videos to tiktok_videos.csv

What came out

Six videos took 12 seconds, and all six came back.

Author Length (s) Plays Likes Comments Saves
musiced13 60.3 628,073 84,393 446 5,022
codingwithalexz 33.4 3,451 213 5 202
foodreviewclub 178.2 88,895 3,152 108 533
jessreadsalott 78.4 10,505 1,665 2 103
alexaaliftss 27.1 8,336 1,080 3 173
brothers.cucina 19.0 3,531,735 184,724 1,891 25,423

Counts change between reads, so store the read time next to them.

What it costs

Each video is 2 credits, so the run above cost 12 credits and 1,000 videos cost 2,000. You get 100 free credits a month; $19 buys 10,000 credits that never expire, and plans for higher volume cover longer lists. Set your key and your first video is a CSV row in seconds.

To list one account's videos, see TikTok API get user videos; for the comments under a video, see TikTok API get comments. For the creator's exact followers and likes, see the TikTok user info 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.