# Douban Scraper - Reviews, Ratings, Movies & Books (`scrapewise/douban-scraper`) Actor

Scrape Douban (豆瓣) without login: long-form reviews, short comments with ratings, and full subject data for movies, TV shows and books. Search, ready-made lists (Top 250, now showing) and subject URLs. Built for Chinese-language corpora, sentiment analysis and market research. Failed items are free.

- **URL**: https://apify.com/scrapewise/douban-scraper.md
- **Developed by:** [Scrapewise Data](https://apify.com/scrapewise) (community)
- **Categories:** Social media, News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.00 / 1,000 long-form reviews

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/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

## Douban Scraper: reviews, discussions, ratings, movies and books

Scrape [Douban](https://www.douban.com) (豆瓣), China's largest reviews and interest community,
**without an account**. Long-form reviews with their full text, **group discussions with the
whole post and its replies**, short comments with ratings, and complete subject records for
movies, TV shows and books, from search, from ready-made lists or from any URL.

Built for Chinese-language corpora, sentiment analysis, entertainment research and market
tracking, where what matters is **the text people wrote**, not only the score.

| What you need | What this Actor does | Typical price here |
|---|---|---|
| Long-form reviews with full text | `reviews` per subject, opened one by one | US$ 10.00 / 1,000 |
| Group discussions with the full post | topics from any group, newest first | US$ 10.00 / 1,000 |
| Replies inside a discussion | 50 per request | US$ 4.00 / 1,000 |
| Short comments with ratings | 20 per request, newest first | US$ 4.00 / 1,000 |
| Full subject record | rating, votes, genres, cast or author, synopsis | US$ 10.00 / 1,000 |
| Search and ready-made lists | Top 250, now in cinemas, hot TV, book lists | US$ 4.00 / 1,000 |

Rows that could not be delivered (removed subject, no reviews, a blocked page) come back with a
stable `errorCode` and **are never charged**.

### What you can ask for

| You send | You get |
|---|---|
| `urls`: `https://movie.douban.com/subject/1292052/`, `https://book.douban.com/subject/1084336/` or a bare id | the full subject record plus its long-form reviews (and short comments, if you ask) |
| `searchQueries`: `matrix`, `三体` | subjects matching the term, in Chinese or English |
| `collections`: `movie_top250`, `movie_showing`, `tv_hot`, `book_top250` | the list, up to `maxItems`, `rank` included |
| `groups`: `https://www.douban.com/group/732764/` or `732764` | that group's topics, each with the full post text, plus replies if you ask |
| `groups`: a single discussion URL `.../group/topic/<id>/` | just that thread and its replies |
| `searchQueries` with `searchType: group` | group profiles: name, members, topic count |

Available lists, with how many rows each one holds (checked 22/09/2026):

| List | Rows | What it is |
|---|---|---|
| `movie_top250` | 250 | Douban's all-time Top 250 films |
| `book_top250` | 250 | the same for books |
| `tv_hot` | 204 | TV shows people are watching now |
| `book_fiction`, `book_nonfiction` | 100 each | current fiction and non-fiction charts |
| `show_hot` | 60 | variety shows |
| `tv_domestic` | 49 | Chinese TV shows |
| `movie_showing` | 20 | now in cinemas |
| `movie_weekly_best` | 10 | the weekly critics' board |

Ask for more than a list holds and you simply get the whole list.

### Output

One row per thing, with `type` telling them apart: `subject`, `review`, `comment`, `group`,
`topic`. Discussion rows carry `groupId`, `groupName` and `topicId`, so replies join back to
their thread and their group.

```json
{
  "type": "review",
  "id": "1000369",
  "subjectId": "1292052",
  "subjectType": "movie",
  "title": "肖申克的救赎",
  "reviewTitle": "十年·肖申克的救赎",
  "rating": 5,
  "text": "距离斯蒂芬·金和德拉邦特们缔造这部伟大的作品已经有十年了……",
  "textLength": 2284,
  "createdAt": "2005-05-12 20:44:13",
  "voteCount": 4200,
  "commentsCount": 1082,
  "authorName": "某人",
  "url": "https://movie.douban.com/review/1000369/",
  "scrapedAt": "2026-09-22T18:40:11.002Z"
}
```

A `subject` row carries `title`, `originalTitle`, `year`, `ratingValue`, `ratingCount`,
`genres`, `countries`, `durations`, `directors`, `actors` for screen titles, and `author`,
`press`, `pubdate`, `pages` for books, plus `intro`, `commentCount`, `reviewCount` and
`coverUrl`.

#### Error codes

| errorCode | Meaning |
|---|---|
| `SUBJECT_NOT_FOUND` | The subject was removed, is private or never existed |
| `INVALID_SUBJECT` | The line is not a Douban subject URL or id |
| `NO_REVIEWS`, `NO_COMMENTS`, `NO_TOPICS` | That subject or group has nothing public of that kind |
| `GROUP_NOT_FOUND`, `TOPIC_NOT_FOUND` | The group or discussion is gone, private or never existed |
| `INVALID_GROUP`, `INVALID_TOPIC` | The line is not a Douban group or discussion URL or id |
| `NO_RESULTS` | The search term returned nothing public |
| `COLLECTION_NOT_FOUND` | No list with that name, or it came back empty |
| `BLOCKED` | Douban refused every retry for that request. Run again or switch the proxy group. |
| `ITEM_UNREADABLE` | One row came in a shape this Actor cannot read. Only that row is lost, and it is free. |
| `UNEXPECTED` | Something unforeseen broke on that request. The run keeps everything already delivered, and nothing extra is charged. |

### Pricing

Pay per event, no monthly fee and no charge per run:

| Event | Price |
|---|---|
| List item, short comment, reply or group profile | US$ 0.004 (US$ 4.00 per 1,000) |
| Full subject record | US$ 0.01 (US$ 10.00 per 1,000) |
| Long-form review or group topic | US$ 0.01 (US$ 10.00 per 1,000) |

A default run (one movie, its full record and 10 reviews) costs **US$ 0.11**. One thousand
reviews for a sentiment dataset cost **US$ 10.00**. The Top 250 list, as rows, costs **US$ 1.00**.
Twenty discussions from a group, with 50 replies each, costs **US$ 4.20**.

### How it works, and what it will not do

- **No login, no account, no cookies of yours.** Everything comes from Douban's public mobile
  API, the same one the mobile website calls.
- **Douban rate-limits by IP**, and the penalty lasts for minutes, so the Actor rotates sessions
  and IPs on every block and falls back to residential proxy. Keep the proxy on.
- **Only public content, and no user tracking.** Reviews and comments carry the text, the
  rating, the date and the display name. This Actor never returns user ids, profile links or
  avatars, and there is no mode to scrape a person's profile.
- Douban's desktop pages are behind a block page; this Actor does not try to break it, it uses
  the public mobile API instead.

### FAQ

**Do failed rows cost anything?** No. Only rows with real content are charged, and duplicates
inside a run are removed before charging.

**Can I get the complete review text?** Yes, `fullReviewText` is on by default and opens each
review. Turn it off and you get the abstract Douban shows in the list, at the same price.

**Chinese or English?** Both work in search. The content comes as Douban stores it, which for
most subjects is Chinese.

**Which rows have the most text?** Long-form reviews are the densest single rows, around a
couple of thousand characters each. Group discussions bring the volume instead: the post itself
plus dozens of replies, all of them text people wrote.

**Why are there two prices for a subject?** A row from a search or a list is cheap because it
comes 20 or 100 at a time. Opening the subject for the full record costs one request each, so it
is charged as a full record. `includeSubjectDetails` controls that, and it is off by default.

# Actor input Schema

## `urls` (type: `array`):

One per line. Movie, TV show or book pages (https://movie.douban.com/subject/1292052/, https://book.douban.com/subject/1084336/), group pages (https://www.douban.com/group/732764/) or a single discussion (https://www.douban.com/group/topic/123456789/). Bare ids work for subjects. Each subject returns its full record plus its long-form reviews; each group returns its topics.

## `searchQueries` (type: `array`):

Keywords to search on Douban, one per line. Chinese and English both work. Each term returns up to 'Max items' subjects.

## `searchType` (type: `string`):

Which catalogue the search terms run against. 'Groups' returns group profiles you can then feed into the groups field.

## `collections` (type: `array`):

Douban list names, one per line. Sizes checked on 22/09/2026: movie\_top250 (250), book\_top250 (250), tv\_hot (204), book\_fiction (100), book\_nonfiction (100), show\_hot (60), tv\_domestic (49), movie\_showing (20, now in cinemas), movie\_weekly\_best (10). Asking for more than a list holds returns the whole list.

## `groups` (type: `array`):

Group URLs or ids (https://www.douban.com/group/732764/, 732764) return that group's topics with the full post text. A discussion URL (https://www.douban.com/group/topic/123456789/) returns just that thread. Groups are where the long Chinese-language discussion lives.

## `maxItems` (type: `integer`):

Maximum subjects per search term or per list. Subject URLs are always returned in full.

## `maxReviewsPerSubject` (type: `integer`):

Long-form reviews to fetch for each subject, on top of the subject itself. Off by default because every review is charged like a subject: asking for one movie with 10 reviews costs 11 items, not 1. Set 5 or 10 when the reviews are what you came for.

## `fullReviewText` (type: `boolean`):

Opens each review to get the complete text instead of the abstract (one extra request per review). Same price.

## `maxCommentsPerSubject` (type: `integer`):

How many short comments with ratings to collect for each subject URL. They come 20 per request and are charged as list items.

## `maxTopicsPerGroup` (type: `integer`):

How many topics to collect from each group, newest first. Each topic is charged as a long-form item.

## `fullTopicText` (type: `boolean`):

Opens each topic to get the complete post instead of the abstract (one extra request per topic). Same price.

## `maxRepliesPerTopic` (type: `integer`):

How many replies to collect from each topic. They come 50 per request and are charged as list items. 0 turns replies off.

## `includeSubjectDetails` (type: `boolean`):

Off: search and list rows come with what the listing gives (title, year, rating, cover, card subtitle). On: each row is opened for the full record, which costs one request per subject and is charged as a full record.

## `proxyConfiguration` (type: `object`):

Douban rate-limits by IP, so proxy is required. Apify datacenter proxy is the default; blocked requests are retried on a new IP and fall back to residential.

## Actor input object example

```json
{
  "urls": [
    "https://movie.douban.com/subject/1292052/"
  ],
  "searchType": "movie",
  "maxItems": 30,
  "maxReviewsPerSubject": 0,
  "fullReviewText": true,
  "maxCommentsPerSubject": 0,
  "maxTopicsPerGroup": 20,
  "fullTopicText": true,
  "maxRepliesPerTopic": 0,
  "includeSubjectDetails": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

## `resultsCsv` (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 = {
    "urls": [
        "https://movie.douban.com/subject/1292052/"
    ],
    "maxItems": 30,
    "maxReviewsPerSubject": 0,
    "maxTopicsPerGroup": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapewise/douban-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 = {
    "urls": ["https://movie.douban.com/subject/1292052/"],
    "maxItems": 30,
    "maxReviewsPerSubject": 0,
    "maxTopicsPerGroup": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("scrapewise/douban-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 '{
  "urls": [
    "https://movie.douban.com/subject/1292052/"
  ],
  "maxItems": 30,
  "maxReviewsPerSubject": 0,
  "maxTopicsPerGroup": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call scrapewise/douban-scraper --silent --output-dataset

```

## MCP server setup

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