TwoSec

TikTok hashtag API: videos and views for any hashtag

Look up any TikTok hashtag's total video and view counts, then pull the videos that use it, with plays, likes, comments, shares and the creator behind each one. Useful for picking hashtags, finding creators in a niche and benchmarking content.

Setup

You need Python 3, requests (pip install requests) and a key from the RapidAPI listing; the free plan's 100 requests are enough to try it. Put the key in an environment variable called RAPIDAPI_KEY.

import os
import time

import requests

BASE = "https://tiktok-video-creator-api.p.rapidapi.com"
HEADERS = {
    "X-RapidAPI-Key": os.environ["RAPIDAPI_KEY"],
    "X-RapidAPI-Host": "tiktok-video-creator-api.p.rapidapi.com",
}


def get(path, **params):
    """GET a path and return the JSON. Retries rate limits and upstream errors."""
    for attempt in range(4):
        response = requests.get(BASE + path, headers=HEADERS, params=params, timeout=30)
        if response.status_code in (429, 502, 503) and attempt < 3:
            time.sleep(2 ** attempt)
            continue
        response.raise_for_status()
        return response.json()

Hashtag counts

GET /v1/tiktok/hashtags/{name} takes the hashtag without # and is case-insensitive.

curl --request GET \
  --url 'https://tiktok-video-creator-api.p.rapidapi.com/v1/tiktok/hashtags/cosplay' \
  --header "X-RapidAPI-Key: $RAPIDAPI_KEY" \
  --header 'X-RapidAPI-Host: tiktok-video-creator-api.p.rapidapi.com'

Real response, cover link shortened

{
  "id": "33380",
  "name": "cosplay",
  "url": "https://www.tiktok.com/tag/cosplay",
  "description": "#Cosplay your favorite character, and show the world your power!",
  "cover": "https://p19-common-sign.tiktokcdn-eu.com/…",
  "stats": { "videos": 47846185, "views": 453906817449 }
}

An unknown hashtag returns 404.

Compare hashtags

One request per hashtag gives you its size. Views per video is a rough measure of how much attention each post under the tag gets:

for tag in ["cosplay", "cosplaygirl", "anime", "costume"]:
    try:
        info = get(f"/v1/tiktok/hashtags/{tag}")
    except requests.HTTPError as err:
        print(tag, "not found" if err.response.status_code == 404 else err)
        continue
    s = info["stats"]
    per_video = s["views"] // max(s["videos"], 1)
    print(f'#{tag:<14} {s["videos"]:>12,} videos {s["views"]:>17,} views {per_video:>8,} per video')

The line for #cosplay, from the response above

#cosplay          47,846,185 videos   453,906,817,449 views    9,486 per video

Videos for a hashtag

GET /v1/tiktok/hashtags/{name}/videos returns about 30 videos per page, in TikTok's order.

curl --request GET \
  --url 'https://tiktok-video-creator-api.p.rapidapi.com/v1/tiktok/hashtags/cosplay/videos' \
  --header "X-RapidAPI-Key: $RAPIDAPI_KEY" \
  --header 'X-RapidAPI-Host: tiktok-video-creator-api.p.rapidapi.com'

Real response, shortened to one video, media links shortened

{
  "hashtag": "cosplay",
  "hashtag_id": "33380",
  "count": 1,
  "has_more": true,
  "next_cursor": "MzA6MzMzODA",
  "videos": [
    {
      "id": "7689617214588177684",
      "url": "https://www.tiktok.com/@ramenshelz/video/7689617214588177684",
      "description": "Look at ME transition!! 👀🖤 #fyp #hairstyle #hairinspo #fitcheck #transition ",
      "created_at": "2026-09-25T23:22:11Z",
      "duration": 7,
      "width": 576,
      "height": 1024,
      "is_photo_post": false,
      "is_pinned": false,
      "is_ad": false,
      "cover": "https://p16-common-sign.tiktokcdn-eu.com/…",
      "dynamic_cover": "https://p16-common-sign.tiktokcdn-eu.com/…",
      "play_url": "https://v16-webapp-prime.tiktok.com/…",
      "images": [],
      "hashtags": ["fyp", "hairstyle", "hairinspo", "fitcheck", "transition"],
      "stats": { "plays": 5682, "likes": 1430, "comments": 27, "shares": 37, "bookmarks": 176 },
      "author": {
        "id": "6548975542870507530",
        "username": "ramenshelz",
        "nickname": "Shelz",
        "avatar": "https://p19-common-sign.tiktokcdn-eu.com/…",
        "verified": false,
        "sec_uid": "MS4wLjABAAAAfN_R8oQcdK8Z30zK9kwiU2laZjEGyqJTkDrgnI0u7RdbgITPEnCcekAEXBOvQZIA",
        "url": "https://www.tiktok.com/@ramenshelz",
        "stats": { "followers": 79600, "following": 123, "likes": 1800000, "videos": 195, "friends": 0 }
      },
      "music": {
        "id": "7253890704814951174",
        "title": "Ashley look at me Mal Bertha Oficial",
        "author": "Mal Bertha Oficial",
        "original": true,
        "duration": 8,
        "cover": "https://p16-common-sign.tiktokcdn-eu.com/…",
        "play_url": "https://v45.tiktokcdn-eu.com/…"
      }
    }
  ]
}

hashtags lists the tags TikTok parsed from the description, which isn't always the full set a video is filed under; this one came from the #cosplay feed without cosplay in its description.

def hashtag_videos(tag, max_pages=5):
    videos, params = {}, {}
    for _ in range(max_pages):
        data = get(f"/v1/tiktok/hashtags/{tag}/videos", **params)
        for v in data.get("videos") or []:
            videos[v["id"]] = v
        if not data.get("has_more") or not data.get("next_cursor"):
            break
        params = {"cursor": data["next_cursor"]}
    return list(videos.values())


videos = hashtag_videos("cosplay")

Rank by engagement

Engagement rate here is likes, comments, shares and bookmarks divided by plays. It shows which posts hold attention, independent of the creator's size:

def engagement(v):
    s = v["stats"]
    return (s["likes"] + s["comments"] + s["shares"] + s["bookmarks"]) / max(s["plays"], 1)


for v in sorted(videos, key=engagement, reverse=True)[:10]:
    followers = (v["author"].get("stats") or {}).get("followers", 0)
    print(f'{engagement(v):.1%}  {v["stats"]["plays"]:>9,} plays  '
          f'@{v["author"]["username"]} ({followers:,} followers)  {v["url"]}')

The line for the video above

29.4%      5,682 plays  @ramenshelz (79,600 followers)  https://www.tiktok.com/@ramenshelz/video/7689617214588177684

To list the creators active in a hashtag, collect v["author"] from each video and sort by follower count; then pull their own videos.

Things to know

Next steps

Plans

Hashtag info is one request; each page of about 30 videos is one request. A free plan covers testing. Plans, monthly quotas and rate limits are listed on the RapidAPI listing. For more volume or a custom plan, use Contact provider on the listing.