[GH-ISSUE #386] Cannot refresh token (http status: 401, code:-1) #228

Closed
opened 2026-02-27 23:21:29 +03:00 by kerem · 1 comment
Owner

Originally created by @paunovic on GitHub (Jul 2, 2019).
Original GitHub issue: https://github.com/spotipy-dev/spotipy/issues/386

I'm having following code, which is supposed to refresh auth token once it expires:

import re
import time
import logging
import spotipy
import itertools
from slugify import slugify
from spotipy import oauth2


logger = logging.getLogger(__name__)


class Spotify:
    def __init__(self, user_id, client_id, client_secret, credentials_path):
        self.user_id = user_id
        self.client_id = client_id
        self.client_secret = client_secret

        self.credentials_path = credentials_path

        self.scope = 'playlist-modify-private playlist-modify-public'
        self.redirect_uri = 'http://localhost:8888/callback/'

        self.oauth = oauth2.SpotifyOAuth(
            client_id=self.client_id,
            client_secret=self.client_secret,
            redirect_uri=self.redirect_uri,
            scope=self.scope,
            cache_path=self.credentials_path
        )

        self.client = None
        self.current_user = None
        self.user_id = None
        self.display_name = None

        self.connect_and_authorize()

    def execute(self, method, **kwargs):
        """Wrapper method for spotify API client calls, refreshes token in case API call fails"""

        delay, retry_count = 4, 8  # 4, 8, 16, 32, 64, 128, 256, 512 seconds delay

        for _ in range(retry_count):
            try:
                return method(**kwargs)
            except BaseException as e:
                logger.error(e)

                time.sleep(delay)

                logger.info('Refreshing token...')
                self.refresh_token()

                delay += delay

    def connect_and_authorize(self):
        logger.info(f'Authorizing...')

        auth_token = self.get_token()

        self.client = spotipy.Spotify(auth=auth_token)
        self.client.trace = False

        self.current_user = self.client.current_user()
        self.user_id = self.current_user['id']
        self.display_name = self.current_user['display_name']

    def get_token(self):
        token_info = self.oauth.get_cached_token()

        if not token_info:
            auth_url = self.oauth.get_authorize_url()
            print(auth_url)
            response = input('Open the link above and copy/paste the URL here: ')
            code = self.oauth.parse_response_code(response)
            token_info = self.oauth.get_access_token(code)

        return token_info['access_token'] if token_info else None

    def refresh_token(self):
        cached_token = self.oauth.get_cached_token()
        refresh_token = cached_token['refresh_token']
        new_token = self.oauth.refresh_access_token(refresh_token)
        logging.info(f'Refresh token: {refresh_token}')
        logging.info(f'New token: {new_token}')
        self.client = spotipy.Spotify(auth=new_token['access_token'])
        return new_token

    def get_playlists(self, user_id=None):
        if user_id is None:
            user_id = self.user_id

        limit = 50  # 50 is max limit according to Spotify API specs
        offset = 0

        playlists = list()

        while True:
            result = self.execute(self.client.user_playlists, user=user_id, limit=limit, offset=offset)

            # remove None items, from some reason spotify API sometimes returns None item amongst other playlists
            items = [item for item in result['items'] if item is not None]

            playlists.extend(items)

            if len(items) < limit:
                break

            offset += limit

        return playlists

.execute() is a try..except wrapper around all spotify client calls, so that it can refresh token once it expires. However, I keep getting following errors in succession once it tries to refresh token:

2019-07-02 18:24:14 src.api.spotify                +48   E   http status: 401, code:-1 - https://api.spotify.com/v1/search?q=xxx%2BS%2A&limit=4&offset=0&type=playlist:
 The access token expired
2019-07-02 18:24:30 src.api.spotify                +52   I   Refreshing token...
2019-07-02 18:24:30 root                           +85   I   Refresh token: AQDQ-ObbuEKoEhcSWFn_uuz7AxxxxxxxxxxSgA96ZxxxnXbk_axCT2jM_M6KOmsNVXLd7SbHdh7uCbfCEwhI2TA7WFtpISYUgNCB0Ce1ODa5B_7wkWxmLs5JC_858p5Y288A
2019-07-02 18:24:30 root                           +86   I   New token: {'access_token': 'BQCCfMYJTZxxxxxxxxxxWM82TjhA9n6YdmB_zS5L4SFpl9yzVwjO7F_ojb-Zk8_3PQBWxRKIpoIxxxxxxBbalsTk_A2eGUoVwLpVaSFOhF-3PrB7KeWTjQVSeowLMvbJUuuNjB-GFUv86cgCEObS4c6gFxAq1W5qGJsS5BKqc__mtFLbFOCxjDnM1UYqMzqXOkNdJpFfmL6Gm5IMLo3pV4gkD6aw', 'token_type': 'Bearer', 'expires_in': 3600, 'scope': 'playlist-modify-private playlist-modify-public', 'expires_at': 1562088270, 'refresh_token': 'AQDQ-ObbuEKoEhcSWFn_uuz7Aexv44wDxxxxxxxxxxyNnXbk_axCT2jM_M6KOmsNxxxxxxxxxxh7uCbfCEwhI2TA7WFtpISYUgNCB0Ce1ODa5B_7wkWxmLs5JC_858p5Y288A'}

refresh_token stays the same, and access_token keeps changing. Any ideas what am I doing wrong? I was following this issue: https://github.com/plamere/spotipy/issues/83 but it seems like on my end it doesn't work.

Originally created by @paunovic on GitHub (Jul 2, 2019). Original GitHub issue: https://github.com/spotipy-dev/spotipy/issues/386 I'm having following code, which is supposed to refresh auth token once it expires: ``` import re import time import logging import spotipy import itertools from slugify import slugify from spotipy import oauth2 logger = logging.getLogger(__name__) class Spotify: def __init__(self, user_id, client_id, client_secret, credentials_path): self.user_id = user_id self.client_id = client_id self.client_secret = client_secret self.credentials_path = credentials_path self.scope = 'playlist-modify-private playlist-modify-public' self.redirect_uri = 'http://localhost:8888/callback/' self.oauth = oauth2.SpotifyOAuth( client_id=self.client_id, client_secret=self.client_secret, redirect_uri=self.redirect_uri, scope=self.scope, cache_path=self.credentials_path ) self.client = None self.current_user = None self.user_id = None self.display_name = None self.connect_and_authorize() def execute(self, method, **kwargs): """Wrapper method for spotify API client calls, refreshes token in case API call fails""" delay, retry_count = 4, 8 # 4, 8, 16, 32, 64, 128, 256, 512 seconds delay for _ in range(retry_count): try: return method(**kwargs) except BaseException as e: logger.error(e) time.sleep(delay) logger.info('Refreshing token...') self.refresh_token() delay += delay def connect_and_authorize(self): logger.info(f'Authorizing...') auth_token = self.get_token() self.client = spotipy.Spotify(auth=auth_token) self.client.trace = False self.current_user = self.client.current_user() self.user_id = self.current_user['id'] self.display_name = self.current_user['display_name'] def get_token(self): token_info = self.oauth.get_cached_token() if not token_info: auth_url = self.oauth.get_authorize_url() print(auth_url) response = input('Open the link above and copy/paste the URL here: ') code = self.oauth.parse_response_code(response) token_info = self.oauth.get_access_token(code) return token_info['access_token'] if token_info else None def refresh_token(self): cached_token = self.oauth.get_cached_token() refresh_token = cached_token['refresh_token'] new_token = self.oauth.refresh_access_token(refresh_token) logging.info(f'Refresh token: {refresh_token}') logging.info(f'New token: {new_token}') self.client = spotipy.Spotify(auth=new_token['access_token']) return new_token def get_playlists(self, user_id=None): if user_id is None: user_id = self.user_id limit = 50 # 50 is max limit according to Spotify API specs offset = 0 playlists = list() while True: result = self.execute(self.client.user_playlists, user=user_id, limit=limit, offset=offset) # remove None items, from some reason spotify API sometimes returns None item amongst other playlists items = [item for item in result['items'] if item is not None] playlists.extend(items) if len(items) < limit: break offset += limit return playlists ``` `.execute()` is a try..except wrapper around all spotify client calls, so that it can refresh token once it expires. However, I keep getting following errors in succession once it tries to refresh token: ``` 2019-07-02 18:24:14 src.api.spotify +48 E http status: 401, code:-1 - https://api.spotify.com/v1/search?q=xxx%2BS%2A&limit=4&offset=0&type=playlist: The access token expired 2019-07-02 18:24:30 src.api.spotify +52 I Refreshing token... 2019-07-02 18:24:30 root +85 I Refresh token: AQDQ-ObbuEKoEhcSWFn_uuz7AxxxxxxxxxxSgA96ZxxxnXbk_axCT2jM_M6KOmsNVXLd7SbHdh7uCbfCEwhI2TA7WFtpISYUgNCB0Ce1ODa5B_7wkWxmLs5JC_858p5Y288A 2019-07-02 18:24:30 root +86 I New token: {'access_token': 'BQCCfMYJTZxxxxxxxxxxWM82TjhA9n6YdmB_zS5L4SFpl9yzVwjO7F_ojb-Zk8_3PQBWxRKIpoIxxxxxxBbalsTk_A2eGUoVwLpVaSFOhF-3PrB7KeWTjQVSeowLMvbJUuuNjB-GFUv86cgCEObS4c6gFxAq1W5qGJsS5BKqc__mtFLbFOCxjDnM1UYqMzqXOkNdJpFfmL6Gm5IMLo3pV4gkD6aw', 'token_type': 'Bearer', 'expires_in': 3600, 'scope': 'playlist-modify-private playlist-modify-public', 'expires_at': 1562088270, 'refresh_token': 'AQDQ-ObbuEKoEhcSWFn_uuz7Aexv44wDxxxxxxxxxxyNnXbk_axCT2jM_M6KOmsNxxxxxxxxxxh7uCbfCEwhI2TA7WFtpISYUgNCB0Ce1ODa5B_7wkWxmLs5JC_858p5Y288A'} ``` `refresh_token` stays the same, and `access_token` keeps changing. Any ideas what am I doing wrong? I was following this issue: https://github.com/plamere/spotipy/issues/83 but it seems like on my end it doesn't work.
kerem closed this issue 2026-02-27 23:21:29 +03:00
Author
Owner

@shillshocked commented on GitHub (Jul 28, 2019):

I was getting this issue too, but I figured it out thanks to #83 like you mentioned. It's not straightforward, you really have to pay attention, as all the code won't be there or be applicable to you. The way I did class definitions was more in line with their example. Make sure that you're referring to the right object. It seems like your overwriting your refreshed token with an additional token.

<!-- gh-comment-id:515751082 --> @shillshocked commented on GitHub (Jul 28, 2019): I was getting this issue too, but I figured it out thanks to #83 like you mentioned. It's not straightforward, you really have to pay attention, as all the code won't be there or be applicable to you. The way I did class definitions was more in line with their example. Make sure that you're referring to the right object. It seems like your overwriting your refreshed token with an additional token.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/spotipy#228
No description provided.