# Spotify Play Count Scraper: Streams for Tracks, Albums, Artists (`eduair94/spotify-play-count-scraper`) Actor

Spotify play counts (stream counts) for any track, every track on an album and an artist's top tracks, plus monthly listeners and followers. Paste URLs, no API key needed. Pay per result.

- **URL**: https://apify.com/eduair94/spotify-play-count-scraper.md
- **Developed by:** [Eduardo Airaudo](https://apify.com/eduair94) (community)
- **Categories:** Social media, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 1,000 play count rows

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?

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

## Spotify Play Count Scraper

Get the all-time **play count** (stream count) Spotify shows for a song, as a plain number you can sort, chart and export. Paste Spotify links and get one row per track: a single track, **every track on an album**, or an **artist's top tracks with monthly listeners, followers and world rank**. No Spotify API key, no login, **$1.00 per 1,000 results**.

### What does Spotify Play Count Scraper do?

It reads the play counts Spotify shows publicly and returns them as structured data:

| You paste                    | You get                                                                                                              |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| A track URL, URI or ID       | 1 row: the track's play count, album, release date and duration                                                      |
| An album URL, URI or ID      | 1 row per track on the album (up to `maxTracksPerAlbum`), in album order                                             |
| An artist URL, URI or ID     | 1 row per top track (usually 10) with its play count, plus the artist's monthly listeners, followers and world rank |

Mix all three in one run. Every row has a numeric `playCount`, the track `name`, its `artists`, a Spotify `url`, and the `inputUrl` you entered, so you can match results back to your list.

- Exact numbers such as `5587020553`, not rounded "5.5B" labels.
- Accepts `open.spotify.com` links (with or without `?si=` and `intl-xx`), `spotify:` URIs and bare IDs.
- Failed, invalid and repeated inputs are never charged.
- Most runs finish in seconds.

### How to use Spotify Play Count Scraper

1. Paste Spotify track, album or artist links into **Spotify URLs, URIs or IDs** (`urls`), one per line.
2. Click **Start**.
3. Open the **Play counts** tab of the dataset, or download the results as CSV, Excel, JSON or HTML.

### Input

| Field               | Type                           | Default  | What it does                                                                                                            |
| ------------------- | ------------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------- |
| `urls`              | array of strings               | required | Spotify track, album or artist URLs, `spotify:` URIs or 22-character IDs. The type is detected from each URL or URI.   |
| `defaultType`       | `track` / `album` / `artist`   | `track`  | Type used for bare IDs, which carry no type of their own. Links and URIs always keep their own type.                    |
| `maxTracksPerAlbum` | integer, 1-200                 | `50`     | How many tracks to return per album input, in album order. Each track is one result.                                    |
| `includeRaw`        | boolean                        | `false`  | Adds the full upstream Spotify response under `raw` on every result (much larger output).                               |

#### Play counts of individual tracks

```json
{
    "urls": [
        "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b",
        "spotify:track:7qiZfU4dY1lWllzX7mPBI3"
    ]
}
```

#### Play counts of every track on an album

```json
{
    "urls": ["https://open.spotify.com/album/6s84u2TUpR3wdUv4NgKA2j"],
    "maxTracksPerAlbum": 200
}
```

#### An artist's top tracks with monthly listeners

```json
{
    "urls": ["https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02"]
}
```

#### A mixed list

This is the prefilled input: two tracks, one album and one artist in the same run (23 results).

```json
{
    "urls": [
        "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b",
        "https://open.spotify.com/track/7qiZfU4dY1lWllzX7mPBI3",
        "https://open.spotify.com/album/6s84u2TUpR3wdUv4NgKA2j",
        "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02"
    ]
}
```

#### Bare IDs

A bare ID has no type, so tell the Actor what it is with `defaultType`:

```json
{
    "urls": ["1McMsnEElThX1knmY4oliG", "06HL4z0CvFAxyc27GXpf02"],
    "defaultType": "artist"
}
```

### Output

One dataset row per track. The **Play counts** table shows `name`, `artists`, `playCount`, `albumName`, `entityType`, `url`, `inputUrl` and `scrapedAt`. The **Artist top tracks** table shows `artistName`, `topTrackRank`, `name`, `playCount`, `monthlyListeners`, `followers`, `worldRank` and `url`.

A track input:

```json
{
    "name": "Blinding Lights",
    "artists": ["The Weeknd"],
    "playCount": 5587020553,
    "id": "0VjIjW4GlUZAMYd2vXMi3b",
    "type": "track",
    "uri": "spotify:track:0VjIjW4GlUZAMYd2vXMi3b",
    "url": "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b",
    "artistIds": ["1Xyo4u8uXC1ZmMpatF05PJ"],
    "albumId": "4yP0hdKOZPNshxUOjY0cZj",
    "albumName": "After Hours",
    "albumUri": "spotify:album:4yP0hdKOZPNshxUOjY0cZj",
    "imageUrl": "https://i.scdn.co/image/ab67616d00001e028863bc11d2aa12b54f5aeb36",
    "releaseDate": "2020-03-20T00:00:00Z",
    "durationMs": 200040,
    "trackNumber": 9,
    "explicit": false,
    "inputUrl": "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b",
    "entityType": "track",
    "scrapedAt": "2026-09-13T19:11:54.070Z",
    "data": { "…": "Spotify track object" }
}
```

An album input gives one row per track:

```json
{
    "name": "drivers license",
    "artists": ["Olivia Rodrigo"],
    "playCount": 2949798629,
    "id": "5wANPM4fQCJwkGd4rN57mH",
    "type": "track",
    "uri": "spotify:track:5wANPM4fQCJwkGd4rN57mH",
    "url": "https://open.spotify.com/track/5wANPM4fQCJwkGd4rN57mH",
    "artistIds": ["1McMsnEElThX1knmY4oliG"],
    "durationMs": 242013,
    "trackNumber": 3,
    "discNumber": 1,
    "explicit": true,
    "albumId": "6s84u2TUpR3wdUv4NgKA2j",
    "albumUri": "spotify:album:6s84u2TUpR3wdUv4NgKA2j",
    "inputUrl": "https://open.spotify.com/album/6s84u2TUpR3wdUv4NgKA2j",
    "entityType": "album",
    "scrapedAt": "2026-09-13T19:11:53.442Z",
    "data": { "…": "Spotify album track entry" }
}
```

An artist input gives one row per top track, with the artist's stats on each:

```json
{
    "name": "The Fate of Ophelia",
    "artists": ["Taylor Swift"],
    "playCount": 1655436525,
    "id": "53iuhJlwXhSER5J2IYYv1W",
    "type": "track",
    "uri": "spotify:track:53iuhJlwXhSER5J2IYYv1W",
    "url": "https://open.spotify.com/track/53iuhJlwXhSER5J2IYYv1W",
    "artistIds": ["06HL4z0CvFAxyc27GXpf02"],
    "albumId": "4a6NzYL1YHRUgx9e3YZI6I",
    "albumUri": "spotify:album:4a6NzYL1YHRUgx9e3YZI6I",
    "imageUrl": "https://i.scdn.co/image/ab67616d00001e02d7812467811a7da6e6a44902",
    "durationMs": 226073,
    "discNumber": 1,
    "explicit": false,
    "topTrackRank": 1,
    "artistId": "06HL4z0CvFAxyc27GXpf02",
    "artistName": "Taylor Swift",
    "monthlyListeners": 100466571,
    "followers": 163965313,
    "worldRank": 5,
    "inputUrl": "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02",
    "entityType": "artist",
    "scrapedAt": "2026-09-13T19:11:54.240Z",
    "data": { "…": "Spotify top-track entry" }
}
```

#### Output fields

| Field                                                                  | Description                                                                                          |
| ---------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| `name`                                                                 | Track name                                                                                           |
| `artists`                                                              | Names of the credited artists (`artistIds` has their Spotify IDs)                                    |
| `playCount`                                                            | All-time Spotify play count (stream count), as a number                                             |
| `id`, `uri`, `url`                                                     | Track ID, `spotify:track:` URI and open.spotify.com link                                             |
| `albumName`, `albumId`, `albumUri`                                     | The track's album (`albumName` for track inputs)                                                     |
| `releaseDate`, `imageUrl`                                              | Release date (track inputs) and cover image (track and artist inputs)                                |
| `durationMs`, `trackNumber`, `discNumber`, `explicit`                  | Track details, when Spotify returns them                                                             |
| `topTrackRank`                                                         | Artist inputs: position of the track in the artist's Spotify top tracks                              |
| `artistName`, `artistId`, `monthlyListeners`, `followers`, `worldRank` | Artist inputs: the artist you entered and their Spotify stats (`worldRank` only when ranked)         |
| `inputUrl`                                                             | The URL, URI or ID you entered, exactly as entered                                                   |
| `entityType`                                                           | What you entered: `track`, `album` or `artist`                                                       |
| `scrapedAt`                                                            | When the play count was read                                                                         |
| `data`                                                                 | The Spotify object the row was built from                                                            |
| `raw`                                                                  | Full upstream response, only with `includeRaw`                                                       |

The run's key-value store also holds `RUN_SUMMARY` (inputs by type, results delivered, failures and the run outcome) and, when an input fails, `ERRORS` (each failed input with its reason and `charged: false`).

### Pricing

**$1.00 per 1,000 results** (pay per event). One result is one row: one track with its play count.

- No start fee and no monthly rental.
- Failed, invalid and empty inputs are free: an ID Spotify does not know, a playlist link, a typo.
- A link repeated in the same run is fetched and charged once.
- Paid Apify plans get discounted result prices.
- Set a maximum cost per run and the Actor stops there, without charging more.

| You enter                     | Results | Cost    |
| ----------------------------- | ------- | ------- |
| 1 track                       | 1       | $0.001  |
| 1 album with 11 tracks        | 11      | $0.011  |
| 1 artist (top 10 tracks)      | 10      | $0.010  |
| The four prefilled links      | 23      | $0.023  |
| 10,000 tracks                 | 10,000  | $10.00  |

### FAQ

#### What is a Spotify play count?

It is the number Spotify shows next to each track on artist and album pages: how many times the track has been streamed on Spotify, all time. Spotify counts a play once a track has been listened to for at least 30 seconds. This Actor returns it as `playCount`, a whole number.

#### How fresh are the play counts?

Every run reads Spotify's public counter live. Spotify refreshes that counter periodically, usually about once a day, so two runs on the same day tend to return the same number. To track stream growth, schedule the Actor daily and compare `playCount` per `id` across `scrapedAt`.

#### Why do album rows have no album name?

Spotify's album track list names each track but not the album, so album rows carry the album's `albumId` and `albumUri` (from your input) but no `albumName`, cover or release date. Artist top-track rows have the `albumId` and cover, but no `albumName` either. Enter track links when you need `albumName` and `releaseDate` on every row.

#### Why did I get fewer rows than there are tracks?

Tracks that Spotify returns without a play count are skipped and not charged, and album inputs stop at `maxTracksPerAlbum`. Artist inputs return Spotify's top tracks only (usually 10); add the artist's album links to cover the whole catalog.

#### What happens with a wrong or unsupported link?

It is listed in the `ERRORS` record with the reason and `charged: false`. Typical reasons: Spotify does not know the ID, the link is a playlist or podcast, or the text is not a Spotify link. The run still succeeds, with a status message such as "Delivered 22 items; 1 query had no data on Spotify … and was not charged." Temporary Spotify or network errors are retried first. A run fails only when it delivered nothing because of a temporary error, so Apify's retry and alert settings can react.

#### Do I need a Spotify account or API key?

No. You only need an Apify account.

#### Can I call it via API or connect it to other tools?

Yes. This call starts a run and returns the results:

```bash
curl -X POST "https://api.apify.com/v2/acts/eduair94~spotify-play-count-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"urls": ["https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b"]}'
```

JavaScript, with the `apify-client` package:

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('eduair94/spotify-play-count-scraper').call({
    urls: ['https://open.spotify.com/album/6s84u2TUpR3wdUv4NgKA2j'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const item of items) console.log(item.name, item.playCount);
```

Python, with the `apify-client` package:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("eduair94/spotify-play-count-scraper").call(
    run_input={"urls": ["https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02"]}
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["name"], item["playCount"], item.get("monthlyListeners"))
```

You can also schedule runs, get a webhook when a run finishes, and send results to Google Sheets, Slack, Make, Zapier and other tools with Apify integrations.

#### Is it legal to scrape Spotify play counts?

Play counts are public: Spotify shows them to every visitor. The Actor collects no personal data. You are responsible for making sure your use of the data complies with Spotify's terms and the laws that apply to you.

#### I need other Spotify data

[Spotify Scraper](https://apify.com/eduair94/spotify-scraper) covers lyrics, song credits, playlists, charts, concerts, search and more, including the same play counts.

### Use cases

- **Music marketing**: measure what a release campaign, a playlist placement or a viral moment did to a track's streams.
- **A\&R and talent scouting**: compare catalogs and spot breakout tracks by stream count and monthly listeners.
- **Royalty estimation**: multiply streams by a per-stream rate (commonly cited at $0.003-$0.005) to estimate what a track, album or catalog earned.
- **Chart and stream tracking**: schedule daily runs and chart each track's stream growth.
- **Catalog valuation and due diligence**: quantify a catalog's performance before buying, financing or licensing it.
- **Research and journalism**: back stories and reports with exact stream counts.

# Actor input Schema

## `urls` (type: `array`):

One per line: track, album or artist links from open.spotify.com, spotify: URIs such as spotify:track:0VjIjW4GlUZAMYd2vXMi3b, or bare 22-character IDs. Mixed lists work: each line's type is detected from its URL or URI. A track returns its play count, an album returns the play count of every track on it, and an artist returns the play counts of their top tracks plus monthly listeners, followers and world rank.

## `defaultType` (type: `string`):

How to read a bare 22-character ID that is not a URL or spotify: URI. URLs and URIs always use their own type, so for a list of links you can leave this as Track.

## `maxTracksPerAlbum` (type: `integer`):

For album inputs: how many tracks to return, in album order (up to 200). Each track is one result. Artist inputs always return Spotify's top tracks (usually 10).

## `includeRaw` (type: `boolean`):

Attach the full upstream Spotify response under `raw` on every result. All results of one album or artist repeat the same response, so the output gets much larger. Off by default: `data` already holds each track's own Spotify object.

## Actor input object example

```json
{
  "urls": [
    "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b",
    "https://open.spotify.com/track/7qiZfU4dY1lWllzX7mPBI3",
    "https://open.spotify.com/album/6s84u2TUpR3wdUv4NgKA2j",
    "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02"
  ],
  "defaultType": "track",
  "maxTracksPerAlbum": 50,
  "includeRaw": false
}
```

# Actor output Schema

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

Every result of this run: one row per track with its play count.

## `resultsCsv` (type: `string`):

The same results as CSV for spreadsheets, without the nested `data` and `raw` fields.

## `runSummary` (type: `string`):

Inputs by type, results delivered and failed inputs for this run. Failed inputs are listed in the ERRORS record and never charged.

# 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 = {
    "urls": [
        "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b",
        "https://open.spotify.com/track/7qiZfU4dY1lWllzX7mPBI3",
        "https://open.spotify.com/album/6s84u2TUpR3wdUv4NgKA2j",
        "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("eduair94/spotify-play-count-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 = { "urls": [
        "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b",
        "https://open.spotify.com/track/7qiZfU4dY1lWllzX7mPBI3",
        "https://open.spotify.com/album/6s84u2TUpR3wdUv4NgKA2j",
        "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("eduair94/spotify-play-count-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 '{
  "urls": [
    "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b",
    "https://open.spotify.com/track/7qiZfU4dY1lWllzX7mPBI3",
    "https://open.spotify.com/album/6s84u2TUpR3wdUv4NgKA2j",
    "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02"
  ]
}' |
apify call eduair94/spotify-play-count-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,eduair94/spotify-play-count-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/28Y4VaIkWzw8cbbkH/builds/YLHwhX8loANN9tFy2/openapi.json
