# Spotify Scraper—Play Counts, Monthly Listeners & Playlists (`eduair94/spotify-scraper`) Actor

Spotify play counts for tracks, albums, playlists and whole discographies, plus monthly listeners, world rank, charts with streams, lyrics and podcasts. Paste any link. Pay per result.

- **URL**: https://apify.com/eduair94/spotify-scraper.md
- **Developed by:** [Eduardo Airaudo](https://apify.com/eduair94) (community)
- **Categories:** Social media, Developer tools, Automation
- **Features:** Limited permissions
- **Stats:** 181 total users, 76 monthly users, 99.9% runs succeeded, 2 bookmarks
- **User rating**: 5.00 out of 5 stars

## Pricing

from $0.60 / 1,000 scraped items

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: Play Counts, Monthly Listeners & Playlists

Get Spotify **play counts** (all-time streams) for tracks, albums, playlists and whole artist discographies, **artist analytics** (monthly listeners, followers, world rank, top cities, social links), and **playlists and Spotify Charts with daily streams**. Paste any mix of Spotify links and each one is scraped according to its type. Lyrics, song credits, audio features, podcasts, concerts and search are included too.

No Spotify account or API key is needed. You pay only for the rows you get: **$1.00 per 1,000 results**, less on paid Apify plans.

### What does Spotify Scraper do?

| Job                    | You paste                                       | You get                                                                                                                                                                                                                        |
| ---------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Play counts**        | Track, album, playlist or artist links; ISRC codes | One row per track with a numeric `playCount`, plus album, label, release date and ISRC. Covers single tracks, every track on an album (with the album total), every track in a playlist, and an artist's whole discography. |
| **Artist analytics**   | Artist links, or artist names                   | Monthly listeners, followers, world rank, top 5 cities, verified badge, bio, Instagram, X, Facebook and Wikipedia links, discography counts, latest release, top tracks with play counts, and related artists.               |
| **Playlists & charts** | Playlist links; country codes                   | Playlist followers, owner and track count, and full tracklists with play counts and add dates. Spotify Charts by country: Top 200 with daily streams, Viral, top artists and top albums, each with rank change, peak and days on chart. |

It also covers Spotify's own **genres, moods, activities and tempo** for tracks and artists, time-synced lyrics, song credits (writers and producers), audio features (tempo, key, energy, danceability, valence), podcast shows and episodes, Spotify search, concerts, recommendations, user profiles, and ISRC and UPC lookups. It can also find the matching track, album or artist on YouTube Music, Apple Music, Amazon Music and other platforms.

### How to use Spotify Scraper

1. Paste Spotify links, `spotify:` URIs or IDs into **Spotify links, IDs or keywords**, one per line. You can mix tracks, albums, artists and playlists.
2. Leave **Data category** on **Auto**, or pick a category from the tables below. For example, `playlist_play_counts` returns every track of a playlist with its play count.
3. Click **Start**. Then open the dataset tabs (**Overview**, **Tracks & play counts**, **Artists**, **Albums**, **Playlists**, **Charts**, **Concerts**, **Podcasts**, **Audio features**, **Genres & moods**) or export the results as CSV, Excel or JSON.

### Auto: paste any Spotify link

`auto` is the default category. Each line is scraped according to the type of link, and plain text is searched on Spotify:

```json
{
    "queries": [
        "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b",
        "https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj",
        "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02",
        "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M",
        "Daft Punk"
    ]
}
```

This input returns 5 rows (5 results, $0.005):

| Line                     | Runs as                                          | The row has                                                                                     |
| ------------------------ | ------------------------------------------------ | ----------------------------------------------------------------------------------------------- |
| Track link               | `track`                                          | `playCount`, artists, album, release date, duration, ISRC, popularity                           |
| Album link               | `album`                                          | label, UPC, © and ℗ lines, album type, track count, popularity                                  |
| Artist link              | `artist_overview`                                | monthly listeners, followers, world rank, top cities, social links, discography counts         |
| Playlist link            | `playlist`                                       | followers, owner, track count, description                                                      |
| Show or episode link     | `show` or `episode`                              | publisher, episode count and languages; or duration, release date and the show                  |
| User or concert link     | `user_profile` or `partner_concert`              | followers and public playlists; or date, venue, lineup and tickets                              |
| Plain text (`Daft Punk`) | Spotify's top search hit, scraped as its type    | the matched entity (an artist here), with `resolvedFrom: "search"` and `matchedName`             |
| Bare 22-character ID     | The type in **Type of bare IDs** (track by default) | as above                                                                                      |

Auto accepts open.spotify.com links (including `/intl-xx/`, `/embed/` and `?si=` links), `spotify:` URIs, spotify.link short links and bare IDs, also inside quotes or brackets or followed by a comma, as pasted from a CSV or JSON list. If you enter the same track, album or artist twice, it is scraped and charged once.

Auto returns one row per link. To get every track of an album, a playlist or an artist, use the play-count categories below.

### Play counts

| Category                         | Paste                       | One row per                                                                             | Columns besides `playCount`                                                                                           |
| -------------------------------- | --------------------------- | --------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| `track` (also used by Auto)      | Track links or IDs          | track                                                                                   | `artists`, `albumName`, `releaseDate`, `durationMs`, `isrc`, `popularity`, `explicit`, `trackNumber`, `imageUrl`      |
| `album_play_counts`              | Album links                 | track on the album                                                                      | `albumName`, `albumType`, `label`, `copyrightC`, `copyrightP`, `releaseDate`, `albumTotalPlayCount`, `trackNumber`    |
| `playlist_play_counts`           | Playlist links              | track in the playlist                                                                   | `position`, `addedAt`, `playlistName`, `playlistOwner`, `albumName`, `artists`, `durationMs`                          |
| `artist_discography_play_counts` | Artist links                | track on the artist's albums, singles, EPs and compilations (newest first, each track once) | `albumName`, `albumType`, `label`, `releaseDate`, `albumTotalPlayCount`, `trackNumber`                            |
| `artist_play_counts`             | Artist links                | top track (up to 10)                                                                    | `topTrackRank`, plus the artist's `monthlyListeners`, `followers` and `worldRank`                                     |
| `isrc`                           | ISRC codes (`USUG11904206`) | ISRC code                                                                               | the first track Spotify lists for the code, with the `track` columns. Other tracks with the same ISRC are in `metadata.otherTrackIds` |
| `track_play_count`               | Track links or IDs          | track                                                                                   | `albumName`, `releaseDate`, `durationMs`, `explicit` (one track per request; `track` is faster for long lists)        |

- `playCount` is an exact number, such as `5631276067`. Spotify shows `0` until a track passes 1,000 streams.
- Album, playlist and discography categories return up to **Max results per query** rows per input (default 50, maximum 1,000). Raise it for long playlists and big discographies.
- In `track_play_count`, `album_play_counts`, `playlist_play_counts`, `artist_play_counts` and `artist_discography_play_counts`, a track that Spotify returns without a play count is skipped and not charged. `track` and `isrc` rows still arrive with their other columns if a play count cannot be read; `RUN_SUMMARY` counts them under `playCounts.missing`.

#### Every track of an artist's discography

```json
{
    "category": "artist_discography_play_counts",
    "queries": ["https://open.spotify.com/artist/163tK9Wjr9P9DmM0AVK7lm"],
    "maxResultsPerQuery": 1000
}
```

#### Album play counts output sample

```json
{
    "category": "album_play_counts",
    "query": "https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj",
    "name": "Alone Again",
    "artists": ["The Weeknd"],
    "playCount": 232644924,
    "albumName": "After Hours",
    "albumType": "album",
    "label": "Republic Records",
    "copyrightP": "℗ 2020 The Weeknd XO, Inc., marketed by Republic Records, a division of UMG Recordings, Inc.",
    "releaseDate": "2020-03-20T00:00:00Z",
    "trackNumber": 1,
    "durationMs": 250053,
    "explicit": true,
    "albumTotalPlayCount": 14241532644,
    "id": "6b5P51m8xx2XA6U7sdNZ5E",
    "url": "https://open.spotify.com/track/6b5P51m8xx2XA6U7sdNZ5E",
    "imageUrl": "https://i.scdn.co/image/ab67616d00001e028863bc11d2aa12b54f5aeb36"
}
```

A `playlist_play_counts` row adds the track's place in the playlist:

```json
{
    "category": "playlist_play_counts",
    "name": "Stop The Wedding!",
    "artists": ["Ashe"],
    "playCount": 90942260,
    "position": 1,
    "addedAt": "2026-09-04T04:02:23.110Z",
    "playlistId": "37i9dQZF1DXcBWIGoYBM5M",
    "playlistName": "Today’s Top Hits",
    "playlistOwner": "Spotify",
    "albumName": "Stop The Wedding!",
    "durationMs": 198840,
    "url": "https://open.spotify.com/track/3zOYmiNOuyDL0ClxJcEJ0T"
}
```

### Artist analytics

`artist_overview` (Auto uses it for artist links) returns one row per artist:

```json
{
    "category": "artist_overview",
    "name": "Taylor Swift",
    "monthlyListeners": 106764975,
    "followers": 165400798,
    "worldRank": 5,
    "verified": true,
    "topCities": [
        { "city": "London", "country": "GB", "region": "ENG", "listeners": 1714272 },
        { "city": "Quezon City", "country": "PH", "region": "00", "listeners": 1474171 }
    ],
    "instagramUrl": "https://instagram.com/taylorswift",
    "twitterUrl": "https://twitter.com/taylorswift13",
    "albumsCount": 34,
    "singlesCount": 80,
    "compilationsCount": 1,
    "latestRelease": { "id": "4hF2gTGuPYlykYuphDxi8J", "name": "The Life of a Showgirl: The Encore", "type": "album", "releaseDate": "2026-09-25" },
    "topTracks": [
        { "id": "1BxfuPKGuaTgP7aM0Bbdwr", "name": "Cruel Summer", "playCount": 3509373490 },
        { "id": "1u8c2t2Cy7UBoG4ArRcF5g", "name": "Blank Space", "playCount": 2631900405 }
    ],
    "relatedArtists": [
        { "id": "1McMsnEElThX1knmY4oliG", "name": "Olivia Rodrigo" },
        { "id": "74KM79TiuVKeVCqs8QtB0B", "name": "Sabrina Carpenter" }
    ],
    "id": "06HL4z0CvFAxyc27GXpf02",
    "url": "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02"
}
```

The sample is shortened. A real row has all 5 top cities, every link and gallery image, up to 10 top tracks and the related artists Spotify lists.

| Category                      | One row per                                                                                         |
| ----------------------------- | --------------------------------------------------------------------------------------------------- |
| `artist_overview`             | artist: the columns above, plus `description` (bio), `headerImageUrl`, `galleryImageUrls` and `externalLinks` |
| `artist_albums`               | album, with release date, type and track count                                                      |
| `artist_singles`              | single or EP                                                                                        |
| `artist_appears_on`           | release the artist appears on (Spotify returns up to 50)                                            |
| `artist_discovered_on`        | playlist where listeners discovered the artist (up to 50)                                           |
| `artist_featuring`            | playlist that features the artist                                                                  |
| `artist_related`              | related artist ("Fans also like")                                                                   |
| `artist_discography_overview` | artist: album, single and compilation counts                                                        |
| `artist_concerts`             | upcoming concert, with venue, address, coordinates and ticket links                                 |
| `artist`                      | artist from Spotify's Web API: image and popularity, 50 per request. Turn on **Extra data → Artist stats** (`include: ["stats"]`) for followers, monthly listeners, world rank and top cities, or use `artist_overview` |
| `artist_insights`             | artist: genre, mood and tempo profile of their top tracks (see below)                               |

### Genres, moods and tempo

`track_insights` returns Spotify's own descriptors for each track: genres, moods and activities (strongest first), the tempo, who wrote and produced it, whether it has lyrics and the vocal language.

```json
{
    "category": "track_insights",
    "name": "Blinding Lights",
    "artists": ["The Weeknd"],
    "genres": ["pop", "electropop", "dance pop", "synthpop"],
    "moods": ["upbeat", "happy", "spooky"],
    "activities": ["gaming"],
    "tempo": 171,
    "hasLyrics": true,
    "languages": ["en"],
    "writers": ["Max Martin", "Oscar Holter", "Abel Tesfaye"],
    "producers": ["Max Martin", "Oscar Holter", "The Weeknd"],
    "isrc": "USUG11904206",
    "previewUrl": "https://p.scdn.co/mp3-preview/51c08d92815cce4ac2de94a7335a430b81234624",
    "id": "0VjIjW4GlUZAMYd2vXMi3b",
    "url": "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b"
}
```

The sample is shortened. Each genre, mood and activity comes with Spotify's weight (0 to 1) in `data`, and `data.credits` lists every credit with its role.

| Category          | Paste                                 | One row per                                                                                  |
| ----------------- | ------------------------------------- | -------------------------------------------------------------------------------------------- |
| `track_insights`  | Track links or IDs (50 per request)   | track: `genres`, `moods`, `activities`, `tempo`, `hasLyrics`, `languages`, `writers`, `producers`, `previewUrl` |
| `artist_insights` | Artist links or IDs (20 per request)  | artist: `genres`, `moods` and `activities` of their top tracks, with average `tempo`; how many top tracks carry each tag is in `data` |

#### Extra data on track, album and artist rows

**Extra data** (`include`) adds more to the regular `track`, `album`, `album_by_upc`, `artist`, `artist_overview`, `playlist_tracks`, `recommendations`, `search_tracks` and `search_multi` (its tracks) rows, Auto included, and to the track charts (`chart_top_200_tracks`, `chart_viral_tracks`). Each option takes a little longer and costs nothing extra.

| Option         | Adds                                                                                                  |
| -------------- | ----------------------------------------------------------------------------------------------------- |
| `insights`     | `track`, `playlist_tracks`, `recommendations`, track search and track chart rows: the `track_insights` columns above. `artist` and `artist_overview` rows (Auto's artist links): the `artist_insights` columns. |
| `stats`        | `artist` rows: `followers`, `monthlyListeners`, `worldRank` and `topCities`.                          |
| `playcounts`   | `album` rows: the play count of every track in `data.tracks.items`, and `albumTotalPlayCount`. `playlist_tracks`, `recommendations`, track search and track chart rows: `playCount`, the lifetime plays (editorial playlists have it anyway; chart rows keep their `streams`). |
| `total_tracks` | `track` rows: the album's track count in `data.album.total_tracks`.                                   |

A value Spotify cannot provide at that moment is left out of the row, and the run carries on.

### Playlists and charts

| Category               | Paste          | One row per                                                                                                       |
| ---------------------- | -------------- | ----------------------------------------------------------------------------------------------------------------- |
| `playlist`             | Playlist links | playlist: `followers`, `ownerName`, `totalTracks`, `description`, `snapshotId`                                    |
| `playlist_tracks`      | Playlist links | track: `addedAt`, artists, album, duration, and `playCount` when Spotify includes it                              |
| `playlist_play_counts` | Playlist links | track: `playCount`, `position`, `addedAt`, playlist name and owner                                                |
| `chart_top_200_tracks` | Country codes  | chart entry: `rank`, `streams`, `previousRank`, `rankChange`, `peakRank`, `entryStatus`, `appearancesOnChart`, `peakDate`, `entryDate`, artists, label |
| `chart_viral_tracks`   | Country codes  | chart entry: the same columns, without `streams`                                                                   |
| `chart_top_artists`    | Country codes  | artist entry with rank movement                                                                                   |
| `chart_top_albums`     | Country codes  | album entry with rank movement, artists and label                                                                 |
| `chart_top_monthly_listeners` | `GLOBAL` (the input is ignored) | one of the global Top 50 artists by monthly listeners: `monthlyListeners` as a whole number (129,800,000) and `monthlyListenersMillions` (129.8) |
| `chart_top_followers`  | `GLOBAL` (the input is ignored) | one of the global Top 50 artists by followers                                                    |
| `new_releases`         | Country codes  | new album or single in that country                                                                               |

- Enter one country code per line, such as `US`, `GB` or `MX`, or `GLOBAL` for the worldwide chart. Lines that are not country codes are skipped with a warning; if none is left, the **Market** setting is used. `new_releases` needs a country, so `GLOBAL` does not work there.
- Leave **Chart date** empty for the latest chart, or enter `YYYY-MM-DD` for a past one.
- A chart comes in one request. Set **Max results per query** to `200` to get the whole Top 200 (the default is 50).
- The two Top 50 lists are the same worldwide, so each is fetched once per run whatever you enter.
- When Spotify has not updated a country's new-releases list for more than 30 days, the run delivers nothing for that country and charges nothing.

```json
{
    "category": "chart_top_200_tracks",
    "queries": ["US", "GB"],
    "maxResultsPerQuery": 200
}
```

A Top 200 row:

```json
{
    "category": "chart_top_200_tracks",
    "query": "US",
    "country": "US",
    "rank": 1,
    "name": "Nicole Kidman",
    "artists": ["ADÉLA"],
    "streams": 1098450,
    "previousRank": 1,
    "rankChange": 0,
    "peakRank": 1,
    "entryStatus": "NO_CHANGE",
    "appearancesOnChart": 38,
    "consecutiveAppearancesOnChart": 38,
    "peakDate": "2026-09-22",
    "entryDate": "2026-09-04",
    "label": "Capitol Records",
    "releaseDate": "2026-09-04",
    "id": "70cHKK8bHAfJrOGVnfRG9J",
    "url": "https://open.spotify.com/track/70cHKK8bHAfJrOGVnfRG9J"
}
```

### More Spotify data

| Category                                                    | Paste                                       | One row per                                                                                                   |
| ----------------------------------------------------------- | ------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| `track_lyrics`                                              | Track links                                 | track: `lyrics` as plain text, with time-synced lines in `data.lines`                                         |
| `search_lyrics`                                             | Lyrics or song titles                       | the best-matching track, with its lyrics                                                                      |
| `track_credits`                                             | Track links                                 | track: `performers`, `writers`, `producers`; full credits in `data`                                           |
| `audio_features`                                            | Track links or IDs (25 per request)         | track: `tempo`, `key`, `modality` (major or minor), `energy`, `danceability`, `valence`, `loudness`, `acousticness`, `instrumentalness`, `liveness`, `speechiness`, `timeSignature` |
| `recommendations`                                           | A seed track                                | recommended track (up to 100)                                                                                 |
| `album`, `album_metadata`                                   | Album links                                 | album: label, © and ℗ lines, type, track count, release date (`album` adds `upc` and `popularity`, and track play counts with **Extra data**) |
| `album_tracks`                                              | Album links                                 | track on the album, with `playCount`                                                                          |
| `album_by_upc`                                              | UPC or EAN barcodes                         | the album with that barcode, with the `album` columns                                                         |
| `show`, `show_episodes`, `episode`                          | Podcast show or episode links               | show (publisher, episode count, languages); every episode of a show; one episode                             |
| `user_profile`, `user_followers`                            | User links or usernames                     | profile (followers, public playlists); follower                                                               |
| `search_multi`, `search_tracks`, `search_artists`, `search_albums`, `search_playlists`, `search_users`, `search_podcasts`, `search_episodes`, `search_genres` | Keywords | search result, paged up to **Max results per query** |
| `search_top_results`, `search_suggestions`                  | Keywords                                    | top result or autocomplete suggestion (up to 100)                                                             |
| `search_concert_locations`                                  | City or place names                         | location, with the `geoHash` to use in `concerts_by_location`                                                 |
| `concerts_by_location`                                      | Geohashes                                   | concert in the next 12 months                                                                                 |
| `search_concert_artists`                                    | Artist names                                | upcoming concert of the best-matching artist                                                                  |
| `partner_concert`                                           | Concert links                               | concert: date, venue, lineup, ticket providers                                                                |
| `partner_track`, `partner_album`, `partner_playlist`, `partner_artist_overview`, `partner_artist_discography` | Links | Spotify's full app object under `data`, for developers                     |

### Input

| Field                  | Default | What it does                                                                                                                       |
| ---------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `category`             | `auto`  | What to scrape (see the tables above).                                                                                             |
| `queries`              | —       | Required. One input per line: links, URIs, IDs, keywords, country codes, ISRC or UPC codes, depending on the category.             |
| `defaultType`          | `track` | Auto only: how to read a bare 22-character ID (`track`, `album`, `artist`, `playlist`, `show` or `episode`).                       |
| `include`              | `[]`    | Extra data on `track`, `album`, `album_by_upc`, `artist`, `playlist_tracks`, `recommendations` and track search rows: `insights`, `stats`, `playcounts`, `total_tracks` (see [Genres, moods and tempo](#genres-moods-and-tempo)). |
| `maxResultsPerQuery`   | `50`    | Rows per input for list categories, 1 to 1,000. Long lists are paged automatically.                                                |
| `concurrency`          | `5`     | Inputs processed at once (1 to 20). A batch of IDs fetched in one request counts as one. The Actor slows down by itself when Spotify throttles. |
| `delayMs`              | `0`     | Pause after each input (or batch), in milliseconds.                                                                                |
| `market`               | `US`    | 2-letter country for regional results, and for charts when the input has no country code.                                         |
| `chartDate`            | —       | `YYYY-MM-DD` for a past chart (empty: the latest). Also the start date of `concerts_by_location`.                                  |
| `geoHash`              | —       | Location filter for `artist_concerts` and `search_concert_artists`.                                                                |
| `enrichConcertDetails` | —       | Adds venue, address, coordinates and tickets to each concert, at one extra request per concert. On for artist concert categories unless you turn it off. |
| `concertDetailsLimit`  | `20`    | Concerts enriched per input (1 to 50).                                                                                             |
| `parsedConcerts`       | `false` | Returns concert payloads in a simplified flat shape.                                                                               |
| `includeRaw`           | `false` | Keeps Spotify's full object under `data` and adds the whole response under `raw` (much larger rows).                               |
| `enrichWithContrast`   | —       | Adds the matching entity on `ytmusic`, `applemusic`, `amazonmusic`, `pandora`, `gaana` or `tencent` to track, album and artist rows, under `contrast`. |

### Output

Every row has `category`, `query` (the input as you entered it), `scrapedAt`, the flat columns shown above, and `data`, which holds Spotify's object for that row. Presentation-only blocks such as music videos and merch are left out of `data` unless `includeRaw` is on. Lists such as `artists`, `topCities` and `topTracks` stay as arrays in JSON. In CSV they become numbered columns.

The **Output** tab links the CSV without the nested `data`, `raw`, `metadata` and `contrast` payloads, the run summary, and the failed inputs. Through the API, add `&omit=data,raw,metadata,contrast` to the dataset items URL for the same lean CSV, or `&fields=name,artists,playCount,url` to pick columns.

### Pricing

You pay per result. One result is one row in the dataset.

| Discount tier                       | Per result | Per 1,000 results |
| ----------------------------------- | ---------- | ----------------- |
| Free Apify plan                     | $0.001     | $1.00             |
| Bronze                              | $0.0009    | $0.90             |
| Silver                              | $0.00075   | $0.75             |
| Gold, Platinum and Diamond          | $0.0006    | $0.60             |

Your discount tier follows your Apify subscription; paid plans get the lower prices.

- No start fee, no monthly rental and no platform usage charges.
- Failed inputs, invalid links, repeated entities, empty results and Spotify placeholder entries are never charged.
- Set a maximum cost per run, and the Actor stops at that amount without going over. The run summary says how many inputs were left.

| Example run (Free plan prices)                                          | Results | Cost    |
| ----------------------------------------------------------------------- | ------- | ------- |
| 1 track link                                                            | 1       | $0.001  |
| The 4 prefilled links (track, album, artist, playlist)                  | 4       | $0.004  |
| Every track of a 14-track album (`album_play_counts`)                   | 14      | $0.014  |
| Every track of a 150-track playlist (`playlist_play_counts`, max results ≥ 150) | 150 | $0.15 |
| An artist's discography with 85 tracks (`artist_discography_play_counts`) | 85    | $0.085  |
| The US Top 200 (`chart_top_200_tracks`, max results 200)                | 200     | $0.20   |
| 10,000 track links                                                      | 10,000  | $10.00 ($6.00 at Gold) |

### FAQ

#### What is a Spotify play count?

It is the all-time number of streams Spotify shows next to each track on artist and album pages. Spotify counts a stream after 30 seconds of listening. This Actor returns it as `playCount`, an exact whole number.

#### Why is the play count 0?

Spotify shows a play count only after a track passes 1,000 streams, and reports `0` below that. New or niche releases read `0` until they cross the threshold. The row is still what Spotify publishes.

#### How fresh is the data?

Every run reads Spotify live. Spotify refreshes play counts about once a day, so two runs on the same day usually return the same number. To track growth, schedule the Actor (for example daily) and compare `playCount`, `monthlyListeners` or `followers` per `id` across `scrapedAt`.

#### How many results can I get?

- Up to 1,000 rows per input in list categories (**Max results per query**, default 50). Lists are paged automatically.
- Single entities (a track, an album, an artist profile, a playlist) are one row per input.
- `artist_appears_on` and `artist_discovered_on` return at most 50 rows, because Spotify stops there.
- `search_top_results`, `search_suggestions` and `recommendations` return up to 100 rows.
- There is no limit on inputs per run. A run stops early only at your maximum cost per run, or 30 seconds before its timeout, so the summary is always saved. Inputs left out are counted in `RUN_SUMMARY`.

#### Why did an input fail, and was I charged?

Failed inputs are never charged. Each one is listed in the `ERRORS` record of the run's key-value store, with the reason and a `kind`:

- `permanent`: retrying cannot help. Spotify has no data for the input (an unknown ID, a track without lyrics, a search with no results), or the input does not fit the category. For example, an artist link under `track` fails at once, without a request, with a hint to use `auto` or `artist_overview`.
- `transient`: a temporary problem on Spotify's side or ours. It is retried with backoff, and tried once more at the end of the run when time allows.
- `internal`: a bug in this Actor. Please report it on the **Issues** tab.

The run's status message sums it up, for example "Delivered 4 items; 1 query had no data on Spotify … and was not charged." A run ends **FAILED** only when it delivered nothing and a temporary error remained, so Apify's retry and alert settings can react.

#### What is in RUN_SUMMARY?

`RUN_SUMMARY` lists:

- the inputs planned, repeats removed and inputs ignored;
- the categories that Auto routed to;
- rows delivered;
- failures split into `transientErrors`, `permanentErrors` and `internalErrors`, and the failed inputs;
- `warnings` for inputs that delivered only part of their rows;
- whether the maximum cost per run or the timeout cut the run short;
- Spotify placeholder entries that were skipped;
- the outcome and status message.

Find it on the **Output** tab or in the run's key-value store.

#### Why did I get fewer rows than expected?

- **Max results per query** defaults to 50. Raise it for long playlists, discographies, charts and search.
- Repeated entities are scraped and charged once.
- Spotify sometimes puts placeholder entries (errors, unavailable items) in its lists. These are skipped and not charged.
- Spotify personalizes some editorial playlists, so pages can overlap. Repeated tracks are left out and not charged, and a warning appears in `RUN_SUMMARY`.
- In the play-count categories, tracks without a play count are skipped.

#### Why is `followers` empty on `artist` rows?

Spotify's Web API no longer returns artist followers or genres. Turn on **Extra data → Artist stats** and **Insights**, or use `artist_overview` (Auto does this for artist links), which has followers, monthly listeners, world rank and top cities. `artist_insights` gives genres.

#### What does `linkedFromId` mean?

Spotify sometimes relinks a track to another version that is playable in your market. The row then describes the playable track (`id`), and `linkedFromId` is the ID you entered.

#### How fast is it?

Track and artist links are fetched 50 per request, albums 20 and audio features 25. **Extra data** adds up to a few seconds per request. Long lists are paged 3 pages at a time, and rows are saved in batches. Most runs finish within seconds. When Spotify throttles, the Actor slows down by itself and speeds up again afterwards.

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

No. You only need an Apify account.

#### Is the service up?

The Spotify data API behind this Actor is monitored around the clock. If a run fails or returns less than you expected, open an issue in the Actor's **Issues** tab with the run ID and it will be looked at.

#### Is it legal to scrape Spotify?

This Actor reads only what Spotify shows publicly: play counts, charts, artist pages, playlists. Some categories (user profiles, followers) return the public profile data of Spotify users. Make sure your use of the data complies with Spotify's terms and with the data-protection laws that apply to you, such as GDPR.

### Use the API

This call starts a run, waits for it and returns the rows. Synchronous calls wait up to 5 minutes; for large runs, use the clients below.

```bash
curl -X POST "https://api.apify.com/v2/acts/eduair94~spotify-scraper/run-sync-get-dataset-items?omit=data,raw&maxTotalChargeUsd=1" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"queries": ["https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b", "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02"]}'
```

`maxTotalChargeUsd` caps the cost of the run.

JavaScript, with the `apify-client` package:

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('eduair94/spotify-scraper').call({
    category: 'artist_discography_play_counts',
    queries: ['https://open.spotify.com/artist/163tK9Wjr9P9DmM0AVK7lm'],
    maxResultsPerQuery: 1000,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const item of items) console.log(item.albumName, 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-scraper").call(
    run_input={
        "category": "playlist_play_counts",
        "queries": ["https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"],
        "maxResultsPerQuery": 100,
    }
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["position"], item["name"], item["playCount"])
```

Genres, moods and tempo of a chart, with each track's lifetime plays (`include` works the same on track, album, artist, playlist track, recommendation and track search rows):

```python
run = client.actor("eduair94/spotify-scraper").call(
    run_input={
        "category": "chart_top_200_tracks",
        "queries": ["US"],
        "include": ["insights", "playcounts"],
    }
)
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["rank"], item["name"], item.get("genres"), item.get("tempo"), item.get("playCount"))
```

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.

### Use cases

- **Music marketing**: measure what a release, a playlist placement or a viral moment did to a track's streams.
- **A\&R and talent scouting**: compare artists by monthly listeners, world rank and top cities, and spot breakout tracks.
- **Royalty estimates and catalog valuation**: sum the play counts of a whole discography or an album (`albumTotalPlayCount`) before buying, financing or licensing a catalog.
- **Playlist pitching**: find the playlists that feature an artist or where listeners discover them, with each playlist's followers and owner.
- **Chart tracking**: collect daily Top 200 streams and rank movement per country on a schedule.
- **Research**: lyrics, credits, audio features and podcast catalogs as clean tables.

### Related

- [Spotify Play Count Scraper](https://apify.com/eduair94/spotify-play-count-scraper): a simpler input form for play counts only.
- [Spotify Monthly Listeners Scraper](https://apify.com/eduair94/spotify-monthly-listeners-scraper): monthly listeners, followers, world rank and top cities, 50 artists per request.
- [Spotify Playlist Scraper](https://apify.com/eduair94/spotify-playlist-scraper): whole playlists with every track's play count, priced per playlist, with change tracking.
- [Spotify Artist Scraper](https://apify.com/eduair94/spotify-artist-scraper): full artist profiles with biography, social links, top tracks and related artists.
- [Spotify Charts Scraper](https://apify.com/eduair94/spotify-charts-scraper): Top 200, top artists and top albums by country, daily or weekly, with streams.
- [Spotify Related Artists Scraper](https://apify.com/eduair94/spotify-related-artists-scraper): "Fans also like" lists with each related artist's monthly listeners, followers and world rank, up to two levels deep.
- [Spotify Podcast Scraper](https://apify.com/eduair94/spotify-podcast-scraper): podcast shows with every episode's title, description, release date and duration, by link or keyword.

# Actor input Schema

## `category` (type: `string`):

Which data to extract. Leave it on 'Auto' to paste any mix of Spotify links: each link is scraped according to its type (track → track with play count, album → album, artist → artist profile with monthly listeners, followers, world rank and top cities, playlist → playlist, user → profile, show → podcast, episode → episode). Plain text is searched on Spotify and resolved to its top match; other links (other sites, audiobooks, local files) and malformed IDs fail without a search or a charge.

▶ Play counts (stream counts):
• 'track_play_count' = all-time play count of each track.
• 'album_play_counts' = play count of every track on an album, with the album's label, release date and total.
• 'artist_play_counts' = an artist's top tracks with play counts, plus monthly listeners, followers and world rank.
• 'artist_discography_play_counts' = every track of an artist's albums, singles, EPs and compilations (newest first, up to 'Max results per query' rows per artist).
• 'playlist_play_counts' = every track of a playlist with its play count and position.
• 'isrc' = input ISRC codes (e.g. USUG11904206): the matching track with its play count.
Spotify reports 0 until a track passes 1,000 streams.

▶ Charts and new releases: enter country codes (US, GB, GLOBAL…) as the input; anything else is ignored and the Market below is used. A new-releases list that Spotify has not refreshed for over 30 days is not delivered (nothing is charged).

▶ Other inputs: 'album_by_upc' takes UPC/EAN barcodes; 'audio_features' takes track links or IDs (25 per request).

▶ Genres and moods: 'track_insights' = Spotify's genres, moods and activities with their weights, tempo (BPM), credits with roles, whether the track has lyrics and its vocal languages. 'artist_insights' = an artist's genre / mood / tempo profile built from their top tracks. To get the same data on 'track' and 'artist' rows, use 'Extra data' below.

⚠️ Concert categories — pick the right one:
• 'search_concert_locations' = look up CITIES/PLACES (input: place names like 'London'). Returns geoHash/geonameId.
• 'search_concert_artists' = upcoming concerts BY ARTIST NAME (input: artist names like 'The Fratellis').
• 'artist_concerts' = the same with a Spotify artist ID/URL.
• 'concerts_by_location' = every concert at a geoHash.

## `queries` (type: `array`):

One per line. Auto and the ID categories: open.spotify.com links (including /intl-xx/ and /embed/ links), spotify.link short links, spotify: URIs or bare 22-character IDs. Search categories: keywords. Charts and new releases: country codes such as US, GB or GLOBAL. 'isrc': ISRC codes; 'album_by_upc': UPC/EAN barcodes. The same entity entered twice is scraped and charged once.

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

Category Auto only: how to read a bare 22-character ID. Links and spotify: URIs always use their own type.

## `include` (type: `array`):

Optional data added to 'track', 'album', 'album_by_upc', 'artist', 'artist_overview', 'playlist_tracks', 'recommendations', 'search_tracks' and 'search_multi' (its tracks) rows (Auto included), and the two track charts ('chart_top_200_tracks', 'chart_viral_tracks'), each at a little extra time and no extra charge:
• Insights — tracks: genres, moods, activities, tempo (BPM), credits, lyrics flag and vocal languages; artists ('artist', and 'artist_overview', which Auto uses for artist links): a genre / mood / tempo profile from their top tracks.
• Artist stats — followers, monthly listeners, world rank and top cities on 'artist' rows.
• Play counts — 'album' rows: the play count of every track inside, and the album total; 'playlist_tracks', 'recommendations', track search and track chart rows: each track's lifetime play count (editorial playlists have it anyway).
• Album track count — fills the album's track count inside 'track' rows' data.
A value Spotify could not provide this time is left out of the row; the run never fails because of it. Other categories ignore this setting.

## `maxResultsPerQuery` (type: `integer`):

Rows per input for list categories (playlist and album tracklists, discographies, search results, charts, new releases, podcast episodes, album, playlist and discography play counts). Long lists are paged automatically up to 1,000 rows. Spotify returns at most 50 for 'appears on' and 'discovered on'. Single-entity categories always return one row.

## `concurrency` (type: `integer`):

Inputs processed at once. Tracks and artists are fetched 50 per request, albums 20 and audio features 25, so such a group counts as one input here. The Actor slows down automatically while Spotify is throttling and speeds up again afterwards.

## `delayMs` (type: `integer`):

Pause after each input (or each group of inputs fetched in one request). Use 0 for max speed.

## `market` (type: `string`):

2-letter country code for regional results (e.g. US, GB, DE). Charts and new releases use it when the input names no country.

## `chartDate` (type: `string`):

For chart categories (leave empty for the latest chart) and the start date of 'concerts_by_location'.

## `geoHash` (type: `string`):

Optional location filter for 'artist_concerts' and 'search_concert_artists'. Spotify geohash (e.g. '6cb19y38v7py' for London). Leave empty for global tour data.

## `enrichConcertDetails` (type: `boolean`):

Enriches every concert with venue name, address (city / region / country / coordinates), lineup, ticket providers and related concerts, at 1 extra request per concert (capped by 'concertDetailsLimit'). Left unset, it is on for 'artist_concerts' and 'search_concert_artists' (which otherwise only return the city) and off elsewhere.

## `concertDetailsLimit` (type: `integer`):

Cap on how many concerts get enriched when 'enrichConcertDetails' is on. Avoids rate limits.

## `parsedConcerts` (type: `boolean`):

Return concert data in a normalized flat shape (artists, offers, location, related concerts) instead of raw GraphQL response. Affects 'partner_concert', 'artist_concerts', 'search_concert_artists', and enriched details.

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

Keep the full upstream object under 'data' (instead of a copy without music videos, merch and other presentation blocks) and attach the whole response under 'raw' for single-entity categories. Off by default for slimmer output.

## `enrichWithContrast` (type: `string`):

Attach the matching entity on another streaming platform to track, album, artist, artist overview and album metadata rows (under 'contrast'). Optional.

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

Ignored: the data category decides the mode. Kept so older saved inputs keep working.

## Actor input object example

```json
{
  "category": "auto",
  "queries": [
    "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b",
    "https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj",
    "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02",
    "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
  ],
  "defaultType": "track",
  "include": [],
  "maxResultsPerQuery": 50,
  "concurrency": 5,
  "delayMs": 0,
  "market": "US",
  "concertDetailsLimit": 20,
  "parsedConcerts": false,
  "includeRaw": false,
  "enrichWithContrast": ""
}
```

# Actor output Schema

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

Every row of this run: one row per entity with flat columns (id, name, type, url, imageUrl, artists, playCount, followers, …) and the upstream payload under `data`.

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

The same rows as CSV for spreadsheets, without the nested `data`, `raw`, `metadata` and `contrast` payloads.

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

Queries, rows delivered, failed queries and the run outcome. Failed queries are never charged.

## `errors` (type: `string`):

Each failed query with its reason and whether a retry could help (`kind`: permanent or transient). Written only when a query failed; never charged.

## `liveView` (type: `string`):

Browse the dataset in the Apify Console with the Overview, Tracks & play counts, Artists, Albums, Playlists, Charts, Concerts, Podcasts and Audio features views.

# 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 = {
    "queries": [
        "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b",
        "https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj",
        "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02",
        "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("eduair94/spotify-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 = { "queries": [
        "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b",
        "https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj",
        "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02",
        "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M",
    ] }

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

```

## MCP server setup

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