XHS (Xiaohongshu) Usage Guide
Xiaohongshu API documentation organized based on TikHub OpenAPI (
https://api.tikhub.io).
Table of Contents
General Notes
a. Calling strategy: use multiple series in combination (important)
At present, the most stable Xiaohongshu API series is App V2. It is strongly recommended that all users adopt a "primary series + 1~2 backup series" combination strategy, using 2~3 series together to improve overall business availability.
b. Call priority: App V2 (recommended) > App V1 (fallback) > Web V3 (third option)
App V2 is the primary recommended series. It is currently the most stable and has the most complete data, so it is recommended as the first choice; App V1 is close to App V2 in terms of field definitions and is suitable as the first backup fallback; Web V3 is the third backup Web channel open to enterprise users, requiring
xsec_token(which can be extracted from a share link). However, the data dimensions returned are fewer than App V2 / App V1, so even enterprise users are advised to combine multiple series reasonably rather than using only Web V3; Web V2 / Web series only have a small number of available interfaces and stability is not guaranteed, so they are not recommended as the main option and should only be used as a supplement when the first three series do not meet requirements.
c. One-sentence recommendation: Do not rely on just one series. In production, it is recommended to configure at least 2 series for primary/backup use; when enterprise users use Web V3, please additionally combine it with App V2 / App V1 to make up for missing data dimensions.
d. Returned field reminder: App series interfaces (App V2 / App V1) have similar structures, and field names can basically correspond to each other; however, Web series interfaces (Web V3 / Web V2 / Web) return JSON structures that differ from one another, and field names, nesting levels, and data dimensions may all be different. When using them, be sure to first check the actual returned JSON fields of each interface before parsing and mapping.
1. Single Note
Xiaohongshu notes are divided into two types: image notes (text-and-image notes) and video notes. The App V2 series provides separate endpoints for both types, with the most complete data; Web V3 uses the same interface for both types, distinguished by response fields.
General recommendation: prioritize the App V2 series; enterprise users can combine it with Web V3 in scenarios where they can obtain
xsec_token.
Comprehensive example: using three series together to get single note details
Below is a sample code snippet demonstrating the combined calling approach of primary series (App V2) → backup 1 (App V1) → backup 2 (Web V3), trying in order of priority; if the previous one succeeds, return immediately, otherwise fall back to the next one.
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)Tip: the success check above (
code == 200) is only illustrative. In practice, please judge based on the JSON fields returned by each series; since the returned structures differ across series, it is recommended to write separate parsing logic for each series.
1.1 Image Note (Text-and-Image Note)
1.1.1 [App V2] Get text-and-image note details ⭐ Recommended
Get the full detail data of a text-and-image note (image URLs, title, body, tags, engagement data, etc.).
- Method: GET
- Path:
/api/v1/xiaohongshu/app_v2/get_image_note_detail - Official docs: docs.tikhub.io/420136391e0
- Parameters:
note_id(string, optional): note ID, e.g."697c0eee000000000a03c308"share_text(string, optional): Xiaohongshu share link (supports APP / Web)- Either one of the two;
note_idis preferred; if both are provided,note_idtakes precedence
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] Get note information V1 (text-and-image only, no video download link)
The App V1 note interface is only applicable to text-and-image notes. The response does not include a video download link, so do not use it to fetch video notes; for video notes, use App V2's get_video_note_detail instead.
- Method: GET
- Path:
/api/v1/xiaohongshu/app/get_note_info - Official docs: docs.tikhub.io/310965839e0
- Parameters:
note_id(string, optional)share_text(string, optional)- Either one of the two;
note_idis preferred
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] Get note details (text/image and video)
Web V3 endpoint, applicable to both text/image and video. Requires xsec_token (extracted from the share link, see the "supporting tool interfaces" above).
- Method: GET
- Path:
/api/v1/xiaohongshu/web_v3/fetch_note_detail - Official docs: docs.tikhub.io/438852168e0
- Parameters:
note_id(string, required)xsec_token(string, required)
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 Video Note
Do not use App V1's
get_note_infofor video notes, as the returned content does not include a video download link. Please use the App V2 or Web V3 options below.
1.2.1 [App V2] Get video note details ⭐ Recommended
Get the full detail data of a video note (video URL, cover, duration, title, body, engagement data, etc.).
- Method: GET
- Path:
/api/v1/xiaohongshu/app_v2/get_video_note_detail - Official docs: docs.tikhub.io/420136392e0
- Parameters:
note_id(string, optional): e.g."697c0eee000000000a03c308"share_text(string, optional)- Either one of the two;
note_idis preferred
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] Get note details (video supported)
Same endpoint as text/image; call with note_id + xsec_token.
- Method: GET
- Path:
/api/v1/xiaohongshu/web_v3/fetch_note_detail - Official docs: docs.tikhub.io/438852168e0
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 Information
Use user_id to obtain a Xiaohongshu user's public profile information (nickname, avatar, bio, follower count, following count, note count, etc.). All three series provide user information interfaces; App V2 has the most complete fields, while App V1 / Web V3 are suitable as backups.
General recommendation: prioritize the App V2 series; if only
user_idis available, you can also use App V1 / Web V3.
💡 Don't know how to get
user_id? You can first use the/api/v1/xiaohongshu/app/get_user_id_and_xsec_tokentool interface (official docs) to pass in any Xiaohongshu user profile share link (either long or short link is fine), and it will parse outuser_idandxsec_token, which can then be fed into the user information interfaces below. See 2.3 below for details.
Comprehensive example: using three series together to get user information
Below is a sample code snippet demonstrating the combined calling approach of primary series (App V2) → backup 1 (App V1) → backup 2 (Web V3), trying in order of priority; if the previous one succeeds, return immediately, otherwise fall back to the next one.
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)Tip: the success check above (
code == 200) is only illustrative. In practice, please judge based on the JSON fields returned by each series; since the returned structures differ across series, it is recommended to write separate parsing logic for each series.
2.1 [App V2] Get user information ⭐ Recommended
Get detailed information for a specified user, including nickname, avatar, bio, follower count, following count, note count, etc.
- Method: GET
- Path:
/api/v1/xiaohongshu/app_v2/get_user_info - Official docs: docs.tikhub.io/420136395e0
- Parameters:
user_id(string, optional): user ID, e.g."61b46d790000000010008153"share_text(string, optional): Xiaohongshu user share link (supports APP / Web)- Either one of the two;
user_idis preferred; if both are provided,user_idtakes precedence
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] Get user information
App V1 user information interface.
- Method: GET
- Path:
/api/v1/xiaohongshu/app/get_user_info - Official docs: docs.tikhub.io/310965845e0
- Parameters:
user_id(string, required)
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] Supporting tool: extract user_id and xsec_token from a user share link
If you only have a user profile share link (both long and short links are supported), you can first use this interface to parse out user_id and xsec_token, and then call the user information interface above.
- Method: GET
- Path:
/api/v1/xiaohongshu/app/get_user_id_and_xsec_token - Official docs: docs.tikhub.io/364605901e0
- Parameters:
share_link(string, required): Xiaohongshu user share link
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] Get user information
Web V3 user public profile interface, requiring only user_id.
- Method: GET
- Path:
/api/v1/xiaohongshu/web_v3/fetch_user_info - Official docs: docs.tikhub.io/438852177e0
- Parameters:
user_id(string, required)
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 Works
Fetch the list of notes posted by the user according to user_id (mixed text/image and video). All interfaces use cursor-based pagination (cursor). The App V2 series additionally provides a "user public favorite notes list" interface (faved notes), while App V1 / Web V3 only cover "published notes".
General recommendation: prioritize the App V2 series; if only
user_idis available, you can also use App V1 / Web V3.💡 Don't know how to get
user_id? Refer to the tool interface in 2.3 above (official docs).
Comprehensive example: using three series together to get a user's published notes
Below is a sample code snippet demonstrating the combined calling approach of primary series (App V2) → backup 1 (App V1) → backup 2 (Web V3), trying in order of priority; if the previous one succeeds, return immediately, otherwise fall back to the next one.
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)Tip: the success check above (
code == 200) is only illustrative. In practice, please judge based on the JSON fields returned by each series; since the returned structures differ across series, it is recommended to write separate parsing logic for each series.
3.1 [App V2] Get a user's published note list ⭐ Recommended
Get the list of notes published by the specified user, using cursor-based pagination.
- Method: GET
- Path:
/api/v1/xiaohongshu/app_v2/get_user_posted_notes - Official docs: docs.tikhub.io/420136396e0
- Parameters:
user_id(string, optional): user ID, e.g."61b46d790000000010008153"share_text(string, optional): Xiaohongshu user share link (supports APP / Web)- Either one of the two;
user_idis preferred; if both are provided,user_idtakes precedence cursor(string, optional): pagination cursor; leave blank for the first request; when paging, take thenotesof the last note in thecursorlist from the previous response (path example:$.data.data.notes[-1].cursor)
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] Get a user's publicly favorited note list (App V2 only)
Get the list of notes publicly favorited by the specified user (not notes posted by the user themselves, but content they have favorited), using cursor-based pagination. This interface is only available in App V2; App V1 / Web V3 do not have the corresponding capability.
- Method: GET
- Path:
/api/v1/xiaohongshu/app_v2/get_user_faved_notes - Official docs: docs.tikhub.io/420136397e0
- Parameters:
user_id(string, optional): e.g."5a8cf39111be10466d285d6b"share_text(string, optional)- Either one of the two;
user_idis preferred cursor(string, optional): pagination cursor; leave blank for the first request; when paging, pass thenote_idof the last note on the previous page
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] Get user works list
App V1 user works interface, covering only published notes, using cursor-based pagination.
- Method: GET
- Path:
/api/v1/xiaohongshu/app/get_user_notes - Official docs: docs.tikhub.io/310965846e0
- Parameters:
user_id(string, required)cursor(string, optional): leave blank for the first request; when paging, take thenotesof the last note in thenote_idlist from the previous page
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())Returned structure (key fields):
notes[]: note array, each item includesnote_id,type(normal= text/image /video= video),display_title,desc,liked_count,cover,user, etc.cursor: next-page cursorhas_more: whether there is more data
3.4 [Web V3] Get user note list
Web V3 user works interface, using cursor-based pagination, with support for specifying the number of items per page (maximum 30).
- Method: GET
- Path:
/api/v1/xiaohongshu/web_v3/fetch_user_notes - Official docs: docs.tikhub.io/438852178e0
- Parameters:
user_id(string, required)cursor(string, optional): pagination cursornum(integer, optional): items per page, default 30, maximum 30
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. Comments
Xiaohongshu comments are divided into two levels: top-level comments (the comment list under a note) and second-level comments (replies/sub-comment list under a specific comment). All three series provide these two levels of interfaces; App V2 has the richest fields, while App V1 / Web V3 are suitable as backups.
General recommendation: prioritize the App V2 series; the Web V3 interface requires
xsec_token(which can be extracted from the share link, see the comprehensive example in 1. Single Note / the tool interface in 2.3).
4.1 Top-level Comments (comment list under a note)
Comprehensive example: using three series together to get top-level comments
Below is a sample code snippet demonstrating the combined calling approach of primary series (App V2) → backup 1 (App V1) → backup 2 (Web V3).
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)Tip: the success check above (
code == 200) is only illustrative. In practice, please judge based on the JSON fields returned by each series.
4.1.1 [App V2] Get note comment list ⭐ Recommended
- Method: GET
- Path:
/api/v1/xiaohongshu/app_v2/get_note_comments - Official docs: docs.tikhub.io/420136394e0
- Parameters:
note_id(string, optional): note IDshare_text(string, optional): share link (eithernote_idornote_id;note_idis preferred)cursor(string, optional): pagination cursor, leave blank for the first requestindex(integer, optional): comment index, pass0on the first requestpageArea(string, optional): collapse state,UNFOLDED(default) /FOLDEDsort_strategy(string, optional): sort order,default/latest_v2(default) /like_count
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 note comments
- Method: GET
- Path:
/api/v1/xiaohongshu/app/get_note_comments - Official docs: docs.tikhub.io/310965840e0
- Parameters:
note_id(string, required)start(string, optional): pagination cursor, leave blank for the first request; supports two formats — simple format (e.g."682b0133000000001c03618d") or JSON format (e.g.{"cursor":"...","index":2,"pageArea":"UNFOLDED"})sort_strategy(integer, optional):1- default order (default) /2- latest comments
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 note comments
- Method: GET
- Path:
/api/v1/xiaohongshu/web_v3/fetch_note_comments - Official docs: docs.tikhub.io/438852169e0
- Parameters:
note_id(string, required)xsec_token(string, required): can be extracted from the share linkcursor(string, optional): pagination cursor
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 Second-level Comments (Sub-comments / reply list)
Get all replies (sub-comments) under a specific top-level comment; all three series cover this as well. Note that in Web V3 the parameter is called root_comment_id, while in the other two series it is called comment_id.
Comprehensive example: using three series together to get sub-comments
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 note second-level comment list ⭐ Recommended
- Method: GET
- Path:
/api/v1/xiaohongshu/app_v2/get_note_sub_comments - Official docs: docs.tikhub.io/420748830e0
- Parameters:
note_id(string, optional)share_text(string, optional) (eithernote_idornote_id;note_idis preferred)comment_id(string, required): parent comment IDcursor(string, optional): leave blank for the first request; when paging, take it from$.data.cursorindex(integer, optional): pass1on the first request; when paging, take it from$.data.cursor
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 sub-comments
- Method: GET
- Path:
/api/v1/xiaohongshu/app/get_sub_comments - Official docs: docs.tikhub.io/310965841e0
- Parameters:
note_id(string, required)comment_id(string, required): top-level comment IDstart(string, optional): pagination cursor, taken from the last sub-comment ID on the previous page (e.g."6806642d000000001f01991b")
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 sub-comments
- Method: GET
- Path:
/api/v1/xiaohongshu/web_v3/fetch_sub_comments - Official docs: docs.tikhub.io/438852170e0
- Parameters:
note_id(string, required)root_comment_id(string, required): parent comment IDxsec_token(string, required)num(integer, optional): number of items returned, default10cursor(string, optional): pagination cursor
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. Search
Xiaohongshu search is divided into two categories: search notes and search users.
- Search notes: provided by App V2 / App V1 / Web V3; App V2 has the richest fields (supports sorting, note type, time filtering, AI mode, etc.).
- Search users: only provided by App V2 and Web V3; App V1 does not have a user search interface.
General recommendation: prioritize the App V2 series; when paging, remember to carry over the
search_id/session_idreturned by the first search (parameter names differ slightly across series).
5.1 Search Notes
Comprehensive example: using three series together to search notes
Below is a sample code snippet demonstrating the combined calling approach of primary series (App V2) → backup 1 (App V1) → backup 2 (Web V3).
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)Tip: the success check above (
code == 200) is only illustrative. In practice, please judge based on the JSON fields returned by each series; when paging, remember to pass through thesearch_id/session_idfrom the first response.
5.1.1 [App V2] Search notes ⭐ Recommended
- Method: GET
- Path:
/api/v1/xiaohongshu/app_v2/search_notes - Official docs: docs.tikhub.io/420136398e0
- Parameters:
keyword(string, required): search keyword, e.g."美食推荐"page(integer, optional): page number, starting from1sort_type(string, optional): sort order,general(comprehensive, default) /time_descending(latest) /popularity_descending(most liked) /comment_descending(most commented) /collect_descending(most favorited) /english_preferred(English first)note_type(string, optional): note type,不限(default) /视频笔记/普通笔记/直播笔记time_filter(string, optional): publication time,不限(default) /一天内/一周内/半年内search_id(string, optional): when paging, pass the value from the first responsesearch_session_id(string, optional): when paging, pass the value from the first responsesource(string, optional): source, defaultexplore_feedai_mode(integer, optional): AI mode,0(off, default) /1(on)
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] Search notes
- Method: GET
- Path:
/api/v1/xiaohongshu/app/search_notes - Official docs: docs.tikhub.io/310965843e0
- Parameters:
keyword(string, required)page(integer, required): page number, starting from1search_id(string, optional): when paging, pass the value from the first responsesession_id(string, optional): when paging, pass the value from the first responsesort_type(string, optional):general(default) /time_descending/popularity_descending/comment_descending/collect_descendingfilter_note_type(string, optional):不限(default) /视频笔记/普通笔记filter_note_time(string, optional):不限(default) /一天内/一周内/半年内
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] Search notes
- Method: GET
- Path:
/api/v1/xiaohongshu/web_v3/fetch_search_notes - Official docs: docs.tikhub.io/438852171e0
- Parameters:
keyword(string, required)page(integer, optional): default1sort(string, optional):general(comprehensive, default) /time_descending(latest) /popularity_descending(hottest)note_type(integer, optional):0= all (default) /1= text/image /2= video
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 Search Users
⚠️ Note: App V1 does not have a user search interface; this section only includes the App V2 and Web V3 series.
Comprehensive example: using two series together to search users
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] Search users ⭐ Recommended
Returns 20 results per page by default, with pagination supported.
- Method: GET
- Path:
/api/v1/xiaohongshu/app_v2/search_users - Official docs: docs.tikhub.io/420136399e0
- Parameters:
keyword(string, required): search keyword, e.g."美食博主"page(integer, optional): page number, starting from1search_id(string, optional): when paging, pass the value from the first responsesource(string, optional): source, defaultexplore_feed
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] Search users
- Method: GET
- Path:
/api/v1/xiaohongshu/web_v3/fetch_search_users - Official docs: docs.tikhub.io/438852172e0
- Parameters:
keyword(string, required)page(integer, optional): default1
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. Topics
Xiaohongshu topic-related interfaces are divided into two parts: topic details and note list under a topic.
⚠️ Important note:
- The Web V3 series does not have topic interfaces; this section only includes the App V2 and App V1 series.
- App V1's old interface
/api/v1/xiaohongshu/app/get_notes_by_topicis deprecated; please useget_topic_notesin this section instead.- All interfaces use
page_id(topic/topic tag ID) as the unique identifier.
6.1 Topic Details
Only App V2 provides the topic details interface (topic name, views, discussion count, share information, etc.). App V1 / Web V3 do not have the corresponding capability.
6.1.1 [App V2] Get topic details ⭐ App V2 only
- Method: GET
- Path:
/api/v1/xiaohongshu/app_v2/get_topic_info - Official docs: docs.tikhub.io/420136407e0
- Parameters:
page_id(string, required): topic page ID, e.g."5c1cc866febed9000184b7c1"source(string, optional): source, defaultnormalnote_id(string, optional): source note ID, can be passed when jumping to a topic from a note
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 Topic Note List (notes under a topic)
Get the list of notes under a certain topic/topic tag. Both App V2 and App V1 provide this, but the parameters and pagination fields differ significantly and need to be adapted separately.
Comprehensive example: using two series together to get topic notes
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)Tip: the success check above (
code == 200) is only illustrative. In practice, please judge based on the JSON fields returned by each series; when paging, remember to pass through the corresponding cursor field (the fields differ between the two series, see below).
6.2.1 [App V2] Get topic note list ⭐ Recommended
- Method: GET
- Path:
/api/v1/xiaohongshu/app_v2/get_topic_feed - Official docs: docs.tikhub.io/420136408e0
- Parameters:
page_id(string, required): topic page IDsort(string, optional):trend(hottest, default) /time(latest)cursor_score(string, optional): pagination cursor score; when paging, pass thecursor_scoreof the last item on the previous pagelast_note_id(string, optional): when paging, pass the last note ID from the previous page (items[-1].id)last_note_ct(string, optional): when paging, pass the creation time of the last note from the previous page (items[-1].create_time)session_id(string, optional): session ID, keep consistent when pagingfirst_load_time(string, optional): initial load timestamp, keep consistent when pagingsource(string, optional): source, defaultnormal
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 works by topic tag (replacement for deprecated get_notes_by_topic)
⚠️ App V1's old interface
/api/v1/xiaohongshu/app/get_notes_by_topicis deprecated; please use this interface directly.
- Method: GET
- Path:
/api/v1/xiaohongshu/app/get_topic_notes - Official docs: docs.tikhub.io/454758056e0
- Parameters:
page_id(string, required): topic tag IDfirst_load_time(string, required): first request timestamp (milliseconds), Python retrieval:int(time.time() * 1000)sort(string, optional):hot(comprehensive, default) /time(latest) /trend(hottest)last_note_ct(string, optional): when paging, pass thecreate_timeof the last note on the previous pagelast_note_id(string, optional): when paging, pass the last note ID from the previous pagecursor_score(string, optional): when paging, pass thecursor_scoreof the last note on the previous pagesession_id(string, optional): session ID, generated by the server on the first request, return it when paging
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# }