Blog/Tutorials//Updated

Douyin User Search API: Python & cURL Creator Search (2026)

Douyin user search API tutorial: find creators by keyword with the SandBase Model API in cURL and Python, with a dated live test and pagination notes.

douyin-user-search-api-tutorial-2026 cover

Douyin User Search API: Find Creators by Keyword

Key takeaway — douyin/search/user-search-v2 searches public Douyin creator accounts by keyword through POST /v1/api/douyin/search/user-search-v2, with only keyword and cursor in the body. In the 2026-10-01 tests each page returned 30 accounts, and pages can overlap, so follow cursor while has_more is true and deduplicate by user_id. The catalog listed the endpoint as Free as of 2026-10-01.

Need to find Douyin creators in a specific niche? Whether you’re building a KOL discovery tool, monitoring competitors, or automating social media research, the Douyin User Search API through SandBase lets you search public Douyin creator accounts by keyword from your own code.

In this tutorial, you’ll learn how to call the endpoint, parse the response, and integrate it into real workflows, with curl and Python examples tested on 2026-10-01 (UTC).

Why Search Douyin Users by API?

Douyin (the Chinese counterpart of TikTok) has a very large creator base, and manually searching for creators through the app is tedious and doesn’t scale. An API-based approach lets you:

  • Discover KOLs (Key Opinion Leaders): Find influencers in any niche (beauty, tech, food, fitness) by searching relevant keywords.
  • Monitor competitors: Re-run keyword searches to see which accounts show up for your brand or category over time.
  • Build social listening tools: Automate the discovery of creators talking about your brand or industry.
  • Power marketing automation: Feed creator data into your CRM or outreach tools for partnership campaigns.
  • Conduct market research: Understand who the visible voices are in a category on Douyin.

What is SandBase?

SandBase is a unified API gateway that aggregates many social media and data APIs under one consistent interface. Instead of dealing with different authentication methods and response formats for each platform, you call one endpoint with one API key.

For Douyin, the SandBase Douyin catalog lists 262 endpoints as of 2026-10-01, including user search, video search, and creator profiles, all callable through POST https://api.sandbase.ai/v1/api/<model> with one API key.

SandBase Douyin API catalog page showing Douyin Endpoints with the 262 SHOWN counter and an endpoint marked Available and Free

Caption: The SandBase Douyin catalog shows “262 SHOWN” endpoints, which is the source of the endpoint count above (captured 2026-10-02).

Scope: public, read-only data

This workflow returns public, read-only Douyin data. It needs a SandBase API key, and SandBase is not an official Douyin partner. It does not give you private-account data, DMs, owner-only analytics, or any publishing, messaging, or account actions.

SandBase user-search-v2Douyin Open Platform (open.douyin.com)
AuthenticationOne SandBase API keyDeveloper app plus user/account authorization
Access scopePublic creator search resultsAuthorized, account-linked workflows
Typical useKeyword creator discovery and researchApps acting on behalf of authorized Douyin users

Prerequisites

Before you start, you’ll need:

  1. A SandBase account: Sign up at sandbase.ai
  2. An API key: Generate one from your SandBase dashboard
  3. Credits: SandBase uses a credit system; as of 2026-10-01 the catalog lists douyin/search/user-search-v2 as Free.

For this endpoint you don’t register a Douyin developer app or implement a Douyin OAuth flow; the SandBase API key is the only credential in the request.

API Overview

Here’s the key information for keyword creator search on Douyin:

ParameterValue
Endpointhttps://api.sandbase.ai/v1/api/douyin/search/user-search-v2
MethodPOST
Modeldouyin/search/user-search-v2
AuthenticationBearer token (your SandBase API key)
Inputkeyword (string), cursor (integer, 0 for the first page)
OutputA page of matching creator accounts

Open the user-search-v2 API reference for the full request schema. This is the Model API POST /v1/api/... route from the endpoint reference, not the catalog’s GET /apis/v1/... listing. The request schema has only keyword and cursor; there is no result-count parameter, so you slice locally.

SandBase API reference for douyin/search/user-search-v2 showing POST /v1/api/douyin/search/user-search-v2 with optional cursor and keyword fields

Caption: The user-search-v2 reference documents POST /v1/api/douyin/search/user-search-v2 with just two body fields, cursor (0 for the first page) and keyword (captured 2026-10-02).

If you already know a creator’s name or Douyin ID, douyin/creator/user-search (required user_name) is a lighter lookup. On 2026-10-01 I called it with {"user_name": "人民日报"} (the People’s Daily media account; run id db1e6236-5baf-43b4-824e-d14c557ce9de). It returned user_infos[] with only avatar, nick_name, short_id, and a numeric-string user_id (first entry: 人民日报, short_id rmrbxmt), with no follower counts. That’s why this tutorial uses user-search-v2 for keyword discovery.

SandBase API reference page for douyin/creator/user-search, the name/ID lookup with a single required User Name input

