Spotify Playlist Tracker avatar

Spotify Playlist Tracker

Pricing

Pay per event

Go to Apify Store
Spotify Playlist Tracker

Spotify Playlist Tracker

Monitor public Spotify playlists and emit added, removed, moved, and metadata-changed track events with persistent snapshots and complete pagination.

Pricing

Pay per event

Rating

0.0

(0)

Developer

Stas Persiianenko

Stas Persiianenko

Maintained by Community

Actor stats

0

Bookmarked

1

Total users

1

Monthly active users

6 days ago

Last modified

Share

Track changes in public Spotify playlists without Spotify OAuth or a user account. This Spotify playlist tracker saves an ordered snapshot, compares it with the previous run, and emits track-level added, removed, moved, and metadata_changed events.

Use it as a scheduled playlist monitor, a catalog-quality signal, or a clean input for notifications and downstream data workflows. The Actor follows every page of the public playlist response instead of stopping at Spotify's 100-track embed preview.

What does Spotify Playlist Tracker do?

For each public playlist URL, the Actor:

  1. resolves its public identity and owner;
  2. fetches all available ordered track pages;
  3. loads the prior snapshot for the same monitorKey and playlist;
  4. compares track occurrences, positions, and public metadata;
  5. writes only detected changes to the default dataset; and
  6. saves the current snapshot for the next run.

A first run can emit every current track as added, which gives you a useful baseline dataset immediately. Set emitInitialAdds to false when you want a silent baseline instead.

Who is it for?

  • Playlist curators watching additions, removals, and ranking changes.
  • Labels and artist teams tracking public playlist placements.
  • Music-data teams feeding playlist changes into a warehouse.
  • Automation builders sending Slack, email, or webhook notifications.
  • Catalog QA teams detecting renamed tracks, artist changes, duration changes, explicit flags, and availability changes.

This Actor covers public playlist history from the moment you create a baseline. It does not reconstruct changes that happened before the first run.

Why use this playlist monitor?

A playlist export answers “what is in the playlist now?” This Actor answers “what changed since my last check?”

Key differences from a one-time Spotify scraper:

  • persistent, versioned snapshots across runs;
  • occurrence-aware comparison when a track appears more than once;
  • complete pagination for playlists longer than 100 tracks;
  • separate move and metadata-change events;
  • stable playlist, track, and monitor identifiers for integrations;
  • no private account, user library, or OAuth client required.

Getting started

  1. Open the Actor input.
  2. Add one or more public Spotify playlist URLs.
  3. Choose a stable monitorKey, such as weekly-editorial-monitor.
  4. Keep emitInitialAdds enabled for an immediate baseline export, or disable it for a silent first run.
  5. Run the Actor and inspect Playlist changes in the dataset.
  6. Schedule the same input hourly, daily, or weekly.
  7. Connect the dataset to your notification, database, or automation workflow.

Reuse the same monitorKey on later runs. Changing it creates an independent history. Do not enable resetSnapshots in a normal schedule.

Input parameters

FieldTypeDefaultDescription
playlistUrlsstring arrayrequiredOne to 20 public open.spotify.com/playlist/... URLs or spotify:playlist:... URIs.
monitorKeystringdefaultSnapshot namespace. Reuse it to continue one monitoring history.
emitInitialAddsbooleantrueEmit every current track as added when no prior snapshot exists.
resetSnapshotsbooleanfalseIgnore and replace prior snapshots for this run.

Example input:

{
"playlistUrls": [
"https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"
],
"monitorKey": "todays-top-hits-daily",
"emitInitialAdds": true,
"resetSnapshots": false
}

Monitoring several playlists

One run can check up to 20 playlists:

{
"playlistUrls": [
"https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M",
"https://open.spotify.com/playlist/37i9dQZF1DWWQRwui0ExPn"
],
"monitorKey": "editorial-and-focus-playlists",
"emitInitialAdds": false
}

Each playlist has its own snapshot inside the monitor namespace. A temporary failure on one URL is logged while other valid playlists continue. The run fails when none of the supplied playlists can be checked.

Output fields

Every dataset row is one detected change.

