# Spotify Scraper: Monthly Listeners, Playlists & Tracks (`vant47/spotify-artist-playlist-scraper`) Actor

Get Spotify artists' monthly listeners, followers, top cities and top tracks, plus playlists with followers and track play counts, from links or search. $0.0035 per profile or direct track: 100 cost $0.35. Optional collection tracks $0.001 each. No login. Daily change monitoring.

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

## Pricing

from $2.80 / 1,000 music profiles

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

## Spotify Scraper: Monthly Listeners, Playlists & Tracks

For music marketers, artist teams, labels and playlist researchers monitoring Spotify audiences and catalogs. Get listeners, followers, top cities, artist top tracks, playlists and song play counts from public links or search. Search matches receive full detail enrichment.

A music profile or direct track lookup costs **$0.0035**, so 100 cost **$0.35** before plan discounts. Optional track rows from playlists and albums cost **$0.001 each**. An artist's nested top tracks are included in the artist price. There is also Apify's small $0.00005 start fee. No Spotify login, developer application or API key is required.

Validation: 38 varied cloud inputs passed; ten output rows matched rendered public pages on 29 October 2026.

### What you get

Each music record starts with a readable verdict, a type and its stable Spotify ID. Counts are numbers suitable for spreadsheets, rather than abbreviations such as 92m. Missing values are `null`. A run also creates a free `SUMMARY` dataset row and a `SUMMARY` key-value record with coverage, skipped duplicates, unavailable inputs, request statistics and spending-limit information.

| Record | Fields | Intended use |
| --- | --- | --- |
| Artist | `artistId`, `name`, `monthlyListeners`, `followers`, `worldRank`, `verified`, `topCities`, `topTracks`, `genres`, `url` | Track an audience, compare artists and check campaigns |
| Playlist | `playlistId`, `name`, `owner`, `followers`, `trackCount`, `description`, `url` | Research public playlists and monitor follower changes |
| Track | `trackId`, `name`, `artists`, `album`, `playCount`, `durationMs`, `releaseDate`, `explicit`, `trackNumber`, `url` | Compare song performance and enrich a catalog |
| Album | `albumId`, `name`, `artists`, `releaseDate`, `trackCount`, `label`, `url` | Identify releases and optionally retrieve their tracks |
| Every music record | `verdict`, `type`, `observedAt`; image URL when supplied | Join daily exports using IDs and observation timestamps |
| Watch observation | Previous listeners or followers, absolute changes, `previousObservedAt`, `changeStatus` | Deliver a baseline once and then only changed profiles |

Artist `topCities` contains city, country, region and listeners. These selected cities do not sum to monthly listeners. `topTracks` includes IDs, names, exact plays, durations, artists and album links for Spotify's selected top tracks, not the complete discography.

Genres are currently absent from the signed-out web-player response and remain `null`. World rank and verification also remain `null` when the source does not supply them. The Actor does not infer a genre, verified badge or rank from a biography or from similar artists.

Playlist `owner` is the public display name only. No curator emails, account identifiers, private profiles or contact enrichment are collected. Descriptions are converted to plain text. Private, deleted, personalized or region-restricted playlists may be unavailable even when the URL format is valid.

Search follows Spotify ranking and can include loose recommendations. Use exact URLs for strict artist or release identity.

### Start in three steps

1. Paste public Spotify links into `startUrls`, or add names to `searchTerms` and choose `searchType`.
2. Set `maxItems`. Leave `includeTracks` off for a cheap profile-only snapshot. Enable it when you want separate album or playlist track rows.
3. Run the Actor and open the Music overview, Audience and changes, or Tracks and play counts dataset view. Export JSON, CSV or Excel through Apify.

The prefilled input contains two artist links and a 20-record limit. A measured two-artist cloud test completed in 5.45 seconds. Large jobs are paced; increase the run timeout for jobs that need over an hour. Proxies and retries can add runtime.

#### Example: compare two artist audiences

```json
{
  "startUrls": [
    "https://open.spotify.com/artist/4gzpq5DPGxSnKTe4SA8HAU",
    "https://open.spotify.com/artist/4Z8W4fKeB5YxbusRsdQVPb"
  ],
  "maxItems": 20,
  "includeTopCities": true
}
```

