{
  "openapi": "3.0.1",
  "info": {
    "title": "RedNote Xiaohongshu Scraper — Posts, Comments, Profiles, Video",
    "description": "Scrape RedNote (Xiaohongshu) posts, comments, profiles and video — six modes in one Actor. Chinese social media and user generated content at the source: Chinese reviews, China consumer opinion, china market research and the creator data behind influencer marketing. No login for posts and profiles.",
    "version": "2.9",
    "x-build-id": "7dLWNPLBSyDkqSYMv"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/zhorex~rednote-xiaohongshu-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-zhorex-rednote-xiaohongshu-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/zhorex~rednote-xiaohongshu-scraper/runs": {
      "post": {
        "operationId": "runs-sync-zhorex-rednote-xiaohongshu-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/zhorex~rednote-xiaohongshu-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-zhorex-rednote-xiaohongshu-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "required": [
          "mode"
        ],
        "properties": {
          "mode": {
            "title": "Scraping Mode",
            "enum": [
              "user_posts",
              "profile",
              "post_details",
              "comments",
              "video",
              "search"
            ],
            "type": "string",
            "description": "Choose what you want to scrape from RedNote. Which modes work WITHOUT cookies: 'User Posts' and 'User Profile' run anonymously (RedNote gates the per-post note ID on anonymous profile feeds, so you get title / likes / cover / type but not post URLs). 'Post Details', 'Post Comments' and 'Video Download' work anonymously as long as the URL you paste still carries its xsec_token — copy the full URL straight from the browser or the app's share sheet. Note that anonymous profile feeds do NOT expose that token, so you cannot source it from this Actor's own cookieless output; with a cookieString you can. 'Search Posts' is the one mode RedNote reserves for logged-in sessions: anonymous keyword runs get served a generic recommendation feed, which this Actor detects and drops rather than bill you for it — so add a cookieString (Advanced, below) before using search.",
            "default": "user_posts"
          },
          "searchQuery": {
            "title": "Search Query",
            "type": "string",
            "description": "The search term to look for on RedNote. Required for 'search' mode. Note: RedNote gates real keyword-search results behind a logged-in session — anonymous runs are often served a generic recommendation feed instead of query matches. The Actor detects this and returns only genuine matches (you are never charged for an unrelated feed). For reliable keyword search, supply your own logged-in cookieString under Advanced below."
          },
          "userUrl": {
            "title": "User Profile URL",
            "type": "string",
            "description": "RedNote user profile URL or user ID. Required for 'user_posts' and 'profile' modes. Example: https://www.xiaohongshu.com/user/profile/USER_ID Tip: to watch several creators in ONE run (and one Schedule), use <b>Profile URLs (bulk)</b> below instead — it is cheaper per post, because browser startup is paid once for the whole batch."
          },
          "userUrls": {
            "title": "More profile URLs (bulk — one run, many creators)",
            "type": "array",
            "description": "One run, many creators. Prefilled with two profiles verified to return posts on an anonymous residential IP, so your first run comes back with data — measured at 16-61 posts per run. Swap in the creators you track: a watchlist here pulls every creator's recent posts in a single run, and one browser start covers the whole batch, so it is cheaper per post than one run per profile. Note: RedNote serves anonymous profile feeds from a per-IP gate — some accounts return an empty feed without a <code>cookieString</code>, and the Actor skips those without charging you. Want a hands-off daily feed instead of full pulls? Put this on an Apify Schedule and turn on <code>deltaMode</code> — but read what that changes under Delta mode below before you do: it bills only unseen posts, so a full pull and a watch cost very different amounts.",
            "items": {
              "type": "string"
            }
          },
          "postUrls": {
            "title": "Post URLs",
            "type": "array",
            "description": "One or more RedNote post URLs. Required for 'post_details', 'comments', and 'video' modes. IMPORTANT: keep the whole URL including '?xsec_token=...' — copy it from your browser's address bar or the app's Share > Copy Link. A bare /explore/<id> URL without the token only works if you also supply a cookieString, because RedNote refuses to serve the post to anonymous callers without one.",
            "items": {
              "type": "string"
            }
          },
          "maxResults": {
            "title": "Max results (set higher for bulk runs)",
            "minimum": 0,
            "maximum": 5000,
            "type": "integer",
            "description": "Maximum number of results to return per run. Applies to search, user_posts, and comments modes. Typical patterns: 20-50 for one-off lookups, 200-500 for daily monitoring crons, 1,000-5,000 for KOL monitoring / brand sweeps / AI training corpus pulls. 0 = unlimited. Cost preview per 1,000 results: posts $40, comments $20, profiles $80, video $100 — you are billed per result actually extracted, and records that fail extraction are neither returned nor charged.",
            "default": 100
          },
          "sortBy": {
            "title": "Sort By",
            "enum": [
              "general",
              "time_descending",
              "popularity_descending"
            ],
            "type": "string",
            "description": "Sort order for search results.",
            "default": "general"
          },
          "filterByType": {
            "title": "Filter by Content Type",
            "enum": [
              "all",
              "note",
              "video"
            ],
            "type": "string",
            "description": "Filter results by content type.",
            "default": "all"
          },
          "filterByMinLikes": {
            "title": "Minimum Likes",
            "minimum": 0,
            "type": "integer",
            "description": "Only return posts with at least this many likes. 0 = no filter.",
            "default": 0
          },
          "includeComments": {
            "title": "Include Comments",
            "type": "boolean",
            "description": "When scraping posts (search, user_posts, post_details), also scrape comments for each post. This will slow down the scraper and increase costs.",
            "default": false
          },
          "maxComments": {
            "title": "Max Comments per Post",
            "minimum": 1,
            "maximum": 5000,
            "type": "integer",
            "description": "Maximum number of comments to scrape per post. Only used when includeComments is true or mode is 'comments'.",
            "default": 100
          },
          "proxyConfiguration": {
            "title": "Proxy Configuration",
            "type": "object",
            "description": "Proxy settings. <b>Leave this as it comes: Apify Proxy on automatic (datacenter).</b> Measured 2026-08-26 on two creator profiles, same input, datacenter against residential: <b>66 rows vs 61, at 39% of the cost</b> — datacenter returned MORE posts for less than half the money, because residential bills every megabyte the browser downloads and this Actor moves ~3 MB per profile. The old default forced RESIDENTIAL on everyone on the basis that RedNote blocks datacenter IPs; that is no longer true for creator profiles and feeds. <b>When to switch to RESIDENTIAL:</b> if a run comes back with no posts on a profile you know is public, or the log shows every pre-flight probe failing — set apifyProxyGroups: [\"RESIDENTIAL\"] for that run. It costs roughly 2.5x more, so use it as the fallback it is, not as the default.",
            "default": {
              "useApifyProxy": true
            }
          },
          "concurrency": {
            "title": "Concurrency",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "Number of pages processed in parallel for the post_details / comments / video modes (single-page modes ignore this). Higher = faster but uses more memory. Capped at 10 — above that, RESIDENTIAL proxy and Xiaohongshu rate limits become the bottleneck.",
            "default": 4
          },
          "blockResources": {
            "title": "Block non-essential resources",
            "type": "boolean",
            "description": "When enabled, images / fonts / tracking pixels are blocked at the network layer. Cuts bandwidth ~50% with no impact on extracted data (media URLs are still emitted in the output — only the bytes are skipped). Disable only for debugging.",
            "default": true
          },
          "liteMode": {
            "title": "Lite mode — 3-10x faster, recommended for bulk runs",
            "type": "boolean",
            "description": "Recommended for bulk monitoring (>500 results / run) and AI training corpus pulls where you only need post metadata, not full body content. When enabled, returns only essential fields per item (postId, postUrl, xsecToken, title, likes, type, scrapedAt for posts; minimal subset for profiles). Skips body content, image lists, comment expansion. The xsec_token in postUrl is preserved so search → post_details two-stage pipelines still work on lite output. 3-10x faster than full mode.",
            "default": false
          },
          "sentimentAnalysis": {
            "title": "Sentiment analysis (Chinese)",
            "type": "boolean",
            "description": "Tag each post / comment with Chinese sentiment — polarity (positive / neutral / negative) + a -1.0…+1.0 score (SnowNLP model for Chinese text, keyword fallback for English). Ideal for brand-sentiment tracking on first-person consumer reviews. Optional add-on, off by default.",
            "default": false
          },
          "deltaMode": {
            "title": "Delta mode — only new since last run (search / user_posts)",
            "type": "boolean",
            "description": "Returns ONLY posts not seen in previous runs of the same stream — a scheduled brand or KOL monitor that hands you just the new posts each run, with no de-duplication on your side. <b>Understand the trade before you switch it on:</b> a full pull returns a creator's whole recent feed (typically 16-61 posts) and bills for all of them; a delta run returns only what has appeared since the last run, so on a quiet day it returns nothing and bills nothing. Creators post a few times a week, so a daily delta monitor is a small trickle by design, not a broken run. Pick delta when you want to be told what is NEW; leave it off when you want the data itself.",
            "default": false
          },
          "deltaStateKey": {
            "title": "Delta state key",
            "type": "string",
            "description": "Names an independent delta stream so multiple scheduled monitors don't collide (e.g. 'nike-daily' vs 'adidas-daily'). Seen-post state persists across runs under this key. Only used when deltaMode is on.",
            "default": "default"
          },
          "networkCapture": {
            "title": "Network response capture (v2.1 fast path)",
            "type": "boolean",
            "description": "Capture data-bearing API responses directly during page load for faster extraction. Falls back to Vue state / DOM parsing automatically when capture finds nothing — disable only for debugging. No effect on output schema.",
            "default": true
          },
          "cookieString": {
            "title": "Cookie string (needed for Search; optional elsewhere)",
            "type": "string",
            "description": "<b>You do not need this for the default path.</b> Anonymous <code>user_posts</code> and <code>profile</code> runs return posts on their own — measured at 16-61 posts per run against a plain creator watchlist. Add a cookie when you need one of these four things: <b>(1) keyword Search</b> — RedNote reserves real query matching for logged-in sessions, and anonymous search is served a generic recommendation feed, which this Actor detects and drops rather than bill you for; <b>(2) per-post note IDs and ready-to-pipe post URLs</b> out of user_posts, so you can chain into post_details or comments; <b>(3) full profile fields</b>; <b>(4) post_details on URLs that have lost their xsec_token.</b> <b>How to copy it in about 30 seconds:</b> (1) open xiaohongshu.com in your browser and log in, (2) press F12 and open the Network tab, (3) reload the page and click any request, (4) copy the whole <code>cookie:</code> request header and paste it here. It is your own session; it is never logged or stored by this Actor."
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}