Spotify Playlist Tracker
Pricing
Pay per event
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
Maintained by CommunityActor stats
0
Bookmarked
1
Total users
1
Monthly active users
6 days ago
Last modified
Categories
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:
- resolves its public identity and owner;
- fetches all available ordered track pages;
- loads the prior snapshot for the same
monitorKeyand playlist; - compares track occurrences, positions, and public metadata;
- writes only detected changes to the default dataset; and
- 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
- Open the Actor input.
- Add one or more public Spotify playlist URLs.
- Choose a stable
monitorKey, such asweekly-editorial-monitor. - Keep
emitInitialAddsenabled for an immediate baseline export, or disable it for a silent first run. - Run the Actor and inspect Playlist changes in the dataset.
- Schedule the same input hourly, daily, or weekly.
- 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
| Field | Type | Default | Description |
|---|---|---|---|
playlistUrls | string array | required | One to 20 public open.spotify.com/playlist/... URLs or spotify:playlist:... URIs. |
monitorKey | string | default | Snapshot namespace. Reuse it to continue one monitoring history. |
emitInitialAdds | boolean | true | Emit every current track as added when no prior snapshot exists. |
resetSnapshots | boolean | false | Ignore 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.
| Field | Meaning |
|---|---|
changeType | added, removed, moved, or metadata_changed. |
playlistId, playlistUrl, playlistName | Current public playlist identity. |
ownerName | Current public owner display name, when available. |
monitorKey | Namespace used for this comparison. |
trackId, trackUri, trackUrl | Stable Spotify track identifiers. |
trackName, artists, album | Human-readable track metadata. |
previousPosition | Prior one-based position; null for additions. |
currentPosition | Current one-based position; null for removals. |
changedFields | Fields responsible for a move or metadata event. |
previousTrack | Complete prior track row; null for additions. |
currentTrack | Complete current track row; null for removals. |
previousSnapshotAt | Timestamp of the compared snapshot. |
detectedAt | Timestamp 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-watcheditorial-playlists-eucatalog-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:
| Workflow | Delivered changes | BRONZE event-charge formula |
|---|---|---|
| Daily check with no changes | 0 | $0.00110 start |
| Small update | 5 | $0.00110 + 5 × $0.00078257 |
| First baseline of 50 tracks | 50 | $0.00110 + 50 × $0.00078257 |
| Large baseline of 100 tracks | 100 | $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:
- run the Task on a schedule;
- trigger a webhook when the run succeeds;
- read dataset items;
- filter by
changeTypeor artist; - 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 osfrom apify_client import ApifyClientclient = 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.
Related Automation Lab Actors
- Spotify Playlist Search and Metadata Scraper finds public playlists by keyword and exports current playlist details.
- Spotify Songs Scraper extracts current public track, album, artist, and playlist records.
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.