Skip to content

Monitoring Hashtags

How exactly can we monitor hashtags on TikTok? Well, we need to find posts that use the hashtag we're interested in. You're in luck! The EnsembleData API provides two endpoints that allow you to do just that. The first is the Hashtag Search endpoint.

Hashtag Search API

API Documentation

Sample Response

Let's find some posts that use the hashtag magic.

import requests

result = requests.get(
    "https://ensembledata.com/apis/tt/hashtag/posts",
    params={
        "name": "magic",
        "cursor": 0,
        "token": "API_TOKEN",
    }
).json()["data"]

posts = result["data"]

# print(posts[0])
print("Number of posts:", len(posts))

# We'll need this later!
next_cursor = result["nextCursor"]
from ensembledata.api import EDClient

client = EDClient("API_TOKEN")
result = client.tiktok.hashtag_search(hashtag="magic", cursor=0)
posts = result.data["data"]

# print(posts[0])
print("Number of posts:", len(posts))   

# We'll need this later!
next_cursor = result.data.get("nextCursor")
const { EDClient } = require("ensembledata");

const client = new EDClient({ token: "API_TOKEN" });
let result = await client.tiktok.hashtagSearch({ hashtag: "magic" });
let posts = result.data.data;

// console.log(posts[0]);
console.log("Number of posts:", posts.length);

// We'll need this later!
let nextCursor = result.data.nextCursor;

Output:

Number of posts: 20

Excellent! We've got some posts that use the hashtag magic. But hang on, we got only got 20 posts, where are the rest? 😕

Indeed, we've only fetched the first batch of posts. Let's see how we can get the next batch of posts.

Cursor handling

We're going to need the help of our good friend, the cursor. To get the next batch of posts, we'll call the Hashtag Search API again but this time with the next cursor value we got from the previous request.

result = requests.get(
    "https://ensembledata.com/apis/tt/hashtag/posts",
    params={
        "name": "magic",
        "cursor": next_cursor,
        "token": "API_TOKEN",
    }
).json()["data"]

posts = result["data"]
next_cursor = result["nextCursor"]
result = client.tiktok.hashtag_search(hashtag="magic", cursor=next_cursor)
posts = result.data["data"]
next_cursor = result.data.get("nextCursor")
result = await client.tiktok.hashtagSearch({ 
    hashtag: "magic",
    cursor: nextCursor
});
posts = result.data.data; 
nextCursor = result.data.nextCursor;

You can continue this process until you've fetched all the available posts for this hashtag. You'll know you've fetched all the posts once there is no 'nextCursor' in the response.

Note

The maximum number of posts you can fetch for a given hashtag varies depending on the popularity of the hashtag. Very popular hashtags tend to have a maximum of 4000-5000 posts, while some hashtags may not have any posts at all.

Cursor handling example

Here's an example of how you could manually handle the cursor to fetch posts for a given hashtag.

posts = list()
cursor = 0

for _ in range(10):
    result = requests.get(
        "https://ensembledata.com/apis/tt/hashtag/posts",
        params={
            "name": "magic",
            "cursor": cursor,
            "token": "API_TOKEN",
        }
    ).json()["data"]
    posts.extend(result["data"])
    cursor = result.get("nextCursor", None)

    # If there is no next cursor, we've fetched all the available posts
    if cursor is None:
        break

print("Number of posts:", len(posts))
posts = list()
cursor = None

for _ in range(10):
    result = client.tiktok.hashtag_search(hashtag="magic", cursor=cursor)
    posts.extend(result.data["data"])
    cursor = result.data.get("nextCursor")

    # If there is no next cursor, we've fetched all the available posts
    if cursor is None:
        break

print("Number of posts:", len(posts))
let posts = [];
let cursor;

for (let i = 0; i < 10; i++) {
    result = await client.tiktok.hashtagSearch({ 
        hashtag: "magic",
        cursor,
    });
    posts.push(...result.data.data);
    cursor = result.data.nextCursor;

    // If there is no next cursor, we've fetched all the available posts
    if (cursor === undefined) {
        break;
    }
}

console.log("Number of posts:", posts.length);

Output:

Number of posts: 200

That works nicely! But what if I told you there's an easier way... 🤔

Read on traveller!

Full Hashtag Search API

API Documentation

Sample Response

Automatic cursor handling

The second endpoint is the Full Hashtag Search, whose functionality is a lot like it sounds. It fetches all the posts available for a given hashtag in one go. Under the hood, it uses the same Hashtag Search endpoint we used above, but it handles the cursor for you. Let's take a look.

result = requests.get(
    "https://ensembledata.com/apis/tt/hashtag/recent-posts",
    params={
        "name": "magic",
        "days": "100000",
        "token": "API_TOKEN",
    }
).json()["data"]

posts = result["posts"]
result = client.tiktok.full_hashtag_search(hashtag="magic")
posts = result.data["data"]
const result = await client.tiktok.fullHashtagSearch({ hashtag: "magic" })
const posts = result.data["data"]

That easy! ✨

Warning

The Full Hashtag Search API can take quite a long time to respond, due to all the requests it has to send internally. Make sure to set a high enough timeout (> 5 mins) if you are configuring your own HTTP requests. If you are using one of the EnsembleData API packages, this is handled for you!

Limiting the number of posts

You may not want to get all the posts, and for this reason the Full Hashtag Search API provides two extra parameters we can use to configure the request:

  1. max_cursor: tells the API to stop fetching posts after a certain cursor value.
  2. days: filters out posts older than the specified number of days.

Here we are fetching those that use the hashtag magic and are at most 30 days old within the first 2000 posts.

result = requests.get(
    "https://ensembledata.com/apis/tt/hashtag/recent-posts",
    params={
        "name": "magic",
        "max_cursor": 2000,
        "days": "30",
        "token": "API_TOKEN",
    }
).json()["data"]

posts = result["posts"]
print("Number of posts:", len(posts))
result = client.tiktok.full_hashtag_search(
    hashtag="magic",
    max_cursor=2_000,
    days=30
)
posts = result.data["data"]
print("Number of posts:", len(posts))
const result = await client.tiktok.fullHashtagSearch({
    hashtag: "magic",
    maxCursor: 2_000,
    days: 30
});
const posts = result.data["data"];
console.log("Number of posts:", posts.length);

Output:

Number of posts: 873

Warning

Pay close attention if using the max_cursor and the days parameters together. In this case the API will most likely return fewer posts than the specified max_cursor value. Only posts created within days number of days will be returned.