Social-data integrations often fail in boring places: a copied page token expires, a cursor is reused with the wrong resource, a timeout is mistaken for an empty page, or a missing metric is silently converted into zero.
I built the public examples for XHS Data API around those failure modes rather than around the happy path alone. The API exposes normalized public Xiaohongshu (RedNote) note details, top-level comments, author profiles, published-note pages, media inventories, and sequential batches.
The complete Python and Node.js examples are available from the developer website as a versioned download.
Start With A Complete Public URL
Detail and comment requests use the complete public note URL, including its current xsec_token. Keep the URL and RapidAPI key in server-side environment variables:
export X_RAPIDAPI_KEY="your_rapidapi_key"
export XHS_NOTE_URL="complete_current_public_note_url"
First validate the URL locally:
parsed = client.parse_note_url(os.environ["XHS_NOTE_URL"])
detail = client.detail_from_url(os.environ["XHS_NOTE_URL"])
print(parsed["note_id"], detail["note"].get("title"))
The parser does not fetch upstream data. This separates malformed-input errors from upstream availability errors before the expensive step begins.
Treat Cursor State As A Contract
The first comment request has no cursor. Every later request must use the exact next_cursor returned by the previous page and keep the same note URL:
cursor = None
seen = set()
while True:
page = client.comments_page(note_url, cursor=cursor, count=10)
for comment in page["items"]:
if comment["comment_id"] not in seen:
seen.add(comment["comment_id"])
yield comment
if not page["has_more"]:
break
cursor = page["next_cursor"]
The client repository also deduplicates IDs defensively. A cursor is short-lived and resource-bound; editing it or moving it to another note is a client error.
A Timeout Is Not An Empty Page
When an upstream page cannot finish within the service budget, the API returns a structured error instead of 200 with an empty list:
{
"code": 503,
"msg": "Comments did not load",
"error_code": "REQUEST_TIMEOUT",
"data": {
"request_id": "support-id",
"retry_after": 3
}
}
Wait for Retry-After, then retry the identical URL and cursor. Do not advance the chain. Long cooldowns are intentionally not hidden behind aggressive automatic retries.
Preserve Unknown Values
Public profile cards and note summaries do not always contain full engagement or media fields. The normalized contract returns null when the source did not supply a value. That is different from numeric zero and boolean false.
This detail matters in dashboards. Converting unknown likes to zero changes averages, rankings, and trend lines. The user-note endpoints expose content coverage so an application can choose a lightweight summary page or request a small detail-enriched page.
Keep Support IDs, Not Secrets
Every response includes data.request_id. Log that ID with the endpoint and HTTP status. Do not log RapidAPI keys, cookies, browser state, or complete signed URLs.
Try The Examples
The repository includes:
- a reusable Python client with structured errors and bounded retries;
- Node.js 20 examples using built-in
fetch; - duplicate-safe comment and user-note pagination;
- asynchronous batch submission and polling;
- troubleshooting guidance for
400,401,403,429, and503responses.
Start with the developer guides or download the client examples. The current public API focuses on stable read workflows and does not advertise note search or child-comment replies.
XHS Data API is independent and is not affiliated with or endorsed by Xiaohongshu/RedNote. Use public data lawfully and follow applicable law, third-party rights, and source-platform rules.
Top comments (0)