# RedNote (Xiaohongshu) Scraper (`devcake/rednote-scraper`) Actor

Scrape Xiaohongshu posts by keyword, collect comments and replies from post links, and export titles, authors, engagement, images and full details, no cookies required.

- **URL**: https://apify.com/devcake/rednote-scraper.md
- **Developed by:** [devcake](https://apify.com/devcake) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.50 / 1,000 search results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Search RedNote posts and collect comments

Find RedNote (Xiaohongshu) posts by keyword and collect comments from selected posts. This RedNote search and comments scraper produces an Apify dataset for content research, engagement comparison, and product feedback.

### What can you do with this RedNote scraper?

- 🔎 **Discover posts** by keyword, publication window, and post type.
- 🖼️ **Collect post data:** titles, authors, engagement, and optional full details.
- 💬 **Read conversations:** collect comments and optional replies from supplied posts.
- 📤 **Export and repeat:** download CSV, Excel, or JSON and schedule runs on Apify.

**Keyword searches return posts. Comments are collected only from the post URLs or IDs you provide; finding a post does not automatically collect its comments.** Both operations can run independently in the same run. The Actor does not search creator profiles, download media files, or fetch full post details from a link alone.

### How to search Xiaohongshu posts

1. Open **Input** and replace the sample keyword with your topic.
2. Set **Max results**, **Search order**, **Note type**, and **Published within** as needed.
3. Enable **Include full note details** for more post content.
4. Click **Start**, then open **Output** when finished.

Search starts with your selected order and may supplement results from other orders if more results are needed. Each post's `sortSource` identifies its discovery order; the combined results are not guaranteed to be globally sorted by popularity or date.

### How to collect RedNote comments and replies

1. Paste post links or IDs into **Post URLs**.
2. Set **Max comments per post**, **Comment order**, and reply options.
3. For a **comments-only** run, clear the sample keyword (`keywords: []` in JSON input).
4. Click **Start**, then select the **Comments** output.

To collect comments from discovered posts: run a keyword search → select posts → start another run with their IDs in **Post URLs**. Keeping keywords also runs a separate search.

### Input reference

Limits are maximums, not guaranteed result counts.

| Input field | Default | Options and limits |
| --- | --- | --- |
| `keywords` | Form prefill: `旅行` (travel) | Up to 20 keywords. Clear for comments-only runs. |
| `maxResults` | `20` | 1–500 unique posts **per keyword**, not per run. |
| `sortType` | `general` | Most relevant (`general`), most popular (`popularity_descending`), or newest (`time_descending`). Other orders may supplement results. |
| `noteType` | `all` | `all`, `video`, `image`, or `live`. |
| `timeFilter` | `all` | Any time (`all`), past day (`1d`), past week (`1w`), or past six months (`6mo`). |
| `includeNoteDetails` | `false` | Add available full text, dates, tags, and media information; enriched, delivered posts incur a separate detail charge. |
| `noteUrls` | Empty | Up to 20 post URLs or IDs for comment collection. |
| `maxCommentsPerNote` | `20` | 1–1,000 top-level comments per post; excludes nested replies. |
| `sortBy` | `recommended` | `recommended`, `latest`, or `most_liked`. Sorting applies to accessible comments. |
| `includeReplies` | `true` | Include replies beneath each top-level comment. Set `false` to omit replies. |
| `maxRepliesPerComment` | `5` | 1–100 replies per comment; `0` requests all accessible replies, subject to collection limits. Applies when replies are enabled. |

### What data will you get?

| Result | What you can expect |
| --- | --- |
| 🔎 Search result | Post ID, link, keyword, title, type, author, cover, and available engagement counts. |
| 🖼️ Full note details | Available full text, publication/update dates, tags, gallery links, and video information. |
| 💬 Comment | Text, comment/post IDs, author, time, likes, post link, and nested replies. |

Choose an output, then a view:

| Output | Views | Best for |
| --- | --- | --- |
| **All results** | All results | Every delivered post and comment, with text previews, authors, dates, and likes. This is the default dataset. |
| **Posts** | Notes overview / Note details | Scan search results or read full text, tags, and media when available. Contains posts only. |
| **Comments** | Comments / Comment details | Scan comments, image attachments, and reply counts, or inspect complete text and nested replies. Contains comments only. |

Posts found under multiple keywords retain each context but are charged once per run. Copies in separate outputs add no result charges. `previewText` gives untitled posts and image-only comments a readable preview without changing their original text.

#### Export comments and replies

For a comments-only export, open **Storage**, select the `comments` dataset, then export **JSON** with all fields to preserve nested replies. The Run page's general Export button uses the default dataset, which includes both types in mixed runs. CSV/Excel can use flat author, date, and count fields; replies require a separate transformation for one reply per row.

`recordType` identifies `search_note` or `comment`. Match a comment's `noteId` (also `note_id`) to a post's `id`; its own `id` identifies the comment. Comments include flat `authorName`, `likesCount`, and UTC `publishedAt`, while preserving `user`, `like_count`, and Unix-seconds `time` for existing integrations. `repliesCount` is the reported total; `collectedRepliesCount` counts distinct delivered replies across both reply arrays.

### Example output

These are shortened, fictional rows; actual fields depend on availability. Post links are omitted, and gallery links use `example.com` placeholders.

#### 🔎 Simple keyword search

With **Include full note details** off, a search for **旅行** might return:

```json
{
  "recordType": "search_note",
  "id": "6a44e9d00000000000000001",
  "keyword": "旅行",
  "sortSource": "general",
  "title": "Weekend travel ideas",
  "previewText": "Weekend travel ideas",
  "noteType": "normal",
  "authorName": "Travel Notes",
  "likesCount": 124,
  "commentsCount": 8,
  "savesCount": 23,
  "detailStatus": "card_only"
}
```

#### 🖼️ Search with full note details

Turn **Include full note details** on to add available text, dates, tags, and media information to the same post:

```json
{
  "recordType": "search_note",
  "id": "6a44e9d00000000000000001",
  "keyword": "旅行",
  "title": "Weekend travel ideas",
  "previewText": "Weekend travel ideas",
  "description": "Three quiet places to visit this weekend...",
  "noteType": "normal",
  "authorName": "Travel Notes",
  "likesCount": 124,
  "publishedAt": "2026-07-01T10:20:00+00:00",
  "tagNames": ["旅行", "weekend trips"],
  "imageCount": 2,
  "imageUrls": [
    "https://example.com/gallery-1.jpg",
    "https://example.com/gallery-2.jpg"
  ],
  "detailStatus": "complete"
}
```

#### 💬 Post comments and replies

For a post link, each top-level comment is one row. Requested replies are nested inside it:

```json
{
  "recordType": "comment",
  "id": "comment-001",
  "note_id": "6a44e9d00000000000000001",
  "noteId": "6a44e9d00000000000000001",
  "content": "This looks lovely! Which trail is it?",
  "previewText": "This looks lovely! Which trail is it?",
  "authorName": "Weekend Explorer",
  "likesCount": 12,
  "publishedAt": "2026-07-01T11:20:00+00:00",
  "repliesCount": 1,
  "collectedRepliesCount": 1,
  "like_count": 12,
  "time": 1782904800,
  "user": {
    "userid": "reader-001",
    "nickname": "Weekend Explorer"
  },
  "sort_by": "recommended",
  "sub_comment_count": 1,
  "sub_comments": [],
  "replies": [
    {
      "id": "reply-001",
      "note_id": "6a44e9d00000000000000001",
      "content": "It's near the lake!",
      "like_count": 2,
      "time": 1782908400,
      "user": {
        "userid": "creator-001",
        "nickname": "Travel Notes"
      }
    }
  ]
}
```

`sub_comments` is an inline preview; `replies` contains requested replies. They can overlap, or the preview can be empty. Deduplicate by reply `id` if combining them.

### Ideas for using your results

| User job | Recommended setup | What to use |
| --- | --- | --- |
| Content research | Topic keywords + full note details | Post text, tags, authors, and media links for content examples. |
| Engagement comparison | Topic keywords; full details off | Available likes, comments, saves, and shares for per-post comparison. |
| Product feedback | Selected product or campaign post URLs + replies | Comment conversations for feedback analysis. |
| Recurring topic research | Recent time window + newest-first search + scheduled runs | Compare post IDs, dates, and engagement across runs; check the search order and whether dates are approximate. |
| Creator discovery | Topic keywords | Review authors appearing in results and their posts' visible engagement. |

Perform comparisons, sentiment analysis, engagement-rate calculations, and trend scoring separately. Scheduling repeats collection without adding these analyses.

### How much does it cost?

Result charges apply when records are delivered. Prices below are in USD **per 1,000 results**:

| Delivered result | Free | Starter | Scale | Business |
| --- | ---: | ---: | ---: | ---: |
| 🔎 Search result | $5.00 | $4.50 | $4.00 | $3.50 |
| 🖼️ Full note details, added to a search result | +$5.00 | +$4.33 | +$3.67 | +$3.00 |
| 💬 Top-level comment | $3.50 | $3.00 | $2.50 | $2.00 |
| ↩️ Reply | $1.50 | $1.33 | $1.17 | $1.00 |

For example, on **Starter**, 20 distinct search results cost **$0.09**. If all 20 also have full note details, the total is **$0.1766** (about **$0.18**), plus the Actor Start charge. At the default setup, the **Actor Start** charge is **$0.00005**, and platform usage is included. Comments and replies are charged separately only when delivered. The same distinct post, comment, or reply ID is not charged twice within a run. A run with no results can still incur the start charge. Check the Actor's **Pricing** tab for the current rates before you start.

### Good to know

#### Do I need to log in to RedNote?

No. You don't enter a RedNote password in the Actor's form. Access still depends on what RedNote makes available; if it requires verification or limits requests, collection stops rather than promising missing results.

#### Will I always get the number of posts or comments I request?

Not necessarily. A topic or post may have fewer accessible results, and collection limits can reduce the total. Some publication dates are approximate, which can affect date filtering.

#### Can I use a post link to get the full post and its comments?

A post link starts **comment collection**. Full note details are available for posts found through **search keywords**. Combining both inputs does not link the operations automatically. Content and availability can change, so review the dataset before using it for a decision.

# Actor input Schema

## `keywords` (type: `array`):

Enter one or more keywords. The sample keyword is only a starting point; each keyword gets its own result limit.

## `maxResults` (type: `integer`):

Choose the maximum unique notes per keyword. Start with 20 for a quick run.

## `sortType` (type: `string`):

Start with this search order. Other orders may supplement results; sortSource identifies each post's discovery order.

## `noteType` (type: `string`):

Choose which kinds of notes to include. Live notes are filtered from all-note results.

## `timeFilter` (type: `string`):

Keep notes within this time window. When a source date is missing, the note ID provides the date estimate.

## `includeNoteDetails` (type: `boolean`):

Off by default. Turn on for full text, publication date, tags, gallery and video details. Each unique delivered note then adds a detail charge.

## `noteUrls` (type: `array`):

Enter up to 20 Rednote post URLs or IDs to collect their comments. Clear keywords for comments-only runs, or keep keywords to run a separate search alongside comment collection.

## `maxCommentsPerNote` (type: `integer`):

Start with up to 20 top-level comments per post for a quick run. Increase the limit when needed; posts with fewer comments return fewer.

## `sortBy` (type: `string`):

Choose how to order comments. Newest and most liked require reading all accessible comment pages before sorting.

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

Collect replies to each top-level comment.

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

Limit replies attached to each comment. Zero requests all accessible replies.

## Actor input object example

```json
{
  "keywords": [
    "旅行"
  ],
  "maxResults": 20,
  "sortType": "general",
  "noteType": "all",
  "timeFilter": "all",
  "includeNoteDetails": false,
  "maxCommentsPerNote": 20,
  "sortBy": "recommended",
  "includeReplies": true,
  "maxRepliesPerComment": 5
}
```

# Actor output Schema

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

All delivered rows in the compatible default dataset, with a readable overview for every record type.

## `notes` (type: `string`):

Only keyword-discovered posts. Choose Notes overview to scan or Note details for full content and media.

## `comments` (type: `string`):

Only top-level comments, with author names, dates, likes, attachments, and nested replies.

# 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 = {
    "keywords": [
        "旅行"
    ],
    "maxResults": 20,
    "maxCommentsPerNote": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("devcake/rednote-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 = {
    "keywords": ["旅行"],
    "maxResults": 20,
    "maxCommentsPerNote": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("devcake/rednote-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 '{
  "keywords": [
    "旅行"
  ],
  "maxResults": 20,
  "maxCommentsPerNote": 20
}' |
apify call devcake/rednote-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,devcake/rednote-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/d9RDPVu5IPf6YTrqu/builds/ZCRjx52giGbcyElIY/openapi.json