#### Example: an album and its tracks

```json
{
  "startUrls": [
    "https://open.spotify.com/album/6ZG5lRT77aJ3btmArcykra"
  ],
  "includeTracks": true,
  "maxItems": 20
}
```

This tested album returns one album and ten tracks, plus the free summary. Track rows carry album, release date, plays and parentId; SUMMARY.collections records membership.

### Input reference

| Input | Default | Meaning |
| --- | --- | --- |
| `startUrls` | Empty outside the prefill | Artist, playlist, album or track links. Canonical links, supported `intl-xx` links, embed links and Spotify URIs are normalized. Query-string sharing parameters are removed. |
| `searchTerms` | Empty | Up to 50 names or keyword queries. May be combined with links. |
| `searchType` | `artist` | One of `artist`, `playlist`, `track`, `album`. Direct links keep their own type. |
| `maxItems` | `100` | Maximum unique music rows across the whole run, from 1 to 10,000. Collection parents and their tracks share the same limit. |
| `includeTracks` | `false` | Retrieve separate paid track rows from album and playlist contents. Does not change the nested artist top-track list. |
| `includeTopCities` | `true` | Include artist city statistics where available. With this disabled, `topCities` is `null`. |
| `onlyChangedSinceLastRun` | `false` | Compare artist listeners and followers, or playlist followers, with the same watch's previous successful observation. |
| `watchId` | Empty | Required for change mode. Use 1 to 80 letters, digits, underscores or hyphens. |
| `proxyConfiguration` | No added proxy | Optional Apify proxy settings. Signed-out cloud datacenter access passed the build tests. |

Aliases `urls`, `keywords` and `query` are accepted. Bad inputs produce free notes or pre-run validation errors. Missing items and empty results have no music-record charge. Search considers at most 1,000 ranked results per term.

`maxItems` covers parents and tracks together. A playlist with a limit of six can return one playlist and five tracks, plus free notes and the summary. Repeated tracks are charged once; their first delivered occurrence determines the direct or collection unit.

### Monitor audiences every day

Create an Apify task using the public artist or playlist links you want to watch. Turn on `onlyChangedSinceLastRun` and choose a stable `watchId`, for example `weekly-roster`. Add a daily or weekly schedule in your own Apify account. The Actor does not create schedules automatically.

The first run delivers a baseline. Later artist rows require changed listeners or followers; playlist rows require changed followers. Rows include previous values and absolute differences.

Unchanged profiles are free and counted in the summary. An empty changed-only dataset can be valid; the start fee still applies. Watches have no historical backfill.

Keep runs for a watch ID sequential. An unfinished-run marker prevents a later run from replacing an incomplete baseline. Resume the interrupted run or use another watch ID. Overlapping runs are not supported.

Playlist edits, world rank, top cities and top tracks do not trigger this filter. Albums and direct tracks are always returned. For complete catalog snapshots, leave it off. Watch state lives in a named Apify key-value store in your account; deleting it resets the baseline.

### Pricing and spending controls

| Useful unit | Base price | Bronze | Silver | Gold and higher |
| --- | ---: | ---: | ---: | ---: |
| Artist, playlist or album profile | $0.0035 | $0.003325 | $0.00315 | $0.0028 |
| Direct or searched track lookup | $0.0035 | $0.003325 | $0.00315 | $0.0028 |
| Optional collection track row | $0.001 | $0.00095 | $0.0009 | $0.0008 |

Apify's $0.00005 platform start fee is additional. Public-data requests, compute, storage operations during execution and optional Apify proxy use are included in the Actor's pay-per-event price. You do not need a separate Spotify API subscription.

At base prices, 100 artist profiles cost $0.35 plus the start fee. One playlist with 50 unique included tracks costs $0.0535 plus the start fee. One album with ten included tracks costs $0.0135 plus the start fee. Artist top tracks nested inside a profile do not add track charges. These examples assume the source returns every requested item and no duplicates.

