# Spotify Artist Analytics & Monthly Listeners Tracker (`fanndev/spotify-artist-analytics-tracker`) Actor

Track any Spotify artist's monthly listeners, followers and top-5 listener cities over time, with per-run growth deltas. Also returns top tracks with lifetime play counts, the playlists driving discovery, upcoming concerts and social links. No Spotify account or API key needed.

- **URL**: https://apify.com/fanndev/spotify-artist-analytics-tracker.md
- **Developed by:** [Faisal Ahdan naufal](https://apify.com/fanndev) (community)
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.50 / 1,000 results

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 Artist Analytics & Monthly Listeners Tracker

Read the numbers on any Spotify artist page — **monthly listeners**, followers,
the **five cities with the most listeners** — and, because Spotify publishes no
history at all, remember them so the next run can tell you which way they moved.

Built for artist managers, A\&R, promoters and PR teams who need growth evidence
rather than a screenshot: schedule it daily or weekly across a watchlist and
each run answers *how fast, in which direction, in which cities*.

No Spotify account, no Spotify for Artists login, no API key, no browser.

***

### What you get per artist

| Field | Notes |
| --- | --- |
| **`monthlyListeners`** | Unique listeners in the last 28 days |
| **`followers`** | Accounts following the artist |
| **`topCities`** | Five cities with city, country, region and listener counts |
| `listenersPerFollower` | Reach that has not converted into a following yet |
| **`monthlyListenersChange`** + `…Percent`, `…PerDay`, `trend` | Movement since the previous run |
| `topTracks` | Ten most-played tracks with **lifetime play counts** |
| **`discoveredOnPlaylists`** | The playlists actually feeding the artist new listeners |
| `featuredInPlaylists`, `relatedArtists` | Editorial placement and Spotify's similarity graph |
| `upcomingConcerts` | Dates, venues, cities, festival flag |
| `socialLinks` | Facebook, Instagram, Twitter, TikTok, YouTube, Wikipedia |
| `albumCount`, `singleCount`, `latestReleaseName`, `latestReleaseDate` | Catalogue at a glance |
| `biography`, `avatarImage`, `headerImage` | Press-kit material |

***

### Quick start

```json
{
  "artistUrls": ["https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt"],
  "artistNames": ["Tulus", "NIKI"],
  "trackChanges": true,
  "exportFormats": ["csv"]
}
```

Artists can be given as links **or** plain names — a name costs one extra
search request, and the run log prints which artist it matched so you can spot
an ambiguous one.

***

### How the growth tracking works

Spotify shows today's number and nothing else. To turn that into a trend, each
run writes its readings to a **named key-value store** (`trackingStoreName`,
default `spotify-artist-analytics`) and compares the next run against it.

- The **first run** has nothing to compare against: rows are marked
  `isFirstReading: true`. That is the baseline, not a failure.
- Every later run adds `monthlyListenersChange`, `…ChangePercent`,
  `…ChangePerDay`, `followersChange`, `topTrackPlaycountChange`, `trend`,
  `previousReadingAt` and `daysSincePreviousReading`.
- `…ChangePerDay` is what makes a weekly run comparable with a daily one.
- Use a **named** store, not the run's own — a run-scoped store vanishes with
  the run and every run would look like the first. Point several scheduled runs
  at the same name to build one history; use different names to keep separate
  watchlists apart.

Schedule it daily for a launch campaign, weekly for a roster.

***

### Cost

**One request per artist**, plus one to pick up an anonymous token. A 200-artist
watchlist is 201 requests. Looking an artist up by name adds one request each.

***

### Limits worth knowing

- **Monthly listeners are a rolling 28-day figure Spotify refreshes on its own
  schedule**, so two runs hours apart will often show no change. Daily is the
  most granular cadence that means anything.
- **`worldRank` is null for almost everyone.** Spotify sends `0` for artists
  outside its published global ranking; that is normalised to `null` here so it
  cannot be misread as first place.
- **Top cities are always five**, and they are listener counts, not stream
  counts.
- **`discoveredOnPlaylists` arrives padded with placeholder entries** that
  resolve to nothing. They are dropped, so the count is of real playlists.
- This reads the **public artist page**. It is not Spotify for Artists and does
  not expose stream-by-stream, demographic or save data.

***

### Output

Every run writes to the Apify dataset. Set `exportFormats` to also drop a
ready-made `spotify-artist-analytics.csv`, `.xlsx`, `.json` or `.ndjson` into
the run's key-value store. Nested fields flatten poorly into CSV, so switch on
`emitTopTrackRows` if you want the top tracks as their own spreadsheet rows.

See [CRAWLING\_METHOD.md](CRAWLING_METHOD.md) for how the data is obtained.

# Actor input Schema

## `artistUrls` (type: `array`):

Spotify artists to read. Share links, /intl-xx/ localised links, spotify:artist: URIs and bare artist ids all work.

## `artistNames` (type: `array`):

Artists to look up by name instead of by link, one per line. Each name costs one extra search request and the run logs which artist it matched, so check the log when a name is ambiguous.

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

The same artist links, in the request-list format, for callers that already keep one.

## `trackChanges` (type: `boolean`):

Remember this run's numbers and report the change next time: absolute delta, percentage, a per-day rate and an up/down/flat trend for monthly listeners, followers and the top track's play count. The first run has nothing to compare against and is marked isFirstReading.

## `trackingStoreName` (type: `string`):

Named key-value store that holds the previous reading. Scheduled runs pointed at the same name build one history; use different names to keep separate watchlists apart.

## `includeTopTracks` (type: `boolean`):

Attach the artist's ten most-played tracks, each with its lifetime play count, as a nested field on the artist record.

## `emitTopTrackRows` (type: `boolean`):

Write each top track as its own TOP\_TRACK dataset row as well. Handy for spreadsheets, since nested fields flatten badly into CSV.

## `includeDiscovery` (type: `boolean`):

Attach the playlists Spotify says the artist is being discovered on - the most actionable list on the page for an artist team - plus the playlists featuring them and the artists Spotify considers similar.

## `includeConcerts` (type: `boolean`):

Attach the upcoming dates Spotify lists for the artist, with venue, city and whether it is a festival.

## `maxArtists` (type: `integer`):

Ceiling on how many artists a single run reads, so an oversized watchlist cannot run away.

## `exportFormats` (type: `array`):

Besides the dataset, write ready-made files into this run's key-value store.

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

Off by default and genuinely optional: the endpoint this actor reads has no WAF and no IP block, so the platform's own address reaches it. Turn it on only for very large watchlists.

## Actor input object example

```json
{
  "artistUrls": [
    "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt"
  ],
  "trackChanges": true,
  "trackingStoreName": "spotify-artist-analytics",
  "includeTopTracks": true,
  "emitTopTrackRows": false,
  "includeDiscovery": true,
  "includeConcerts": true,
  "maxArtists": 200,
  "exportFormats": [],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Every artist reading, optional top-track rows and any error records from this run.

# 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 = {
    "artistUrls": [
        "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("fanndev/spotify-artist-analytics-tracker").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 = { "artistUrls": ["https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt"] }

# Run the Actor and wait for it to finish
run = client.actor("fanndev/spotify-artist-analytics-tracker").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 '{
  "artistUrls": [
    "https://open.spotify.com/artist/0gxyHStUsqpMadRV0Di1Qt"
  ]
}' |
apify call fanndev/spotify-artist-analytics-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fanndev/spotify-artist-analytics-tracker"
        }
    }
}
```

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/ySbFGDWOFjgx1vOBK/builds/QKvgwXwPa1RE1SZpv/openapi.json
