# QQ Music Scraper (`crawlerbros/qq-music-scraper`) Actor

Scrape QQ Music (y.qq.com, Tencent) without login - search songs, fetch by song URL, top-100 rank charts, album tracks and playlist tracks with cover art, file sizes and pay status.

- **URL**: https://apify.com/crawlerbros/qq-music-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Automation, Developer tools, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

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

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## QQ Music Scraper

Scrapes [QQ Music](https://y.qq.com/) (QQ音乐, Tencent) — **without login** — via the public `c.y.qq.com` JSON endpoints.

### Data source

Music data comes from the public QQ Music web endpoints (y.qq.com `c.y.qq.com` FCG JSON APIs) — no login, no API key. See the Notes section for endpoint-level caveats.

### What it does

| Mode | Endpoint (public, no auth) | Output |
|---|---|---|
| `search` | `c.y.qq.com/soso/fcgi-bin/client_search_cp` | Paginated song search |
| `bySongUrl` | `fcg_play_single_song.fcg?songmid=` (+ optional LRC lyric) | Full song record |
| `byToplist` | `fcg_myqq_toplist.fcg` + `fcg_v8_toplist_cp.fcg?topid=` | Chart summary + top-100 tracks |
| `byAlbum` | `fcg_v8_album_detail_cp.fcg?albumid=` | Album + full track list |
| `byPlaylist` | `fcg_ucc_getcdinfo_byids_cp.fcg?disstid=` | Playlist + full track list |

All endpoints verified live (HTTP 200 with real content) from a datacenter network. The `musicu.fcg` aggregator (used by the SPA) rejects datacenter clients (`code 500003`), so this actor uses the older plaintext `c.y.qq.com` FCG endpoints instead — they return the same data.

### Output fields

**song records (`recordType: "song"`)** — `mid`, `mediaMid`, `songId`, `name`, `singers[]`, `singer`, `singerMids[]`, `album`, `albumId`, `albumMid`, `coverUrl`, `durationSec`, `pubTimeSec`, `pubTimeText`, `vid` (MV id), `size128`, `size320`, `sizeFlac` (bytes), `payPlay`, `payDownload`, `payStatus`, `lyric` (optional, bySongUrl), `sourceUrl`, `scrapedAt`.

**toplist / album / playlist records** — chart/album/playlist summary fields (`toplistId`, `listenCount`, `trackCount`, `creatorName`, `listenerCount`, `visitCount`, `creatorAvatarUrl`, `language`, `description`, `tags[]`, `createTimeMs`, `updateTimeMs`, …).

**error records (`recordType: "error"`)** — invalid URLs, missing songs/albums/playlists (never silently dropped).

Every data record carries `sourceUrl`, `scrapedAt` and `recordType`; error records carry `inputValue` in place of `sourceUrl` (the offending input, not a page URL). Null/empty fields are stripped before push.

### Filters

- `minDurationSec` / `maxDurationSec`
- `containsKeyword` (title substring)
- `singerKeyword` (primary-singer substring)

### Notes

- Cover URLs are derived from the album mid: `https://y.gtimg.cn/music/photo_new/T002R300x300M000{albumMid}.jpg` — verified HTTP 200 `image/jpeg` from a clean shell.
- Some user playlists return an empty `songlist` from the public playlist endpoint (their track lists are only served to logged-in users); the actor still emits the playlist info record and 0 tracks rather than failing.
- Duplicate song URLs in `songUrls` (mode=bySongUrl) are deduped to a single unique record per song mid. `maxItems` is a hard cap on ALL emitted records including `error` records.
- `byArtist` is NOT exposed: the singer-track FCG endpoints return HTTP 404 without login/cookies on all tested variants (documented limitation).
- Auto-escalation: on 403/429 the actor lazily engages the Apify AUTO (datacenter) proxy with exponential backoff.
- Memory: 1024 MB (Tier 1, plain HTTP).

# Actor input Schema

## `mode` (type: `string`):

What to fetch.

## `searchQuery` (type: `string`):

Free-text query (mode=search).

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

QQ Music song URLs, e.g. `https://y.qq.com/n/ryqq/songDetail/001Bbywq2gicae`.

## `toplistId` (type: `string`):

QQ Music chart to fetch (top 100 tracks).

## `includeToplistInfo` (type: `boolean`):

Emit the toplist summary record before its tracks (mode=byToplist).

## `albumId` (type: `integer`):

QQ Music album id, e.g. 20612.

## `albumUrls` (type: `array`):

QQ Music album URLs as an alternative to albumId.

## `playlistId` (type: `string`):

QQ Music playlist disstid (long number), e.g. 5315973668.

## `playlistUrls` (type: `array`):

QQ Music playlist URLs as an alternative to playlistId.

## `includeLyric` (type: `boolean`):

Attach first 2000 chars of the LRC lyric to song records.

## `minDurationSec` (type: `integer`):

Drop songs shorter than this.

## `maxDurationSec` (type: `integer`):

Drop songs longer than this.

## `containsKeyword` (type: `string`):

Only keep songs whose title contains this substring (case-insensitive).

## `singerKeyword` (type: `string`):

Only keep songs whose primary singer contains this substring.

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

Hard cap on emitted records.

## Actor input object example

```json
{
  "mode": "search",
  "searchQuery": "周杰伦",
  "songUrls": [],
  "includeToplistInfo": true,
  "albumUrls": [],
  "playlistUrls": [],
  "includeLyric": false,
  "maxItems": 30
}
```

# Actor output Schema

## `items` (type: `string`):

Dataset containing all scraped QQ Music records (recordType: song | toplist | album | playlist | error).

# 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 = {
    "mode": "search",
    "searchQuery": "周杰伦",
    "songUrls": [],
    "includeToplistInfo": true,
    "albumUrls": [],
    "playlistUrls": [],
    "includeLyric": false,
    "maxItems": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/qq-music-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 = {
    "mode": "search",
    "searchQuery": "周杰伦",
    "songUrls": [],
    "includeToplistInfo": True,
    "albumUrls": [],
    "playlistUrls": [],
    "includeLyric": False,
    "maxItems": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/qq-music-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 '{
  "mode": "search",
  "searchQuery": "周杰伦",
  "songUrls": [],
  "includeToplistInfo": true,
  "albumUrls": [],
  "playlistUrls": [],
  "includeLyric": false,
  "maxItems": 30
}' |
apify call crawlerbros/qq-music-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/qq-music-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/oMrlMd5obzr3Dk5KS/builds/Pz38Pco8i8G4uLW5L/openapi.json
