# Spotify Playlist Intelligence (`khadinakbar/analyze-spotify-playlist`) Actor

Analyze public Spotify playlists — followers, track mix, artist concentration, playcount distribution, duplicates, duration stats. HTTP-only, cookieless, MCP-ready.

- **URL**: https://apify.com/khadinakbar/analyze-spotify-playlist.md
- **Developed by:** [Khadin Akbar](https://apify.com/khadinakbar) (community)
- **Categories:** Social media, AI, MCP servers
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 playlist analyzeds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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 Intelligence

**Spotify Playlist Intelligence** helps A\&R teams, playlist marketers, and AI agents analyze public Spotify playlists into one structured **intelligence report** per list. Paste one or more playlist links and get follower counts, artist concentration (HHI), top artists, duplicate tracks, duration stats, playcount percentiles (p50/p90), release-year histograms, an editorial heuristic, and an optional sampled tracklist. Each row is designed for editorial research, curator QA, and agent tool calls — focused on playlist analytics rather than a raw catalog export.

The Actor is HTTP-only: it uses Spotify's public Partner API with an embed fallback when the partner route is unavailable. Apify Residential proxy is enabled by default because Spotify blocks datacenter IPs. On Apify you also get API access, scheduling, webhooks, integrations, and execution monitoring. MCP-ready via `apify--analyze-spotify-playlist`.

For artists, albums, tracks, podcasts, or keyword search across entity types, continue with [Spotify All-in-One Scraper](https://apify.com/khadinakbar/spotify-all-in-one-scraper).

### Best fit for this Actor

- Editorial or chart playlist mix analysis — concentration, duplicates, playcount spread, release-year shape.
- Curator QA on public user playlists before sharing or pitching placements.
- Label and A\&R scouting — see which artists dominate a chart playlist and how track playcounts cluster inside the list.
- Growth snapshots — supply `previousSnapshots` with earlier follower counts to compute `followersDelta` in the same run.
- AI agents and dashboards — one flat `playlist-intelligence` row per playlist with a nested `analytics` object.

### Workflow scenario

A playlist marketer starts with RapCaviar, sets `maxTracks` to 50, and keeps `includeAnalytics` enabled. The run returns followers, `analytics.artistConcentrationHhi`, `analytics.topArtists`, playcount p50/p90, duplicate count, and duration medians in one dataset row. They export CSV, compare two editorial lists side by side, and pass handles that need full artist or track catalog data to [Spotify All-in-One Scraper](https://apify.com/khadinakbar/spotify-all-in-one-scraper) for deeper entity scraping. Scheduled reruns with `previousSnapshots` turn each report into a follower delta snapshot over time.

### Quick start input

```json
{
  "playlistUrls": [
    "https://open.spotify.com/playlist/37i9dQZF1DX0XUsuxWHRQd"
  ],
  "maxTracks": 50,
  "includeTracklist": true,
  "includeAnalytics": true,
  "enrichArtistGenres": false,
  "maxPlaylists": 5,
  "previousSnapshots": [
    {
      "playlistId": "37i9dQZF1DX0XUsuxWHRQd",
      "followers": 15800000
    }
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"]
  }
}
```

`playlistUrls` accepts full playlist URLs, `spotify:playlist:` URIs, or bare 22-character playlist IDs. Duplicates merge before billing; `maxPlaylists` caps analyzed playlists per run.

### Input reference

| Field | What it controls |
| --- | --- |
| `playlistUrls` | Required. Public playlist URLs, URIs, or IDs. |
| `maxTracks` | Tracks fetched and analyzed per playlist (1–1000). Default 100. |
| `includeTracklist` | Include sampled `tracks[]`. Default true. |
| `includeAnalytics` | Include derived `analytics` object. Default true. |
| `enrichArtistGenres` | Fetch genres for up to 8 top artists (Partner API only). Default false. |
| `previousSnapshots` | Optional `{ playlistId, followers }` pairs for delta math. |
| `maxPlaylists` | Cap on unique playlists processed and billed (1–100). Default 50. |
| `proxyConfiguration` | Proxy for Spotify HTTP. Residential recommended and pre-enabled. |

### What data you receive

Each successful run writes one dataset row per analyzed playlist (`type: playlist-intelligence`).

```json
{
  "type": "playlist-intelligence",
  "id": "37i9dQZF1DX0XUsuxWHRQd",
  "uri": "spotify:playlist:37i9dQZF1DX0XUsuxWHRQd",
  "url": "https://open.spotify.com/playlist/37i9dQZF1DX0XUsuxWHRQd",
  "name": "RapCaviar",
  "description": "New music from Drake, Kendrick Lamar, Future and more.",
  "owner": {
    "name": "Spotify",
    "username": "spotify",
    "uri": "spotify:user:spotify"
  },
  "followers": 15842100,
  "followersDelta": 42100,
  "format": "editorial",
  "totalTracks": 50,
  "coverArt": "https://i.scdn.co/image/ab67616d0000b273example",
  "analytics": {
    "analyticsVersion": "1.0.0",
    "trackCount": 50,
    "totalTracksDeclared": 50,
    "uniqueArtists": 41,
    "topArtists": [
      { "name": "Drake", "count": 4, "share": 0.08 },
      { "name": "Future", "count": 3, "share": 0.06 }
    ],
    "artistConcentrationHhi": 0.0421,
    "duplicateTrackCount": 0,
    "durationTotalMs": 10245000,
    "durationAvgMs": 204900,
    "durationMedianMs": 198000,
    "explicitShare": 0.76,
    "playcount": {
      "sum": 8420000000,
      "p50": 98000000,
      "p90": 420000000,
      "missing": 0,
      "available": 50
    },
    "releaseYears": { "2026": 18, "2025": 22, "2024": 10 },
    "genreMix": null,
    "editorialHeuristic": {
      "isLikelyEditorial": true,
      "reason": "format_or_owner_spotify"
    }
  },
  "tracks": [
    {
      "name": "Example Track",
      "uri": "spotify:track:6DCZPtHk3ywpFa5FAdVice",
      "playcount": 245000000,
      "durationMs": 203000,
      "explicit": true,
      "artists": ["Example Artist"],
      "releaseDate": "2026-03-01"
    }
  ],
  "popularityDataAvailable": true,
  "dataSource": "partner",
  "scrapedAt": "2026-09-17T12:00:00.000Z"
}
```

| Field | Description |
| --- | --- |
| `type` | Always `playlist-intelligence`. |
| `id` / `uri` / `url` | Spotify playlist ID, URI, and canonical link. |
| `name` / `description` | Public playlist title and description when exposed. |
| `owner` | `{ name, username, uri }` owner metadata. |
| `followers` | Public follower count. |
| `followersDelta` | `followers − previousSnapshots.followers` when a snapshot matches. |
| `format` | Spotify playlist format string when available. |
| `totalTracks` | Declared total track count on the playlist. |
| `coverArt` | Cover image URL. |
| `analytics.trackCount` | Tracks sampled in this report (≤ `maxTracks`). |
| `analytics.uniqueArtists` | Distinct primary artists in the sample. |
| `analytics.topArtists` | Top 10 artists with `name`, `count`, `share`. |
| `analytics.artistConcentrationHhi` | Herfindahl–Hirschman Index (0–1); higher = more concentrated. |
| `analytics.duplicateTrackCount` | Repeated track URIs in the sample. |
| `analytics.durationTotalMs` / `durationAvgMs` / `durationMedianMs` | Duration stats from sampled tracks. |
| `analytics.explicitShare` | Share of explicit tracks (0–1) when known. |
| `analytics.playcount.p50` / `p90` | Playcount percentiles when Partner API data is available. |
| `analytics.playcount.sum` / `missing` / `available` | Aggregate and coverage counters. |
| `analytics.releaseYears` | Histogram `{ "2024": 12, "2023": 8, … }`. |
| `analytics.genreMix` | Optional top-genre mix when `enrichArtistGenres` is true. |
| `analytics.editorialHeuristic` | `{ isLikelyEditorial, reason }` — heuristic signal from public metadata. |
| `tracks[]` | Sampled track rows when `includeTracklist` is true. |
| `popularityDataAvailable` | `false` when embed fallback omits playcounts. |
| `dataSource` | `partner` or `embed`. |
| `scrapedAt` | ISO 8601 collection timestamp. |

Download the dataset as JSON, CSV, Excel, or HTML. `OUTPUT` and `RUN_SUMMARY` in the default key-value store include `outcome`, `itemsPushed`, and `chargedEventCounts`.

### Pricing

This Actor uses **Pay per event (PPE)** with **platform usage pass-through**. Confirm current prices on the live [Pricing tab](https://apify.com/khadinakbar/analyze-spotify-playlist/pricing) — that tab is the source of truth if this README ever lags.

| Event | Price | When charged |
| --- | --- | --- |
| `apify-actor-start` | $0.00005 | Once per run (minimum one event per GB memory). |
| `playlist-analyzed` | **$0.02** | Once per successfully persisted playlist report. |

**Cost examples (result events only):**

- One playlist at 50 tracks: about **$0.02** plus platform usage (typically a few seconds of compute and residential proxy transfer).
- Ten playlists in one run: about **$0.20** in `playlist-analyzed` events plus usage.

`maxTracks`, tracklist inclusion, and analytics depth add no extra PPE — only analyzed playlists are billed. Empty matches receive no primary event charge. Residential proxy usage passes through to the caller.

### Use through the API

```bash
curl -X POST "https://api.apify.com/v2/acts/khadinakbar~analyze-spotify-playlist/runs" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "playlistUrls": ["https://open.spotify.com/playlist/37i9dQZF1DX0XUsuxWHRQd"],
    "maxTracks": 50,
    "includeAnalytics": true
  }'
```

Poll the run, then fetch dataset items from the default dataset URL returned in the run object. Read `OUTPUT` for terminal `outcome` and billing reconciliation.

### Use with AI agents through Apify MCP

Connect via <https://mcp.apify.com>. Tool namespace: `apify--analyze-spotify-playlist`.

> Analyze the public Spotify playlist at `https://open.spotify.com/playlist/37i9dQZF1DX0XUsuxWHRQd` with maxTracks 50. Return playlist name, followers, analytics.artistConcentrationHhi, analytics.topArtists, analytics.playcount.p50, analytics.playcount.p90, analytics.editorialHeuristic, popularityDataAvailable, dataSource, and scrapedAt. Read OUTPUT.outcome and itemsPushed if the dataset is empty. Cost scope: one playlist-analyzed event plus platform usage.

### Agent prompt card

```
Goal: Produce a Spotify playlist intelligence report for a public playlist URL.

Input:
- playlistUrls: one or more open.spotify.com/playlist/… URLs (required)
- maxTracks: 50 for a quick editorial scan, up to 1000 for deep analysis
- includeAnalytics: true (default)
- includeTracklist: false when you only need the analytics block
- enrichArtistGenres: true when genreMix is needed (Partner API only)
- previousSnapshots: optional [{ playlistId, followers }] for followersDelta

Return from each dataset row:
- name, url, followers, followersDelta
- analytics.uniqueArtists, analytics.artistConcentrationHhi, analytics.topArtists
- analytics.duplicateTrackCount, analytics.durationAvgMs
- analytics.playcount.p50, analytics.playcount.p90, popularityDataAvailable
- analytics.editorialHeuristic, dataSource, scrapedAt

Interpretation:
- HHI near 1.0 = one artist dominates; near 0 = very diverse.
- popularityDataAvailable=false means embed fallback — playcount percentiles omitted.
- editorialHeuristic is a public-signal estimate from owner and format metadata.

On empty dataset: read OUTPUT.outcome (VALID_EMPTY, INVALID_INPUT, UPSTREAM_FAILED).
Pricing: $0.02 per playlist-analyzed plus platform usage. Billing is per playlist, per track depth.
```

### Connect the workflow

- Playlist analytics report (this Actor) → editorial mix, concentration, duplicates, playcount spread.
- Artist, album, track, podcast, or search scraping → [Spotify All-in-One Scraper](https://apify.com/khadinakbar/spotify-all-in-one-scraper).

For artist, album, track, show, and episode inputs, continue with the sibling Spotify All-in-One Scraper; this Actor returns `INVALID_INPUT` with routing guidance for non-playlist URLs.

### Best results

- Pass public playlist URLs, URIs, or 22-character IDs; keep Apify Residential proxy enabled for stable Partner API access.
- Set `maxTracks` to match your analysis depth — analytics apply to the fetched sample up to the cap.
- Supply `previousSnapshots` when you store prior follower counts and want `followersDelta` in the same row.
- Enable `enrichArtistGenres` when you need `genreMix` on Partner API routes.
- When `dataSource` is `embed`, expect baseline metadata with `popularityDataAvailable: false` and playcount percentiles omitted.
- Pair this Actor with Spotify All-in-One Scraper when the next step needs full artist, album, or track catalog rows.

### Builder's note

I built this Actor around Spotify's public Partner API path with a self-healing TOTP token flow — the web-player secret and version rotate, so the runtime extracts fresh credentials from the bundle each run instead of pinning stale values. When the partner route is unavailable, the embed page supplies baseline playlist metadata; a deleted or unavailable playlist that returns embed "Page not found" finishes as `VALID_EMPTY` with zero playlist charges. In my testing, datacenter IPs hit Spotify's edge block immediately, so Apify Residential is required by default for reliable yield on public playlists.

### FAQ, legal, and responsible use

**Do I need a Spotify developer app or API key?** No. The Actor works from public web-player routes without login.

**Is this affiliated with Spotify?** Spotify is a trademark of its owner. This independent Actor is not affiliated with, associated with, or endorsed by Spotify.

**How should I use the output?** This Actor retrieves publicly visible Spotify playlist metadata and derived statistics available without logging in. You are responsible for complying with applicable laws, Spotify's Terms of Use, and your own data-governance policies. Use the output only for purposes you are authorized to pursue. Before production use, review the [Apify Exclusion Policy](https://apify.com/terms/exclusion-policy) to confirm your playlist research workflow stays within platform rules on excluded content and use cases.

Issues and feature requests: use the Actor **Issues** tab on [Apify Console](https://console.apify.com).

# Changelog

This Actor's version history is a separate document: https://apify.com/khadinakbar/analyze-spotify-playlist/changelog.md

# Actor input Schema

## `playlistUrls` (type: `array`):

Public Spotify playlists to analyze. Accepts full URLs (https://open.spotify.com/playlist/37i9dQZF1DX0XUsuxWHRQd), URIs (spotify:playlist:37i9dQZF1DX0XUsuxWHRQd), or bare 22-character playlist IDs. Artist, album, track, show, and episode URLs are rejected — use spotify-all-in-one-scraper for those. Duplicates are merged; maxPlaylists caps how many unique playlists are billed.

## `maxTracks` (type: `integer`):

How many playlist tracks to fetch and include in analytics (and optionally the tracklist). Partner API paginates in pages of 100. Higher values add run time but not extra PPE — billing is per playlist analyzed, not per track. Hard cap 1000.

## `includeTracklist` (type: `boolean`):

When true (default), each report includes the sampled tracks array (name, artists, playcount, duration, explicit flag). Set false for compact agent rows with analytics only.

## `includeAnalytics` (type: `boolean`):

When true (default), each report includes the analytics object: unique artists, HHI concentration, duplicate count, duration stats, playcount percentiles, release-year histogram, and editorial heuristic.

## `enrichArtistGenres` (type: `boolean`):

When true, fetches public genre tags for up to 8 top artists via the Partner API and attaches genreMix to analytics. Adds extra HTTP calls and run time. Default false. Ignored when the embed fallback is used (no playcount/genre path).

## `previousSnapshots` (type: `array`):

Optional JSON array of earlier follower counts for delta calculation. Each item: { "playlistId": "22-char-id", "followers": number }. When a playlist ID matches, the report includes followersDelta = current followers minus the snapshot value.

## `maxPlaylists` (type: `integer`):

Hard cap on unique playlists processed and billed (playlist-analyzed events) in one run. Default 50; prefill 5 keeps quality tests cheap.

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

Proxy for all Spotify HTTP requests. Spotify blocks datacenter IPs at its edge, so Apify Residential is strongly recommended and enabled by default. Leave as-is unless you have a specific reason to change it.

## Actor input object example

```json
{
  "playlistUrls": [
    "https://open.spotify.com/playlist/37i9dQZF1DX0XUsuxWHRQd"
  ],
  "maxTracks": 50,
  "includeTracklist": true,
  "includeAnalytics": true,
  "enrichArtistGenres": false,
  "previousSnapshots": [],
  "maxPlaylists": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `dataset` (type: `string`):

Dataset rows — one playlist-intelligence report per analyzed playlist.

## `OUTPUT` (type: `string`):

Terminal outcome, itemsPushed, charged event counts, and warnings.

## `RUN_SUMMARY` (type: `string`):

Extended terminal diagnostics including runId, datasetId, and timestamps.

# 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 = {
    "playlistUrls": [
        "https://open.spotify.com/playlist/37i9dQZF1DX0XUsuxWHRQd"
    ],
    "maxTracks": 50,
    "includeTracklist": true,
    "includeAnalytics": true,
    "enrichArtistGenres": false,
    "previousSnapshots": [],
    "maxPlaylists": 5,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("khadinakbar/analyze-spotify-playlist").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 = {
    "playlistUrls": ["https://open.spotify.com/playlist/37i9dQZF1DX0XUsuxWHRQd"],
    "maxTracks": 50,
    "includeTracklist": True,
    "includeAnalytics": True,
    "enrichArtistGenres": False,
    "previousSnapshots": [],
    "maxPlaylists": 5,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("khadinakbar/analyze-spotify-playlist").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 '{
  "playlistUrls": [
    "https://open.spotify.com/playlist/37i9dQZF1DX0XUsuxWHRQd"
  ],
  "maxTracks": 50,
  "includeTracklist": true,
  "includeAnalytics": true,
  "enrichArtistGenres": false,
  "previousSnapshots": [],
  "maxPlaylists": 5,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call khadinakbar/analyze-spotify-playlist --silent --output-dataset

```

## MCP server setup

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

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/nMXOCczs0eh2iRit5/builds/A0pooZZLhakHf78rX/openapi.json
