August 28, 2025
939 Views
Default

Руководство по использованию API TikHub 小红书

TikHub предоставляет три типа интерфейсов Xiaohongshu: App, Web v2 и старую версию Web, среди которых серия App является самой стабильной, а серия Web v2 — самой быстро исправляемой. В этой статье подробно рассматриваются функции, приоритеты и лучшие практики каждого интерфейса, чтобы помочь вам выбрать самый стабильный и надёжный интерфейс и повысить эффективность сбора данных.

Руководство по использованию XHS (小红书)

Документация по API Xiaohongshu, составленная на основе TikHub OpenAPI (https://api.tikhub.io).

Содержание


Общие сведения

a. Стратегия вызова: использование нескольких серий в комбинации (важно)

На данный момент интерфейсы Xiaohongshu наиболее стабильны в серии App V2. Настоятельно рекомендуется всем пользователям использовать стратегию сочетания "основная серия + 1~2 резервные серии", комбинируя 2~3 серии, чтобы повысить общую доступность бизнеса.

b. Приоритет вызова: App V2 (рекомендуется) > App V1 (резерв) > Web V3 (третья альтернатива)

App V2 — основная рекомендуемая серия, на данный момент самая стабильная и с наиболее полными данными, рекомендуется как первый выбор; App V1 по составу полей близка к App V2 и подходит как первый резервный вариант; Web V3 — это третий альтернативный веб-канал, открытый для корпоративных пользователей, требует xsec_token (можно извлечь из ссылки на публикацию), но возвращает меньше измерений данных, чем App V2 / App V1, поэтому даже корпоративным пользователям рекомендуется разумно сочетать несколько серий, а не использовать только Web V3; Web V2 / Web поддерживает лишь небольшую часть интерфейсов, стабильность также не гарантируется, поэтому не рекомендуется как основной вариант и подходит только как дополнение, если первые три серии не удовлетворяют требованиям.

c. Краткая рекомендация: не делайте ставку только на одну серию. В production рекомендуется как минимум настроить 2 серии в режиме основной/резервной; при использовании Web V3 корпоративным пользователям следует дополнительно сочетать его с App V2 / App V1 для восполнения измерений данных.

d. Подсказка по возвращаемым полям: Интерфейсы серии App (App V2 / App V1) имеют похожую структуру, названия полей в основном можно сопоставить друг с другом; однако JSON-структуры интерфейсов серии Web (Web V3 / Web V2 / Web) различаются, имена полей, уровни вложенности и измерения данных могут отличаться, поэтому перед использованием обязательно сначала посмотрите фактические поля JSON-ответа каждого интерфейса, а затем выполняйте разбор и сопоставление.


1. Одна заметка

Заметки Xiaohongshu делятся на два типа: текстово-графические заметки (заметки с изображениями) и видео-заметки. Серия App V2 предоставляет отдельные эндпоинты для обоих типов, с наиболее полными данными; Web V3 обрабатывает оба типа через один и тот же интерфейс, различая их по полям ответа.

Общая рекомендация: в первую очередь используйте серию App V2; корпоративные пользователи в сценариях, где можно получить xsec_token, могут сочетать её с Web V3.

Комплексный пример: получение деталей одной заметки с использованием трёх серий

Ниже приведён пример кода, демонстрирующий логику комбинированного вызова основная серия (App V2) → резерв 1 (App V1) → резерв 2 (Web V3), с последовательными попытками по приоритету: если предыдущий вызов успешен, сразу возвращается результат, при неудаче выполняется переход к следующему.

python
1import requests
2
3BASE_URL = "https://api.tikhub.io"
4HEADERS = {
5    "Authorization": "Bearer YOUR_API_KEY",
6    "accept": "application/json",
7}
8
9NOTE_ID = "697c0eee000000000a03c308"
10XSEC_TOKEN = "ABxxxxxxxxxxxxxx"   # Required for Web V3, extract from share link / Web V3 需要,可从分享链接抽取
11IS_VIDEO = False                  # Note type: True=video note, False=image note / 笔记类型:True=视频笔记,False=图文笔记
12
13
14# --- Primary: App V2 / 主系列:App V2 ---
15def fetch_by_app_v2(note_id: str, is_video: bool):
16    if is_video:
17        path = "/api/v1/xiaohongshu/app_v2/get_video_note_detail"
18    else:
19        path = "/api/v1/xiaohongshu/app_v2/get_image_note_detail"
20    return requests.get(f"{BASE_URL}{path}", headers=HEADERS,
21                        params={"note_id": note_id})
22
23
24# --- Fallback 1: App V1 (image notes only; no video download URL, not recommended for videos) / 备用 1:App V1(仅图文有效,视频不含下载链接,不建议用于视频)---
25def fetch_by_app_v1(note_id: str):
26    path = "/api/v1/xiaohongshu/app/get_note_info"
27    return requests.get(f"{BASE_URL}{path}", headers=HEADERS,
28                        params={"note_id": note_id})
29
30
31# --- Fallback 2: Web V3 (enterprise users only, requires xsec_token) / 备用 2:Web V3(企业用户专用,需要 xsec_token)---
32def fetch_by_web_v3(note_id: str, xsec_token: str):
33    path = "/api/v1/xiaohongshu/web_v3/fetch_note_detail"
34    return requests.get(f"{BASE_URL}{path}", headers=HEADERS,
35                        params={"note_id": note_id, "xsec_token": xsec_token})
36
37
38# --- Try all three series in order / 三系列依次尝试 ---
39def get_note_detail(note_id: str, xsec_token: str, is_video: bool):
40    # 1) Primary: App V2 / 主系列:App V2
41    try:
42        r = fetch_by_app_v2(note_id, is_video)
43        if r.ok and r.json().get("code") == 200:
44            return {"source": "app_v2", "data": r.json()}
45    except Exception as e:
46        print("App V2 调用失败:", e)
47
48    # 2) Fallback 1: App V1 (skip this step for video notes) / 备用 1:App V1(视频笔记建议跳过此步)
49    if not is_video:
50        try:
51            r = fetch_by_app_v1(note_id)
52            if r.ok and r.json().get("code") == 200:
53                return {"source": "app_v1", "data": r.json()}
54        except Exception as e:
55            print("App V1 调用失败:", e)
56
57    # 3) Fallback 2: Web V3 / 备用 2:Web V3
58    try:
59        r = fetch_by_web_v3(note_id, xsec_token)
60        if r.ok and r.json().get("code") == 200:
61            return {"source": "web_v3", "data": r.json()}
62    except Exception as e:
63        print("Web V3 调用失败:", e)
64
65    return None
66
67
68result = get_note_detail(NOTE_ID, XSEC_TOKEN, IS_VIDEO)
69print(result)

Подсказка: проверка успешности выше (code == 200) приведена как пример; в реальности следует проверять по JSON-полям, возвращаемым каждой серией; структуры ответов у разных серий не совпадают, поэтому рекомендуется для каждой серии писать отдельную логику разбора.

1.1 Заметка с изображениями (текстово-графическая заметка)

1.1.1 [App V2] Получить подробности текстово-графической заметки ⭐ Рекомендуется

Получить полные данные о текстово-графической заметке (адреса изображений, заголовок, основной текст, теги, данные взаимодействия и т. д.).

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app_v2/get_image_note_detail
  • Официальная документация: docs.tikhub.io/420136391e0
  • Параметры:
    • note_id (string, необязательно): ID заметки, например "697c0eee000000000a03c308"
    • share_text (string, необязательно): ссылка на публикацию Xiaohongshu (поддерживаются APP / Web)
    • Один из двух; приоритет у note_id; если переданы оба, используется note_id
python
1import requests
2
3BASE_URL = "https://api.tikhub.io"
4HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}
5
6url = f"{BASE_URL}/api/v1/xiaohongshu/app_v2/get_image_note_detail"
7params = {
8    "note_id": "697c0eee000000000a03c308",
9    # "share_text": "https://www.xiaohongshu.com/discovery/item/...",
10}
11r = requests.get(url, headers=HEADERS, params=params)
12print(r.json())