Set **Maximum charge per run** for large jobs. The Actor saves a row before charging it, and stops when the next unit will not fit. Empty searches, unavailable links, retries, duplicates, notes and summaries add no music-unit charges. Reboots reconcile saved rows and acknowledged charges before continuing.

### Output example from a real cloud run

Selected cloud fields from 29 October 2026; later counts can differ.

```json
{
  "verdict": "91,971,310 monthly listeners.",
  "type": "artist",
  "artistId": "4gzpq5DPGxSnKTe4SA8HAU",
  "name": "Coldplay",
  "monthlyListeners": 91971310,
  "followers": 65999220,
  "worldRank": 9,
  "topCities": [
    {"city": "Mexico City", "country": "MX", "region": "CMX", "listeners": 1430995}
  ],
  "genres": null,
  "verified": true,
  "url": "https://open.spotify.com/artist/4gzpq5DPGxSnKTe4SA8HAU"
}
```

Track `artists` contains public IDs, names and links. `album` contains its ID, name and link. Durations use milliseconds. Release dates retain the source precision. `playCountText` preserves thresholds such as `<1000`; thresholds are not converted into invented exact counts.

### API use

Start a run with the Apify API and then fetch the default dataset. Keep your Apify token in an environment variable and use an Authorization header. No Spotify credentials belong in the input.

```bash
curl --request POST \
  --header "Authorization: Bearer $APIFY_TOKEN" \
  --header "Content-Type: application/json" \
  --data '{"searchTerms":["Coldplay"],"searchType":"artist","maxItems":3}' \
  'https://api.apify.com/v2/acts/vant47~spotify-artist-playlist-scraper/runs'
```

Poll the returned run ID until completion, then read `/v2/datasets/DATASET_ID/items?clean=1`. Short jobs can use `run-sync-get-dataset-items`. Preserve full JSON for nested city and top-track arrays.

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("vant47/spotify-artist-playlist-scraper").call(
    run_input={"searchTerms": ["ambient"], "searchType": "playlist", "maxItems": 5}
)
rows = list(client.dataset(run["defaultDatasetId"]).iterate_items())
profiles = [row for row in rows if row.get("type") == "playlist"]
```

### Use with AI agents (MCP)

Connect your MCP client to `https://mcp.apify.com` and ask it to run `vant47/spotify-artist-playlist-scraper`. Give the assistant concrete URLs or search terms, a result type, a maximum record count and whether included tracks are needed. Ask it to read the summary as well as the dataset so truncated collections and unavailable inputs are not mistaken for complete coverage.

Example: Find two Spotify artist matches for Coldplay with listeners, followers and top-track plays, below $0.02. For a playlist plus ten tracks, ask for `maxItems: 11` because the parent also counts.

Join exports by stable IDs. Apify tasks, schedules and webhooks connect to Sheets, n8n, Make or Zapier. The Actor sends no messages and modifies no playlist or playback state.

### Reliability and honest limits

Requests are serial, at least 1.25 seconds apart, with fresh retry connections and Retry-After support. Public embeds supply anonymous web-player sessions. No account cookies, login, challenge solving, playback or audio downloads are used.

Retired query identifiers can be rediscovered from Spotify's current public page assets. Authentication changes, blocked routes and removed fields can still require maintenance. Failures appear in free notes and the summary; metrics are never fabricated.

Collections are paged within item and spending limits. Removed tracks, local files, episodes and unavailable entries are not charged. Global deduplication can make the row count smaller than the playlist count. `SUMMARY.collections` records observed positions, delivered track IDs and truncation. A playlist edited during a run is not an atomic snapshot.

Availability can vary by market. A normalized locale link does not select a country's account catalog. There is no country or store-price mode. Monthly listeners are a rolling audience measure, not lifetime streams. Play counts need not update after each play.

### FAQ

**Does search return monthly listeners and play counts?** Yes, matches are fetched through the detailed item route. If the source omits a field for an individual item it remains `null` and is not replaced with an estimate.

**Why can a playlist have more positions than returned track rows?** A cap, duplicate track, unavailable item or non-track entry can reduce unique output. Read the collection coverage and truncation flags in the summary before interpreting the result.

