# Social Note Comments Scraper (`jcgonz/social-note-comments-scraper`) Actor

Unofficial RedNote / Xiaohongshu comments scraper. Extract public comments, authors, likes, reply counts, locations, timestamps, and optional nested replies from post URLs. Export structured results to JSON, CSV, Excel, or use them through the Apify API.

- **URL**: https://apify.com/jcgonz/social-note-comments-scraper.md
- **Developed by:** [Julio Gonzalez](https://apify.com/jcgonz) (community)
- **Categories:** Social media, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.50 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Social Note Comments Scraper

Extract normalized comments and optional second-level replies from public RedNote / Xiaohongshu posts and save them to an Apify dataset.

> Unofficial tool. Not affiliated with, endorsed by, or operated by RedNote / Xiaohongshu.

### Input

- **Post URLs** — one or more public Xiaohongshu / RedNote post URLs or supported share links (required)
- **Maximum comments per post** — default `100`
- **Include replies** — default `false`
- **Maximum replies per comment** — default `20`
- **Comment order** — `Latest` or `Hot / most liked`

The input form requires at least one post URL, which prevents accidental empty runs.

### Output

Each dataset item is a normalized top-level comment or reply. Fields can include:

- item type (`comment` or `reply`)
- comment ID and parent comment ID
- comment/reply text
- author ID, name, and avatar URL when available
- like count
- timestamp
- location label when supplied by the source
- reply count for top-level comments
- source post URL

The public Actor does **not** expose the raw TikHub response object or the TikHub API credential.

### TikHub configuration

The Actor uses TikHub's Xiaohongshu App V2 API as its upstream provider. Configure this secret environment variable in the Actor settings:

`TIKHUB_API_KEY`

`TIKHUB_TOKEN` is accepted as an operator fallback.

For full Xiaohongshu URLs, the Actor extracts and sends `note_id`, which TikHub documents as preferred. For supported short/share links where the note ID cannot be extracted locally, it uses TikHub's `share_text` parameter.

### Pagination and replies

Top-level comments follow TikHub's documented pagination contract:

- first request: empty cursor, index `0`, pageArea `UNFOLDED`
- next request: reuse the previous response's cursor, index, and pageArea

Second-level replies follow TikHub's documented sub-comment pagination contract:

- first request: empty cursor, index `1`
- next request: reuse cursor and index from the previous response

Replies are fetched only when the top-level source metadata indicates that replies exist. This avoids blindly issuing a paid sub-comment request for every comment.

If a later pagination request is rejected after earlier pages succeeded, the Actor keeps the already returned dataset results and stops that pagination branch cleanly.

### Upstream safety controls

The Actor implements conservative TikHub request handling:

- one TikHub request at a time per Actor run
- minimum 500 ms interval between upstream requests by default
- maximum three attempts only for transient network/5xx failures
- exponential backoff with jitter
- HTTP/API `401`, `403`, and `429` immediately halt further TikHub requests in that run
- HTTP `400` and other request-specific client errors are not hammered with retries
- hard upstream request cap per run (default `2,000`)
- pagination loop protection
- duplicate dataset protection
- Apify spending-limit detection stops further upstream work as soon as the SDK reports the run limit has been reached
- clearly unrelated URLs are rejected before making a TikHub request

Operator-only environment variables:

- `TIKHUB_MIN_INTERVAL_MS` — default `500`; minimum enforced `250`
- `TIKHUB_MAX_REQUESTS_PER_RUN` — default `2000`

### API routes used

- `GET /api/v1/xiaohongshu/app_v2/get_note_comments`
- `GET /api/v1/xiaohongshu/app_v2/get_note_sub_comments`

### Verification

Run from inside the Actor folder:

```bash
python3.14 self_test.py
```

Expected output:

```text
Social Note Comments Scraper v1.0 final self-test passed (22 checks).
```

The release self-test covers exact first-request parameters, top-level pagination handoff, sub-comment pagination, preservation of first-page results after a later-page HTTP 400, nested replies, duplicate protection, spending-limit stop behavior, authentication/rate-limit circuit breakers, retry caps, request caps, serialization of concurrent calls, input validation, and Actor schemas.

### Responsible use

Use this Actor only for lawful purposes and public data, subject to applicable privacy, intellectual-property, and platform requirements. Do not use it to redistribute protected content without authorization or to expose upstream credentials/direct API access.

# Actor input Schema

## `postUrls` (type: `array`):

One or more public RedNote/Xiaohongshu post share URLs.

## `maxCommentsPerPost` (type: `integer`):

Maximum number of top-level comments to return for each post.

## `includeReplies` (type: `boolean`):

Also fetch second-level replies for comments that have replies.

## `maxRepliesPerComment` (type: `integer`):

Safety/cost limit for second-level replies under each top-level comment.

## `sort` (type: `string`):

Latest sorts by time; Hot sorts by like count.

## Actor input object example

```json
{
  "postUrls": [
    "https://www.xiaohongshu.com/explore/6764f52c000000000900c655"
  ],
  "maxCommentsPerPost": 10,
  "includeReplies": false,
  "maxRepliesPerComment": 20,
  "sort": "latest"
}
```

# Actor output Schema

## `results` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "postUrls": [
        "https://www.xiaohongshu.com/explore/6764f52c000000000900c655"
    ],
    "maxCommentsPerPost": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("jcgonz/social-note-comments-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "postUrls": ["https://www.xiaohongshu.com/explore/6764f52c000000000900c655"],
    "maxCommentsPerPost": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("jcgonz/social-note-comments-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "postUrls": [
    "https://www.xiaohongshu.com/explore/6764f52c000000000900c655"
  ],
  "maxCommentsPerPost": 10
}' |
apify call jcgonz/social-note-comments-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jcgonz/social-note-comments-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/RbJSImk1hty663oYm/builds/PtE6f9wo2FAZbGtps/openapi.json
