Sync/Async API wrapper for Spotify's web API


License
MIT
Install
pip install pyfy==2.2.0

Documentation

Logo

Build Status Software License Code style: black Downloads Monthly Downloads

Welcome 👋

Pyfy is a Sync + Async Pythonic Spotify Client that focuses on ease of use in personal projects and API stability and security for production grade codebases.

Setup ⚙️

$ pip install pyfy

Quick Start 🎛️

Sync:

from pyfy import Spotify

spt = Spotify('your_access_token')

spt.play()
spt.volume(85)
spt.next()
spt.pause()

Async:

import asyncio
from pyfy import AsyncSpotify

spt = AsyncSpotify('your_access_token')

async def search():
    return await spt.search('A tout le monde')

search_result = asyncio.run(search())

Getting Started 👩

You should start by creating client credentials from Spotify's Developers console

Next edit your application's settings and set a Redirect URL. If it's for personal use then set it as:

http://localhost:9000 Port can be any port of choice, not necessarily 9000

Next, copy your:

  1. Client ID
  2. Client Secret
  3. Redirect URL (That you just set)

Next, figure out the scopes that you think you'll need from here: https://developer.spotify.com/documentation/general/guides/scopes/

e.g. ["user-library-modify", "app-remote-control"]

Next, follow the first authentication scheme from below (it's the one you'll most likely need, unless you're sure otherwise)

Authentication Schemes 👩‍🎤

1. Authorization Code Flow (OAuth2) (recommended)

Suitable if you want to access user-related resources. e.g. user-playlists, user-tracks etc.

Click here for full working examples with Sanic(async) and Flask(sync)

from pyfy import Spotify, ClientCreds, UserCreds, AuthError, ApiError

client = ClientCreds(
    client_id='clientid',
    client_secret='client_secret',
    redirect_uri='https://localhost:9000",
    scopes=["user-library-modify", "app-remote-control"]
)
spt = Spotify(client_creds=client)

def authorize():
    # Fist step of OAuth, Redirect user to spotify's authorization endpoint
    if spt.is_oauth_ready:
        return redirect(spt.auth_uri())

# Authorization callback
def callback(grant):
    try:
        user_creds = spt.build_credentials(grant=grant)
    except AuthError as e:
        abort(401)
        logging.info(e.msg)
        logging.info(e.http_response)
    else:
        db.insert(user_creds)
        return redirect(url_for_home)

def get_user_tracks():
    try:
        return json.dumps(spt.user_tracks())
    except ApiError:
        abort(500)

2. User's Access Token get from here

Same as the Authorization Code Flow above but without a refresh token. Suitable for quick runs.

from pyfy import Spotify
spt = Spotify('your access token')

3. Client Credentials Flow (OAauth2):

Suitable for when you want to access public information quickly. (Accessing user information is porhibited using this method)

from pyfy import ClientCreds, Spotify

client = ClientCreds(client_id=client_id, client_secret=client_secret)
spt = Spotify(client_creds=client)
spt.authorize_client_creds()

API endpoints 🌐

Albums:

Artists:

Browse:

Episodes:

Follow:

User Library:

Personalization:

Player:

Playlists:

Search:

Shows:

Tracks:

Users Profile:

Pagination 📖

from pyfy import Spotify

user_creds = {'access_token': '...', 'refresh_token': '....'}

spt = Spotify(user_creds=user_creds)

user_top_tracks = spt.user_top_tracks(limit=5)

next_page_1 = spt.next_page(user_top_tracks)
next_page_2 = spt.next_page(next_page_1)

previous_page_1 = spt.previous_page(next_page_2)
previous_page_1 === next_page_1  # True

Documentation 📑

For a detailed documentation of Pyfy's API, please visit: https://pyfy.readthedocs.io/en/latest where you'll find:

Backward Incompatibility Notices

V2:

  1. Removed Spotify.oauth_uri property in favor of Spotify.auth_uri method.

  2. Spotify.play() now accepts, track_ids, artist_ids etc. instead of resource_ids + resource_names

  3. Oauth2 state handling:

    • Removed deprecated enforce_state_check functionality

    • Removed state attribute from user_creds

    • Oauth2 state checking is no longer done by Pyfy's client and should be handled manually

Testing 👩‍🔬:

Please visit: https://pyfy.readthedocs.io/en/latest/#testing

Contributors

Big thank you to our amazing contributors: