Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

alt text

SpotAPI v2

The fully async Python client for Spotify's public & private API. No API key. No Premium. No rate-limit babysitting.

PyPI Python Async Typed License Stars

⚠️ This is the async-v2 beta branch. It is under active development and the API may change before the stable spotapi.v2.0.0 release. For the stable v1 library see main.


What's new in v2

v1 v2
I/O model Synchronous Fully async (asyncio)
Pagination for page in gen: async for page in gen:
Type safety Partial Full — py.typed, typed data wrappers
HTTP tls-client wreq with connection pooling & retry
Auth CAPTCHA solver required TOTP-based (no solver needed)
Session Manual refresh Auto-refresh background task
Codebase Flat structure Layered: connection/, datastruct/, specialized/

Installation

# Latest beta
pip install "spotapi==2.0.0b1"

# Or directly from this branch
pip install "git+https://github.com/Aran404/SpotAPI@async-v2"

Quick start

Unauthenticated — public search

import asyncio
import spotapi

async def main() -> None:
    async for page in spotapi.v2.Public.search_tracks("Radiohead"):
        for track in page:
            duration_s = track.duration.total_milliseconds // 1000
            print(f"{track.name}  ({duration_s}s)  —  {track.uri}")

asyncio.run(main())

Search artists with pagination control

import asyncio
import spotapi

async def main() -> None:
    # Yields one page (up to 100 results) at a time
    async for page in spotapi.v2.Public.search_artists("Tame Impala"):
        for artist in page:
            verified = artist.on_platform_reputation_trait.verification.is_verified
            print(f"{artist.profile.name}  verified={verified}")

asyncio.run(main())

Search albums

import asyncio
import spotapi

async def main() -> None:
    async for page in spotapi.v2.Public.search_albums("OK Computer"):
        for album in page:
            artists = ", ".join(a.profile.name for a in album.artists.items)
            print(f"{album.name} ({album.date.year}) — {artists}")

asyncio.run(main())

Search podcasts

import asyncio
import spotapi

async def main() -> None:
    async for page in spotapi.v2.Public.search_podcasts("Lex Fridman"):
        for podcast in page:
            print(f"{podcast.name} by {podcast.publisher.name}")

asyncio.run(main())

Architecture overview

v2/
├── base.py                  # BaseClient — pathfinder query + pagination
├── client.py                # AsyncClient — thin HTTP facade + context manager
├── session.py               # BundleSession + AuthSession — tokens, TOTP, auto-refresh
├── public.py                # Public — typed search generators
│
├── connection/
│   ├── http.py              # HTTPClient — wreq wrapper, retry + backoff, browser emulation
│   ├── websocket.py         # WebSocketClient — heartbeat, event dispatch
│   └── types.py             # ResponseSuccess / ResponseFailure, backoff types
│
├── datastruct/
│   ├── object_dict.py       # ObjectDict — attribute-access dict for raw JSON
│   ├── pool.py              # Pool[T] — generic async object pool
│   └── event_handler.py     # EventDispatcher — async event system
│
├── specialized/
│   ├── totp.py              # TOTP generation — no CAPTCHA solver required
│   └── data_wrappers/
│       ├── _common.py       # Shared color/visual dataclasses
│       ├── track.py         # Track
│       ├── artist.py        # Artist
│       ├── album.py         # Album
│       ├── playlist.py      # Playlist
│       └── podcast.py       # Podcast
│
├── types/
│   ├── logger.py            # LoggerProtocol + 5 concrete loggers
│   └── exceptions.py        # HTTPError, WebsocketError, BaseClientError
│
└── utils/
    ├── cache.py             # timed_cache — TTL-based async/sync cache decorator
    ├── random.py            # Weighted random selection
    └── strings.py           # JS bundle parsing, hash extraction

Logging

v2 ships five ready-to-use loggers. All implement LoggerProtocol so you can drop in your own.

from spotapi.v2.types import LoggerColour, JsonLogger, NoopLogger, MultiLogger, Level

# Pretty coloured output to stderr (default)
logger = LoggerColour(min_level=Level.INFO)

# Structured JSON — good for log aggregation pipelines
json_logger = JsonLogger(min_level=Level.WARNING)