**Can a reboot charge the same saved row twice?** Delivery is serialized, keyed by run and record identity, and reconciled with dataset rows and authoritative charge counts after a restart. Ambiguous recovery stops further charging. The release is also checked with a real cloud reboot between saving a row and charging it.

**Is this an official Spotify product?** No. This independently built tool reads public Spotify data. Review Spotify's terms and the permissions relevant to your intended use. Access to a public page does not grant unrestricted rights to reuse its content.

# Actor input Schema

## `startUrls` (type: `array`):

Public artist, playlist, album or track links. Canonical, intl locale and embed URLs are accepted. No private playlists, short links, login or account cookies. Artist profiles cost $0.0035 each before plan discounts. Direct track lookups also cost $0.0035 before discounts.

## `searchTerms` (type: `array`):

Names or keywords, for example Coldplay or ambient. Search results receive full detail enrichment, including listener or play counts when supplied. At most 50 terms. Can be combined with links. Up to the first 1,000 ranked source results per term are considered, within maxItems.

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

The kind of public music result to search for. Direct links retain their own type.

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

Total unique charged artist, playlist, album and track rows across the entire run. Parent rows and includeTracks rows share this limit. Free notes and SUMMARY are additional. 100 profiles cost $0.35 before discounts and the small start fee. Increase the run timeout for large jobs: direct lookups are paced and thousands can take hours.

## `includeTracks` (type: `boolean`):

Deliver separate track rows at $0.001 each before discounts. Playlist tracks receive full play-count enrichment. Album tracks include the source album context. Pagination continues until maxItems or the spending limit. Artist topTracks are always included inside the artist price.

## `includeTopCities` (type: `boolean`):

Include the city, country and listener count when the public artist source provides them. Otherwise null.

## `onlyChangedSinceLastRun` (type: `boolean`):

Use a stable watchId for sequential runs. First run delivers a baseline. Later runs deliver only artists whose monthly listeners or followers changed and playlists whose followers changed. Unchanged profiles have no profile charge. Albums and tracks are always delivered. Track edits alone do not make a playlist changed.

## `watchId` (type: `string`):

Required for change monitoring. Use a stable name of 1 to 80 letters, digits, underscores or hyphens. Different IDs keep separate baselines. Keep runs sequential. An unfinished run blocks this watch until resumed or a new ID is chosen.

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

Cloud datacenter access without an added proxy passed testing. Enable Apify datacenter proxy if your route is refused. Residential is optional and can increase platform costs. No outside service or account credential is required.

## Actor input object example

```json
{
  "startUrls": [
    "https://open.spotify.com/artist/4gzpq5DPGxSnKTe4SA8HAU",
    "https://open.spotify.com/artist/4Z8W4fKeB5YxbusRsdQVPb"
  ],
  "searchType": "artist",
  "maxItems": 20,
  "includeTracks": false,
  "includeTopCities": true,
  "onlyChangedSinceLastRun": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `music` (type: `string`):

No description

## `audience` (type: `string`):

No description

## `tracks` (type: `string`):

No description

## `summary` (type: `string`):

No description

## `collections` (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 = {
    "startUrls": [
        "https://open.spotify.com/artist/4gzpq5DPGxSnKTe4SA8HAU",
        "https://open.spotify.com/artist/4Z8W4fKeB5YxbusRsdQVPb"
    ],
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("vant47/spotify-artist-playlist-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 = {
    "startUrls": [
        "https://open.spotify.com/artist/4gzpq5DPGxSnKTe4SA8HAU",
        "https://open.spotify.com/artist/4Z8W4fKeB5YxbusRsdQVPb",
    ],
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("vant47/spotify-artist-playlist-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 '{
  "startUrls": [
    "https://open.spotify.com/artist/4gzpq5DPGxSnKTe4SA8HAU",
    "https://open.spotify.com/artist/4Z8W4fKeB5YxbusRsdQVPb"
  ],
  "maxItems": 20
}' |
apify call vant47/spotify-artist-playlist-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vant47/spotify-artist-playlist-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/SfsgLNhh34eEYtETc/builds/9bG81S2h4klYunnBI/openapi.json