Caption: The douyin/creator/user-search reference takes a single required user_name, the lighter name/ID lookup described above; this image predates the 2026-10-02 captures.

In my user-search-v2 runs on 2026-10-01, each result carried (among other fields):

  • nick_name: display name
  • fans_cnt: follower count
  • like_cnt: total likes received
  • publish_cnt: number of posts
  • avatar_url: avatar image
  • user_id: a value in sec_user_id format (MS4wLjABAAAA...), usable in profile and post-list calls

These field names are observed-only, not documented guarantees. Bios and verification labels did not appear in these results.

Step 1: Your First API Call (curl)

Let’s search for Douyin creators related to 咖啡 (coffee):

curl -X POST https://api.sandbase.ai/v1/api/douyin/search/user-search-v2 \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $SANDBASE_API_KEY" \
  -d '{"keyword": "咖啡", "cursor": 0}'

Understanding the Response

Tested on 2026-10-01 (UTC) with the generic keyword for coffee: the request above returned HTTP 200, status: completed, and one page of 30 accounts (run id c3e55399-822e-4fa4-83ac-42aba82f93b2). The endpoint reference documents the payload under outputs[0].data. Inside it, this endpoint wrapped results in one more data key next to code and message. Real response, trimmed to the first result and six of its fields:

{
  "id": "c3e55399-822e-4fa4-83ac-42aba82f93b2",
  "status": "completed",
  "model": "douyin/search/user-search-v2",
  "outputs": [
    {
      "data": {
        "code": 0,
        "message": "",
        "data": {
          "cursor": 30,
          "has_more": true,
          "user_list": [
            {
              "nick_name": "咖啡",
              "fans_cnt": 2803302,
              "like_cnt": 20239511,
              "publish_cnt": 381,
              "avatar_url": "https://p26.douyinpic.com/aweme/100x100/aweme-avatar/...",
              "user_id": "MS4wLjABAAAA..."
            }
          ]
        }
      }
    }
  ]
}

The payload fields are observed in this run, not a documented schema. To get the next page, I sent the returned cursor as the next request’s cursor while has_more was true. In my test for 护肤 (skincare) on 2026-10-01, page 1 (cursor: 0) and page 2 (cursor: 30) each returned 30 accounts, and one account appeared on both pages (runs be6a6551-9d72-4c38-b629-5ac1cf2ed33c, 7edbfcce-79ca-45d6-a911-374351ffdd84). Deduplicate by user_id when you merge pages.

Step 2: Python Integration

For production use, here’s a clean Python implementation:

import requests


class DouyinUserSearch:
    """Search Douyin creators through the SandBase Model API."""

    def __init__(self, api_key: str):
        self.api_key = api_key
        self.endpoint = "https://api.sandbase.ai/v1/api/douyin/search/user-search-v2"

    def search_page(self, keyword: str, cursor: int = 0) -> dict:
        """Fetch one page of results. Returns the inner payload
        ({"cursor", "has_more", "user_list"} in my runs)."""
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.api_key}",
        }
        payload = {"keyword": keyword, "cursor": cursor}

        response = requests.post(self.endpoint, headers=headers, json=payload, timeout=60)
        response.raise_for_status()
        body = response.json()

        outputs = body.get("outputs") or []
        if body.get("status") != "completed" or not outputs:
            raise RuntimeError(f"SandBase call did not complete: {body.get('status')} {body.get('error')}")
        data = outputs[0].get("data") or {}
        return data.get("data") or {}

    def search(self, keyword: str, count: int = 10) -> list[dict]:
        """Return up to `count` unique creators, following `cursor` while `has_more` is true."""
        users, seen, cursor = [], set(), 0
        while len(users) < count:
            page = self.search_page(keyword, cursor)
            for user in page.get("user_list") or []:
                if user.get("user_id") not in seen:
                    seen.add(user.get("user_id"))
                    users.append(user)
            if not page.get("has_more") or page.get("cursor") is None:
                break
            cursor = page["cursor"]
        return users[:count]


# Usage
api_key = "your_sandbase_api_key_here"
client = DouyinUserSearch(api_key)

# Search for coffee-related creators
users = client.search("咖啡", count=10)

for user in users:
    print(f"Name: {user.get('nick_name')}")
    print(f"Followers: {user.get('fans_cnt', 0):,}")
    print(f"Posts: {user.get('publish_cnt')}")
    print(f"sec_user_id: {user.get('user_id')}")
    print("---")

Adding Error Handling

For production systems, add retry logic and proper error handling:

import time
from typing import Optional

