Answers

How do I get an AI daily report of what competitors posted on Xiaohongshu and Douyin?

Short answer

Keep a list of competitor account IDs, pull the first page of each account's posts once a day (Xiaohongshu $0.02 and Douyin $0.002 a page), keep what is new or growing since yesterday, and hand that to an LLM to summarize. Watching 10 accounts on each platform costs $0.22 a day.

A tea drinks brand watches ten rivals on Xiaohongshu and ten on Douyin. Today someone opens twenty profiles every Monday and copies numbers into a sheet, and by then a campaign that launched on Wednesday is old news. A daily job can do the opening and copying, and an LLM can write the three paragraphs the team actually reads: who posted what, which post took off, and whether a rival started a new campaign.

One-time setup: the account IDs

The list endpoints need each account's ID. Get it once from a profile link:

  • Xiaohongshu account profile takes a profile URL such as xiaohongshu.com/user/profile/5f12... and returns the ID, followers and note count.
  • Douyin account profile takes a profile URL or a v.douyin.com share link and returns the account's sec_uid (it starts with MS4wLjABAAAA), which is the ID Douyin uses.

Store the IDs in a file. That is {{cost:xiaohongshu.users.get10+douyin.users.get10}} for twenty accounts, once.

The daily pull

The first page covers several days of posting for almost any brand, so one call per account per day is enough.

Monitoring Calls a day Cost a day Cost for 30 days
10 Xiaohongshu + 10 Douyin accounts 20 {{cost:xiaohongshu.users.notes.list10+douyin.users.videos.list10}} {{cost:xiaohongshu.users.notes.list300+douyin.users.videos.list300}}
Plus a weekly follower check +20 a week — +{{cost:xiaohongshu.users.get40+douyin.users.get40}}

Code

import json, os, pathlib, requests

API = "https://api.okdata.online"
H = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}
RIVALS = {"xiaohongshu": ["5f1234567890abcdef123456"], "douyin": ["MS4wLjABAAAA..."]}
PATHS = {"xiaohongshu": "/v1/xiaohongshu/users/notes/list", "douyin": "/v1/douyin/users/videos/list"}
STATE = pathlib.Path("rivals.json")

before = json.loads(STATE.read_text()) if STATE.exists() else {}
now, report = {}, []
for platform, ids in RIVALS.items():
    for account in ids:
        body = requests.get(API + PATHS[platform], headers=H, timeout=60, params={
            "id": account, "fields": "id,url,title,text,published_at,metrics.likes,metrics.comments,author.name"}).json()
        if body["code"] != "ok":
            report.append(f"{platform} {account}: {body['code']}")
            continue
        for p in sorted(body["data"]["items"], key=lambda x: x["published_at"], reverse=True):
            likes = p["metrics"]["likes"] or 0
            now[p["id"]] = likes
            if p["id"] not in before:
                report.append(f"NEW {platform} {p['author']['name']}: {p['title'] or p['text'][:60]} ({likes} likes) {p['url']}")
            elif likes - before[p["id"]] > 1000:
                report.append(f"GROWING {platform} {p['author']['name']}: +{likes - before[p['id']]} likes {p['url']}")
STATE.write_text(json.dumps(now))
print("\n".join(report))  # hand these lines to your LLM with the brief

Then one LLM call: "These are yesterday's competitor posts. Summarize themes, flag any post growing fast, and note anything that looks like a new campaign or product." Post the result to a group chat or email.

Gotchas

  • Douyin profiles can pin older videos to the top, and they may come first in the list. Sort by published_at yourself, as the code does.
  • Xiaohongshu hides view counts, so metrics.views is null and listed in meta.unavailable. Compare likes, saves and comments instead.
  • Only public posts appear. Deleted posts simply vanish from the list.
  • The 1,000-like growth threshold is a placeholder; set it per account size.

Other ways

Coze or Feishu workflows that scrape with a pasted cookie work until the cookie expires; they suit a quick trial. Chinese analytics dashboards such as 千瓜 for Xiaohongshu or 蝉妈妈 for Douyin give charts, rankings and history without code, and are the better buy for a team that wants a dashboard more than a daily message. With three or four rivals, opening their profiles by hand each morning is honestly fine. More on this job: competitor monitoring.

Updated