Refresh token spotipy
Asked Answered
G

3

5

I am using spotipy to retrieve some tracks from Spotify using python. I get a token expiration error thus, I want to refresh my token. But I don't understand how to get the refresh token from spotipy.

Is there another way to refresh the token or recreate one?

Thank you.

Guzel answered 20/2, 2018 at 11:0 Comment(0)
M
4

The rough process that Spotipy takes with access tokens is:

  1. Get the token from the cache (is actually more than just access token, also refresh and expiry date info)
  2. If token was in the cache and has expired, refresh it
  3. If token wasn't in the cache, then prompt_for_user_token() will handle you completing the OAuth flow in browser, after which it will save it to the cache.

So it will be refreshed automatically if you ask Spotipy for your access token (e.g. with prompt_for_user_token() or by setting up a SpotifyOAuth object directly) and it has cached the access token / refresh token previously. Cache location should be .cache-<username> in the working directory by default, so you can access the tokens manually there.


If you provide the Spotipy Spotify() client with auth param for authorization, it will not be able to refresh the access token automatically and I think it will expire after about an hour. You can provide it a client_credentials_manager instead, which it will request the access token from. The only requirement of an implementation of the client_credentials_manager object is that it provides a get_access_token() method which takes no params and returns an access token.

I tried this out in a fork a while back, here's the modification to the SpotifyOAuth object to allow it to act as a client_credentials_manager and here's the equivalent of prompt_for_user_token() that returns the SpotifyOAuth object that you can pass to Spotipy Spotify() client as a credentials manager param.

Maxi answered 20/2, 2018 at 14:27 Comment(5)
Do you know if it is possible to automatize the copy-pasting of the opened browser page containing the code? I want to put my code on a server but I don't know how to deal with the cope/paste of the URL. Thank you. – Guzel
@mina, I got spotipy auth to work on the server (AWS Lambda) by doing a one time manual copy and paste on my laptop and then copying the .cache-<username> file to the server. This file contains a "refresh_token" which I believe allows it to refresh the access_token automatically. – Stepp
@Stepp I just wanted to say that you are the man!! I have been searching so long for a way to automate my pipeline and this worked!! – Diastole
@Diastole πŸ‘πŸ‘πŸ‘ – Stepp
@Rach Sharp I'm getting an error: client.py, line 92, in _auth_headers token = self.client_credentials_manager.get_access_token() TypeError: get_access_token() missing 1 required positional argument: 'code' when I used your fork. Do you know why this is occuring? – Garble
T
0

Because this problem took me a while to figure out, I'm going to put my solution here. This works for running Spotipy on a server eternally (or at least has for the past 12 hours). You have to run it once locally to generate the .cache file, but once that has occurred, your server can then use that cache file to update it's access token and refresh token when needed.

import spotipy
scopes = 'ugc-image-upload user-read-playback-state user-modify-playback-state user-read-currently-playing ...'
sp = spotipy.Spotify(auth_manager=spotipy.SpotifyOAuth(scope=scopes))
while True:
    try:
        current_song = sp.currently_playing()
        do something...
    except spotipy.SpotifyOauthError as e:
        sp = spotipy.Spotify(auth_manager=spotipy.SpotifyOAuth(scope=scopes))

Thesda answered 26/9, 2021 at 17:28 Comment(0)
F
0

I saw the solution by mardiff which absolutely works, but I didn't like that it waits for an error to occur and then fixes it so I found a solution which doesn't require catching errors, using methods which spotipy already has implemented.

import spotipy
from spotipy.oauth2 import SpotifyOAuth
import time

USERNAME = '...'
CLIENT_ID = '...'
CLIENT_SECRET = '...'
SCOPE = 'user-read-currently-playing'

def create_spotify():
    auth_manager = SpotifyOAuth(
        scope=SCOPE,
        username=USERNAME,
        redirect_uri='http://localhost:8080',
        client_id=CLIENT_ID,
        client_secret=CLIENT_SECRET)

    spotify = spotipy.Spotify(auth_manager=auth_manager)

    return auth_manager, spotify

def refresh_spotify(auth_manager, spotify):
    token_info = auth_manager.cache_handler.get_cached_token()
    if auth_manager.is_token_expired(token_info):
        auth_manager, spotify = create_spotify()
    return auth_manager, spotify

if __name__ == '__main__':
    auth_manager, spotify = create_spotify()

    while True:
        auth_manager, spotify = refresh_spotify(auth_manager, spotify)
        playing = spotify.currently_playing()
        if playing:
            print(playing['item']['name'])
        else:
            print('Nothing is playing.')
        time.sleep(30)

Using this method you check if the token is expired (or within 60 seconds of expiring) before each use of the spotify object. Creating new auth_manager and spotify objects as needed.

Forrester answered 25/12, 2021 at 2:7 Comment(0)

© 2022 - 2024 β€” McMap. All rights reserved.