1.1.2 [App V1] Получить информацию о заметке V1 (только текстово-графическая, без ссылки на скачивание видео)

Интерфейс заметок App V1 подходит только для текстово-графических заметок. В ответе нет ссылки на скачивание видео, поэтому не используйте его для видео-заметок; для видео-заметок используйте get_video_note_detail из App V2.

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app/get_note_info
  • Официальная документация: docs.tikhub.io/310965839e0
  • Параметры:
    • note_id (string, необязательно)
    • share_text (string, необязательно)
    • Один из двух, приоритет у note_id
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/app/get_note_info"
2params = {
3    "note_id": "697c0eee000000000a03c308",
4}
5r = requests.get(url, headers=HEADERS, params=params)
6print(r.json())

1.1.3 [Web V3] Получить подробности заметки (универсально для текста/видео)

Эндпоинт Web V3, универсален для текстово-графических и видео-заметок. Требуется xsec_token (извлекается из ссылки на публикацию, см. выше раздел «Инструменты-спутники»).

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/web_v3/fetch_note_detail
  • Официальная документация: docs.tikhub.io/438852168e0
  • Параметры:
    • note_id (string, обязательно)
    • xsec_token (string, обязательно)
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/web_v3/fetch_note_detail"
2params = {
3    "note_id": "697c0eee000000000a03c308",
4    "xsec_token": "ABxxxxxxxxxxxxxx",
5}
6r = requests.get(url, headers=HEADERS, params=params)
7print(r.json())

1.2 Видео-заметка

Для видео-заметок не используйте get_note_info из App V1, в ответе этого интерфейса нет ссылки на скачивание видео. Используйте App V2 или Web V3 ниже.

1.2.1 [App V2] Получить подробности видео-заметки ⭐ Рекомендуется

Получить полные данные о видео-заметке (адрес видео, обложка, длительность, заголовок, основной текст, данные взаимодействия и т. д.).

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app_v2/get_video_note_detail
  • Официальная документация: docs.tikhub.io/420136392e0
  • Параметры:
    • note_id (string, необязательно): например "697c0eee000000000a03c308"
    • share_text (string, необязательно)
    • Один из двух, приоритет у note_id
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/app_v2/get_video_note_detail"
2params = {
3    "note_id": "697c0eee000000000a03c308",
4    # "share_text": "https://www.xiaohongshu.com/discovery/item/...",
5}
6r = requests.get(url, headers=HEADERS, params=params)
7print(r.json())

1.2.2 [Web V3] Получить подробности заметки (универсально для видео)

Тот же эндпоинт, что и для текстово-графических заметок; вызывать достаточно с note_id + xsec_token.

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/web_v3/fetch_note_detail
  • Официальная документация: docs.tikhub.io/438852168e0
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/web_v3/fetch_note_detail"
2params = {
3    "note_id": "697c0eee000000000a03c308",
4    "xsec_token": "ABxxxxxxxxxxxxxx",
5}
6r = requests.get(url, headers=HEADERS, params=params)
7print(r.json())

2. Информация о пользователе

Через user_id можно получить публичный профиль пользователя Xiaohongshu (никнейм, аватар, описание, число подписчиков, число подписок, число заметок и т. д.). Все три серии предоставляют интерфейс информации о пользователе; App V2 даёт наиболее полный набор полей, App V1 / Web V3 подходят как резерв.

Общая рекомендация: в первую очередь используйте серию App V2; при наличии только user_id можно также использовать App V1 / Web V3.

💡 Не знаете, как получить user_id? Можно сначала использовать этот интерфейс-инструмент /api/v1/xiaohongshu/app/get_user_id_and_xsec_token (официальная документация), передав туда любую ссылку на страницу профиля пользователя Xiaohongshu (подойдёт и длинная, и короткая ссылка), и он извлечёт user_id и xsec_token, после чего их можно передать в интерфейс информации о пользователе ниже. См. ниже 2.3.

Комплексный пример: получение информации о пользователе с использованием трёх серий

Ниже приведён пример кода, демонстрирующий логику комбинированного вызова основная серия (App V2) → резерв 1 (App V1) → резерв 2 (Web V3), с последовательными попытками по приоритету: если предыдущий вызов успешен, сразу возвращается результат, при неудаче выполняется переход к следующему.

python
1import requests
2
3BASE_URL = "https://api.tikhub.io"
4HEADERS = {
5    "Authorization": "Bearer YOUR_API_KEY",
6    "accept": "application/json",
7}
8
9USER_ID = "61b46d790000000010008153"
10
11
12# --- Primary: App V2 / 主系列:App V2 ---
13def fetch_user_by_app_v2(user_id: str):
14    path = "/api/v1/xiaohongshu/app_v2/get_user_info"
15    return requests.get(f"{BASE_URL}{path}", headers=HEADERS,
16                        params={"user_id": user_id})
17
18
19# --- Fallback 1: App V1 / 备用 1:App V1 ---
20def fetch_user_by_app_v1(user_id: str):
21    path = "/api/v1/xiaohongshu/app/get_user_info"
22    return requests.get(f"{BASE_URL}{path}", headers=HEADERS,
23                        params={"user_id": user_id})
24
25
26# --- Fallback 2: Web V3 / 备用 2:Web V3 ---
27def fetch_user_by_web_v3(user_id: str):
28    path = "/api/v1/xiaohongshu/web_v3/fetch_user_info"
29    return requests.get(f"{BASE_URL}{path}", headers=HEADERS,
30                        params={"user_id": user_id})
31
32
33# --- Try all three series in order / 三系列依次尝试 ---
34def get_user_info(user_id: str):
35    # 1) Primary: App V2 / 主系列:App V2
36    try:
37        r = fetch_user_by_app_v2(user_id)
38        if r.ok and r.json().get("code") == 200:
39            return {"source": "app_v2", "data": r.json()}
40    except Exception as e:
41        print("App V2 调用失败:", e)
42
43    # 2) Fallback 1: App V1 / 备用 1:App V1
44    try:
45        r = fetch_user_by_app_v1(user_id)
46        if r.ok and r.json().get("code") == 200:
47            return {"source": "app_v1", "data": r.json()}
48    except Exception as e:
49        print("App V1 调用失败:", e)
50
51    # 3) Fallback 2: Web V3 / 备用 2:Web V3
52    try:
53        r = fetch_user_by_web_v3(user_id)
54        if r.ok and r.json().get("code") == 200:
55            return {"source": "web_v3", "data": r.json()}
56    except Exception as e:
57        print("Web V3 调用失败:", e)
58
59    return None
60
61
62result = get_user_info(USER_ID)
63print(result)

Подсказка: проверка успешности выше (code == 200) приведена как пример; в реальности следует проверять по JSON-полям, возвращаемым каждой серией; структуры ответов у разных серий не совпадают, поэтому рекомендуется для каждой серии писать отдельную логику разбора.

2.1 [App V2] Получить информацию о пользователе ⭐ Рекомендуется

Получить подробную информацию о заданном пользователе, включая никнейм, аватар, описание, число подписчиков, число подписок, число заметок и т. д.

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app_v2/get_user_info
  • Официальная документация: docs.tikhub.io/420136395e0
  • Параметры:
    • user_id (string, необязательно): ID пользователя, например "61b46d790000000010008153"
    • share_text (string, необязательно): ссылка на профиль пользователя Xiaohongshu (поддерживаются APP / Web)
    • Один из двух; приоритет у user_id; если переданы оба, используется user_id
python
1import requests
2
3BASE_URL = "https://api.tikhub.io"
4HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}
5
6url = f"{BASE_URL}/api/v1/xiaohongshu/app_v2/get_user_info"
7params = {
8    "user_id": "61b46d790000000010008153",
9    # "share_text": "https://www.xiaohongshu.com/user/profile/...",
10}
11r = requests.get(url, headers=HEADERS, params=params)
12print(r.json())

2.2 [App V1] Получить информацию о пользователе

Интерфейс информации о пользователе App V1.

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app/get_user_info
  • Официальная документация: docs.tikhub.io/310965845e0
  • Параметры:
    • user_id (string, обязательно)
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/app/get_user_info"
2params = {
3    "user_id": "61b46d790000000010008153",
4}
5r = requests.get(url, headers=HEADERS, params=params)
6print(r.json())

2.3 [App V1] Инструмент-спутник: извлечь user_id и xsec_token из ссылки на профиль пользователя

Если у вас есть только ссылка на страницу профиля пользователя (поддерживаются и длинные, и короткие ссылки), можно сначала использовать этот интерфейс, чтобы извлечь user_id и xsec_token, а затем вызвать интерфейс информации о пользователе выше.

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app/get_user_id_and_xsec_token
  • Официальная документация: docs.tikhub.io/364605901e0
  • Параметры:
    • share_link (string, обязательно): ссылка на профиль пользователя Xiaohongshu
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/app/get_user_id_and_xsec_token"
2params = {
3    "share_link": "https://xhslink.com/m/xxxxx",
4}
5r = requests.get(url, headers=HEADERS, params=params)
6print(r.json())
7# Example response fields / 返回示例字段:
8# {
9#   "data": {
10#       "user_id": "61b46d790000000010008153",
11#       "xsec_token": "ABxxxxxxxxxxxxxx"
12#   }
13# }

2.4 [Web V3] Получить информацию о пользователе

Интерфейс публичного профиля пользователя Web V3, требуется только user_id.

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/web_v3/fetch_user_info
  • Официальная документация: docs.tikhub.io/438852177e0
  • Параметры:
    • user_id (string, обязательно)
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/web_v3/fetch_user_info"
2params = {
3    "user_id": "61b46d790000000010008153",
4}
5r = requests.get(url, headers=HEADERS, params=params)
6print(r.json())

3. Работы пользователя

Получить список заметок, опубликованных этим пользователем, по user_id (смешанные текстово-графические/видео), все интерфейсы используют постраничную навигацию по cursor. Серия App V2 дополнительно предоставляет интерфейс «список публично сохранённых заметок пользователя» (faved notes), а App V1 / Web V3 покрывают только «опубликованные заметки».

Общая рекомендация: в первую очередь используйте серию App V2; при наличии только user_id можно также использовать App V1 / Web V3.

💡 Не знаете, как получить user_id? См. инструмент-спутник выше в 2.3 (официальная документация).

Комплексный пример: получение списка опубликованных заметок пользователя с использованием трёх серий

Ниже приведён пример кода, демонстрирующий логику комбинированного вызова основная серия (App V2) → резерв 1 (App V1) → резерв 2 (Web V3), с последовательными попытками по приоритету: если предыдущий вызов успешен, сразу возвращается результат, при неудаче выполняется переход к следующему.

python
1import requests
2
3BASE_URL = "https://api.tikhub.io"
4HEADERS = {
5    "Authorization": "Bearer YOUR_API_KEY",
6    "accept": "application/json",
7}
8
9USER_ID = "61b46d790000000010008153"
10CURSOR = ""   # Empty for first request; pass previous response's cursor for pagination / 首次请求留空;翻页时传上一次返回的 cursor
11
12
13# --- Primary: App V2 / 主系列:App V2 ---
14def fetch_user_notes_app_v2(user_id: str, cursor: str = ""):
15    path = "/api/v1/xiaohongshu/app_v2/get_user_posted_notes"
16    return requests.get(f"{BASE_URL}{path}", headers=HEADERS,
17                        params={"user_id": user_id, "cursor": cursor})
18
19
20# --- Fallback 1: App V1 / 备用 1:App V1 ---
21def fetch_user_notes_app_v1(user_id: str, cursor: str = ""):
22    path = "/api/v1/xiaohongshu/app/get_user_notes"
23    return requests.get(f"{BASE_URL}{path}", headers=HEADERS,
24                        params={"user_id": user_id, "cursor": cursor})
25
26
27# --- Fallback 2: Web V3 / 备用 2:Web V3 ---
28def fetch_user_notes_web_v3(user_id: str, cursor: str = "", num: int = 30):
29    path = "/api/v1/xiaohongshu/web_v3/fetch_user_notes"
30    return requests.get(f"{BASE_URL}{path}", headers=HEADERS,
31                        params={"user_id": user_id, "cursor": cursor, "num": num})
32
33
34# --- Try all three series in order / 三系列依次尝试 ---
35def get_user_notes(user_id: str, cursor: str = ""):
36    # 1) Primary: App V2 / 主系列:App V2
37    try:
38        r = fetch_user_notes_app_v2(user_id, cursor)
39        if r.ok and r.json().get("code") == 200:
40            return {"source": "app_v2", "data": r.json()}
41    except Exception as e:
42        print("App V2 调用失败:", e)
43
44    # 2) Fallback 1: App V1 / 备用 1:App V1
45    try:
46        r = fetch_user_notes_app_v1(user_id, cursor)
47        if r.ok and r.json().get("code") == 200:
48            return {"source": "app_v1", "data": r.json()}
49    except Exception as e:
50        print("App V1 调用失败:", e)
51
52    # 3) Fallback 2: Web V3 / 备用 2:Web V3
53    try:
54        r = fetch_user_notes_web_v3(user_id, cursor)
55        if r.ok and r.json().get("code") == 200:
56            return {"source": "web_v3", "data": r.json()}
57    except Exception as e:
58        print("Web V3 调用失败:", e)
59
60    return None
61
62
63result = get_user_notes(USER_ID, CURSOR)
64print(result)

