# QQ Music Artist Scraper (`ideal_warhead_1ua/qqmusic-artist-scraper`) Actor

Extract follower counts, total songs, and per-track comment counts for one artist or a batch of them from QQ Music. Optional comment section users (nickname, likes, text). No login or browser needed.

- **URL**: https://apify.com/ideal_warhead_1ua/qqmusic-artist-scraper.md
- **Developed by:** [贺 宇乐](https://apify.com/ideal_warhead_1ua) (community)
- **Categories:** Social media, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 歌曲

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

## QQ Music Artist Scraper

Extract **fans count, total songs, and per-song comment counts** for one artist or a whole list of them — from QQ Music (Tencent's music platform, the largest in China).

No login, no cookies, no headless browser. Everything comes from public JSON endpoints, so a run takes seconds, not minutes.

### What you get

| Field | Description | Example (Jay Chou) |
|---|---|---|
| `fansCount` | Artist follower count | 50,942,569 |
| `totalSongCount` | Total tracks in catalog | 1013 |
| `totalAlbumCount` / `totalMvCount` | Albums / music videos | 43 / 808 |
| `commentCount` | Comments per track | "Sunny Day" → 230,665 |
| `nick` | Commenter display name | count configurable |
| `praiseNum` | Likes on a comment | — |

Plus per track: album name, release date, duration, has-MV flag, VIP-only flag, language, genre, and a direct song URL.

### What is NOT available

Be aware of these before buying — Tencent does not expose them through any public endpoint. Any tool claiming otherwise is guessing:

- **Play counts per song** — QQ Music stopped exposing them publicly in 2021; no `play_count` field exists anywhere in the API
- **Likes / favorites per song** — only per-comment likes (`praiseNum`) exist; track-level favorites are not public
- **Follower list / fan names** — the fan list lives inside the mobile app behind a login wall; there is no web endpoint
- **Full comment history** — QQ Music serves 25 comments per page, caps pagination depth at roughly 4,500 pages, and blocks an IP after about 10 rapid requests. This Actor returns up to **500 comments per track** (the top of the section), not the entire thread. Nobody can export all 230,000 comments of "Sunny Day" — the platform does not serve them to anonymous clients

> If you need "who is listening", set `commentsPerSong` to collect commenter names — it is the closest public substitute.

### Input

| Parameter | Default | Description |
|---|---|---|
| `artists` | Jay Chou | **List of artists, batch supported.** One per line, in Chinese, English, or a QQ Music artist MID (e.g. `0025NhlN2yWrP4`). Max 20 per run, duplicates removed automatically |
| `artist` | — | Single artist, kept for backward compatibility. Ignored when `artists` is set |
| `maxSongs` | 20 | Max tracks **per artist** (up to 500). Each track costs one extra request for its comment count |
| `includeCommentStats` | true | Fetch comment count per track. Turn off to halve request volume |
| `strictMatch` | false | Reject fuzzy name matches. QQ Music search is fuzzy — a typo still returns some artist. When on, mismatches are skipped and logged as `error` (not charged) |
| `commentsPerSong` | 0 | Comment details per track (0 = none, up to **500**). Requests are throttled to one every 2.5s and share a 120-page budget per run |
| `sort` | 1 | Track order: 1 by popularity / 2 by release date / 5 default |

#### Batch example

```json
{
  "artists": ["Jay Chou", "Taylor Swift", "JJ Lin", "Eason Chan"],
  "maxSongs": 30,
  "commentsPerSong": 5
}
```

4 artists × 30 tracks × 5 comments ≈ 4 profiles + 120 tracks + 600 comments ≈ **$0.38**.

### Output

Every row carries a `type` field:

- `type = artist` — one per artist: fans, total songs/albums/MVs, bio, region, profile URL, top-3 search candidates
- `type = song` — one per track: title, artists, album, release date, duration, comment count, VIP flag, URL
- `type = comment` — only when `commentsPerSong > 0`: nickname, likes, content, timestamp
- `type = error` — an artist that could not be resolved (`reason` explains why). **Never charged**; it exists so you can audit who is missing

Every `song` record also carries `commentStatus`, so you never have to guess why a count is missing:

| Value | Meaning |
|---|---|
| `ok` | Retrieved normally |
| `off` | `includeCommentStats` was disabled |
| `throttled` | QQ Music rate-limited the run; collection stopped early |
| `budget` | The 120-page comment budget for this run was used up |
| `error` | The request failed after retries |

Artist records also carry two audit fields:

- `artistQuery` — exactly what you typed, useful for reconciling batches
- `matchType` — `exact` (name matches) or `fuzzy` (likely the wrong artist; the record shows who was actually matched)

Export the dataset as **JSON / CSV / Excel** directly from the run page.

### Use cases

- Track competitor artists' follower growth over time (pair with Apify Schedules)
- Measure audience engagement per release, using comment volume as the proxy QQ Music actually publishes
- Build a "most-discussed tracks" ranking for a genre or label roster
- Feed a dashboard or spreadsheet with Chinese music market data that has no English-language equivalent

### FAQ

**It matched the wrong artist.**
QQ Music search is fuzzy. Check `matchType` — `fuzzy` means the name did not match. Set `strictMatch: true` to skip those, or pass the artist MID instead of a name.

**Search returns nothing, or the run logs `search-failed`.**
The scraper tries QQ Music's autocomplete endpoint first, then falls back to the full-text search API. The latter is often blocked (HTTP 500) from data-center and overseas IPs, which is exactly what Apify runs on. If both endpoints fail, pass an **artist MID** instead of a name — for example `0025NhlN2yWrP4` (Jay Chou). MID lookups skip search entirely and always work. You can find a MID in any QQ Music artist page URL: `y.qq.com/n/ryqq/singer/<MID>`.

**Some comment counts are `null`.**
Check `commentStatus` on that row. `throttled` means QQ Music cut the run off (the whole run stops requesting comments; songs and profiles keep going). `budget` means you hit the 120-page cap. `off` means you disabled `includeCommentStats`. Retry later — throttling clears after a while, but it is IP-based and lasts at least 30 minutes.

**Can I export every comment of a song?**
No, and no tool can. QQ Music returns 25 comments per page and blocks an IP after roughly 10 rapid requests; a track with 230,000 comments would need 9,200 pages, far beyond the ~4,500-page depth the API allows. This Actor gives you the top 500 per track plus the exact total, which is what comment-volume analysis actually needs.

**How many artists can I run at once?**
20 per run. For larger rosters, split across Tasks or Schedules. Note the synchronous API endpoint has a 280-second limit — use the async run endpoint for big batches.

**What happens if my budget runs out mid-run?**
The scraper stops immediately at the current artist, records why in the run status, and keeps everything already collected. No partial data is lost and nothing is charged for unfinished work.

**Can I use this outside China?**
Yes. Requests go out from Apify's servers, so QQ Music's playback geo-restrictions do not apply. Note that the full-text search endpoint is sometimes blocked from foreign IPs — the Actor handles that by trying the autocomplete endpoint first, and you can always pass an artist MID to skip search altogether.

### Pricing

Pay per event, no subscription:

- Artist profile — **$5 per 1,000**
- Track — **$2 per 1,000**
- Comment detail — **$0.20 per 1,000**

A typical run of 50 tracks for one artist costs about **$0.11**.

### Legal

This Actor reads only data that QQ Music serves to anonymous visitors. It does not bypass login walls, solve CAPTCHAs, or decrypt signed parameters. Commenter nicknames are user-generated content — use them for aggregate analysis only, not for profiling, marketing outreach, or resale. Doing so would violate both Tencent's terms of service and China's Personal Information Protection Law (PIPL).

For research and analytics use. Not affiliated with Tencent.

# Actor input Schema

## `artists` (type: `array`):

One artist per line: Chinese name, English name, or QQ Music artist MID (e.g. 0025NhlN2yWrP4). Max 20 per run, duplicates removed. 每行一个歌手，单次最多 20 位，自动去重。

## `artist` (type: `string`):

Use this only when scraping one artist. Ignored if the list above is filled. 只想跑一位歌手时填这里，上方列表已填则忽略；全空默认周杰伦。

## `maxSongs` (type: `integer`):

Takes the top N tracks per artist under the chosen sort order. Each track costs one extra request for its comment count. 上限 500，对每位歌手单独生效。

## `includeCommentStats` (type: `boolean`):

Turn off to halve request volume, but the commentCount field will be empty. 关闭后歌曲记录里没有评论数字段。

## `strictMatch` (type: `boolean`):

QQ Music search is fuzzy — a typo still returns some artist. When on, mismatched names are skipped and logged as an error (not charged). 开启后名字对不上的直接跳过并记 error，不计费。

## `commentsPerSong` (type: `integer`):

Adds nickname, likes, and comment text for each track. 0 means comment counts only. Max 500 (= 20 pages). Requests are throttled to 2.5s apart to stay under QQ Music's rate limit; a 120-page budget per run applies. 0 表示只要评论总数；上限 500 条（20 页），请求按 2.5 秒间隔串行发送，单次运行最多 120 页。

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

Determines which tracks are collected first. Popularity puts signature hits first. 热度排序能优先拿到代表作。

## Actor input object example

```json
{
  "artists": [
    "Jay Chou",
    "Taylor Swift",
    "JJ Lin"
  ],
  "maxSongs": 20,
  "includeCommentStats": true,
  "strictMatch": false,
  "commentsPerSong": 0,
  "sort": "1"
}
```

# Actor output Schema

## `dataset` (type: `string`):

JSON 数组；加 ?format=csv 可导出表格

## `csv` (type: `string`):

直接用 Excel 打开

## `runLog` (type: `string`):

接口失败或数据为空时看这里

# 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 = {
    "artists": [
        "Jay Chou",
        "Taylor Swift",
        "JJ Lin"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("ideal_warhead_1ua/qqmusic-artist-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 = { "artists": [
        "Jay Chou",
        "Taylor Swift",
        "JJ Lin",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("ideal_warhead_1ua/qqmusic-artist-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 '{
  "artists": [
    "Jay Chou",
    "Taylor Swift",
    "JJ Lin"
  ]
}' |
apify call ideal_warhead_1ua/qqmusic-artist-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ideal_warhead_1ua/qqmusic-artist-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/wI1ahvFWEad3usnDc/builds/JtzmxdDa1kZPh2rWj/openapi.json