# Fan-out to multiple loggers at once
combined = MultiLogger(logger, json_logger)

# Silence everything
noop = NoopLogger()

# Bind extra context fields that appear on every subsequent record
scoped = logger.bind(request_id="abc123")
scoped.info("Token refreshed", token_version=2)

Connection pool & browser emulation

Every HTTPClient automatically selects a randomised browser profile (Chrome, Edge, Firefox, Opera) weighted towards modern versions, and a randomised OS (Windows 30×, macOS 6×, Linux 2×). A shared ClientPool reuses connections across requests.

from spotapi.v2.connection import HTTPClient, ClientPool

# Get a pooled client (shared across BaseClient instances)
http = await ClientPool.get()

# Or create a dedicated client with a proxy
async with HTTPClient(proxies=[wreq.Proxy.http("http://user:pass@host:port")]) as http:
    response = await http.get("https://open.spotify.com/")

Migration from v1

For a full side-by-side comparison of the v1 and v2 APIs, see MIGRATION.md.

# v1
from spotapi import Song
song = Song()
for batch in song.paginate_songs("weezer"):
    for item in batch:
        print(item["item"]["data"]["name"])

# v2
import spotapi
async for page in spotapi.v2.Public.search_tracks("weezer"):
    for track in page:
        print(track.name)

Contributing

All contributions are welcome. The async rewrite is still in progress and there are plenty of well-scoped tasks available — see CONTRIBUTING.md for the full guide and the open good first issues.

git clone https://github.com/Aran404/SpotAPI
cd SpotAPI
git checkout async-v2
pip install -e ".[dev]"

Legal notice

Disclaimer: This repository is provided for educational purposes only. The author accepts no responsibility for misuse. Accessing private Spotify endpoints may violate Spotify's Terms of Service. Use responsibly. See LEGAL_NOTICE.md for full details.


License

GPL-3.0 © Aran404

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

spotapi-2.0.0b2.tar.gz (224.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

spotapi-2.0.0b2-py3-none-any.whl (29.2 kB view details)

Uploaded Python 3

File details

Details for the file spotapi-2.0.0b2.tar.gz.

File metadata

  • Download URL: spotapi-2.0.0b2.tar.gz
  • Upload date:
  • Size: 224.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.0

File hashes

Hashes for spotapi-2.0.0b2.tar.gz
Algorithm Hash digest
SHA256 72dd54221be8fad8c2ebe09ee59b5ae0a60c30f1ae86204ca83d3f5044dd5296
MD5 646d27dc307980fbcee4c1b60f37d1d9
BLAKE2b-256 713afb40a89e4a7e385819dba3e558f8c6e9fc783bbb5293be9038c233dca07b

See more details on using hashes here.

File details

Details for the file spotapi-2.0.0b2-py3-none-any.whl.

File metadata

  • Download URL: spotapi-2.0.0b2-py3-none-any.whl
  • Upload date:
  • Size: 29.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.0

File hashes

Hashes for spotapi-2.0.0b2-py3-none-any.whl
Algorithm Hash digest
SHA256 43731144b02d7fae67a92678ee70e8d9313ea168efbe1a73ea771ab381de06fc
MD5 e3492e45246f365b8a1defb7d1bf5595
BLAKE2b-256 92805a37840c8932f05ab69555ab1558738485fd70e58369670c4773cdfa5b1b

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

2.0.0b2 This release

2 files

1.2.8

2 files

1.2.7

2 files

1.2.5

2 files

1.2.4

2 files

1.2.3

2 files

1.2.2

2 files

1.2.1

2 files

1.2.0

2 files

1.1.9

2 files

1.1.8

2 files

1.1.7

2 files

1.1.6

2 files

1.1.5

2 files

1.1.4

2 files

1.1.3

2 files

1.1.2

2 files

1.1.1

2 files

1.1.0

2 files

1.0.9

2 files

1.0.8

2 files

1.0.7

2 files

1.0.6

2 files

1.0.5

2 files

1.0.4

2 files

1.0.3

2 files

1.0.2

2 files

1.0.1

2 files

1.0.0

2 files

0.2.0

2 files

0.1.0

2 files

0.0.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page