Подсказка: проверка успешности выше (code == 200) приведена как пример; в реальности следует проверять по JSON-полям, возвращаемым каждой серией; структуры ответов у разных серий не совпадают, поэтому рекомендуется для каждой серии писать отдельную логику разбора.

3.1 [App V2] Получить список опубликованных заметок пользователя ⭐ Рекомендуется

Получить список опубликованных заметок заданного пользователя, с использованием постраничной навигации по cursor.

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app_v2/get_user_posted_notes
  • Официальная документация: docs.tikhub.io/420136396e0
  • Параметры:
    • user_id (string, необязательно): ID пользователя, например "61b46d790000000010008153"
    • share_text (string, необязательно): ссылка на профиль пользователя Xiaohongshu (поддерживаются APP / Web)
    • Один из двух, приоритет у user_id; если переданы оба, используется user_id
    • cursor (string, необязательно): cursor для пагинации, при первом запросе оставить пустым; при переходе на следующую страницу взять notes последней заметки из списка в предыдущем ответе, а именно cursor (пример пути: $.data.data.notes[-1].cursor)
python
1import requests
2
3BASE_URL = "https://api.tikhub.io"
4HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}
5
6url = f"{BASE_URL}/api/v1/xiaohongshu/app_v2/get_user_posted_notes"
7params = {
8    "user_id": "61b46d790000000010008153",
9    "cursor": "",   # Empty for first request / 首次留空
10}
11r = requests.get(url, headers=HEADERS, params=params)
12print(r.json())

3.2 [App V2] Получить список публично сохранённых заметок пользователя (только App V2)

Получить список заметок, публично сохранённых заданным пользователем (не тех, что он сам опубликовал, а тех, что он сохранил), с использованием постраничной навигации по cursor. Этот интерфейс доступен только в App V2, в App V1 / Web V3 аналогичной возможности нет.

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app_v2/get_user_faved_notes
  • Официальная документация: docs.tikhub.io/420136397e0
  • Параметры:
    • user_id (string, необязательно): например "5a8cf39111be10466d285d6b"
    • share_text (string, необязательно)
    • Один из двух, приоритет у user_id
    • cursor (string, необязательно): cursor для пагинации, при первом запросе оставить пустым; при переходе на следующую страницу передавать note_id последней заметки на предыдущей странице
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/app_v2/get_user_faved_notes"
2params = {
3    "user_id": "5a8cf39111be10466d285d6b",
4    "cursor": "",
5}
6r = requests.get(url, headers=HEADERS, params=params)
7print(r.json())

3.3 [App V1] Получить список работ пользователя

Интерфейс работ пользователя App V1 покрывает только опубликованные заметки и использует постраничную навигацию по cursor.

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app/get_user_notes
  • Официальная документация: docs.tikhub.io/310965846e0
  • Параметры:
    • user_id (string, обязательно)
    • cursor (string, необязательно): при первом запросе оставить пустым; при переходе на следующую страницу взять notes последней заметки из списка note_id на предыдущей странице
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/app/get_user_notes"
2params = {
3    "user_id": "61b46d790000000010008153",
4    "cursor": "",
5}
6r = requests.get(url, headers=HEADERS, params=params)
7print(r.json())

Структура ответа (ключевые поля):

  • notes[]: массив заметок, каждая содержит note_id, type (normal=текстово-графическая / video=видео), display_title, desc, liked_count, cover, user и т. д.
  • cursor: cursor следующей страницы
  • has_more: есть ли ещё данные

3.4 [Web V3] Получить список заметок пользователя

Интерфейс работ пользователя Web V3 использует постраничную навигацию по cursor, можно указать количество элементов на странице (максимум 30).

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/web_v3/fetch_user_notes
  • Официальная документация: docs.tikhub.io/438852178e0
  • Параметры:
    • user_id (string, обязательно)
    • cursor (string, необязательно): cursor для пагинации
    • num (integer, необязательно): количество на странице, по умолчанию 30, максимум 30
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/web_v3/fetch_user_notes"
2params = {
3    "user_id": "61b46d790000000010008153",
4    "cursor": "",
5    "num": 30,
6}
7r = requests.get(url, headers=HEADERS, params=params)
8print(r.json())

4. Комментарии

Комментарии Xiaohongshu делятся на два уровня: комментарии первого уровня (список комментариев под заметкой) и комментарии второго уровня (список ответов/подкомментариев под конкретным комментарием). Все три серии предоставляют интерфейсы для этих двух уровней; App V2 имеет наиболее богатый набор полей, App V1 / Web V3 подходят как резерв.

Общая рекомендация: в первую очередь используйте серию App V2; для интерфейсов Web V3 требуется xsec_token (можно извлечь из ссылки на публикацию, см. комплексный пример в 1. Одна заметка / инструмент-спутник 2.3).

4.1 Комментарии первого уровня (список комментариев под заметкой)

Комплексный пример: получение комментариев первого уровня с использованием трёх серий

Ниже приведён пример кода, демонстрирующий логику комбинированного вызова основная серия (App V2) → резерв 1 (App V1) → резерв 2 (Web V3).

python
1import requests
2
3BASE_URL = "https://api.tikhub.io"
4HEADERS = {
5    "Authorization": "Bearer YOUR_API_KEY",
6    "accept": "application/json",
7}
8
9NOTE_ID = "697c0eee000000000a03c308"
10XSEC_TOKEN = "ABxxxxxxxxxxxxxx"   # Required for Web V3 / Web V3 需要
11
12
13# --- Primary: App V2 / 主系列:App V2 ---
14def fetch_comments_app_v2(note_id: str, cursor: str = "", index: int = 0):
15    path = "/api/v1/xiaohongshu/app_v2/get_note_comments"
16    return requests.get(f"{BASE_URL}{path}", headers=HEADERS, params={
17        "note_id": note_id,
18        "cursor": cursor,
19        "index": index,
20        "pageArea": "UNFOLDED",
21        "sort_strategy": "latest_v2",
22    })
23
24
25# --- Fallback 1: App V1 / 备用 1:App V1 ---
26def fetch_comments_app_v1(note_id: str, start: str = ""):
27    path = "/api/v1/xiaohongshu/app/get_note_comments"
28    return requests.get(f"{BASE_URL}{path}", headers=HEADERS, params={
29        "note_id": note_id,
30        "start": start,
31        "sort_strategy": 1,
32    })
33
34
35# --- Fallback 2: Web V3 / 备用 2:Web V3 ---
36def fetch_comments_web_v3(note_id: str, xsec_token: str, cursor: str = ""):
37    path = "/api/v1/xiaohongshu/web_v3/fetch_note_comments"
38    return requests.get(f"{BASE_URL}{path}", headers=HEADERS, params={
39        "note_id": note_id,
40        "xsec_token": xsec_token,
41        "cursor": cursor,
42    })
43
44
45# --- Try all three series in order / 三系列依次尝试 ---
46def get_note_comments(note_id: str, xsec_token: str):
47    try:
48        r = fetch_comments_app_v2(note_id)
49        if r.ok and r.json().get("code") == 200:
50            return {"source": "app_v2", "data": r.json()}
51    except Exception as e:
52        print("App V2 调用失败:", e)
53
54    try:
55        r = fetch_comments_app_v1(note_id)
56        if r.ok and r.json().get("code") == 200:
57            return {"source": "app_v1", "data": r.json()}
58    except Exception as e:
59        print("App V1 调用失败:", e)
60
61    try:
62        r = fetch_comments_web_v3(note_id, xsec_token)
63        if r.ok and r.json().get("code") == 200:
64            return {"source": "web_v3", "data": r.json()}
65    except Exception as e:
66        print("Web V3 调用失败:", e)
67
68    return None
69
70
71result = get_note_comments(NOTE_ID, XSEC_TOKEN)
72print(result)

