Migration from v2¶
SpotifyScraper v3 is a ground-up rewrite. The public surface is smaller,
fully typed, and immutable: every fetch returns a frozen dataclass instead of a
plain dict, errors are always exceptions (never error dicts), and there is one
get_* method per entity type. This guide maps every v2.1.5 method to its v3
replacement.
TL;DR
client.get_<entity>_info(url)→client.get_<entity>(value)returning a typed model.- The single argument now accepts a URL, URI, or bare ID interchangeably.
- The CLI is available via the
cliextra; cookie-authenticated lyrics shipped in v3.2 (get_lyrics). - You read fields off the model (
track.name) instead of dict keys (info["title"]).
The new client¶
# v2
from spotify_scraper import SpotifyClient
client = SpotifyClient(cookie_file="cookies.txt")
info = client.get_track_info("https://open.spotify.com/track/4uLU6hMCjMI75M1A2tKUQC")
print(info["name"])
client.close()
# v3
from spotify_scraper import SpotifyClient
with SpotifyClient() as client:
track = client.get_track("4uLU6hMCjMI75M1A2tKUQC")
print(track.name)
The v3 client is a context manager, returns typed models, and accepts a URL,
URI, or bare 22-character ID for any get_* method.
Method map¶
Every public method of v2.1.5's SpotifyClient and its v3 replacement:
| v2.1.5 method | v3 replacement | Notes |
|---|---|---|
get_track_info(url) |
get_track(value) → Track |
Returns a typed Track instead of a dict. Read track.name, track.artists, track.duration_ms, etc. |
get_track_lyrics(url) |
get_lyrics(value) → Lyrics |
Cookie-authenticated; build the client with cookies=. See Lyrics. |
get_track_info_with_lyrics(url) |
get_track(value) + get_lyrics(value) |
Fetch the track and its lyrics in two calls; the lyrics call needs cookies. |
get_album_info(url) |
get_album(value) → Album |
Returns an Album whose full track list is paginated in for you. |
get_artist_info(url) |
get_artist(value) → Artist |
Returns an Artist with top tracks, albums, and singles. |
get_playlist_info(url) |
get_playlist(value, max_tracks=100) → Playlist |
Returns a Playlist. Bound the track count with max_tracks (None = all). |
get_episode_info(url) |
get_episode(value) → Episode |
Returns an Episode. |
get_show_info(url) |
get_show(value, max_episodes=50) → Show |
Returns a Show. Bound the episode count with max_episodes (None = all). |
get_all_info(url) |
Removed | There is no single "fetch everything" call. Detect the entity yourself and call the matching get_*, or fetch the entities you actually need. This keeps each request explicit and avoids hidden over-fetching. |
download_cover(...) |
download_cover(entity, dest=".", *, size="largest", filename=None) |
Now takes a fetched model (any entity with images), not a URL. Returns the written Path. |
download_episode_preview(...) |
download_preview(entity, dest=".", ...) |
Merged into one download_preview that accepts a Track or Episode. |
download_preview_mp3(...) |
download_preview(entity, dest=".", *, filename=None, embed_cover=False) |
Same merged method. Pass embed_cover=True (needs the media extra) to tag the MP3. |
close() |
close() (or with) |
Unchanged in spirit; prefer the context manager. The async client uses aclose(). |
Reading data: models, not dicts¶
v2 returned dicts with string keys; v3 returns frozen, typed dataclasses. The fields are attributes, and naming is normalized.
# v2
info = client.get_track_info(url)
title = info["title"]
artist = info["artists"][0]["name"]
# v3
track = client.get_track(value)
title = track.name
artist = track.artists[0].name
Need a dict back (for JSON, a database, etc.)? Every model has a JSON-safe
to_dict():
data = track.to_dict() # nested models -> dicts, datetimes -> ISO-8601
See the Entities guide for the full field reference of each model.
Exceptions: failures are always raised¶
v2 sometimes returned an error inside the result (e.g. an ERROR key) or raised
inconsistently. v3 always raises; nothing is signaled by a return value.
Every exception derives from SpotifyScraperError:
from spotify_scraper import SpotifyClient, NotFoundError, SpotifyScraperError
with SpotifyClient() as client:
try:
track = client.get_track(value)
except NotFoundError:
... # 404 — the entity does not exist
except SpotifyScraperError as exc:
... # any other library failure
The full tree (URLError, NetworkError → RateLimitedError, TokenError,
AuthenticationError, NotFoundError, ParsingError, MediaError) and catch
patterns are in the Error handling guide.
Cookies¶
v3 accepts cookies via the cookies= constructor argument (a path, a string, or
a mapping), and stores them for authenticated features:
client = SpotifyClient(cookies="cookies.txt")
Public-metadata fetches always work anonymously, with no credentials. Cookies are load-bearing only for cookie-authenticated lyrics (v3.2+).
Lyrics¶
As of v3.2, get_lyrics(value) returns a populated Lyrics
model from Spotify's color-lyrics endpoint, using a web-player token derived
from your sp_dc cookie:
with SpotifyClient(cookies="cookies.txt") as client:
lyrics = client.get_lyrics("4uLU6hMCjMI75M1A2tKUQC")
for line in lyrics.lines:
print(line.start_ms, line.text)
See the Lyrics & cookies guide for how to obtain
an sp_dc cookie and the security implications.
Command-line interface¶
A spotifyscraper command is now available via the cli extra:
pip install "spotifyscraper[cli]"
spotifyscraper track 4uLU6hMCjMI75M1A2tKUQC --pretty
It prints any entity as JSON and downloads cover art or previews. See the CLI guide for every command and its options.
Python version floor¶
v2 supported Python 3.6+. v3 requires Python 3.10 or newer (3.10, 3.11, 3.12, 3.13) to use modern typing and immutable dataclasses. If you are on an older interpreter, upgrade before moving to v3, or stay on v2.x.
Dependencies¶
v2 pulled in requests, beautifulsoup4, pyyaml, eyeD3, and optionally
Selenium. v3's core depends only on httpx.
Tagging (mutagen) and the browser fallback (playwright) are opt-in extras —
see Installation.
Where to next¶
- Quickstart — the v3 API in five minutes.
- Entities — every field on every model.
- Error handling — the exception tree.
- Changelog — the full v3.0 change list.