How to search Xiaohongshu notes and export them to CSV
Two endpoints: Xiaohongshu note search, paged with its cursor, then Xiaohongshu note detail for the notes whose full text and images you need. The worked example below is 8 calls and costs $0.16; a failed call is not charged.
Updated
The job: you want a spreadsheet of what Xiaohongshu shows for a keyword, the notes, who wrote them and how they did, plus the complete text and pictures of the handful that stand out. Content teams use it to brief writers, product teams to see how people describe a category, analysts to track a topic week by week. Search returns note cards; detail returns the whole note. You end with one CSV: every note from the search pages, and for the top five also the full text and every image URL.
No Xiaohongshu account, cookie or xsec_token is involved.
Step by step
Step 1: search, with sort and type
Call Xiaohongshu note search with query the way a person types it: 露营, 露营 装备清单, 新手露营. Two parameters change what you get:
sort:general(the default, Xiaohongshu's own ranking),latest(newest first) orpopular(most engagement first).latestis the one for tracking a topic over time;popularfor "what works".type:all(the default),imagefor image notes orvideofor video notes.
One call returns about 20 notes for $0.02. Each card has id, url, type, title, author (name and ID), published_at, hashtags and metrics: likes, favorites (saves), comments and shares. The text on a search card is only the opening of the note, and images usually holds the cover alone.
curl -G "https://api.okdata.online/v1/xiaohongshu/notes/search" \
-H "Authorization: Bearer $OKDATA_API_KEY" \
--data-urlencode 'query=露营' \
--data-urlencode 'sort=latest' \
--data-urlencode 'type=image'
Step 2: page through the results
For the next page, send page.next_cursor back as cursor, unchanged, with the same query, sort and type. Stop when page.has_more is false, or when you have enough: every page is one call. Results drift further from your keyword the deeper you page, so a few pages of a narrow query (露营 装备清单) usually tell you more than many pages of a broad one (露营).
Step 3: fetch full notes for the ones you keep
Xiaohongshu note detail takes id (or a note link or xhslink share link as url) and returns the full note for $0.02: the whole text, every image in images, hashtags, and fresh metrics. A video note gives its cover image, not the video file.
curl -G "https://api.okdata.online/v1/xiaohongshu/notes/get" \
-H "Authorization: Bearer $OKDATA_API_KEY" \
--data-urlencode 'id=672a4f1d000000001b03c58e'
Fetch detail only for the notes you will read. Search cards already carry the counts, so a table of 60 notes with likes and saves needs no detail calls at all.
Step 4: the script
The script reads three pages of the latest image notes, picks the five with the most saves, fetches them in full and writes one CSV with a row per note.
import csv
import os
import requests
API = "https://api.okdata.online"
HEADERS = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}
SEARCH_PAGES = 3 # each page is one call
FULL_NOTES = 5 # notes to fetch in full; each is one call
def get(path, **params):
body = requests.get(API + path, headers=HEADERS, params=params, timeout=60).json()
if body["code"] != "ok":
raise RuntimeError(f"{body['code']}: {body['message']} (charged: {body['charged']})")
return body
notes, cursor = [], None
for _ in range(SEARCH_PAGES):
params = {"query": "露营", "sort": "latest", "type": "image", **({"cursor": cursor} if cursor else {})}
body = get("/v1/xiaohongshu/notes/search", **params)
notes += body["data"]["items"]
if not body["page"]["has_more"]:
break
cursor = body["page"]["next_cursor"]
notes = list({n["id"]: n for n in notes}.values()) # drop repeats across pages
top = sorted(notes, key=lambda n: n["metrics"]["favorites"] or 0, reverse=True)[:FULL_NOTES]
full = {n["id"]: get("/v1/xiaohongshu/notes/get", id=n["id"])["data"]["item"] for n in top}
with open("xhs_notes.csv", "w", newline="", encoding="utf-8-sig") as f:
out = csv.writer(f)
out.writerow(["id", "title", "author", "published_at", "likes", "saves", "comments", "url", "full_text", "images"])
for n in notes:
d = full.get(n["id"])
m = (d or n)["metrics"]
out.writerow([n["id"], n["title"], n["author"]["name"], n["published_at"], m["likes"], m["favorites"],
m["comments"], n["url"], d["text"] if d else "", " ".join(d["images"] or []) if d else ""])
utf-8-sig lets Excel open the file with the Chinese intact. Ten search pages and 20 full notes would be $0.60.
Good to know
- No view counts. Xiaohongshu does not show views publicly, so
metrics.viewsis null andmeta.unavailablegivesplatformas the reason. Saves (favorites) are the best signal of a note people want to keep. - Times are UTC.
published_atis ISO 8601 in UTC; add eight hours for Beijing time. - Note links.
urlis the plainxiaohongshu.com/explore/<id>link. Opened in a browser without a token it may not load; the xsec_token answer explains why and what to do. - Deleted is free. A note removed between search and detail returns
not_foundand is not charged. - Retries without paying twice. Send an
Idempotency-Keyheader with each call. The same request with the same key within 24 hours returns the stored answer withmeta.replayed: trueand no new charge. - Images are links. Download the ones you need soon after the run; image links can stop working after a while.
For what a search costs at volume, see the Xiaohongshu note search price. To go from these notes to what readers say under them, read the comments with Xiaohongshu note comments.
What the example costs
Three pages of the latest image notes for 露营 (camping), then full text and images of the 5 notes with the most saves
| Endpoint | Calls | Price | Subtotal |
|---|---|---|---|
| Xiaohongshu note search | 3 | $0.02 | $0.06 |
| Xiaohongshu note detail | 5 | $0.02 | $0.10 |
| Total | 8 | $0.16 |
Prices in force when this page was built. A failed call costs nothing.
In your AI (MCP)
Connect the MCP server once, then say what you want. The agent finds these endpoints, reads their prices and calls them on your balance.
SaySearch Xiaohongshu for the latest image notes about 露营 (camping), three pages. Give me a table of every note with title, author, likes, saves, comments and link, and add the full text and image links for the 5 notes with the most saves.
What the agent sends to the call tool first
{
"endpoint": "xiaohongshu.notes.search",
"params": {
"query": "防晒霜 推荐"
},
"idempotency_key": "<a new UUID>"
}