Подсказка: проверка успешности выше (code == 200) приведена как пример; в реальности следует проверять по JSON-полям, возвращаемым каждой серией.

4.1.1 [App V2] Получить список комментариев к заметке ⭐ Рекомендуется

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app_v2/get_note_comments
  • Официальная документация: docs.tikhub.io/420136394e0
  • Параметры:
    • note_id (string, необязательно): ID заметки
    • share_text (string, необязательно): ссылка на публикацию (один из двух с note_id, приоритет у note_id)
    • cursor (string, необязательно): cursor для пагинации, при первом запросе оставить пустым
    • index (integer, необязательно): индекс комментария, при первом запросе передать 0
    • pageArea (string, необязательно): состояние сворачивания, UNFOLDED (по умолчанию) / FOLDED
    • sort_strategy (string, необязательно): сортировка, default / latest_v2 (по умолчанию) / like_count
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/app_v2/get_note_comments"
2params = {
3    "note_id": "697c0eee000000000a03c308",
4    "cursor": "",
5    "index": 0,
6    "pageArea": "UNFOLDED",
7    "sort_strategy": "latest_v2",
8}
9r = requests.get(url, headers=HEADERS, params=params)
10print(r.json())

4.1.2 [App V1] Получить комментарии к заметке

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app/get_note_comments
  • Официальная документация: docs.tikhub.io/310965840e0
  • Параметры:
    • note_id (string, обязательно)
    • start (string, необязательно): cursor для перехода на следующую страницу, при первом запросе оставить пустым; поддерживаются два формата — простой формат (например "682b0133000000001c03618d") или JSON-формат (например {"cursor":"...","index":2,"pageArea":"UNFOLDED"})
    • sort_strategy (integer, необязательно): 1-сортировка по умолчанию (по умолчанию) / 2-сначала новые комментарии
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/app/get_note_comments"
2params = {
3    "note_id": "697c0eee000000000a03c308",
4    "start": "",
5    "sort_strategy": 1,
6}
7r = requests.get(url, headers=HEADERS, params=params)
8print(r.json())

4.1.3 [Web V3] Получить комментарии к заметке

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/web_v3/fetch_note_comments
  • Официальная документация: docs.tikhub.io/438852169e0
  • Параметры:
    • note_id (string, обязательно)
    • xsec_token (string, обязательно): можно извлечь из ссылки на публикацию
    • cursor (string, необязательно): cursor для пагинации
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/web_v3/fetch_note_comments"
2params = {
3    "note_id": "697c0eee000000000a03c308",
4    "xsec_token": "ABxxxxxxxxxxxxxx",
5    "cursor": "",
6}
7r = requests.get(url, headers=HEADERS, params=params)
8print(r.json())

4.2 Комментарии второго уровня (подкомментарии / список ответов)

Получение всех ответов (подкомментариев) под конкретным комментарием первого уровня также покрыто всеми тремя сериями. Обратите внимание, что в Web V3 этот параметр называется root_comment_id, а в двух других сериях — comment_id.

Комплексный пример: получение подкомментариев с использованием трёх серий

python
1import requests
2
3BASE_URL = "https://api.tikhub.io"
4HEADERS = {
5    "Authorization": "Bearer YOUR_API_KEY",
6    "accept": "application/json",
7}
8
9NOTE_ID = "699916e6000000001d0253da"
10COMMENT_ID = "PARENT_COMMENT_ID"  # Top-level comment ID / 一级评论 ID
11XSEC_TOKEN = "ABxxxxxxxxxxxxxx"   # Required for Web V3 / Web V3 需要
12
13
14def fetch_sub_app_v2(note_id, comment_id, cursor="", index=1):
15    path = "/api/v1/xiaohongshu/app_v2/get_note_sub_comments"
16    return requests.get(f"{BASE_URL}{path}", headers=HEADERS, params={
17        "note_id": note_id,
18        "comment_id": comment_id,
19        "cursor": cursor,
20        "index": index,
21    })
22
23
24def fetch_sub_app_v1(note_id, comment_id, start=""):
25    path = "/api/v1/xiaohongshu/app/get_sub_comments"
26    return requests.get(f"{BASE_URL}{path}", headers=HEADERS, params={
27        "note_id": note_id,
28        "comment_id": comment_id,
29        "start": start,
30    })
31
32
33def fetch_sub_web_v3(note_id, root_comment_id, xsec_token, cursor="", num=10):
34    path = "/api/v1/xiaohongshu/web_v3/fetch_sub_comments"
35    return requests.get(f"{BASE_URL}{path}", headers=HEADERS, params={
36        "note_id": note_id,
37        "root_comment_id": root_comment_id,
38        "xsec_token": xsec_token,
39        "cursor": cursor,
40        "num": num,
41    })
42
43
44def get_sub_comments(note_id, comment_id, xsec_token):
45    try:
46        r = fetch_sub_app_v2(note_id, comment_id)
47        if r.ok and r.json().get("code") == 200:
48            return {"source": "app_v2", "data": r.json()}
49    except Exception as e:
50        print("App V2 调用失败:", e)
51
52    try:
53        r = fetch_sub_app_v1(note_id, comment_id)
54        if r.ok and r.json().get("code") == 200:
55            return {"source": "app_v1", "data": r.json()}
56    except Exception as e:
57        print("App V1 调用失败:", e)
58
59    try:
60        r = fetch_sub_web_v3(note_id, comment_id, xsec_token)
61        if r.ok and r.json().get("code") == 200:
62            return {"source": "web_v3", "data": r.json()}
63    except Exception as e:
64        print("Web V3 调用失败:", e)
65
66    return None
67
68
69result = get_sub_comments(NOTE_ID, COMMENT_ID, XSEC_TOKEN)
70print(result)