def search_with_retry(
    client: DouyinUserSearch,
    keyword: str,
    count: int = 10,
    max_retries: int = 3
) -> Optional[list]:
    """Search with exponential backoff retry."""
    for attempt in range(max_retries):
        try:
            return client.search(keyword, count)
        except requests.exceptions.HTTPError as e:
            if e.response.status_code == 429:
                wait_time = 2 ** attempt
                print(f"Rate limited. Retrying in {wait_time}s...")
                time.sleep(wait_time)
            else:
                raise
        except requests.exceptions.RequestException as e:
            print(f"Request failed: {e}")
            if attempt < max_retries - 1:
                time.sleep(2 ** attempt)
    return None

Step 3: Practical Use Cases

Use Case 1: KOL Discovery for Marketing Campaigns

Find top creators in the skincare niche and filter by follower count:

users = client.search("护肤", count=60)

# Filter for mid-tier influencers (100K-500K followers)
mid_tier_kols = [
    user for user in users
    if 100_000 <= user.get("fans_cnt", 0) <= 500_000
]

print(f"Found {len(mid_tier_kols)} mid-tier skincare KOLs")
for kol in mid_tier_kols:
    print(f"  {kol.get('nick_name')} — {kol.get('fans_cnt', 0):,} followers")

Use Case 2: Competitor Monitoring

Track accounts related to your brand or competitors:

competitors = ["品牌A", "品牌B", "品牌C"]

for brand in competitors:
    users = client.search(brand, count=5)
    print(f"\n{brand}: Found {len(users)} related accounts")
    for user in users:
        print(f"  @{user.get('nick_name')} ({user.get('fans_cnt', 0):,} followers)")

Use Case 3: Building a Social Monitoring Agent

Combine creator keyword search with an AI agent framework to build automated social intelligence:

# Pseudocode for an AI agent workflow
keywords = ["你的品牌名", "行业关键词", "竞品名称"]

for keyword in keywords:
    creators = client.search(keyword, count=10)

    # Store results in your database
    for creator in creators:
        save_to_db(creator)  # key on creator["user_id"]

    # Alert if new high-follower accounts appear
    new_accounts = filter_new_accounts(creators)
    if new_accounts:
        send_alert(f"New accounts found for '{keyword}': {new_accounts}")

Combining with Other SandBase APIs

You can combine several search endpoints for cross-platform research. Key fields only; open each reference for the full request schema:

PlatformAPI ModelKey fieldsUse Case
Douyin User Searchdouyin/search/user-search-v2keyword, cursorFind creators
Douyin Video Searchdouyin/search/video-search-v2keyword, cursor (plus optional filters)Find content by keyword
Xiaohongshu Note Searchxiaohongshu/app-v2/search-noteskeyword, page (plus optional fields)Cross-platform research
Weibo User Searchweibo/web-v2/user-searchquery, page (plus optional filters)Find matching Weibo accounts

Each of these returned non-empty results for the coffee keyword in my runs on 2026-10-01 (runs a102bf5b-61bf-42ac-803a-da55633a38e6, 846c4b40-b260-401c-ac2f-254175315626, 4e4e6cf4-9170-49f2-aa42-efd1e0be090d). Their payload shapes differ, so check each reference before parsing.

The user_id from search results is a sec_user_id, which douyin/web/user-profile and douyin/web/user-post-videos accept. Those downstream endpoints have their own conditions (the post-list reference notes the Web API can be unstable and accepts an optional user cookie), so check each reference rather than assuming they behave like user-search-v2.

For more details on Douyin data APIs, check out our guide on Douyin Data API on SandBase. If you’re building AI agents that consume social data, read Social Media Data APIs for AI Agents in 2026.

Pricing and Rate Limits

SandBase meters usage per call against your credit balance, and you can check credit usage in the dashboard. As of 2026-10-01, the catalog lists douyin/search/user-search-v2 as Free, and the model page shows the same:

SandBase model page for douyin/search/user-search-v2 showing Base price Free, sync execution and two input fields

Caption: The douyin/search/user-search-v2 model page lists Base price Free, sync execution and 2 input fields (captured 2026-10-02).

See the SandBase pricing page for current plans. If you get HTTP 429, back off and retry as shown above.

Tips for Best Results

  1. Try Chinese keywords first: Douyin’s audience is mostly Chinese-speaking, so Chinese keywords are a sensible starting point; compare against English terms for your niche.
  2. Be specific: A narrower keyword like 精品咖啡 (specialty coffee) tends to give a more targeted list than 咖啡 (coffee).
  3. Combine searches: Run multiple searches with related keywords to build a comprehensive list.
  4. Cache results: If you don’t need fresh numbers on every run, cache results and refresh them on a schedule that fits your use case.
  5. Respect rate limits: Implement backoff logic to handle 429 responses gracefully.

Summary

SandBase’s user-search-v2 endpoint gives you a simple way to search public Douyin creator accounts by keyword. With one API call per page, you can:

  • Find relevant KOLs for marketing campaigns
  • Monitor which accounts appear for competitor keywords
  • Build automated social listening tools
  • Feed public creator data into AI agents

Get started by signing up for SandBase, then open the user-search-v2 API reference and make your first call.