Your cart is currently empty!
How to Scrape Spotify Public Data (2026): Playlists, Artists, Charts
Spotify exposes more public data than most engineers realize, and scraping it in 2026 is a two-track problem: you can use the official Web API for structured data up to its rate limits, or you can go direct to the frontend endpoints for data the API simply doesn’t surface. This guide covers both tracks for playlists, artist pages, and chart data.
What Spotify Actually Makes Public
Before writing a single line of code, know what you’re targeting. Spotify’s public surface breaks down into three tiers:
- Web API (official): artist metadata, album/track objects, playlist tracks, audio features, search. Rate-limited at ~180 requests per minute on client credentials flow.
- Open Browse endpoints: charts, genre playlists, editorial content at
open.spotify.com. No auth required, rendered server-side with embedded JSON. - Partner/Chartmetric-style data: listener counts, streaming velocity, playlist reach. Not in the public API. Requires scraping the web UI or using third-party aggregators.
Charts specifically live at open.spotify.com/charts/overview and regional URLs like /charts/country/sg/weekly/artists. These pages embed a __NEXT_DATA__ JSON blob in the HTML, the same pattern used by most Next.js apps. That blob is your extraction target.
Scraping via the Official Spotify Web API
For artist metadata and playlist tracks, the Web API is the right starting point. Get a client credentials token first (no user login needed):
import httpx
import base64
CLIENT_ID = "your_client_id"
CLIENT_SECRET = "your_client_secret"
def get_token():
creds = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()
r = httpx.post(
"https://accounts.spotify.com/api/token",
headers={"Authorization": f"Basic {creds}"},
data={"grant_type": "client_credentials"},
)
return r.json()["access_token"]
def get_playlist_tracks(playlist_id: str, token: str):
url = f"https://api.spotify.com/v1/playlists/{playlist_id}/tracks"
headers = {"Authorization": f"Bearer {token}"}
items = []
while url:
r = httpx.get(url, headers=headers, params={"limit": 100}).json()
items.extend(r["items"])
url = r.get("next")
return items
The next field handles pagination automatically. A 500-track playlist resolves in 5 requests. For audio features (tempo, danceability, valence), hit /v1/audio-features?ids=comma,separated,ids with up to 100 IDs per call.
Rate limits are per-app, not per-IP, so rotating tokens across multiple app registrations is the standard scale-out trick. Spotify does not currently block client credentials token generation by IP, but hammering a single app ID past 180 rpm triggers 429s with a Retry-After header. Honor it.
Scraping Charts and Editorial Playlists
The Web API does not expose Spotify’s own chart rankings. For that, you target the HTML directly. Regional weekly charts follow this URL pattern:
https://open.spotify.com/charts/country/{country_code}/weekly/songs
The page ships with a tag containing the full chart payload. A basic extraction looks like:
from bs4 import BeautifulSoup
import json, httpx
def get_chart(country="sg", period="weekly", chart_type="songs"):
url = f"https://open.spotify.com/charts/country/{country}/{period}/{chart_type}"
html = httpx.get(url, headers={"User-Agent": "Mozilla/5.0"}).text
soup = BeautifulSoup(html, "html.parser")
blob = soup.find("script", {"id": "__NEXT_DATA__"})
data = json.loads(blob.string)
return data["props"]["pageProps"]["chartData"]["entries"]
This works cleanly as of Q1 2026. Spotify occasionally restructures the pageProps nesting, so wrap this in a try/except and log the raw keys when it breaks. The chart payload includes rank, track URI, stream count, and delta from the previous period.
For scraping patterns similar to this across other music platforms, How to Scrape Apple Music Charts and Playlists (2026) covers the equivalent Next.js blob extraction for Apple's storefronts.
Handling Anti-Bot and Rate Limiting
Spotify's frontend is more protective than its API. Open pages use Cloudflare and return 403 or CAPTCHA pages if you don't manage headers and request cadence carefully.
Key headers to set:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Accept-Language: en-US,en;q=0.9
Accept-Encoding: gzip, deflate, br
Referer: https://open.spotify.com/
Beyond headers, a comparison of rotation strategies at scale:
| Approach | Cost | Reliability | Best for |
|---|---|---|---|
| Residential proxies (rotating) | High | High | Chart scraping at volume |
| Datacenter proxies | Low | Medium | API token rotation only |
| Mobile proxies (SG/US) | Very high | Very high | Account-auth scraping |
| Direct (no proxy) | Free | Low | Dev/testing only |
For chart data specifically, residential rotation with a 2-5 second delay between requests keeps block rates near zero. The same proxy discipline applies when you're pulling How to Scrape SoundCloud Artist + Track Data (2026) or any audio platform that runs Cloudflare at the edge.
For scraping at scale with rotating IPs, the same infrastructure considerations covered in How to Scrape ZoomInfo Without Account: Public Data Strategies (2026) apply here, particularly the section on request fingerprinting and TLS ja3 matching.
Extracting Artist Listener and Popularity Data
Monthly listener counts appear on artist pages (open.spotify.com/artist/{id}) but are absent from the Web API. The artist page also ships __NEXT_DATA__, and the listener count is typically nested under props.pageProps.artist.stats.monthlyListeners.
A few important caveats:
- Monthly listener counts update roughly every 24-48 hours, not in real time.
- The
popularityfield in the Web API (0-100 score) is a derived metric Spotify recalculates weekly. It correlates loosely with streams but is not a raw stream count. - Playlist follower counts are available via
/v1/playlists/{id}but are often stale by days for large editorial playlists. - Genre tags on artist objects are assigned by Spotify's algorithm and lag behind real-world genre shifts by weeks to months. For richer taxonomy, How to Scrape Last.fm Listening Data and Artist Metadata (2026) gives better genre signal via community tagging.
- Spotify's
related_artistsendpoint (/v1/artists/{id}/related-artists) returns up to 20 algorithmically similar artists, useful for building genre graphs.
For independent label and artist discovery where Spotify data is thin, How to Scrape Bandcamp Artist Pages and Sales Data (2026) fills the gap with actual fan purchase data, which is more reliable for niche genre breakdowns.
Storage and Pipeline Considerations
Spotify IDs are stable URIs (e.g., spotify:artist:06HL4z0CvFAxyc27GXpf02). Use them as primary keys. Track ISRCs are also returned by the API and are useful for deduplication across platforms.
A lightweight collection pipeline looks like:
- Fetch chart snapshots daily, store raw JSON alongside parsed rows
- Upsert artist stats by Spotify URI, timestamp each row
- Store playlist snapshots as versioned records (don't overwrite, append with
scraped_at) - Join on ISRC to cross-reference with Last.fm, Apple Music, or Billboard data
Postgres with a JSONB column for the raw blob and a few extracted columns (id, type, scraped_at, country) handles this well up to mid-millions of rows before you need partitioning.
Bottom line
For most use cases, start with the official Web API for structured track and artist data, then layer in __NEXT_DATA__ extraction for charts and listener counts the API doesn't expose. Use residential proxies for frontend scraping, honor 429 headers, and version your snapshots rather than overwriting them. DRT covers the full stack of music and media platform scraping as part of its ongoing data-collection infrastructure series.
Related guides on dataresearchtools.com
- How to Scrape Apple Music Charts and Playlists (2026)
- How to Scrape SoundCloud Artist + Track Data (2026)
- How to Scrape Bandcamp Artist Pages and Sales Data (2026)
- How to Scrape Last.fm Listening Data and Artist Metadata (2026)
- Pillar: How to Scrape ZoomInfo Without Account: Public Data Strategies (2026)
Leave a Reply