# Spotify Track Play Counts | Albums, Playlists & Artist Stats (`feedminer/spotify-track-playcounts`) Actor

Paste Spotify track, album, artist or playlist links, or search by keyword, and get each track's total play count with its ISRC, popularity, BPM, key, label, UPC and cover, plus artist rows with monthly listeners, followers, world rank, top cities, biography and social links. No login, no API key.

- **URL**: https://apify.com/feedminer/spotify-track-playcounts.md
- **Developed by:** [FeedMiner](https://apify.com/feedminer) (community)
- **Categories:** Social media
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.54 / 1,000 delivered 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?

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

<div style="border-left:3px solid #1C1917;background:#FAFAF9;padding:15px 20px;border-radius:3px">
<strong>Spotify links in (tracks, albums, artists and playlists, mixed) or search terms, and one row per track out with its total play count, its ISRC, popularity, tempo, key and label, plus one row per artist with monthly listeners, followers, world rank, top cities and profile.</strong> A search can also deliver albums, with their tracks' plays added up, or playlists, with their followers. Delivered as JSON, CSV or Excel, or read straight from the API. No Spotify account is involved, yours or ours, and nothing has to be connected.
</div>

🔓 **Nothing to connect.** No Spotify login, no developer app, no API key, no cookies to paste. Every read is the public catalog Spotify's web player shows a logged-out visitor, so nothing of yours can expire.

⚡ **9 947 rows in 60 seconds.** A 10 000-entry playlist read whole on Apify, each row with its play count, ISRC, tempo and key: run `FExbx73xEoGIHeJz6`, 23 October 2026. Speed varies from run to run; the Performance section has the spread.

💸 **$0.90 per 1 000 rows, $0.54 from Gold up.** Under each of the five most-used Spotify data Actors on the Store, at every plan tier, as read on 23 October 2026. A track row, an artist row, an album row and a playlist row cost the same, and a dead link or a podcast costs nothing.

🎚️ **Play count, ISRC, tempo and key on every track row.** Whether the track came from an album, a playlist, an artist's discography, a pasted link or a keyword search, its row carries the total plays, the ISRC, the BPM, the key and its Camelot code, the label and the UPC, in one run with no account.

![How Spotify Track Play Counts works: paste Spotify links or search terms, get one row per track with its play count, ISRC, tempo and key](https://api.apify.com/v2/key-value-stores/RPT1LNaNbQoVImUE9/records/spotify-track-playcounts-how-it-works-v2.png)

#### Copy to your AI assistant

```
feedminer/spotify-track-playcounts on Apify. Returns Spotify play counts and track metadata from pasted links or keyword searches, anonymously: no Spotify account, no developer app, no API key, no cookies. Inputs: urls, a list of Spotify links, mixed: tracks, albums, artists and playlists, as open.spotify.com links with or without an intl-xx/ path or a ?si= tail, or as spotify: URIs; and/or searchTerms, a list of keywords searched on Spotify. Duplicates fold. Podcasts, episodes, audiobooks, spotify.link short links and text that names no Spotify entity are set aside before any read and cost nothing. Four kinds of dataset row, told apart by "type". Track row: type, uri, url, name, artists[], playcount (total plays, all countries together, at collected_at; 0 marks an unplayable track; null when Spotify gave none), popularity (0-100; null on an old copy of a track Spotify now serves under another id), isrc, album_uri, album_name, album_type (ALBUM, SINGLE, EP, COMPILATION), album_total_tracks, release_date (2020-03-20, 2020-03 or 2020, at Spotify's own precision), label, upc, copyrights[{type C or P, text}], cover_url, duration_ms, explicit, disc_number, track_number, playable (in the country the run read from, not everywhere), preview_url (30-second MP3, only for the tracks Spotify still previews, about 4 in 10), bpm, key ("C minor"), camelot_key ("5A"), added_at, playlist_name, playlist_owner, playlist_followers, playlist_description (these five on rows read from a playlist link only; empty or null elsewhere), source (the pasted link or the search that reached the row, as a spotify: URI; a search is spotify:search:<term>), collected_at. Artist row: type, uri, url, name, verified, followers, monthly_listeners, world_rank, top_cities[{city, country, listeners}], albums_count, singles_count, compilations_count, biography (plain text; empty when the artist wrote none), external_links{instagram, twitter, facebook, wikipedia, …: url}, related_artists[{name, uri}] (up to 20), image_url, header_image_url, gallery_urls[], source, collected_at. Album row (album searches only): type, uri, url, name, artists[], playcount (the sum of its tracks' play counts), album_type, total_tracks, release_date, label, upc, copyrights[], cover_url, source, collected_at. Playlist row (playlist searches only): type, uri, url, name, description, owner, owner_uri, followers, total_tracks, image_url, source, collected_at. Each track, artist, album and playlist is delivered and billed once per run, whichever links or searches reach it, the first to reach it naming its source; the one exception is a playlist's track rows, which carry that playlist's context, so a pasted playlist gets its own row for each track it holds, beside the one row any other input reaching that track delivers. A link or term that yields nothing is counted in the run's closing line and costs nothing. Call ApifyClient("TOKEN").actor("feedminer/spotify-track-playcounts").call(run_input={"urls": ["https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj"], "searchTerms": ["lofi"], "searchType": "tracks", "maxResultsPerTerm": 50}), then client.dataset(run["defaultDatasetId"]).list_items().items. Inputs (at least one link or one search term): urls (string[]), searchTerms (string[]), searchType ("tracks", "artists", "albums" or "playlists", default "tracks": the kind of row a search term delivers), maxResultsPerTerm (integer 1-1000, default 50: the most rows one search term delivers; Spotify's search goes no deeper than 1 000 results), artistTracks ("none" = the artist row only, "top" = plus the profile's top tracks, "discography" = plus every track the artist is credited on, across albums, singles and compilations, newest release first, a compilation's tracks by other artists left out and not charged, and a discography whose releases seldom credit the artist stopping once it has read ten tracks per row allowed; default "top"; artist links only, searched artists deliver their own row), maxRowsPerUrl (integer 1-10000, default 1000: the most track rows one album, playlist or artist link delivers, the artist's own row on top), debugMode (bool, default false). Billed per delivered row, whatever its type: $0.90 per 1 000 on Apify's Free plan, $0.81 on Bronze, $0.67 on Silver, $0.54 from Gold up, plus Apify's start fee once per run. Full spec: GET https://api.apify.com/v2/acts/feedminer~spotify-track-playcounts/builds/default (Bearer TOKEN) → inputSchema, actorDefinition.storages.dataset, readme. Token: https://console.apify.com/account/integrations
```

***

### How to scrape play counts from Spotify

Paste the links you want the play counts of, or type what you would search for. That is the whole input.

##### One track

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

One row. A pasted track is read through its album, which is why its row carries the album's name, label and release date as well as the play count, and then looked up for its ISRC, popularity, tempo, key and preview.

##### However the links were copied

```json
{
  "urls": [
    "https://open.spotify.com/intl-fr/album/4yP0hdKOZPNshxUOjY0cZj?si=3f2a",
    "spotify:artist:1Xyo4u8uXC1ZmMpatF05PJ",
    "open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
  ]
}
```

The share button's `?si=` tail, a localised `intl-xx/` path and the app's `spotify:` URIs are all read the same way. Duplicates fold, so a column pasted out of a spreadsheet runs unedited.

##### Search tracks by keyword

```json
{ "searchTerms": ["lofi", "synthwave"], "searchType": "tracks", "maxResultsPerTerm": 100 }
```

Up to 100 tracks per term, in Spotify's own order, each with its play count, ISRC, tempo and key. Every row's `source` names the term that found it, as `spotify:search:lofi`, so several terms come back sortable. Spotify's search always answers something, even to a misspelt term, so read the first rows of a new term before trusting a long list.

##### Find the artists of a scene

```json
{ "searchTerms": ["rap francais"], "searchType": "artists", "maxResultsPerTerm": 50 }
```

One row per artist found, with monthly listeners, followers, world rank, top cities, biography, external links and the artists the profile lists under "Fans also like". A searched artist delivers its own row only; paste its link to get its tracks.

##### Find playlists to pitch to

```json
{ "searchTerms": ["workout", "deep focus"], "searchType": "playlists", "maxResultsPerTerm": 200 }
```

One row per playlist found, with its followers, owner, track count and description. Sort on `followers`, then paste the links of the ones you want into a second run to read their tracks.

##### Albums, with their total plays

```json
{ "searchTerms": ["after hours"], "searchType": "albums", "maxResultsPerTerm": 20 }
```

One row per album found: its type, label, UPC, copyright lines, track count and the plays of all its tracks added up.

##### A playlist, with its curator's context

```json
{ "urls": ["https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"], "maxRowsPerUrl": 10000 }
```

A playlist's rows carry the date each track was added, and the playlist's own name, owner, followers and description. Raise `maxRowsPerUrl` for a long playlist: the default of 1 000 is sized for a first look.

##### An artist roster's audience, and nothing else

```json
{
  "urls": [
    "https://open.spotify.com/artist/1Xyo4u8uXC1ZmMpatF05PJ",
    "https://open.spotify.com/artist/4q3ewBCX7sLwd24euuV69X"
  ],
  "artistTracks": "none"
}
```

One row per artist: monthly listeners, followers, world rank, the top cities the profile lists, the size of the discography, the biography and the links. This is the cheapest way to compare a roster.

##### Every track an artist is credited on

```json
{ "urls": ["spotify:artist:1Xyo4u8uXC1ZmMpatF05PJ"], "artistTracks": "discography", "maxRowsPerUrl": 500 }
```

The artist's row, then every track the artist is credited on, across albums, singles and compilations, newest release first, until the discography ends or `maxRowsPerUrl` rows are delivered. A compilation contributes this artist's tracks only: the others on it are set aside, counted in the closing line, and not charged. Measured on Apify on 23 October 2026: The Weeknd's row and 420 tracks, 8 set aside, in 6.7 s (run `AL0Qv4P4eKiWy2rmu`); Johann Sebastian Bach's row and his 10 000 newest credited tracks, with 37 545 tracks by other composers set aside, in 139.6 s (run `apxG4UGhntP62P3no`). A label's or a compilation series' profile is credited on few of the tracks its releases hold: such a discography stops once it has read ten tracks for each row `maxRowsPerUrl` allows, delivers the credited tracks it found, and the closing line says it stopped early. Spotify groups some releases with their other editions; such a group is read once, through the edition the player shows, so the tracks the other editions repeat are not delivered twice.

##### A real mix

```json
{
  "urls": [
    "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b",
    "https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj",
    "https://open.spotify.com/artist/1Xyo4u8uXC1ZmMpatF05PJ",
    "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
  ],
  "searchTerms": ["lofi"],
  "artistTracks": "top",
  "maxRowsPerUrl": 1000
}
```

A track, an album, an artist with its top tracks, an editorial playlist and a keyword search, in one run. The form's prefill is these four links without the search term. On Apify on 23 October 2026 it delivered 73 rows in 3.6 s (run `l7ryxvnOIOgVEjryu`): the pasted track and two of the artist's top tracks are on the pasted album, so each came once.

### Input parameters

##### What to read

| Parameter | Type | Default | Description |
|---|---|---|---|
| `urls` | string\[] | none | Tracks, albums, artists or playlists, mixed: `open.spotify.com` links with or without their `intl-xx/` part or `?si=` tail, or `spotify:` URIs. Duplicates fold. Podcasts, episodes and audiobooks are set aside before any read. |
| `searchTerms` | string\[] | none | Words to search Spotify for, one per entry. Case does not matter, and a term typed twice is searched once. |

At least one link or one search term is needed; both work in the same run.

##### What a search finds

| Parameter | Type | Default | Description |
|---|---|---|---|
| `searchType` | string | `tracks` | `tracks`, `artists`, `albums` or `playlists`: the kind of row each search term delivers. |
| `maxResultsPerTerm` | integer | `50` | The most rows one search term may deliver, from 1 to 1 000. Spotify's search goes no deeper than 1 000 results and repeats some tracks among them, so a track search can end short of a high cap. |

##### What an artist link brings

| Parameter | Type | Default | Description |
|---|---|---|---|
| `artistTracks` | string | `top` | `none`: the artist's row alone. `top`: the artist's row and the profile's top tracks. `discography`: the artist's row and every track the artist is credited on, across albums, singles and compilations, newest release first; a compilation's tracks by other artists are left out and not charged; when `maxRowsPerUrl` cuts, the newest releases are kept. Artists found by a search deliver their own row only. |

##### How deep a list goes

| Parameter | Type | Default | Description |
|---|---|---|---|
| `maxRowsPerUrl` | integer | `1000` | The most track rows one album, playlist or artist link may deliver, from 1 to 10 000. The artist's own row comes on top. A list longer than this stops there, and the run's closing line says how many links reached the cap. A discography whose releases seldom credit the artist also stops once it has read ten tracks for each row allowed. |

##### Advanced

| Parameter | Type | Default | Description |
|---|---|---|---|
| `debugMode` | boolean | `false` | Verbose log lines for support. Leave off. |

`maxRowsPerUrl` bounds each album, playlist and artist link on its own and `maxResultsPerTerm` each search term, so together they bound the run's cost before it starts. A pasted track link is always one row, and `artistTracks` only changes what an artist link brings.

### What data can you extract from Spotify?

#### The track row

**What it is**: `type` (`"track"`), `uri`, `url`, `name`, and `artists`, the credited artists in Spotify's order.

**Its plays**: `playcount`, the total plays across every country; `popularity`, Spotify's 0-100 score; and `collected_at`, the moment this run read them.

**Its identifiers**: `isrc`, the recording's code, and `upc`, the release's barcode.

**Its release**: `album_uri`, `album_name`, `album_type` (`ALBUM`, `SINGLE`, `EP` or `COMPILATION`), `album_total_tracks`, `release_date` at the precision Spotify states it (`2020-03-20`, `2020-03` or `2020`, never a first of January nobody published), `label`, `copyrights` (each line with its type, `C` for the composition and `P` for the recording) and `cover_url`.

**The track itself**: `duration_ms`, `explicit`, `disc_number`, `track_number`, `playable`, which says whether it plays in the country the run read from, and `preview_url`, the 30-second MP3 Spotify plays as a preview.

**Its sound**: `bpm`, the tempo to three decimals, `key`, as `G minor` or `A# major`, and `camelot_key`, the same key on the Camelot wheel DJs mix by, as `6A`.

**From a playlist**: `added_at`, when the entry joined the playlist, and the playlist's own `playlist_name`, `playlist_owner`, `playlist_followers` and `playlist_description`.

**Where it came from**: `source`, the pasted link or the search that reached this row, as a `spotify:` URI (`spotify:search:lofi` for a search).

#### The artist row

`type` (`"artist"`), `uri`, `url`, `name`, `verified`, `followers`, `monthly_listeners`, `world_rank`, and `top_cities`: one entry per city the profile lists, most listeners first, each with `city`, `country` (ISO code) and `listeners`. Then the profile around it: `albums_count`, `singles_count` and `compilations_count`, the size of the discography; `biography`, as plain text; `external_links`, keyed by site (`instagram`, `twitter`, `facebook`, `wikipedia`, `tiktok`…); `related_artists`, the artists the profile lists under "Fans also like", each with `name` and `uri`; `image_url`, `header_image_url` and `gallery_urls`, the profile's pictures. Then `source` and `collected_at`, as on a track.

#### The album row and the playlist row

Only a search delivers them. An album row carries `name`, `artists`, `playcount` (the plays of all its tracks added up), `album_type`, `total_tracks`, `release_date`, `label`, `upc`, `copyrights` and `cover_url`. A playlist row carries `name`, `description`, `owner`, `owner_uri`, `followers` (its saves), `total_tracks` and `image_url`. Both also carry `type`, `uri`, `url`, `source` and `collected_at`.

![What the rows of Spotify Track Play Counts carry: the play count beside the ISRC, tempo, key and Camelot key on every track, and the artist's monthly listeners, world rank and top cities](https://api.apify.com/v2/key-value-stores/RPT1LNaNbQoVImUE9/records/spotify-track-playcounts-row-anatomy-v2.png)

##### Example rows

A track, as the playlist link of the form's prefill delivered it:

```json
{
  "type": "track",
  "uri": "spotify:track:70cHKK8bHAfJrOGVnfRG9J",
  "url": "https://open.spotify.com/track/70cHKK8bHAfJrOGVnfRG9J",
  "name": "Nicole Kidman",
  "artists": ["ADÉLA"],
  "playcount": 180838962,
  "popularity": 97,
  "isrc": "USUM72606032",
  "album_uri": "spotify:album:2yDFVH9CeOHt0sc9eI0aBs",
  "album_name": "PRIMA",
  "album_type": "ALBUM",
  "album_total_tracks": 11,
  "release_date": "2026-09-04",
  "label": "Capitol Records",
  "upc": "00881061314172",
  "copyrights": [
    { "type": "C", "text": "© 2026 UMG Recordings, Inc." },
    { "type": "P", "text": "℗ 2026 UMG Recordings, Inc." }
  ],
  "cover_url": "https://i.scdn.co/image/ab67616d0000b273ac9d5d5263e9f03802d6864c",
  "duration_ms": 181270,
  "explicit": true,
  "disc_number": 1,
  "track_number": 2,
  "playable": true,
  "preview_url": "https://p.scdn.co/mp3-preview/68bc3cb0611cfe6569ce56eeb025359233168a69",
  "bpm": 140.907,
  "key": "G minor",
  "camelot_key": "6A",
  "added_at": "2026-09-11T04:01:53.033Z",
  "playlist_name": "Today’s Top Hits",
  "playlist_owner": "Spotify",
  "playlist_followers": 33686627,
  "playlist_description": "The hottest 50. Cover: Tate McRae",
  "source": "spotify:playlist:37i9dQZF1DXcBWIGoYBM5M",
  "collected_at": "2026-10-23T12:50:40Z"
}
```

An artist, from the same run, its biography and lists cut short here:

```json
{
  "type": "artist",
  "uri": "spotify:artist:1Xyo4u8uXC1ZmMpatF05PJ",
  "url": "https://open.spotify.com/artist/1Xyo4u8uXC1ZmMpatF05PJ",
  "name": "The Weeknd",
  "verified": true,
  "followers": 129248619,
  "monthly_listeners": 116644295,
  "world_rank": 3,
  "top_cities": [
    { "city": "Mexico City", "country": "MX", "listeners": 1638291 },
    { "city": "London", "country": "GB", "listeners": 1544001 }
  ],
  "albums_count": 14,
  "singles_count": 65,
  "compilations_count": 3,
  "biography": "The Weeknd took over pop music & culture on his own terms filtering R&B, Pop,& hip-hop through an ambitious widescreen lens. …",
  "external_links": {
    "facebook": "https://facebook.com/theweeknd/",
    "instagram": "https://instagram.com/theweeknd/?hl=en",
    "twitter": "https://twitter.com/theweeknd?ref_src=twsrc%5Egoogle%7Ctwcamp%5Eserp%7Ctwgr%5Eauthor",
    "wikipedia": "https://en.wikipedia.org/wiki/The_Weeknd"
  },
  "related_artists": [
    { "name": "Rihanna", "uri": "spotify:artist:5pKCCKE2ajJHZ9KAiaK11H" },
    { "name": "Swae Lee", "uri": "spotify:artist:1zNqQNIdeOUZHb8zbZRFMX" }
  ],
  "image_url": "https://i.scdn.co/image/ab6761610000e5ebc1719ac9e6a75c1c25835018",
  "header_image_url": "https://image-cdn-fa.spotifycdn.com/image/ab6761860000eab1ca40d0e310d671f99295b14c",
  "gallery_urls": ["https://i.scdn.co/image/ab6761670000ecd445c7565ba8453d2710c9c1b8"],
  "source": "spotify:artist:1Xyo4u8uXC1ZmMpatF05PJ",
  "collected_at": "2026-10-23T12:50:33Z"
}
```

An album, as an album search for `after hours` found it:

```json
{
  "type": "album",
  "uri": "spotify:album:4yP0hdKOZPNshxUOjY0cZj",
  "url": "https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj",
  "name": "After Hours",
  "artists": ["The Weeknd"],
  "playcount": 14286101321,
  "album_type": "ALBUM",
  "total_tracks": 14,
  "release_date": "2020-03-20",
  "label": "Republic Records",
  "upc": "00602508924224",
  "copyrights": [
    { "type": "C", "text": "© 2020 The Weeknd XO, Inc., marketed by Republic Records, a division of UMG Recordings, Inc." },
    { "type": "P", "text": "℗ 2020 The Weeknd XO, Inc., marketed by Republic Records, a division of UMG Recordings, Inc." }
  ],
  "cover_url": "https://i.scdn.co/image/ab67616d0000b2738863bc11d2aa12b54f5aeb36",
  "source": "spotify:search:after hours",
  "collected_at": "2026-10-23T12:52:03Z"
}
```

A playlist, as a playlist search for `workout` found it:

```json
{
  "type": "playlist",
  "uri": "spotify:playlist:37i9dQZF1DXe6bgV3TmZOL",
  "url": "https://open.spotify.com/playlist/37i9dQZF1DXe6bgV3TmZOL",
  "name": "Heavy Workout",
  "description": "If your workout doubles as an outlet for your aggression, this is the playlist for you.",
  "owner": "Spotify",
  "owner_uri": "spotify:user:spotify",
  "followers": 2492398,
  "total_tracks": 100,
  "image_url": "https://i.scdn.co/image/ab67706f00000002e753fcf752207f80004def69",
  "source": "spotify:search:workout",
  "collected_at": "2026-10-23T12:52:25Z"
}
```

#### Why some columns are empty on some rows

Each route to a track carries different columns, and this Actor does not invent the missing ones. Every track row, whatever reached it, is looked up for its ISRC, popularity, tempo, key, preview, UPC, album type, cover and copyright lines. Only a playlist link fills `added_at` and the four `playlist_` columns; on the other rows they are empty or null.

Four columns can be empty for a reason that is Spotify's. `preview_url` is filled only for the tracks Spotify still previews: 367 of the first 1 000 rows of a 10 000-entry playlist on Apify on 23 October 2026 (run `FExbx73xEoGIHeJz6`). `popularity` is null on an old copy of a track that Spotify now serves under another id, which is common in old playlists: Spotify keeps the score on the newer copy, and a 0 there would read as unpopular. `biography`, `external_links`, `header_image_url` and `gallery_urls` are filled where the artist set them up on Spotify. And if Spotify's metadata service does not answer for a row, its looked-up columns stay empty and the run's closing line counts it. A column a route does not carry is null or empty, never a zero that would read as a measurement.

#### Why a play count comes with the time it was read

`playcount` is a running total: it is the number of plays at `collected_at`, and it will be higher tomorrow. Two runs of the same links, a week apart, subtracted track by track on `uri`, give the plays in between. A `playcount` of `0` marks a track Spotify serves as unplayable, not one nobody has heard.

#### What a link or a search that gives nothing tells you

A row is a track, an artist, an album or a playlist, so an input that yields none produces no row and costs nothing. The run's closing line, on the Console, says what happened to it:

| The closing line says | What it means |
|---|---|
| not found on Spotify | nothing lives at that id: a dead, removed or mistyped link. Purge it from your list |
| held no track | the album or playlist exists and is empty |
| found nothing on Spotify | the search term returned no result |
| could not be read from Spotify | Spotify would not serve it after every retry. Run it again |
| stopped short by Spotify | the link or term delivered, then a later page was refused: you have what was read before it |
| reached the per-link row cap | the list is longer than `maxRowsPerUrl`. Raise it for more |
| reached the per-term cap | the search has more results than `maxResultsPerTerm`. Raise it for more |
| came without some of their metadata | Spotify's metadata service had nothing for those rows or did not answer: their play counts are there, some looked-up columns are empty |
| not a Spotify link | the entry names no Spotify track, album, artist or playlist |
| a podcast, episode or audiobook | set aside before any read |
| playlist entries that are not tracks | episodes and local files inside a playlist, skipped and not charged |
| tracks that do not credit its artist | tracks by other artists on an artist's compilations, set aside from a discography and not charged |
| already delivered earlier in this run | a track, artist, album or playlist the run had already delivered, for another of your inputs or earlier in the same one: delivered and charged once |
| stopped early: few of the tracks on their releases credit them | an artist link at `discography` whose releases seldom credit the artist, such as a label's profile: it stopped after reading ten tracks for each row `maxRowsPerUrl` allows. You have the credited tracks it found; raise `maxRowsPerUrl` to read deeper |
| Run stopped early | the run was stopped before its end; the line gives how many rows it had delivered |

### What this Actor covers

![What Spotify Track Play Counts reaches, and what it does not](https://api.apify.com/v2/key-value-stores/RPT1LNaNbQoVImUE9/records/spotify-track-playcounts-coverage-v2.png)

It reads Spotify's public catalog from the links you paste and the terms you search: a track's play count with its ISRC, tempo and key, every track of an album or a playlist, an artist's audience and profile, an artist's top tracks or discography, and albums and playlists found by keyword.

No FeedMiner Actor covers the four things on the right today: podcasts, a stream history, genres, and audio features beyond tempo and key. Spotify serves neither an artist's genres nor danceability, energy or valence on any surface this Actor reads without an account, so it does not deliver them. Say so in the Issues tab if you need one of them. For what people say about a release on X, [X Tweet Scraper](https://apify.com/feedminer/x-tweet-scraper) searches posts by keyword, and [X Profile Scraper](https://apify.com/feedminer/x-profile-scraper) reads an artist's X profile with its recent posts.

### Pricing

| Event | What it is |
|---|---|
| `row` | one delivered row, a track, an artist, an album or a playlist alike |
| Actor start | Apify's own fee, charged once when a run starts |

| Apify plan | Per 1 000 `row` events |
|---|---|
| Free | **$0.90** |
| Bronze | **$0.81** |
| Silver | **$0.67** |
| Gold, Platinum, Diamond | **$0.54** |

One event is one row that reached your dataset, so the price per 1 000 events is the price per 1 000 rows. Apart from the start fee, nothing else is billed: not a dead link, a podcast, an episode or an audiobook, a short link, text that names no Spotify entity, a playlist entry that is not a track, or a search result Spotify would not let the run read.

**Each row is billed once per run.** A track, an artist, an album or a playlist reached by several of your links or search terms is delivered and billed once, by the first input that reaches it, whose link or term its `source` names; the closing line counts the rows folded this way. The one exception is a playlist's own track rows: they carry that playlist's name, owner and the date each track joined it, so each pasted playlist gets its own row for a track it holds, beside the one row any other input reaching that track delivers. Every cap counts the rows delivered, so a folded track does not use up a link's or a term's share.

##### Against the market

The five most-used Spotify data Actors on the Store, read through the Store's API on 23 October 2026, with their price per 1 000 rows on Apify's Free plan and from Gold up:

| Actor | Users, last 30 days | Free plan | Gold and up |
|---|---|---|---|
| `beatanalytics/spotify-play-count-scraper` | 185 | $4.00 | $4.00 |
| `automation-lab/spotify-scraper` | 110 | $5.00, plus $0.005 a run | $2.61, plus $0.005 a run |
| `sourabhbgp/spotify-scraper` | 81 | $3.00 | $2.00 |
| `eduair94/spotify-scraper` | 48 | $1.00 | $0.60 |
| `augeas/spotify-monthly-listeners` | 39 | $4.00 | $3.20 |
| **This Actor** | | **$0.90** | **$0.54** |

This Actor is under every one of them at every tier: $0.90 against $1.00 at the cheapest of them on the Free plan, $0.81 against $0.90 on Bronze, $0.67 against $0.75 on Silver and $0.54 against $0.60 from Gold up. Store prices and user counts move, which is why this comparison carries its date.

Compare them on two more things than the price. **What the run needs to exist**: nothing here involves an account, a login or a developer app, on your side or ours. And **what you are billed for**: a row that reached your dataset, never a link you sent in, a dead id, or a podcast.

##### What a real run bills

Each line is an input run on Apify on 23 October 2026, its run id beside it, with the rows it delivered, billed at the prices above, plus the start fee once per run:

| Input | Rows | Free | Bronze | Silver | Gold and up |
|---|---|---|---|---|---|
| The form's prefill: a track, its album, an artist with its top tracks, a playlist (`l7ryxvnOIOgVEjryu`) | 73 | $0.07 | $0.06 | $0.05 | $0.04 |
| Two terms searched for 50 tracks each (`5mNiWWNpxBsdavqME`) | 100 | $0.09 | $0.08 | $0.07 | $0.05 |
| Nine messy entries (six distinct links with a dead track among them, a duplicate, a podcast, a line that is not a link) and three search terms, two of them the same, 20 results each (`Oe2R290BrZbryDYl9`) | 114 | $0.10 | $0.09 | $0.08 | $0.06 |
| The Weeknd's credited tracks, at `discography` (`AL0Qv4P4eKiWy2rmu`) | 421 | $0.38 | $0.34 | $0.28 | $0.23 |
| `lofi` searched to Spotify's depth, 1 000 results asked (`I0z0MQJQaZLMPzoSQ`) | 881 | $0.79 | $0.71 | $0.59 | $0.48 |
| A 10 000-entry playlist (`FExbx73xEoGIHeJz6`) | 9 947 | $8.95 | $8.06 | $6.66 | $5.37 |
| Johann Sebastian Bach's credited tracks at `maxRowsPerUrl` 10 000 (`apxG4UGhntP62P3no`) | 10 001 | $9.00 | $8.10 | $6.70 | $5.40 |
| Eight composers' credited tracks at `maxRowsPerUrl` 10 000 each (`Y62Tk1a7i95RJCJZb`) | 80 008 | $72.01 | $64.81 | $53.61 | $43.20 |

The bill is the row count times the price: in the messy line the dead track, the podcast, the duplicate and the entry that was not a link delivered nothing and cost nothing, and the 4 rows the run had already delivered were not charged again; the 53 entries of the playlist that are not tracks were skipped and not charged, and so were the 37 545 and 333 744 tracks by other composers the discographies set aside.

##### Free tier

Apify's free plan comes with monthly credits. A first look like the form's prefill, 73 rows, costs $0.07 at the free-plan price plus the start fee, so you can see the output before you commit to anything.

### Advanced usage

##### Measure a release's plays week over week

```json
{ "urls": ["https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj"] }
```

Schedule the same input weekly on Apify and subtract each track's `playcount` from the previous run's, joined on `uri`. Nothing is kept between runs on our side, so your previous dataset is the whole state, and `collected_at` says exactly when each total was read.

##### Compare an artist roster

```json
{
  "urls": [
    "https://open.spotify.com/artist/1Xyo4u8uXC1ZmMpatF05PJ",
    "https://open.spotify.com/artist/4q3ewBCX7sLwd24euuV69X"
  ],
  "artistTracks": "none"
}
```

One row per artist, sortable on `monthly_listeners`, `followers` or `world_rank`. `top_cities` names where each artist's listeners are, with their counts, which is the column a tour or a local campaign is planned on; `external_links` gives the Instagram, X and Facebook pages to reach them on.

##### Build a pitch list from a genre

```json
{ "searchTerms": ["indie folk", "acoustic chill"], "searchType": "playlists", "maxResultsPerTerm": 300 }
```

Every playlist Spotify finds for each term, with its followers, owner and description. Keep the ones above the follower count you aim for, then run their links with `maxRowsPerUrl` to see their tempo, keys and what their curators add lately (`added_at`).

##### Prepare a DJ set or a sync brief

```json
{ "urls": ["https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"], "maxRowsPerUrl": 10000 }
```

`bpm`, `key` and `camelot_key` on every row give the tempo range and the harmonic neighbours; `isrc`, `label` and `copyrights` say who to clear a track with; the play count says how known it is.

##### Audit a catalogue

```json
{ "urls": ["spotify:artist:1Xyo4u8uXC1ZmMpatF05PJ"], "artistTracks": "discography", "maxRowsPerUrl": 10000 }
```

Every track the artist is credited on, release by release, each with its play count, ISRC, UPC, label and release date. Group by `album_uri` to rank releases, sort on `release_date` for a timeline, or group by `label` to split a catalogue between labels.

### Integrate Spotify data into your stack

Results flow through the Apify API into Python, JavaScript, Google Sheets, Make, Zapier, n8n, Airtable or Slack. Runs can be scheduled, monitored and chained with other Actors, and the dataset reads as JSON, CSV, Excel or XML.

##### Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

run = client.actor("feedminer/spotify-track-playcounts").call(run_input={
    "urls": [
        "https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj",
        "https://open.spotify.com/artist/1Xyo4u8uXC1ZmMpatF05PJ",
    ],
    "searchTerms": ["lofi"],
    "artistTracks": "top",
})

for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row["type"] == "track":
        print(row["playcount"], row["isrc"], row["bpm"], row["key"], row["name"])
    elif row["type"] == "artist":
        print(row["monthly_listeners"], row["name"], "monthly listeners")
```

##### JavaScript

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

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

const run = await client.actor('feedminer/spotify-track-playcounts').call({
    urls: [
        'https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj',
        'https://open.spotify.com/artist/1Xyo4u8uXC1ZmMpatF05PJ',
    ],
    searchTerms: ['lofi'],
    artistTracks: 'top',
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
for (const row of items) {
    if (row.type === 'track') {
        console.log(row.playcount, row.isrc, row.bpm, row.key, row.name);
    } else if (row.type === 'artist') {
        console.log(row.monthly_listeners, row.name, 'monthly listeners');
    }
}
```

### Performance

Measured on Apify on 23 October 2026, at the default 256 MB, the run id beside each. The searches ran on build 0.1.3 and the rest on 0.1.4; neither path has changed since, except that a discography whose releases seldom credit the artist now stops early, which none of these runs met.

| Measure | Value | Measured on |
|---|---|---|
| A first look | 73 rows in 3.6 s | Apify run `l7ryxvnOIOgVEjryu`: the form's prefill, four links |
| A messy input | 114 rows in 4.1 s | Apify run `Oe2R290BrZbryDYl9`: nine entries and three search terms, 20 results each |
| Two overlapping search terms | 40 rows in 4.4 s | Apify run `LkKcPyaPPqNF1EBlL`: `daft punk` and `daft punk get lucky`, 20 tracks each; 12 results already delivered were folded, and both terms still delivered 20 |
| A keyword search for tracks | 100 rows in 5.6 s | Apify run `5mNiWWNpxBsdavqME`: `lofi` and `Taylor Swift`, 50 tracks each |
| A keyword search for artists | 25 rows in 5.4 s | Apify run `W3jVUa5pnKVRF5Ds5`: `rap francais`, each artist's profile read |
| A keyword search for albums | 40 rows in 4.5 s | Apify run `KBfhB2KdbmzSnfovh`: `after hours` and `jazz classics`, 20 albums each, every track read for the plays |
| A keyword search for playlists | 30 rows in 3.5 s | Apify run `CrBmDtQOR0iQ0xnyo`: `workout`, 30 playlists |
| A track search to Spotify's depth | 881 rows in 39.9 s | Apify run `I0z0MQJQaZLMPzoSQ`: `lofi`, 1 000 asked; Spotify's search ends at 881 distinct tracks for it |
| An artist search to Spotify's depth | 981 rows in 51.5 s | Apify run `KCxmuSTsKuP7f8eeZ`: `rap francais`, 1 000 asked, every profile read |
| One artist's credited tracks | 421 rows in 6.7 s | Apify run `AL0Qv4P4eKiWy2rmu`: The Weeknd at `discography`, 8 tracks set aside |
| A deep playlist | 9 947 rows in 59.6 s | Apify run `FExbx73xEoGIHeJz6`: a 10 000-entry playlist at `maxRowsPerUrl` 10 000 |
| A 10 000-track discography | 10 001 rows in 139.6 s, every track crediting the artist | Apify run `apxG4UGhntP62P3no`: Johann Sebastian Bach at `maxRowsPerUrl` 10 000, 37 545 tracks by other composers set aside |
| Eight discographies in one run | 80 008 rows in 309.5 s, every track crediting its composer | Apify run `Y62Tk1a7i95RJCJZb`: eight composers at `maxRowsPerUrl` 10 000 each, 333 744 tracks by others set aside |
| A run stopped halfway | 7 008 rows kept and billed, stopped at about 48 s | Apify run `pW52zW5gMd3JBBzNF`: the same eight composers, aborted |
| Peak memory on Apify | 10.8 MB to 104.3 MB | every run above, at the default 256 MB; the eight discographies at once are the 104.3 MB |
| ISRC, tempo, key and UPC on track rows | 1 000 of the first 1 000 rows | Apify run `FExbx73xEoGIHeJz6`, the 10 000-entry playlist |
| Preview on track rows | 367 of the first 1 000 rows | Apify run `FExbx73xEoGIHeJz6`: Spotify keeps previews for fewer than half of these tracks |
| Popularity on track rows | 503 of the first 1 000 rows | Apify run `FExbx73xEoGIHeJz6`, whose many old copies carry none; 72 of 72 on the prefill, Apify run `l7ryxvnOIOgVEjryu` |
| Rows that came without their metadata | none | every run above that ran to its end |
| Spotify accounts used | none | every run: there is no account to use |

Speed varies with the exit Spotify's servers see, from one run to the next: on Apify the same 10 000-entry playlist took 47.2 s on one run of 23 October 2026 (run `04Y0Osfe01yoKxaTP`, build 0.1.3) and 59.6 s on another the same day (run `FExbx73xEoGIHeJz6`, build 0.1.4), for the same 9 947 rows. When Spotify's metadata service is slow to answer, a row ships without those columns rather than wait, and the closing line counts it. A deep playlist is read a thousand entries a page, and a page that streams slowly holds the run until it ends or is asked again elsewhere. Rows go to the dataset as the run collects them, a playlist page or a hundred tracks of a discography or a search at a time, in writes of 1 000 rows or once the oldest has waited 30 seconds, so a long run never holds its rows until the end, and a run stopped halfway keeps what it had shipped.

### FAQ

**Do I need a Spotify account, a developer app or an API key?**
No. There is nothing to connect and nothing to keep alive on your side. Every read is the public catalog Spotify's web player serves a logged-out visitor.

**Is the play count the one Spotify shows?**
Yes. It is the total Spotify's own web player prints for the track, all countries together, read at the moment in `collected_at`. It is not an estimate and not a third-party chart.

**Where do the ISRC, tempo and key come from?**
From the same service Spotify's web player reads them from, for every track the run delivers. The tempo and key are the ones the player shows beside a playlist's tracks; the ISRC and the UPC are Spotify's own records of them.

**Why is `popularity` empty on some tracks?**
Because the row is an old copy of a track that Spotify now serves under another id, which old playlists often hold. Spotify keeps the score on the newer copy and states 0 on the old one, so the row says nothing rather than a 0 that would read as unpopular. The play count is there all the same.

**Can I get daily streams?**
Not from one run. The play count is a running total, so the plays over a period are the difference between two runs: schedule the same links and subtract on `uri`. Nothing is kept between runs on our side.

**How deep can it go?**
Up to 10 000 track rows per album, playlist or artist link, the most `maxRowsPerUrl` allows, and up to 1 000 results per search term, the depth Spotify's search itself stops at. A list longer than your cap stops there, and the closing line says how many links or terms reached it.

**How relevant is a search?**
As relevant as Spotify's own search bar, in the same order. Spotify's search always answers something, even to a misspelt term, so check the first rows of a new term.

**What if I stop a run halfway?**
You keep what it had written and pay for that only. When the platform signals the stop, the Actor writes the rows it still holds and ends with "Run stopped early", followed by the count delivered. A run killed without that signal loses the rows not yet written, and is never billed for them. On Apify on 23 October 2026, a run reading eight composers' discographies was stopped at about 48 seconds: it kept the 7 008 rows it had shipped and was billed for those 7 008 (run `pW52zW5gMd3JBBzNF`).

**Why did the same track come back twice?**
Because one of your pasted playlists holds it and another of your inputs reaches it too, or because two of your pasted playlists hold it. A playlist's rows carry that playlist's own name, owner and date added, so each pasted playlist gets its own row for a track it holds, beside the one row any other input reaching that track delivers. Apart from that, a track, an artist, an album or a playlist comes once per run, however many of your links and terms reach it, and the closing line says how many rows were folded that way.

**My `spotify.link` short link was set aside.**
Short links are not read: the run counts them as "not a Spotify link". Open the short link once and paste the `open.spotify.com` address it lands on.

**Why is `playable` false on a track I can play?**
Because `playable` answers for the country the run read from, which this Actor does not pin, and that need not be yours. The play count itself is global and does not depend on it.

**Is the data live?**
Yes. Every run reads Spotify at that moment. Nothing is cached and nothing is kept between runs, which is why `collected_at` is on every row.

**What does it not do?**
It does not read podcasts, episodes or audiobooks, does not carry genres or audio features beyond tempo and key (danceability, energy, valence and the like), does not keep a stream history, and does not download audio.

***

### Support

- Found something off in the output, or need a field that is missing? Open the **Issues** tab on this Actor's page with the input you ran and what you expected. Issues are read daily.
- Need a custom variant, such as a different bound, a filter or a column this one does not carry? Ask in the Issues tab; FeedMiner builds on request.

### Legal compliance

This Actor collects only public data, the same catalog any visitor can see on `open.spotify.com` without signing in. Artist names, biographies, links, track credits and audience figures can relate to identifiable people, so processing information about people in the EU, the UK or California requires a lawful basis under GDPR or CCPA. Use the data for market research, analytics and business intelligence, not for spam or harassment. FeedMiner is not affiliated with Spotify.

***

**FeedMiner** · Fast, honestly priced scrapers, kept alive when platforms change.

Spotify Track Play Counts · [X Tweet Scraper](https://apify.com/feedminer/x-tweet-scraper) · [All FeedMiner Actors](https://apify.com/feedminer)

# Actor input Schema

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

Tracks, albums, artists or playlists, mixed, as copied from the player or the app's share button: open.spotify.com links with or without their intl-xx/ part or ?si= tail, or spotify: URIs. Duplicates fold. A link to nothing yields no row and is counted as not found in the run's closing line; podcasts, episodes and audiobooks are set aside before any read. Leave empty to search only.

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

Words to search Spotify for, one per line, as you would type them in its search bar: a genre such as lofi, an artist's name, a mood. Each term delivers rows of the kind chosen below, in Spotify's order, and works alongside the links above. Case does not matter; a term typed twice is searched once. Empty by default: a search is billed per row like any other.

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

The kind of row each search term delivers: tracks with their play counts, artists with their audience and profile, albums with their tracks' plays added up, or playlists with their followers.

## `maxResultsPerTerm` (type: `integer`):

The most rows one search term may deliver. Spotify's search goes no deeper than 1 000 results, and repeats some tracks among them, so a track search can end short of a high cap.

## `artistTracks` (type: `string`):

What an artist link delivers beside the artist's own row (monthly listeners, followers, world rank, top cities, profile): nothing more, the ten top tracks of the profile, or every track the artist is credited on, across albums, singles and compilations, newest release first. A compilation's tracks by other artists are left out and not charged. Artists found by a search deliver their own row only.

## `maxRowsPerUrl` (type: `integer`):

The most track rows one album, playlist or artist link may deliver; the artist's own row comes on top. A playlist or a discography longer than this stops here, and the closing line says so: this is what bounds the run's cost. A discography whose releases seldom credit the artist also stops once it has read ten tracks for each row allowed.

## `debugMode` (type: `boolean`):

Verbose log lines for support. Leave off.

## Actor input object example

```json
{
  "urls": [
    "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b",
    "https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj",
    "https://open.spotify.com/artist/1Xyo4u8uXC1ZmMpatF05PJ",
    "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
  ],
  "searchType": "tracks",
  "maxResultsPerTerm": 50,
  "artistTracks": "top",
  "maxRowsPerUrl": 1000,
  "debugMode": false
}
```

# Actor output Schema

## `rows` (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 = {
    "urls": [
        "https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b",
        "https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj",
        "https://open.spotify.com/artist/1Xyo4u8uXC1ZmMpatF05PJ",
        "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("feedminer/spotify-track-playcounts").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/album/4yP0hdKOZPNshxUOjY0cZj",
        "https://open.spotify.com/artist/1Xyo4u8uXC1ZmMpatF05PJ",
        "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("feedminer/spotify-track-playcounts").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/album/4yP0hdKOZPNshxUOjY0cZj",
    "https://open.spotify.com/artist/1Xyo4u8uXC1ZmMpatF05PJ",
    "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
  ]
}' |
apify call feedminer/spotify-track-playcounts --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,feedminer/spotify-track-playcounts"
        }
    }
}
```

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/w6Gz8xIf2jTc1y3TR/builds/SaEhxAmsMUkieyAZK/openapi.json
