Spotify Scraper: Playlists, Albums, Artists & Tracks Metadata
Pricing
from $0.50 / 1,000 track or releases
Spotify Scraper: Playlists, Albums, Artists & Tracks Metadata
Scrape Spotify metadata by link: every track of a playlist or an album, an artist's top tracks and releases, single tracks. Track id, name, artists, album, release date, duration, explicit, track number, play count, preview and cover URLs; playlist owner and followers. No login. Misses free.
Pricing
from $0.50 / 1,000 track or releases
Rating
0.0
(0)
Developer
Hyperbach
Maintained by CommunityActor stats
0
Bookmarked
5
Total users
2
Monthly active users
4 days ago
Last modified
Categories
Features
Share
Spotify metadata by link, logged out: every track of a playlist or an album, an artist's top tracks and releases, and single tracks — the track id and URL, name, artists, album, release date, duration, the explicit flag, disc and track number, the play count, the 30-second preview URL and the cover URL, with the playlist's name, owner and followers on a playlist's tracks — several links in one run, a max per link. One free list row per link carries a completeness verdict: COMPLETE (every item of Spotify's count), CAPPED (your limit) or PARTIAL. No login, no API key, no browser, proxies handled for you. Never the audio.
$1.00 per 1,000 result rows on the Free plan, $0.85 on Starter. A run start is $0.001. The default input returns about 31 rows for about $0.032. A value that names nothing is a free row that says why.

