# NetEase Cloud Music Comments Scraper 网易云音乐 (`getascraper/netease-music-comments-scraper`) Actor

Scrape NetEase Cloud Music (网易云音乐) song comments: text, likes, reply threads, commenter nickname and avatar, and timestamps. Input a song URL or ID. No browser needed, uses the site's own comment API directly.

- **URL**: https://apify.com/getascraper/netease-music-comments-scraper.md
- **Developed by:** [GetAScraper](https://apify.com/getascraper) (community)
- **Categories:** Social media, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 comment records

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use 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

## NetEase Cloud Music Comments Scraper 网易云音乐

<table width="100%">
<tr>
<td style="padding:24px 28px;background:#FBEAEC;border:1px solid #F0C4C9;border-top:4px solid #C41E3A;border-radius:12px">
<span style="font-size:23px;font-weight:800;color:#1C1917;line-height:1.3">Get NetEase Cloud Music song comments, likes, and reply threads ready for your spreadsheet in minutes.</span><br>
<span style="font-size:15px;color:#57534E;line-height:1.6">Pull full comment text, engagement counts, and commenter identity from any 网易云音乐 song page, no login or browser required.</span>
</td>
</tr>
</table>

<table width="100%">
<tr>
<td style="padding:14px 12px;width:25%;background:#FFFFFF;border:1px solid #F0C4C9;border-radius:10px 0 0 10px;vertical-align:top">
<span style="font-size:15px;font-weight:800;color:#9E1730">💬 Full comments</span><br>
<span style="font-size:12px;color:#57534E">Comment text, like counts, and reply counts, sorted hot, time, or recommended.</span>
</td>
<td style="padding:14px 12px;width:25%;background:#FFFFFF;border:1px solid #F0C4C9;border-left:none;vertical-align:top">
<span style="font-size:15px;font-weight:800;color:#9E1730">🧵 Reply threads</span><br>
<span style="font-size:12px;color:#57534E">Nested replies with who replied to whom, not just top-level comments.</span>
</td>
<td style="padding:14px 12px;width:25%;background:#FFFFFF;border:1px solid #F0C4C9;border-left:none;vertical-align:top">
<span style="font-size:15px;font-weight:800;color:#9E1730">👤 Commenter identity</span><br>
<span style="font-size:12px;color:#57534E">Nickname and avatar on every row. No raw internal user IDs collected.</span>
</td>
<td style="padding:14px 12px;width:25%;background:#FFFFFF;border:1px solid #F0C4C9;border-left:none;border-radius:0 10px 10px 0;vertical-align:top">
<span style="font-size:15px;font-weight:800;color:#9E1730">⚡ No browser needed</span><br>
<span style="font-size:12px;color:#57534E">Reads the site's own comment feed directly, so every run is fast and cheap.</span>
</td>
</tr>
</table>

**NetEase Cloud Music Comments Scraper** extracts song comments from [music.163.com](https://music.163.com), NetEase Cloud Music (网易云音乐), one of the largest music platforms in China. Give it a song URL or ID and it returns comment text, like counts, reply counts, commenter nickname and avatar, timestamps, and optional nested reply threads, ready to download as JSON, CSV, or Excel. Run it on demand, schedule it to track a viral release day by day, or call it from your own pipeline through the Apify API.

### 🎧 What does NetEase Cloud Music Comments Scraper do?

Most NetEase Cloud Music tools on Apify pull track metadata, playlists, or chart rankings. This one is built for the comment sections themselves, the part of the platform where actual fan reaction, slang, and sentiment live. Point it at a song and it returns every top-level comment the platform will return in one pass, plus the pinned "hot" comments, plus nested replies if you turn that on. No account, cookie, or browser session is needed to read comments; the Actor talks to the platform's own comment feed directly.

### 🎯 Why use it

- **I am a social-culture researcher** looking to collect thousands of real fan comments on viral Chinese songs in order to analyze sentiment and slang trends at scale.
- **I am an NLP dataset builder** looking to gather authentic Chinese internet comment text and reply threads in order to train and evaluate language models on real conversational data.
- **I am a music-marketing analyst** looking to track comment volume and top fan reactions on a new release in order to report engagement back to my label or artist client.

### 🚀 How to use it

<table width="100%">
<tr>
<td style="padding:16px 14px;width:33%;background:#FBEAEC;border:1px solid #F0C4C9;border-radius:10px 0 0 10px;vertical-align:top">
<span style="font-size:12px;font-weight:800;color:#C41E3A;letter-spacing:1px">STEP 1</span><br>
<span style="font-size:14px;font-weight:700;color:#1C1917">Paste a song URL or ID</span><br>
<span style="font-size:12px;color:#57534E">Add one or more music.163.com song links, or just the numeric song IDs.</span>
</td>
<td style="padding:16px 14px;width:33%;background:#FBEAEC;border:1px solid #F0C4C9;border-left:none;vertical-align:top">
<span style="font-size:12px;font-weight:800;color:#C41E3A;letter-spacing:1px">STEP 2</span><br>
<span style="font-size:14px;font-weight:700;color:#1C1917">Pick sort order and limits</span><br>
<span style="font-size:12px;color:#57534E">Choose hot, time, or recommended order, and cap comments and replies per song.</span>
</td>
<td style="padding:16px 14px;width:33%;background:#FBEAEC;border:1px solid #F0C4C9;border-left:none;border-radius:0 10px 10px 0;vertical-align:top">
<span style="font-size:12px;font-weight:800;color:#C41E3A;letter-spacing:1px">STEP 3</span><br>
<span style="font-size:14px;font-weight:700;color:#1C1917">Run and export</span><br>
<span style="font-size:12px;color:#57534E">Click Start. Download results as JSON, CSV, or Excel, or pull them via the API.</span>
</td>
</tr>
</table>

### ⚙️ Input

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `songUrls` | array of strings | No | NetEase Cloud Music song page URLs, for example `https://music.163.com/song?id=186016`. Leave empty if you use `songIds` instead. |
| `songIds` | array of strings | No | Numeric song IDs (the `id=` part of a song URL). Use this if you already have IDs on hand. |
| `sortType` | enum | No | How to order top-level comments: recommended, hottest, or time. Hot pinned comments are always included regardless of this setting. Defaults to hottest. |
| `maxCommentsPerSong` | integer | No | Cap on top-level comments per song. Popular songs can have millions of comments, so this keeps runs predictable. Defaults to `200`. |
| `includeReplies` | boolean | No | Fetch nested replies for every comment that has them. Adds one extra request per replied-to comment. Defaults to off. |
| `maxRepliesPerComment` | integer | No | Cap on nested replies fetched per comment thread. Only applies when `includeReplies` is on. Defaults to `20`. |
| `sinceCommentId` | string | No | For repeat monitoring runs: paste the newest comment ID from your last run. Pagination stops as soon as that ID reappears, so you only get what is new. Works best with `sortType` set to time. |
| `fetchSongTitle` | boolean | No | Look up the song's title and artist and attach them to every row. Adds one extra plain page request per song. Defaults to on. |
| `maxItems` | integer | No | Hard cap on total rows (comments plus replies) across the whole run. Defaults to `500`. |
| `debugLogging` | boolean | No | Print a log line for every single comment and reply emitted, useful for troubleshooting a run. Defaults to off. |
| `proxyConfiguration` | object | No | Proxy settings. Datacenter proxies (the default) work well; switch to residential only if a large run starts seeing blocked or empty responses. |

### 📦 Output

Every comment and reply becomes one row in your dataset. Here is a real example row from a live run:

```json
{
  "songId": "186016",
  "songTitle": "晴天（Sunny Day）",
  "songArtist": "周杰伦",
  "songUrl": "https://music.163.com/song?id=186016",
  "commentId": "4956438",
  "isReply": false,
  "isHot": true,
  "content": "高一听的，那时候遇到了孩儿他妈，然后就这么幸福下来了",
  "likedCount": 823174,
  "replyCount": 14,
  "authorNickname": "蛋蛋是圆D",
  "authorAvatarUrl": "http://p2.music.126.net/FwTFLzZFZOZO5WFL6-JRBg==/2755376139227068.jpg",
  "time": 1413530574252,
  "timeStr": "2014-10-17",
  "scrapedAt": "2026-07-19T06:25:28.792Z"
}
````

You can download the dataset in JSON, CSV, Excel, HTML, or XML directly from the Apify Console, or pull it through the API.

#### Data table

| Field | Type | Description |
| --- | --- | --- |
| `songId` | string | Numeric NetEase song ID this row belongs to. |
| `songTitle` | string | Song title, resolved from the song page when `fetchSongTitle` is on. |
| `songArtist` | string | Performing artist, resolved the same way. |
| `songUrl` | string | Canonical song page URL. |
| `commentId` | string | Unique ID of this comment or reply. |
| `parentCommentId` | string | For replies only: the top-level comment this reply belongs to. |
| `isReply` | boolean | `true` for a nested reply, `false` for a top-level comment. |
| `isHot` | boolean | `true` if this comment came from the platform's pinned "hot comments" set. |
| `content` | string | The comment or reply text. |
| `likedCount` | number | Number of likes on this comment or reply. |
| `replyCount` | number | Number of replies under this comment (top-level comments only). |
| `authorNickname` | string | Public display name of the commenter. |
| `authorAvatarUrl` | string | Commenter's public avatar image URL. |
| `repliedToNickname` | string | For replies only: the nickname of the person being replied to. |
| `time` | number | Comment timestamp in Unix epoch milliseconds. |
| `timeStr` | string | Comment date as a plain string, for example `2014-10-17`. |
| `scrapedAt` | string | ISO timestamp of when this Actor collected the row. |

### 💰 Pricing

Pricing is pay per result and is billed per row successfully saved to your dataset. Empty runs cost nothing. There are no fixed monthly subscriptions or hidden fees. Check the Actor's Pricing tab on Apify for the current rate per 1,000 results.

### ⭐ Enjoying NetEase Cloud Music Comments Scraper?

<table width="100%">
<tr>
<td style="padding:20px 24px 14px;background:#FBEAEC;border:1px solid #F0C4C9;border-left:5px solid #C41E3A;border-radius:10px 10px 0 0">
<span style="font-size:20px;letter-spacing:4px">⭐ ⭐ ⭐ ⭐ ⭐</span><br>
<span style="font-size:17px;font-weight:800;color:#1C1917">Now pulling thousands of real fan comments takes one run instead of a week of manual copy-pasting.</span><br>
<span style="font-size:14px;color:#57534E">A 5-star rating takes 10 seconds and helps other social-culture researchers and dataset builders find it. Your feedback also tells us what to build next.</span>
</td>
</tr>
<tr>
<td style="padding:0;background:#C41E3A;border:1px solid #F0C4C9;border-top:none;border-radius:0 0 10px 10px;text-align:center">
<a href="https://apify.com/getascraper/netease-music-comments-scraper/reviews" style="display:block;padding:13px 16px;color:#FFFFFF;text-decoration:none;font-weight:800;font-size:15px;letter-spacing:0.3px">★&nbsp;&nbsp;Rate this Actor on Apify</a>
</td>
</tr>
</table>

### 💡 Tips and advanced options

- **Turn on `includeReplies` selectively.** Songs with millions of comments can have deep reply threads. Leave it off for a quick overview pull, and turn it on only when you need full conversational context.
- **Use `sinceCommentId` for monitoring runs.** Set `sortType` to time, save the newest `commentId` from your dataset after each run, and pass it back in on the next run to only collect what changed.
- **Start with a small `maxCommentsPerSong`.** Test a run with a low cap first to confirm a song has the comment volume and tone you expect before scaling up.
- **Datacenter proxies are the default and work well.** Only switch to residential if a very large run starts returning blocked or empty pages.

### ❓ FAQ

##### Does this Actor get blocked scraping NetEase Cloud Music?

No blocking was observed in testing: no CAPTCHA, no IP-reputation gate, and no browser fingerprint check on the comment feed. The Actor uses the standard datacenter proxy pool by default, which has proven reliable for this target.

##### Do I need a NetEase account or login to scrape comments?

No. Comment data is public and readable with zero cookies or authentication. The Actor never asks for or stores account credentials.

##### How fresh is the comment data?

Every run reads the live comment feed directly, so results reflect what is on the page at the moment the Actor runs, not a cached snapshot.

##### 网易云音乐评论怎么爬取？(How do I scrape NetEase Cloud Music comments?)

Paste a song URL like `https://music.163.com/song?id=186016` or its numeric ID into the Actor's input, run it, and download the resulting comment dataset as JSON, CSV, or Excel. No coding or login required.

### 🔗 Other actors

- [Ximalaya Scraper 喜马拉雅: Podcasts & Comments](https://apify.com/getascraper/ximalaya-scraper) ↗ - scrapes podcast episodes and listener comments from China's largest audio platform.
- [Kugou Music Scraper: 酷狗音乐 Catalog, Charts & Lyrics](https://apify.com/getascraper/kugou-music-scraper) ↗ - pulls song catalog, chart rankings, and lyrics from another major Chinese music platform.
- [Xigua Video Search Scraper: Keyword, Comments & Video Links](https://apify.com/getascraper/xigua-video-search-scraper) ↗ - searches Xigua Video by keyword and returns video links and comments.
- [2GIS Reviews Scraper: Отзывы 2ГИС](https://apify.com/getascraper/2gis-reviews-scraper) ↗ - collects business reviews and ratings from 2GIS, a similar comment-extraction pattern in a different market.
- [TeamBlind Reviews Scraper: Tech Employer Ratings](https://apify.com/getascraper/teamblind-reviews-scraper) ↗ - extracts employer reviews and ratings from the anonymous professional network Blind.

# Actor input Schema

## `songUrls` (type: `array`):

NetEase Cloud Music song page URLs, e.g. 'https://music.163.com/song?id=186016'. Leave empty if using Song IDs.

## `songIds` (type: `array`):

Numeric NetEase song IDs (the 'id=' part of a song URL), e.g. '186016'.

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

How to order the top-level comments pulled for each song. Hottest comments are usually the most useful for sentiment/NLP work; Time order is best for incremental 'what's new' monitoring together with 'Stop at comment ID' below. Hot comments (top pinned picks) are always included regardless of this setting.

## `maxCommentsPerSong` (type: `integer`):

Cap on top-level comments returned per song (0 = as many as the API will return in one pass). Popular songs can have millions of comments; this keeps runs predictable and affordable.

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

Fetch nested replies for every top-level comment that has replies. Adds one extra request per replied-to comment, so it costs more on songs with deep threads.

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

Cap on nested replies fetched per top-level comment (0 = all available). Only applies when 'Include reply threads' is on.

## `sinceCommentId` (type: `string`):

For monitoring a song's comments over time: paste the newest comment ID you already collected on a previous run. Pagination stops as soon as this ID is seen again, so you only get comments newer than it. Works best with Comment sort order set to Time. Leave empty for a full pull.

## `fetchSongTitle` (type: `boolean`):

Look up the song's title and artist from its page and attach them to every comment row. Adds one extra plain HTML request per song.

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

Hard cap on total rows (comments + replies) across all songs in this run (0 = unlimited).

## `debugLogging` (type: `boolean`):

Print a log line for every single comment/reply emitted, not just per page.

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

No IP-reputation gating was observed against the comment API during testing, so Datacenter proxies (the default) are fast and cheap. Switch to Residential only if you start seeing blocked or empty responses on a large run.

## Actor input object example

```json
{
  "songUrls": [
    "https://music.163.com/song?id=186016"
  ],
  "songIds": [],
  "sortType": "2",
  "maxCommentsPerSong": 200,
  "includeReplies": false,
  "maxRepliesPerComment": 20,
  "sinceCommentId": "",
  "fetchSongTitle": true,
  "maxItems": 500,
  "debugLogging": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# 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 = {
    "songUrls": [
        "https://music.163.com/song?id=186016"
    ],
    "songIds": [],
    "sortType": "2",
    "maxCommentsPerSong": 200,
    "includeReplies": false,
    "maxRepliesPerComment": 20,
    "sinceCommentId": "",
    "fetchSongTitle": true,
    "maxItems": 500,
    "debugLogging": false,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("getascraper/netease-music-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 = {
    "songUrls": ["https://music.163.com/song?id=186016"],
    "songIds": [],
    "sortType": "2",
    "maxCommentsPerSong": 200,
    "includeReplies": False,
    "maxRepliesPerComment": 20,
    "sinceCommentId": "",
    "fetchSongTitle": True,
    "maxItems": 500,
    "debugLogging": False,
    "proxyConfiguration": { "useApifyProxy": True },
}

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

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

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

```

## CLI example

```bash
echo '{
  "songUrls": [
    "https://music.163.com/song?id=186016"
  ],
  "songIds": [],
  "sortType": "2",
  "maxCommentsPerSong": 200,
  "includeReplies": false,
  "maxRepliesPerComment": 20,
  "sinceCommentId": "",
  "fetchSongTitle": true,
  "maxItems": 500,
  "debugLogging": false,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call getascraper/netease-music-comments-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=getascraper/netease-music-comments-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "NetEase Cloud Music Comments Scraper 网易云音乐",
        "description": "Scrape NetEase Cloud Music (网易云音乐) song comments: text, likes, reply threads, commenter nickname and avatar, and timestamps. Input a song URL or ID. No browser needed, uses the site's own comment API directly.",
        "version": "1.0",
        "x-build-id": "5EjGzMs3rBBglhOas"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/getascraper~netease-music-comments-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-getascraper-netease-music-comments-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/getascraper~netease-music-comments-scraper/runs": {
            "post": {
                "operationId": "runs-sync-getascraper-netease-music-comments-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/getascraper~netease-music-comments-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-getascraper-netease-music-comments-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",
                "properties": {
                    "songUrls": {
                        "title": "Song URLs",
                        "type": "array",
                        "description": "NetEase Cloud Music song page URLs, e.g. 'https://music.163.com/song?id=186016'. Leave empty if using Song IDs.",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "songIds": {
                        "title": "Song IDs",
                        "type": "array",
                        "description": "Numeric NetEase song IDs (the 'id=' part of a song URL), e.g. '186016'.",
                        "items": {
                            "type": "string"
                        },
                        "default": []
                    },
                    "sortType": {
                        "title": "Comment sort order",
                        "enum": [
                            "1",
                            "2",
                            "3"
                        ],
                        "type": "string",
                        "description": "How to order the top-level comments pulled for each song. Hottest comments are usually the most useful for sentiment/NLP work; Time order is best for incremental 'what's new' monitoring together with 'Stop at comment ID' below. Hot comments (top pinned picks) are always included regardless of this setting.",
                        "default": "2"
                    },
                    "maxCommentsPerSong": {
                        "title": "Max comments per song",
                        "minimum": 0,
                        "maximum": 1000000,
                        "type": "integer",
                        "description": "Cap on top-level comments returned per song (0 = as many as the API will return in one pass). Popular songs can have millions of comments; this keeps runs predictable and affordable.",
                        "default": 200
                    },
                    "includeReplies": {
                        "title": "Include reply threads",
                        "type": "boolean",
                        "description": "Fetch nested replies for every top-level comment that has replies. Adds one extra request per replied-to comment, so it costs more on songs with deep threads.",
                        "default": false
                    },
                    "maxRepliesPerComment": {
                        "title": "Max replies per comment",
                        "minimum": 0,
                        "maximum": 10000,
                        "type": "integer",
                        "description": "Cap on nested replies fetched per top-level comment (0 = all available). Only applies when 'Include reply threads' is on.",
                        "default": 20
                    },
                    "sinceCommentId": {
                        "title": "Stop at comment ID (incremental runs)",
                        "type": "string",
                        "description": "For monitoring a song's comments over time: paste the newest comment ID you already collected on a previous run. Pagination stops as soon as this ID is seen again, so you only get comments newer than it. Works best with Comment sort order set to Time. Leave empty for a full pull.",
                        "default": ""
                    },
                    "fetchSongTitle": {
                        "title": "Fetch song title & artist",
                        "type": "boolean",
                        "description": "Look up the song's title and artist from its page and attach them to every comment row. Adds one extra plain HTML request per song.",
                        "default": true
                    },
                    "maxItems": {
                        "title": "Maximum total comments",
                        "minimum": 0,
                        "maximum": 1000000,
                        "type": "integer",
                        "description": "Hard cap on total rows (comments + replies) across all songs in this run (0 = unlimited).",
                        "default": 500
                    },
                    "debugLogging": {
                        "title": "Verbose debug logs",
                        "type": "boolean",
                        "description": "Print a log line for every single comment/reply emitted, not just per page.",
                        "default": false
                    },
                    "proxyConfiguration": {
                        "title": "Proxy setup",
                        "type": "object",
                        "description": "No IP-reputation gating was observed against the comment API during testing, so Datacenter proxies (the default) are fast and cheap. Switch to Residential only if you start seeing blocked or empty responses on a large run.",
                        "default": {
                            "useApifyProxy": true
                        }
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