4.2.1 [App V2] Получить список комментариев второго уровня к заметке ⭐ Рекомендуется

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app_v2/get_note_sub_comments
  • Официальная документация: docs.tikhub.io/420748830e0
  • Параметры:
    • note_id (string, необязательно)
    • share_text (string, необязательно) (один из двух с note_id, приоритет у note_id)
    • comment_id (string, обязательно): ID родительского комментария
    • cursor (string, необязательно): при первом запросе оставить пустым, при переходе на следующую страницу брать из $.data.cursor
    • index (integer, необязательно): при первом запросе передать 1, при переходе на следующую страницу брать из $.data.cursor
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/app_v2/get_note_sub_comments"
2params = {
3    "note_id": "699916e6000000001d0253da",
4    "comment_id": "PARENT_COMMENT_ID",
5    "cursor": "",
6    "index": 1,
7}
8r = requests.get(url, headers=HEADERS, params=params)
9print(r.json())

4.2.2 [App V1] Получить подкомментарии

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app/get_sub_comments
  • Официальная документация: docs.tikhub.io/310965841e0
  • Параметры:
    • note_id (string, обязательно)
    • comment_id (string, обязательно): ID комментария первого уровня
    • start (string, необязательно): cursor для перехода на следующую страницу, брать из ID последнего подкомментария на предыдущей странице (например "6806642d000000001f01991b")
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/app/get_sub_comments"
2params = {
3    "note_id": "697c0eee000000000a03c308",
4    "comment_id": "PARENT_COMMENT_ID",
5    "start": "",
6}
7r = requests.get(url, headers=HEADERS, params=params)
8print(r.json())

4.2.3 [Web V3] Получить подкомментарии

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/web_v3/fetch_sub_comments
  • Официальная документация: docs.tikhub.io/438852170e0
  • Параметры:
    • note_id (string, обязательно)
    • root_comment_id (string, обязательно): ID родительского комментария
    • xsec_token (string, обязательно)
    • num (integer, необязательно): количество возвращаемых элементов, по умолчанию 10
    • cursor (string, необязательно): cursor для пагинации
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/web_v3/fetch_sub_comments"
2params = {
3    "note_id": "697c0eee000000000a03c308",
4    "root_comment_id": "PARENT_COMMENT_ID",
5    "xsec_token": "ABxxxxxxxxxxxxxx",
6    "num": 10,
7    "cursor": "",
8}
9r = requests.get(url, headers=HEADERS, params=params)
10print(r.json())

5. Поиск

Поиск в Xiaohongshu делится на два типа: поиск заметок и поиск пользователей.

  • Поиск заметок: доступен во всех трёх сериях App V2 / App V1 / Web V3, при этом App V2 имеет наиболее богатый набор полей (поддерживаются сортировка, тип заметки, фильтр по времени, AI-режим и т. д.).
  • Поиск пользователей: доступен только в App V2 и Web V3, в App V1 интерфейса поиска пользователей нет.

Общая рекомендация: в первую очередь используйте серию App V2; при переходе на следующую страницу не забудьте передать search_id / session_id, возвращённые при первом поиске (названия параметров немного отличаются в разных сериях).

5.1 Поиск заметок

Комплексный пример: поиск заметок с использованием трёх серий

Ниже приведён пример кода, демонстрирующий логику комбинированного вызова основная серия (App V2) → резерв 1 (App V1) → резерв 2 (Web V3).

python
1import requests
2
3BASE_URL = "https://api.tikhub.io"
4HEADERS = {
5    "Authorization": "Bearer YOUR_API_KEY",
6    "accept": "application/json",
7}
8
9KEYWORD = "美食推荐"
10PAGE = 1
11
12
13# --- Primary: App V2 / 主系列:App V2 ---
14def search_notes_app_v2(keyword: str, page: int = 1):
15    path = "/api/v1/xiaohongshu/app_v2/search_notes"
16    return requests.get(f"{BASE_URL}{path}", headers=HEADERS, params={
17        "keyword": keyword,
18        "page": page,
19        "sort_type": "general",
20        "note_type": "不限",
21        "time_filter": "不限",
22    })
23
24
25# --- Fallback 1: App V1 / 备用 1:App V1 ---
26def search_notes_app_v1(keyword: str, page: int = 1):
27    path = "/api/v1/xiaohongshu/app/search_notes"
28    return requests.get(f"{BASE_URL}{path}", headers=HEADERS, params={
29        "keyword": keyword,
30        "page": page,
31        "sort_type": "general",
32        "filter_note_type": "不限",
33        "filter_note_time": "不限",
34    })
35
36
37# --- Fallback 2: Web V3 / 备用 2:Web V3 ---
38def search_notes_web_v3(keyword: str, page: int = 1):
39    path = "/api/v1/xiaohongshu/web_v3/fetch_search_notes"
40    return requests.get(f"{BASE_URL}{path}", headers=HEADERS, params={
41        "keyword": keyword,
42        "page": page,
43        "sort": "general",
44        "note_type": 0,
45    })
46
47
48def search_notes(keyword: str, page: int = 1):
49    try:
50        r = search_notes_app_v2(keyword, page)
51        if r.ok and r.json().get("code") == 200:
52            return {"source": "app_v2", "data": r.json()}
53    except Exception as e:
54        print("App V2 调用失败:", e)
55
56    try:
57        r = search_notes_app_v1(keyword, page)
58        if r.ok and r.json().get("code") == 200:
59            return {"source": "app_v1", "data": r.json()}
60    except Exception as e:
61        print("App V1 调用失败:", e)
62
63    try:
64        r = search_notes_web_v3(keyword, page)
65        if r.ok and r.json().get("code") == 200:
66            return {"source": "web_v3", "data": r.json()}
67    except Exception as e:
68        print("Web V3 调用失败:", e)
69
70    return None
71
72
73result = search_notes(KEYWORD, PAGE)
74print(result)

Подсказка: проверка успешности выше (code == 200) приведена как пример; в реальности следует проверять по JSON-полям, возвращаемым каждой серией; при переходе на следующую страницу не забудьте передать обратно search_id / session_id из первого ответа.

5.1.1 [App V2] Поиск заметок ⭐ Рекомендуется

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app_v2/search_notes
  • Официальная документация: docs.tikhub.io/420136398e0
  • Параметры:
    • keyword (string, обязательно): ключевое слово поиска, например "美食推荐"
    • page (integer, необязательно): номер страницы, начиная с 1
    • sort_type (string, необязательно): сортировка, general (по умолчанию, по совокупности) / time_descending (новые) / popularity_descending (больше всего лайков) / comment_descending (больше всего комментариев) / collect_descending (больше всего сохранений) / english_preferred (английский в приоритете)
    • note_type (string, необязательно): тип заметки, 不限 (по умолчанию) / 视频笔记 / 普通笔记 / 直播笔记
    • time_filter (string, необязательно): время публикации, 不限 (по умолчанию) / 一天内 / 一周内 / 半年内
    • search_id (string, необязательно): при переходе на следующую страницу передавать значение из первого ответа
    • search_session_id (string, необязательно): при переходе на следующую страницу передавать значение из первого ответа
    • source (string, необязательно): источник, по умолчанию explore_feed
    • ai_mode (integer, необязательно): AI-режим, 0 (выключен, по умолчанию) / 1 (включён)
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/app_v2/search_notes"
2params = {
3    "keyword": "美食推荐",
4    "page": 1,
5    "sort_type": "general",
6    "note_type": "不限",
7    "time_filter": "不限",
8    # Pass search_id and search_session_id from first response for pagination / 翻页时需要带上首次响应里的 search_id 和 search_session_id
9    # "search_id": "...",
10    # "search_session_id": "...",
11}
12r = requests.get(url, headers=HEADERS, params=params)
13print(r.json())

