Answers

How do I export all comments from a Xiaohongshu note to Excel or CSV?

Short answer

Call the okdata Xiaohongshu note comments endpoint with the note ID and keep passing the cursor until it runs out; each page of about 10 comments costs $0.02. 1,000 comments take 100 calls and cost $2.00, with text, time, likes, reply count and IP location for each.

A competitor's product note has 2,000 comments and you want them in a spreadsheet to read what people actually complain about. Scrolling in the app stops loading after a while, and scrapers often return only the first ten comments or time out halfway. Here is the approach that runs to the end. The comments endpoint pages through all of them for you, and a short script writes the CSV.

The endpoint

Xiaohongshu note comments takes the note ID and returns about 10 comments per call, each with the comment text, the time it was posted, the commenter's name and ID, likes, the number of replies under it and the IP location Xiaohongshu shows. page.next_cursor points at the next page; when page.has_more is false you have them all.

The note ID is the 24-character string after /explore/ in the link. If you only have an xhslink.com share link, call note detail once with url= and read id from the result.

Cost

Comments Calls Cost
200 20 $0.40
1,000 100 $2.00
2,000 200 $4.00

Every page is charged when it comes back. Set a page cap if you only want a sample.

Script: note ID to CSV

import csv, os, requests

URL = "https://api.okdata.online/v1/xiaohongshu/notes/comments/list"
HEAD = {"Authorization": f"Bearer {os.environ['OKDATA_API_KEY']}"}
note_id, cursor, max_pages = "6650a1b2000000001e00abcd", None, 200

with open("comments.csv", "w", newline="", encoding="utf-8-sig") as f:
    w = csv.writer(f)
    w.writerow(["published_at", "author", "text", "likes", "replies", "ip_location"])
    for _ in range(max_pages):
        params = {"id": note_id, **({"cursor": cursor} if cursor else {})}
        body = requests.get(URL, headers=HEAD, params=params, timeout=60).json()
        for c in body["data"]["items"]:
            w.writerow([c["published_at"], c["author"]["name"], c["text"], c["likes"], c["replies"], c["ip_location"]])
        if not body["page"]["has_more"]:
            break
        cursor = body["page"]["next_cursor"]

utf-8-sig makes Excel open the Chinese text correctly.

Why you get fewer rows than the counter

  • The comment count on the note includes replies. This endpoint returns top-level comments; replies are counted in each row's replies but not listed.
  • Comments the author or the platform has hidden or deleted are not public.
  • Commenter follower counts are null here; look up interesting commenters with the account profile.

Other ways

For one note, copying by hand is fine. MediaCrawler can collect comments and replies with a logged-in account if you accept the account risk. For comment reports across dozens of notes, the word-of-mouth page shows how to go from search to comments to a summary.

Updated