Why this Spotify scraper
- Playlists, albums, artists and tracks in one run. Paste open.spotify.com links (with
/intl-xx/,/embed/or?si=, as you copy them) orspotify:URIs, one a line. A playlist gives its tracks, an album its tracks, an artist its top tracks and its releases, a track its own row. Each link gets its own cap (maxItemsPerUrl), and the run's cap sits on top (maxItems). - The play count on every track. Spotify's all-time stream count comes with each track of a playlist, an album or an artist, beside the album, the release date, the duration, the explicit flag and the disc and track number.
- Whole playlists, checked. A playlist is read page after page in Spotify's own order until every item of Spotify's count is read: the free
listrow says COMPLETE with the count (a 421-track playlist in one page, measured 2026-10-23). A track the playlist lists twice is delivered once; podcast episodes are counted and skipped. - Playlist context on every track. A playlist's tracks carry the playlist's name, owner and follower count and the date each track was added; an artist's list row carries its followers, monthly listeners and world rank.
- Honest runs. An id Spotify does not know is a free
not_foundrow, checked twice; a link that is not Spotify a freeinvalidrow. Every link gets a row.
Who it's for
- Music marketers and labels — the tracks of the playlists that matter to an artist, with each track's play count and the playlist's followers, read again every week.
- Playlist curators and researchers — whole playlists with the date each track was added, the owner and the follower count, to follow what a playlist adds and drops.
- Music data apps — an artist's releases and top tracks, or an album's tracks, with release dates, durations, track numbers, covers and preview URLs.
Quick start
The four kinds of link, 10 rows each
{"startUrls": ["https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b","https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj","https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02","https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"],"maxItemsPerUrl": 10}
Every track of a playlist
{"startUrls": ["https://open.spotify.com/playlist/37i9dQZF1DX4UtSsGT1Sbe"],"maxItemsPerUrl": 0}
An artist's whole discography (releases only)
{"startUrls": ["https://open.spotify.com/artist/1Xyo4u8uXC1ZmMpatF05PJ"],"artistRows": "releases","maxItemsPerUrl": 0}
Output
One row per track or release (and one free list row per link):
| field | meaning |
|---|---|
row_type | track (one track, charged), album (one release of an artist, charged) or list (the link's row with the walk's verdict; free). |
input_index | The 1-based position of the link this row answers in startUrls. |
input_value | The link as you gave it. |
input_type | What the link is: playlist, album, artist or track (empty for a value that is not a Spotify link). |
input_id | The link's Spotify id (22 letters and digits). |
input_url | The link on open.spotify.com, as a URL you can open. |
status | A list row: ok, not_found, invalid, duplicate, failed or not_read (see the FAQ). A track or album row: ok. |
status_detail | Why a list row is not ok, in a sentence. |
scraped_at | When the row was read (UTC). |
position | The row's place in the link's own list: the playlist's order, the album's order, the top-tracks rank (1-10), the releases' order (newest first); 1 for a track link. |
track_id | The track's Spotify id. |
track_url | The track on open.spotify.com. |
track_uri | The track's Spotify URI (spotify:track:<id>). |
name | The track's name; on an album row the release's name; on a list row the playlist's, album's, artist's or track's name. |
artists | The track's artists, in Spotify's order; on an album row the artist of the link. |
artist_ids | The Spotify ids of artists, in the same order. |
album_id | The Spotify id of the track's album (or of the release, on an album row). |
album_url | The album on open.spotify.com. |
album_name | The album's name. |
album_type | album, single, ep or compilation, when the answer names it (an album's tracks, an artist's top tracks and releases, a track link). |
label | The record label, on an album's tracks and on an album link's list row. |
release_date | The album's release date: YYYY-MM-DD, or YYYY-MM / YYYY when Spotify knows only the month or the year. |
duration_ms | The track's length in milliseconds. |
explicit | True when Spotify marks the track explicit. |
disc_number | The disc the track is on (1 for most albums; empty on a track link). |
track_number | The track's number on its disc. |
play_count | Spotify's play count of the track (all-time streams; Spotify shows 0 until a track passes 1,000). |
preview_url | The 30-second preview's URL from the link's embed player: every track of an album, an artist's top tracks, a track link, and the first 100 tracks of a playlist (later tracks have none). Never the audio file itself. |
cover_url | The album cover (the largest size, 640 px); on a list row the playlist's, album's or artist's image. |
playable | False when Spotify marks the track or release not playable for the reader's country. |
added_at | A playlist's track: when it was added to the playlist (UTC). |
total_tracks | An album row: the release's number of tracks; an album link's list row: the album's. |
playlist_id | A playlist's track: the playlist's id. |
playlist_name | A playlist's track: the playlist's name. |
playlist_owner | A playlist's track: the owner's display name (Spotify for Spotify's own playlists). |
playlist_owner_id | A playlist's track: the owner's Spotify user id. |
playlist_followers | A playlist's track: the playlist's followers. |
owner | A playlist's list row: the owner's display name. |
owner_id | A playlist's list row: the owner's Spotify user id. |
followers | A list row: the playlist's or the artist's followers. |
monthly_listeners | An artist's list row: Spotify's monthly listeners. |
world_rank | An artist's list row: Spotify's world rank, when the artist has one. |
items_count | A list row: Spotify's own count of the link's list (a playlist's items, an album's tracks, an artist's top tracks and releases). |
items_delivered | A list row: the track and release rows delivered for the link. |
pages_read | A list row: the pages of the list read. |
repeats_skipped | A list row: tracks skipped because the same list already listed them (a playlist can hold a track twice). |
other_items_skipped | A list row: items that are not tracks (podcast episodes, local files, items Spotify no longer serves): counted, not delivered. |
verdict | A list row: COMPLETE (every item of Spotify's count, or Spotify's own end of the list), CAPPED (your limit) or PARTIAL (a refusal, an empty page below the count, or the time limit stopped it). |
verdict_detail | A list row: the verdict in a sentence, with the counts. |
Example record:
{"row_type": "track","input_index": 2,"input_value": "https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj","input_type": "album","input_id": "4yP0hdKOZPNshxUOjY0cZj","input_url": "https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj","status": "ok","status_detail": null,"scraped_at": "2026-10-23T06:39:05Z","position": 1,"track_id": "6b5P51m8xx2XA6U7sdNZ5E","track_url": "https://open.spotify.com/track/6b5P51m8xx2XA6U7sdNZ5E","track_uri": "spotify:track:6b5P51m8xx2XA6U7sdNZ5E","name": "Alone Again","artists": ["The Weeknd"],"artist_ids": ["1Xyo4u8uXC1ZmMpatF05PJ"],"album_id": "4yP0hdKOZPNshxUOjY0cZj","album_url": "https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj","album_name": "After Hours","album_type": "album","label": "Republic Records","release_date": "2020-03-20","duration_ms": 250053,"explicit": true,"disc_number": 1,"track_number": 1,"play_count": 233244354,"preview_url": "https://p.scdn.co/mp3-preview/77e54c6064335e259d0f571768af5f96c22304d4","cover_url": "https://i.scdn.co/image/ab67616d0000b2738863bc11d2aa12b54f5aeb36","playable": true,"added_at": null,"total_tracks": null,"playlist_id": null,"playlist_name": null,"playlist_owner": null,"playlist_owner_id": null,"playlist_followers": null,"owner": null,"owner_id": null,"followers": null,"monthly_listeners": null,"world_rank": null,"items_count": null,"items_delivered": null,"pages_read": null,"repeats_skipped": null,"other_items_skipped": null,"verdict": null,"verdict_detail": null}
Pricing
Pay for the tracks and releases a run delivers, plus one run start; no platform usage is billed to you. The row price falls with your Apify plan.
| event | unit | Free | Starter | Scale | Business |
|---|---|---|---|---|---|
Track or release (result) | per 1,000 | $1.00 | $0.85 | $0.70 | $0.50 |
Run start (start) | per run | $0.001 | $0.001 | $0.001 | $0.001 |
A track or release row is $1.00 per 1,000 on the Free plan ($0.001 a row). Each run that delivers a charged row also pays the run start, $0.001 once; a run that delivers no charged row pays nothing at all. So one playlist of 100 tracks costs $0.101 on the Free plan, and several links in one run share one start. The free list row of every link, a value that is not a Spotify link (invalid), an id Spotify does not know (not_found), a repeated link (duplicate), a link left at the cap or the time limit (not_read) and a refusal the run could not pass (failed) are never charged. A run that stops early (a timeout, an abort) is charged for the rows it delivered. maxItems counts the charged rows; before the first request the log names the price of each row at your plan and the most the run can cost. Enterprise plans have their own rates: the Actor's Pricing tab shows the price for your plan.
Usage patterns
- Links —
startUrlstakes open.spotify.com links of playlists (/playlist/<id>), albums (/album/<id>), artists (/artist/<id>) and tracks (/track/<id>), with or without/intl-xx/,/embed/and?si=, andspotify:<kind>:<id>URIs. Podcasts, users and short spotify.link links are not read (a freeinvalidrow says so). - What a row is —
row_type=track: one track, in the link's own order (position).row_type=album: one release of an artist (albums, singles, EPs and compilations, newest first).row_type=list: the free row of one link — its name, owner or followers,items_count(Spotify's own count),items_delivered,pages_read,repeats_skipped,other_items_skipped, theverdictwith itsverdict_detail, and thestatuswith its reason. - How far a link goes —
maxItemsPerUrl(default 100; 0 = every track or release the link serves) stops each playlist, album or artist after that many rows. A playlist or an album is read to Spotify's count; an artist gives its top tracks (Spotify lists up to 10) and then its releases, asartistRowschooses.maxItemscaps the charged rows of the whole run.
Input configuration
| field | type | default | what it does |
|---|---|---|---|
startUrls | array | Spotify links to read, one a line: a playlist (https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M: its tracks), an album (its tracks), an artist (its top tracks and its releases) or a track (its own row). Links with /intl-xx/, /embed/ or ?si= and spotify:track:<id> URIs work too. A link that is not a Spotify playlist, album, artist or track (a podcast, a user, a short spotify.link) gets a free invalid row; a link given twice a free duplicate row. | |
maxItemsPerUrl | integer | 100 | Stop each playlist, album or artist after this many rows (tracks, or an artist's top tracks and releases together). 0 = every track or release the link serves. A track link is one row. |
artistRows | both / top_tracks / releases | "both" | What an artist link gives: its top tracks (up to 10, Spotify's own list) and then its releases (albums, singles, EPs and compilations, newest first), the top tracks only, or the releases only. |
maxItems | integer | 0 | Stop the whole run after this many track and release rows (the charged rows). 0 = no run cap; each link still stops at its own limit above. |
feedback | string | A note to the people who maintain this Actor: what you needed and did not get. For example a missing field, a wrong or empty result, or the Actor you switch from or to, and why. The run does not read it: the rows and the charges stay the same. A person reads every note. |
Errors
A run does not fail because of your input. When an input cannot be used — a date that is not a date, an id in the wrong form, two settings that contradict each other — the run ends Succeeded, charges nothing, and says what to change:
- the status message starts with
INPUT REJECTED; - the dataset holds one row,
{"error": true, "code": "…", "message": "…"}, and no results; - the key-value store record
ERRORholds the same object.
From code, check error on the first row before reading results.
A value that is not a Spotify playlist, album, artist or track link (a podcast, a user page, a short spotify.link link) is not an error: it gets one free list row with status invalid that says why, and the run goes on with the others. A run that ends Failed is a fault on our side, never your input; it charges nothing, and we are alerted.
FAQ
Which status is which?
A list row's status is ok (rows served), not_found (Spotify has no playlist, album, artist or track with that id; checked on two connections), invalid (an empty value, or a value that is not a Spotify playlist, album, artist or track link), duplicate (the same link again in the input: read once), failed (Spotify refused every try; free) or not_read (left at maxItems, the charge limit or the run's time limit). A track or album row's status is ok.
Does it give the popularity score or the ISRC?
No. Spotify serves the popularity score and the ISRC through its developer Web API, which refuses a logged-out reader (measured 2026-10-23); the web player serves the play count (all-time streams) instead, and that is on every track row.
Does every track have a preview URL?
Every track of an album, an artist's top tracks and a track link have one when Spotify offers a preview. A playlist's embed player lists its first 100 tracks, so later tracks of a long playlist have no preview URL. The actor never downloads the audio.
Does it need a Spotify account or API key?
No. Everything is read from Spotify's public pages and its web player, logged out.
Integration
JavaScript
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: 'YOUR_TOKEN' });const run = await client.actor('hyperbach/spotify-scraper').call({"startUrls": ["https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b", "https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj", "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02", "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"], "maxItemsPerUrl": 10});const { items } = await client.dataset(run.defaultDatasetId).listItems();
Python
from apify_client import ApifyClientclient = ApifyClient('YOUR_TOKEN')run = client.actor('hyperbach/spotify-scraper').call(run_input={'startUrls': ['https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b', 'https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj', 'https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02', 'https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M'], 'maxItemsPerUrl': 10})items = client.dataset(run['defaultDatasetId']).list_items().items
CLI
$apify call hyperbach/spotify-scraper --input '{"startUrls": ["https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b", "https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj", "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02", "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"], "maxItemsPerUrl": 10}'
REST
curl -X POST "https://api.apify.com/v2/acts/hyperbach~spotify-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \-H 'Content-Type: application/json' -d '{"startUrls": ["https://open.spotify.com/track/0VjIjW4GlUZAMYd2vXMi3b", "https://open.spotify.com/album/4yP0hdKOZPNshxUOjY0cZj", "https://open.spotify.com/artist/06HL4z0CvFAxyc27GXpf02", "https://open.spotify.com/playlist/37i9dQZF1DXcBWIGoYBM5M"], "maxItemsPerUrl": 10}'
AI agents and MCP
Apify's MCP server offers this Actor as a tool to Claude, Cursor, VS Code and any other MCP client. Connect https://mcp.apify.com?tools=hyperbach/spotify-scraper and ask, for example: "Get the tracks of the Spotify playlist 37i9dQZF1DXcBWIGoYBM5M with their metadata". The agent fills the input from the table above and reads the rows from the run's dataset. The input names are the ones in the table above. An agent or a person can add feedback to any run and say what was needed and not delivered: a missing field, a wrong or empty result, the Actor switched from or to, and why. The run returns the same rows at the same price, and a person reads every note.
n8n, Make and Zapier
The Apify node in n8n, the Apify app in Make and the Apify integration in Zapier run this Actor on a schedule or from a trigger and read its dataset. A webhook on the run's end (Integrations on the Actor page) sends the rows on to your own endpoint. Nothing to install on our side.
Support
Disagree with a charge? Write to apify@hyperbach.com with the run ID. We will ask Apify to compensate you, and the charge comes back to your Apify account as platform credit.
Did it do the job? A short review on the Store, at any rating, helps the next buyer choose.
See also
- Telegram Profile Scraper — Telegram channels, groups, bots and users by username or link, with the exact subscriber or member count.
- YouTube Channel Search Scraper — the YouTube channels a keyword finds, with subscribers, the exact video and view counts and the country.
- Threads Scraper — Threads profiles with the exact follower count, their posts and replies with view counts, and keyword and tag search, without a login.
- Substack Scraper — the posts of a Substack newsletter with the full text of free posts, the date, the paywall flag and the likes.
- Weibo Scraper — Weibo posts, profiles, search, comments and the hot-search boards, without a login.
- Pinterest Search Scraper — the pins of a Pinterest search, with the link each pin points to, the image and the pinner.
This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.