5.1.2 [App V1] Поиск заметок

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app/search_notes
  • Официальная документация: docs.tikhub.io/310965843e0
  • Параметры:
    • keyword (string, обязательно)
    • page (integer, обязательно): номер страницы, начиная с 1
    • search_id (string, необязательно): при переходе на следующую страницу передавать значение из первого ответа
    • session_id (string, необязательно): при переходе на следующую страницу передавать значение из первого ответа
    • sort_type (string, необязательно): general (по умолчанию) / time_descending / popularity_descending / comment_descending / collect_descending
    • filter_note_type (string, необязательно): 不限 (по умолчанию) / 视频笔记 / 普通笔记
    • filter_note_time (string, необязательно): 不限 (по умолчанию) / 一天内 / 一周内 / 半年内
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/app/search_notes"
2params = {
3    "keyword": "美食推荐",
4    "page": 1,
5    "sort_type": "general",
6    "filter_note_type": "不限",
7    "filter_note_time": "不限",
8}
9r = requests.get(url, headers=HEADERS, params=params)
10print(r.json())

5.1.3 [Web V3] Поиск заметок

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/web_v3/fetch_search_notes
  • Официальная документация: docs.tikhub.io/438852171e0
  • Параметры:
    • keyword (string, обязательно)
    • page (integer, необязательно): по умолчанию 1
    • sort (string, необязательно): general (по совокупности, по умолчанию) / time_descending (новые) / popularity_descending (самые горячие)
    • note_type (integer, необязательно): 0=все (по умолчанию) / 1=текстово-графические / 2=видео
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/web_v3/fetch_search_notes"
2params = {
3    "keyword": "美食推荐",
4    "page": 1,
5    "sort": "general",
6    "note_type": 0,
7}
8r = requests.get(url, headers=HEADERS, params=params)
9print(r.json())

5.2 Поиск пользователей

⚠️ Внимание: в App V1 нет интерфейса поиска пользователей, в этом разделе есть только две серии: App V2 и Web V3.

Комплексный пример: поиск пользователей с использованием двух серий

python
1import requests
2
3BASE_URL = "https://api.tikhub.io"
4HEADERS = {
5    "Authorization": "Bearer YOUR_API_KEY",
6    "accept": "application/json",
7}
8
9KEYWORD = "美食博主"
10PAGE = 1
11
12
13# --- Primary: App V2 / 主系列:App V2 ---
14def search_users_app_v2(keyword: str, page: int = 1, search_id: str = ""):
15    path = "/api/v1/xiaohongshu/app_v2/search_users"
16    return requests.get(f"{BASE_URL}{path}", headers=HEADERS, params={
17        "keyword": keyword,
18        "page": page,
19        "search_id": search_id,
20    })
21
22
23# --- Fallback: Web V3 / 备用:Web V3 ---
24def search_users_web_v3(keyword: str, page: int = 1):
25    path = "/api/v1/xiaohongshu/web_v3/fetch_search_users"
26    return requests.get(f"{BASE_URL}{path}", headers=HEADERS, params={
27        "keyword": keyword,
28        "page": page,
29    })
30
31
32def search_users(keyword: str, page: int = 1):
33    try:
34        r = search_users_app_v2(keyword, page)
35        if r.ok and r.json().get("code") == 200:
36            return {"source": "app_v2", "data": r.json()}
37    except Exception as e:
38        print("App V2 调用失败:", e)
39
40    try:
41        r = search_users_web_v3(keyword, page)
42        if r.ok and r.json().get("code") == 200:
43            return {"source": "web_v3", "data": r.json()}
44    except Exception as e:
45        print("Web V3 调用失败:", e)
46
47    return None
48
49
50result = search_users(KEYWORD, PAGE)
51print(result)

5.2.1 [App V2] Поиск пользователей ⭐ Рекомендуется

Возвращает фиксированно 20 результатов на страницу, поддерживает пагинацию.

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app_v2/search_users
  • Официальная документация: docs.tikhub.io/420136399e0
  • Параметры:
    • keyword (string, обязательно): ключевое слово поиска, например "美食博主"
    • page (integer, необязательно): номер страницы, начиная с 1
    • search_id (string, необязательно): при переходе на следующую страницу передавать значение из первого ответа
    • source (string, необязательно): источник, по умолчанию explore_feed
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/app_v2/search_users"
2params = {
3    "keyword": "美食博主",
4    "page": 1,
5    # Pass search_id from first response for pagination / 翻页时带上首次响应里的 search_id
6    # "search_id": "...",
7}
8r = requests.get(url, headers=HEADERS, params=params)
9print(r.json())

5.2.2 [Web V3] Поиск пользователей

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/web_v3/fetch_search_users
  • Официальная документация: docs.tikhub.io/438852172e0
  • Параметры:
    • keyword (string, обязательно)
    • page (integer, необязательно): по умолчанию 1
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/web_v3/fetch_search_users"
2params = {
3    "keyword": "口红",
4    "page": 1,
5}
6r = requests.get(url, headers=HEADERS, params=params)
7print(r.json())

6. Темы

Интерфейсы, связанные с темами Xiaohongshu, делятся на две части: подробности темы и список заметок под темой.

⚠️ Важное замечание:

  • В серии Web V3 нет интерфейсов тем, в этом разделе есть только две серии: App V2 и App V1.
  • Старый интерфейс App V1 /api/v1/xiaohongshu/app/get_notes_by_topic устарел, пожалуйста, используйте вместо него get_topic_notes из этого раздела.
  • Все интерфейсы используют page_id (ID темы / тега темы) в качестве единственного идентификатора.

6.1 Подробности темы

Только App V2 предоставляет интерфейс подробностей темы (название темы, просмотры, число обсуждений, информация о репосте и т. д.). App V1 / Web V3 не имеют соответствующей возможности.

6.1.1 [App V2] Получить подробности темы ⭐ Только App V2

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app_v2/get_topic_info
  • Официальная документация: docs.tikhub.io/420136407e0
  • Параметры:
    • page_id (string, обязательно): ID страницы темы, например "5c1cc866febed9000184b7c1"
    • source (string, необязательно): источник, по умолчанию normal
    • note_id (string, необязательно): ID исходной заметки, можно передавать при переходе к теме из заметки
python
1import requests
2
3BASE_URL = "https://api.tikhub.io"
4HEADERS = {"Authorization": "Bearer YOUR_API_KEY"}
5
6url = f"{BASE_URL}/api/v1/xiaohongshu/app_v2/get_topic_info"
7params = {
8    "page_id": "5c1cc866febed9000184b7c1",
9    "source": "normal",
10    # "note_id": "...",  # Optional: pass when navigating from a note / 从笔记跳转过来时可带
11}
12r = requests.get(url, headers=HEADERS, params=params)
13print(r.json())
14# Response contains page_info (name/views/discussions), tabs, share_info, etc. / 返回包含 page_info(名称/浏览量/讨论数)、tabs、share_info 等

