Spotify Scraper: Playlists, Albums, Artists & Tracks Metadata avatar

Spotify Scraper: Playlists, Albums, Artists & Tracks Metadata

Pricing

from $0.50 / 1,000 track or releases

Go to Apify Store
Spotify Scraper: Playlists, Albums, Artists & Tracks Metadata

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.

Pricing

from $0.50 / 1,000 track or releases

Rating

0.0

(0)

Developer

Hyperbach

Hyperbach

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

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.

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) or spotify: 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 list row 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_found row, checked twice; a link that is not Spotify a free invalid row. 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):

fieldmeaning
row_typetrack (one track, charged), album (one release of an artist, charged) or list (the link's row with the walk's verdict; free).
input_indexThe 1-based position of the link this row answers in startUrls.
input_valueThe link as you gave it.
input_typeWhat the link is: playlist, album, artist or track (empty for a value that is not a Spotify link).
input_idThe link's Spotify id (22 letters and digits).
input_urlThe link on open.spotify.com, as a URL you can open.
statusA list row: ok, not_found, invalid, duplicate, failed or not_read (see the FAQ). A track or album row: ok.
status_detailWhy a list row is not ok, in a sentence.
scraped_atWhen the row was read (UTC).
positionThe 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_idThe track's Spotify id.
track_urlThe track on open.spotify.com.
track_uriThe track's Spotify URI (spotify:track:<id>).
nameThe 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.
artistsThe track's artists, in Spotify's order; on an album row the artist of the link.
artist_idsThe Spotify ids of artists, in the same order.
album_idThe Spotify id of the track's album (or of the release, on an album row).
album_urlThe album on open.spotify.com.
album_nameThe album's name.
album_typealbum, single, ep or compilation, when the answer names it (an album's tracks, an artist's top tracks and releases, a track link).
labelThe record label, on an album's tracks and on an album link's list row.
release_dateThe album's release date: YYYY-MM-DD, or YYYY-MM / YYYY when Spotify knows only the month or the year.
duration_msThe track's length in milliseconds.
explicitTrue when Spotify marks the track explicit.
disc_numberThe disc the track is on (1 for most albums; empty on a track link).
track_numberThe track's number on its disc.
play_countSpotify's play count of the track (all-time streams; Spotify shows 0 until a track passes 1,000).
preview_urlThe 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_urlThe album cover (the largest size, 640 px); on a list row the playlist's, album's or artist's image.
playableFalse when Spotify marks the track or release not playable for the reader's country.
added_atA playlist's track: when it was added to the playlist (UTC).
total_tracksAn album row: the release's number of tracks; an album link's list row: the album's.
playlist_idA playlist's track: the playlist's id.
playlist_nameA playlist's track: the playlist's name.
playlist_ownerA playlist's track: the owner's display name (Spotify for Spotify's own playlists).
playlist_owner_idA playlist's track: the owner's Spotify user id.
playlist_followersA playlist's track: the playlist's followers.
ownerA playlist's list row: the owner's display name.
owner_idA playlist's list row: the owner's Spotify user id.
followersA list row: the playlist's or the artist's followers.
monthly_listenersAn artist's list row: Spotify's monthly listeners.
world_rankAn artist's list row: Spotify's world rank, when the artist has one.
items_countA 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_deliveredA list row: the track and release rows delivered for the link.
pages_readA list row: the pages of the list read.
repeats_skippedA list row: tracks skipped because the same list already listed them (a playlist can hold a track twice).
other_items_skippedA list row: items that are not tracks (podcast episodes, local files, items Spotify no longer serves): counted, not delivered.
verdictA 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_detailA 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.

eventunitFreeStarterScaleBusiness
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 — startUrls takes 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=, and spotify:<kind>:<id> URIs. Podcasts, users and short spotify.link links are not read (a free invalid row 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, the verdict with its verdict_detail, and the status with 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, as artistRows chooses. maxItems caps the charged rows of the whole run.

Input configuration

fieldtypedefaultwhat it does
startUrlsarraySpotify 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.
maxItemsPerUrlinteger100Stop 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.
artistRowsboth / 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.
maxItemsinteger0Stop 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.

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 ERROR holds 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 ApifyClient
client = 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}'

Support

apify@hyperbach.com

This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.