FieldMeaning
changeTypeadded, removed, moved, or metadata_changed.
playlistId, playlistUrl, playlistNameCurrent public playlist identity.
ownerNameCurrent public owner display name, when available.
monitorKeyNamespace used for this comparison.
trackId, trackUri, trackUrlStable Spotify track identifiers.
trackName, artists, albumHuman-readable track metadata.
previousPositionPrior one-based position; null for additions.
currentPositionCurrent one-based position; null for removals.
changedFieldsFields responsible for a move or metadata event.
previousTrackComplete prior track row; null for additions.
currentTrackComplete current track row; null for removals.
previousSnapshotAtTimestamp of the compared snapshot.
detectedAtTimestamp of the current snapshot.

Example change record

This shortened example matches the current dataset contract:

{
"type": "playlist_change",
"changeType": "moved",
"playlistId": "37i9dQZF1DXcBWIGoYBM5M",
"playlistUrl": "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M",
"playlistName": "Today’s Top Hits",
"ownerName": "Spotify",
"monitorKey": "todays-top-hits-daily",
"trackId": "4cOdK2wGLETKBW3PvgPWqT",
"trackUri": "spotify:track:4cOdK2wGLETKBW3PvgPWqT",
"trackUrl": "https://open.spotify.com/track/4cOdK2wGLETKBW3PvgPWqT",
"trackName": "Example Song",
"artists": ["Example Artist"],
"album": "Example Album",
"previousPosition": 12,
"currentPosition": 5,
"changedFields": ["position"],
"previousSnapshotAt": "2026-08-01T12:00:00.000Z",
"detectedAt": "2026-08-02T12:00:00.000Z"
}

The complete record also contains previousTrack and currentTrack objects for warehouse updates and audit trails.

How change detection works

Tracks are matched by Spotify track ID and occurrence number. If the same track appears twice, the first occurrence is compared with the first occurrence and the second with the second.

  • A new occurrence produces added.
  • A missing occurrence produces removed.
  • A changed one-based position produces moved.
  • Changes to name, artists, album, duration, explicit status, or playability produce metadata_changed.

One track can produce both a move event and a metadata event in the same run. This keeps filters simple for alerting and analytics.

Persistent snapshots and monitor keys

Snapshots are stored in a dedicated Actor key-value store. Keys contain a hash of monitorKey plus the playlist ID; the plain monitor key is still present in output records for routing.

Choose monitor keys by workflow, for example:

  • label-a-daily-placement-watch
  • editorial-playlists-eu
  • catalog-qa-weekly

A reset replaces the old baseline only after Spotify data has been fetched and change records have been saved. Snapshot data contains public playlist and track metadata, not Spotify credentials.

How much does it cost to monitor Spotify playlist changes?

The Actor uses pay-per-event pricing:

  • a one-time run started event costs $0.00110 per run;
  • each delivered change event costs $0.00078257 at the BRONZE tier;
  • runs with no detected changes pay only the start event and platform usage;
  • playlist snapshots and unchanged tracks have no separate event charge.

At the BRONZE tier, illustrative event charges are:

WorkflowDelivered changesBRONZE event-charge formula
Daily check with no changes0$0.00110 start
Small update5$0.00110 + 5 × $0.00078257
First baseline of 50 tracks50$0.00110 + 50 × $0.00078257
Large baseline of 100 tracks100$0.00110 + 100 × $0.00078257

Apify account tier pricing and platform usage can affect the final total shown for a run. Check the Actor pricing tab for your active tier.

Scheduling and alerts

Create an Apify Task with a stable input, then add a schedule. Daily monitoring works well for editorial playlists; faster schedules may be useful for short-lived campaign playlists.

Common downstream patterns:

  1. run the Task on a schedule;
  2. trigger a webhook when the run succeeds;
  3. read dataset items;
  4. filter by changeType or artist;
  5. send a message or upsert records into a warehouse.

A successful run with zero dataset rows means no supported track change was found since the previous snapshot.

API usage with cURL

Start a synchronous run and receive dataset items:

curl -X POST \
"https://api.apify.com/v2/acts/automation-lab~spotify-playlist-change-monitor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"playlistUrls": ["https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"],
"monitorKey": "api-monitor",
"emitInitialAdds": true
}'

Keep the token in a secret or environment variable, not in source control.

