# Spotify Playlist Scraper - Tracklist, Followers, Change Tracker (`s-r/free-spotify-playlist-intelligence`) Actor

Export any public Spotify playlist as JSON: the full tracklist with artists, album, playcount and date added, plus followers, owner and editorial flag. Run it again to see which tracks were added, removed or moved. For labels, artist managers and playlist pitchers. $0.01 per playlist.

- **URL**: https://apify.com/s-r/free-spotify-playlist-intelligence.md
- **Developed by:** [SR](https://apify.com/s-r) (community)
- **Categories:** Social media, Business
- **Features:** Limited permissions
- **Stats:** 91 total users, 38 monthly users, 100.0% runs succeeded, 2 bookmarks
- **User rating**: No ratings yet

## Pricing

$10.00 / 1,000 playlist analyzeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 Playlist Scraper: Tracks, Metadata and Changes

This Spotify playlist scraper returns public playlist metadata, full tracklists and changes between runs. Supply playlist URLs, Spotify URIs or playlist IDs. You do not need a Spotify account to collect a public playlist. Each successfully analyzed playlist becomes one dataset row, with its tracks nested inside that row. Use the results to monitor editorial selections, follow curator activity, maintain a music catalogue or compare a playlist with its previous state.

### Input for the Spotify playlist scraper

The `playlists` field is required and accepts an array. A playlist ID, a `spotify:playlist:` URI and an `open.spotify.com/playlist/` URL identify the same public playlist. Localized URLs containing a segment such as `intl-nl` also work, and sharing parameters do not change the playlist identity. Input order is preserved. If you supply a playlist twice, you receive two rows and both successful analyses count toward usage.

`trackDiffs` defaults to `true`. Leave it enabled when you want additions, removals and position changes compared with the previous run. Set it to `false` when you only need the current playlist and tracks; the output then omits the `diff` field and leaves your previous snapshots untouched. `pageSize` retains its existing default of 100 and accepts the existing 1–200 range. All available tracks are requested regardless of this setting.

This is the exact input from a successful measurement on 1 October 2026. It includes two public playlists, an invalid value and a nonexistent playlist so that the error behavior is visible alongside the successful results.

```json
{
  "playlists": [
    "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M",
    "https://open.spotify.com/playlist/0vvXsWCC9xrXsKd4FyS8kM",
    "not a playlist",
    "0000000000000000000000"
  ],
  "pageSize": 100,
  "trackDiffs": true
}
```

For regular monitoring, save your input as an Apify task and schedule it at the interval your project needs. Keep the same playlists in subsequent runs when you want a meaningful history. A playlist that is private, removed or unavailable cannot be collected as a public playlist.

### Output and track fields

The default dataset contains one row for each processed input value. Successful rows include `id`, `uri`, `name`, `description`, `followers`, `owner`, `image_url`, `total_tracks`, `is_editorial` and `tracks`. The owner remains an object with `uri`, `name` and `username`. Values that Spotify does not provide remain JSON null; they are not filled with guesses.

Here is a metadata excerpt from the actual first row of that measurement. The full response, including its nested tracks, is available in the product's recorded example.

```json
{
  "id": "37i9dQZF1DXcBWIGoYBM5M",
  "name": "Today’s Top Hits",
  "owner": {
    "uri": "spotify:user:spotify",
    "name": "Spotify",
    "username": "spotify"
  },
  "followers": 33754761,
  "total_tracks": 50,
  "is_editorial": true
}
```

Each track includes its position, Spotify URI and ID, type, name, addition time and adding user where available. Music tracks also include duration, explicit status, playability, playcount, track and disc numbers, artists and album information. Artists are a list of objects; album information remains an object with its URI, name and cover URL. Podcast episodes use their corresponding duration and podcast fields. Positions begin at zero and follow the source playlist order.

New metadata fields include `source`, `platform`, `playlist_id`, `fetched_at`, `url`, `owner_name`, `owner_id` and `track_count`. Existing fields remain available for integrations that already use them. You can export the dataset as JSON, JSONL, CSV or Excel, or retrieve it through the Apify API. JSON preserves the nested track, album and artist structures most directly.

### Track changes between runs

With `trackDiffs` enabled, the actor stores a snapshot for each complete playlist in your persistent named store. The next run compares against that playlist's previous snapshot. Your existing snapshot history continues to be used after the migration.

The `diff` object includes previous and latest snapshot IDs, an `is_first_snapshot` flag, lists of added, removed and moved items, and a summary with added, removed, moved and unchanged counts. A change entry identifies the item URI and name and provides the previous position, new position and position difference where applicable. The first snapshot reports all tracks as added. Later comparisons use the track URI as identity, matching the actor's existing behavior for repeated tracks.

### Use cases for the Spotify playlist scraper

#### Playlist pitching and placement tracking

Labels, distributors and artist managers can follow the editorial and curator playlists they pitch to. A scheduled run shows when a track is added, how its position moves and when it is removed, without checking each playlist by hand.

#### Editorial and curator monitoring

Follow how Spotify's own editorial playlists and independent curators rotate their selections. The `is_editorial` flag separates Spotify-owned playlists from user playlists, and follower counts show reach at each collection time.

#### Catalogue and research datasets

Export complete tracklists with artists, album, duration, explicit status and playcount into a spreadsheet, database or BI tool. Researchers and data teams can build time series of playlist composition from repeated runs.

#### Competitive and market analysis

Compare the playlists that matter in a genre or market: which artists appear, which labels' releases get added and how often a playlist changes. The diff summary gives a quick measure of rotation per run.

### How this Spotify playlist scraper compares

Several actors in the Apify Store return the current tracks of a Spotify playlist, and broader Spotify scrapers cover artists, albums and search. This actor focuses on playlists and adds what a single snapshot cannot show:

- **Changes between runs.** Added, removed and moved tracks are computed for you against the previous complete snapshot, with position differences and a summary count.
- **Full tracklists.** Subsequent pages are requested, so a large playlist is not cut off at its first page; an incomplete playlist is flagged and not charged.
- **Playlist context in every row.** Followers, owner, editorial flag and cover image arrive with the tracks, so you do not need a second actor for playlist metadata.
- **Pay per playlist, not per track.** A 500-track playlist costs the same as a 50-track playlist, and failed or nonexistent playlists are free.

If you need to search Spotify for playlists by keyword or collect artist profiles, a general Spotify scraper fits better; when you already know which playlists to follow, this actor gives the most complete picture per playlist.

### Pricing and result limits

The price is **$0.01 per fully analyzed playlist**, charged through the existing `playlist` event. Track rows inside a playlist do not incur separate charges. Input errors, nonexistent playlists and failed playlist requests are not charged. A playlist returned with an explicit incomplete-result warning is also not charged and does not replace a complete stored snapshot.

Users without a paid Apify plan receive at most ten dataset rows per run. Error rows count toward this delivery limit. Charges cover only successful complete playlists that are actually delivered. Paid Apify users retain the requested playlist list. Check the run output for delivered counts, charge counts, warnings and any partial-result flag.

### FAQ

#### Does this Spotify playlist scraper require a Spotify login?

No. It collects public playlists without a Spotify account. It does not grant access to private playlists or account-only information.

#### How do I get changes rather than a first snapshot?

Run the same playlist again with `trackDiffs` enabled. The comparison uses the most recent complete snapshot saved by your previous run. With diffs disabled, no new snapshot is recorded.

#### What happens when one playlist cannot be read?

That playlist produces an error row containing the original `input`, an `id` when it could be parsed, and an English `error` message. Other readable playlists can still produce their normal rows. The run's error record also lists those failures, and they are not billed.

#### Does a large playlist return only the first page?

The actor requests subsequent pages to collect the full tracklist. If a single playlist cannot be completed within the available request budget, its row explicitly reports partial delivery and the run includes a warning. Its incomplete tracks do not become the next comparison snapshot.

#### Are followers and playcounts estimated?

No. These fields reflect the values returned by Spotify at collection time. They can change between runs, and unavailable values remain null. The actor does not infer listener counts or sales from these numbers.

# Actor input Schema

## `playlists` (type: `array`):

List of Spotify playlist IDs (22-char), URIs (spotify:playlist:...), or open.spotify.com URLs.

## `trackDiffs` (type: `boolean`):

If true, persist playlist snapshots and emit added/removed/moved per run vs the previous one. Run twice to see the diff.

## `pageSize` (type: `integer`):

Pagination size for tracklist fetch (1-200).

## Actor input object example

```json
{
  "playlists": [
    "37i9dQZF1DXcBWIGoYBM5M",
    "https://open.spotify.com/playlist/37i9dQZEVXbMDoHDwVN2tF"
  ],
  "trackDiffs": true,
  "pageSize": 100
}
```

# Actor output Schema

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

Dataset rows produced by this run.

## `output` (type: `string`):

OUTPUT record with the run's counts and status flags.

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

Failures with a code and a redacted message. Absent when the run had none.

# 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 = {
    "playlists": [
        "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("s-r/free-spotify-playlist-intelligence").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 = { "playlists": ["https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"] }

# Run the Actor and wait for it to finish
run = client.actor("s-r/free-spotify-playlist-intelligence").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 '{
  "playlists": [
    "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
  ]
}' |
apify call s-r/free-spotify-playlist-intelligence --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,s-r/free-spotify-playlist-intelligence"
        }
    }
}
```

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/t3EIlTpBNFFb0EVKH/builds/GOmO3Wblj8bQf6mWc/openapi.json