6.2 Список заметок по теме (заметки под темой)

Получить список заметок под определённой темой / тегом темы. Это предоставляют и App V2, и App V1, но параметры и поля пагинации сильно отличаются, поэтому требуется отдельная адаптация.

Комплексный пример: получение заметок по теме с использованием двух серий

python
1import requests
2import time
3
4BASE_URL = "https://api.tikhub.io"
5HEADERS = {
6    "Authorization": "Bearer YOUR_API_KEY",
7    "accept": "application/json",
8}
9
10PAGE_ID = "5c1cc866febed9000184b7c1"
11
12
13# --- Primary: App V2 / 主系列:App V2 ---
14def topic_feed_app_v2(page_id: str, sort: str = "trend"):
15    path = "/api/v1/xiaohongshu/app_v2/get_topic_feed"
16    return requests.get(f"{BASE_URL}{path}", headers=HEADERS, params={
17        "page_id": page_id,
18        "sort": sort,        # trend (hottest) / time (latest) | trend(最热) / time(最新)
19    })
20
21
22# --- Fallback: App V1 / 备用:App V1 ---
23def topic_notes_app_v1(page_id: str, sort: str = "hot"):
24    path = "/api/v1/xiaohongshu/app/get_topic_notes"
25    return requests.get(f"{BASE_URL}{path}", headers=HEADERS, params={
26        "page_id": page_id,
27        "first_load_time": str(int(time.time() * 1000)),  # Millisecond timestamp / 毫秒级时间戳
28        "sort": sort,        # hot (general) / time (latest) / trend (hottest) | hot(综合) / time(最新) / trend(最热)
29    })
30
31
32def get_topic_notes(page_id: str):
33    try:
34        r = topic_feed_app_v2(page_id)
35        if r.ok and r.json().get("code") == 200:
36            return {"source": "app_v2", "data": r.json()}
37    except Exception as e:
38        print("App V2 调用失败:", e)
39
40    try:
41        r = topic_notes_app_v1(page_id)
42        if r.ok and r.json().get("code") == 200:
43            return {"source": "app_v1", "data": r.json()}
44    except Exception as e:
45        print("App V1 调用失败:", e)
46
47    return None
48
49
50result = get_topic_notes(PAGE_ID)
51print(result)

Подсказка: проверка успешности выше (code == 200) приведена как пример; в реальности следует проверять по JSON-полям, возвращаемым каждой серией; при переходе на следующую страницу не забудьте передать соответствующее поле cursor обратно (в двух сериях поля разные, см. ниже).

6.2.1 [App V2] Получить список заметок по теме ⭐ Рекомендуется

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app_v2/get_topic_feed
  • Официальная документация: docs.tikhub.io/420136408e0
  • Параметры:
    • page_id (string, обязательно): ID страницы темы
    • sort (string, необязательно): trend (самые горячие, по умолчанию) / time (новые)
    • cursor_score (string, необязательно): score cursor для пагинации, при переходе на следующую страницу передавать cursor_score последнего item на предыдущей странице
    • last_note_id (string, необязательно): при переходе на следующую страницу передавать ID последней заметки на предыдущей странице (items[-1].id)
    • last_note_ct (string, необязательно): при переходе на следующую страницу передавать время создания последней заметки на предыдущей странице (items[-1].create_time)
    • session_id (string, необязательно): ID сессии, при переходе на следующую страницу должен оставаться тем же
    • first_load_time (string, необязательно): timestamp первой загрузки, при переходе на следующую страницу должен оставаться тем же
    • source (string, необязательно): источник, по умолчанию normal
python
1url = f"{BASE_URL}/api/v1/xiaohongshu/app_v2/get_topic_feed"
2
3# First request: pass only page_id and sort / 首次请求:只传 page_id 和 sort
4params = {
5    "page_id": "5c1cc866febed9000184b7c1",
6    "sort": "trend",
7}
8r = requests.get(url, headers=HEADERS, params=params)
9data = r.json()
10print(data)
11
12# Next page: pass through the following fields from the first response / 翻页请求:从首次响应中取下列字段透传
13# items = data["data"]["items"]
14# next_params = {
15#     "page_id": "5c1cc866febed9000184b7c1",
16#     "sort": "trend",
17#     "cursor_score": items[-1]["cursor_score"],
18#     "last_note_id": items[-1]["id"],
19#     "last_note_ct": items[-1]["create_time"],
20#     "session_id": data["data"]["session_id"],
21#     "first_load_time": data["data"]["first_load_time"],
22# }

6.2.2 [App V1] Получить работы по тегу темы (замена устаревшего get_notes_by_topic)

⚠️ Старый интерфейс App V1 /api/v1/xiaohongshu/app/get_notes_by_topic устарел, пожалуйста, используйте напрямую этот интерфейс.

  • Метод: GET
  • Путь: /api/v1/xiaohongshu/app/get_topic_notes
  • Официальная документация: docs.tikhub.io/454758056e0
  • Параметры:
    • page_id (string, обязательно): ID тега темы
    • first_load_time (string, обязательно): timestamp первого запроса (в миллисекундах), получение в Python: int(time.time() * 1000)
    • sort (string, необязательно): hot (по совокупности, по умолчанию) / time (новые) / trend (самые горячие)
    • last_note_ct (string, необязательно): при переходе на следующую страницу передавать create_time последней заметки на предыдущей странице
    • last_note_id (string, необязательно): при переходе на следующую страницу передавать ID последней заметки на предыдущей странице
    • cursor_score (string, необязательно): при переходе на следующую страницу передавать cursor_score последней заметки на предыдущей странице
    • session_id (string, необязательно): ID сессии, на первом запросе генерируется сервером, при переходе на следующую страницу возвращать обратно
python
1import time
2
3url = f"{BASE_URL}/api/v1/xiaohongshu/app/get_topic_notes"
4
5# First request / 首次请求
6params = {
7    "page_id": "5c1cc866febed9000184b7c1",
8    "first_load_time": str(int(time.time() * 1000)),
9    "sort": "hot",
10}
11r = requests.get(url, headers=HEADERS, params=params)
12data = r.json()
13print(data)
14
15# Next page: keep page_id / first_load_time unchanged, pass session_id and last_* through / 翻页请求:保持 page_id / first_load_time 不变,把 session_id 和 last_* 透传
16# notes = data["data"]["notes"]
17# next_params = {
18#     "page_id": "5c1cc866febed9000184b7c1",
19#     "first_load_time": params["first_load_time"],
20#     "sort": "hot",
21#     "session_id": data["data"]["session_id"],
22#     "last_note_id": notes[-1]["id"],
23#     "last_note_ct": notes[-1]["note"]["create_time"],
24#     "cursor_score": notes[-1].get("cursor_score", ""),
25# }

Enjoyed this article?

Share it with your friends and colleagues!

Default
Last updated: May 15, 2026
相关文章
正在检查服务状态...
Руководство по использованию API TikHub 小红书 - TikHub.io