JavaScript API example

import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/spotify-playlist-change-monitor').call({
playlistUrls: ['https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M'],
monitorKey: 'javascript-monitor',
emitInitialAdds: true,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);

Python API example

import os
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("automation-lab/spotify-playlist-change-monitor").call(run_input={
"playlistUrls": ["https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"],
"monitorKey": "python-monitor",
"emitInitialAdds": True,
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
print(item)

Use with Apify MCP

Add the Actor to Claude Code:

claude mcp add --transport http apify \
"https://mcp.apify.com?tools=automation-lab/spotify-playlist-change-monitor"

Claude Desktop, Cursor, and VS Code setup

Claude Desktop, Cursor, and VS Code can use the same HTTP MCP configuration:

{
"mcpServers": {
"apify": {
"url": "https://mcp.apify.com?tools=automation-lab/spotify-playlist-change-monitor"
}
}
}

Example prompts:

  • “Run my Spotify playlist monitor and summarize newly added tracks.”
  • “Show tracks that moved into the top 10 since the previous snapshot.”
  • “Check two public playlists and group removals by artist.”

Integrations

Useful destinations include:

  • Google Sheets for a simple change log;
  • Slack, Teams, Discord, or email for alerts;
  • Zapier and Make for no-code routing;
  • BigQuery, Snowflake, or PostgreSQL for playlist history;
  • webhooks for custom catalog and campaign systems.

Dataset rows are flat for filtering while the nested before/after track objects preserve comparison detail.

Limits and expected behavior

  • Only public Spotify playlists are supported.
  • Private playlists, user libraries, listening history, account analytics, and Spotify for Artists data are outside scope.
  • The Actor does not download songs, audio files, or cover images.
  • It reports history only after the first saved snapshot.
  • Spotify may hide unavailable or non-track playlist entries from its public surface; only public track rows returned by Spotify are compared.
  • Public endpoint or schema changes can temporarily interrupt extraction.
  • A playlist can be checked only when Spotify exposes it without login.
  • Input is limited to 20 playlists per run to keep checks bounded.

Reliability and retries

Transient network errors, HTTP 429 responses, and temporary server errors are retried with bounded exponential backoff. Invalid URLs and permanent not-found responses are not retried blindly.

The Actor never silently treats a changed or blocked Spotify response as an empty playlist. If all requested playlists fail, the run exits with an error so schedules and integrations can alert you.

Troubleshooting

The second run returned zero rows

That normally means no supported changes were detected. Confirm the same monitorKey was reused and inspect the log line showing the previous snapshot.

Every track appeared as added again

The monitor key changed, resetSnapshots was enabled, or the previous named storage was deleted. Restore the original key and keep reset disabled.

Spotify says the playlist is unavailable

Open the URL in a private browser window. If login is required or the playlist is private, the Actor cannot monitor it.

A moved track generated two records

That track also changed public metadata. Move and metadata events are separate by design so integrations can subscribe to either event type.

Legality

Collect only public data you are authorized to process. Follow Spotify's terms, Apify's platform rules, and applicable copyright, privacy, and database laws. Do not use the Actor to bypass access controls or infer private listening behavior. Store and retain results only as long as your workflow requires.

Spotify is a trademark of Spotify AB. This Actor is an independent automation tool and is not affiliated with or endorsed by Spotify.

Use the search Actor to discover playlists, then pass selected public URLs to this tracker for recurring change detection.

FAQ

Does this require Spotify OAuth?

No. It uses Spotify's anonymous public web-player data surface.

Can it monitor private playlists?

No. Private playlists and account data are intentionally unsupported.

Does it fetch playlists longer than 100 tracks?

Yes. It follows Spotify's public pagination until the reported playlist track count is exhausted. The deep-workflow example fetches every current track from All Out 2010s, even as Spotify changes that playlist's size.

Can I create independent histories for the same playlist?

Yes. Use different monitorKey values. Each key gets an independent snapshot.

Can I suppress first-run rows?

Yes. Set emitInitialAdds to false; the Actor saves the baseline and emits no change rows until a later run differs.

Are unchanged tracks charged as events?

No. Only added, removed, moved, and metadata_changed dataset records use the per-change event. Every run also uses the one-time start event.