[GH-ISSUE #700] KeyError 'total' #414

Closed
opened 2026-02-27 23:22:29 +03:00 by kerem · 7 comments
Owner

Originally created by @sk0903 on GitHub (Jun 30, 2021).
Original GitHub issue: https://github.com/spotipy-dev/spotipy/issues/700

I am creating a user dashboard using plotly and flask to display the top tracks and top artists preferred by a user. My code has been working fine but suddenly I got this error.
image

These are the code blocks

def get_user_top_tracks_artists(self, entity_type="artists", limit=50,time_range="medium_term", offset=0):
        """
        :param entity_type:  artists or tracks
        :param limit: The number of entities to return. Limit is 50
        :param time_range: Over what time frame the affinities are computed. Valid values: long_term
            (calculated from several years of data and including all new data as it becomes available),
            medium_term (approximately last 6 months), short_term (approximately last 4 weeks)
        :param offset: The index of the first entity to return. Default: 0 (i.e., the first track).
            Use with limit to get the next set of entities
        :return: json text
        """
        endpoint = f"https://api.spotify.com/v1/me/top/{entity_type}?time_range={time_range}&limit={limit}&offset={offset}"
        track_artists = json.loads(requests.get(endpoint, headers=self.authorization_header).text)
        return track_artists`
```

```
def df_get_user_top_track_artists(self, entity_type="artists", time_range="medium-term"):
        """
        :return a pandas DataFrame
        """
        total_top_entity = self.get_user_top_tracks_artists(entity_type=entity_type, limit=1,time_range=time_range, offset=0)["total"]
        print(total_top_entity)
        user_top_entity_data = pd.DataFrame()
        for i in range(int(total_top_entity/50)+1):
            temp_json = self.get_user_top_tracks_artists(entity_type=entity_type, limit=50,
                                                             time_range=time_range, offset=i*50)
            if entity_type == "artists":
                temp = us.df_user_top_artists(temp_json)
            else:
                temp = us.df_user_top_tracks(temp_json)
            user_top_entity_data = pd.concat([user_top_entity_data, temp])
        return user_top_entity_data
```
user_data.py code function

```
def df_user_top_artists(data):
    """
    :param data: in json format
    :return pandas dataframe
    """

    name, popularity, image_url, external_url, followers, genres = [], [], [], [], [], []
    for artist in data['items']:
        name.append(artist['name'])
        popularity.append(artist['popularity'])
        try:
            image_url.append(artist['images'][1]['url'])
        except:
            try:
                image_url.append(artist['images'][0]['url'])
            except IndexError:
                image_url.append(np.nan)
        external_url.append(artist['external_urls']['spotify'])
        followers.append(artist['followers']['total'])
        genres.append(artist['genres'])
    
    user_top_artist_data = pd.DataFrame(columns=['name','followers','popularity','genres','image_url', 'external_url'])

    user_top_artist_data['name'] = name
    user_top_artist_data['followers'] = followers
    user_top_artist_data['popularity'] = popularity
    user_top_artist_data['genres'] = genres
    user_top_artist_data['image_url'] = image_url
    user_top_artist_data['external_url'] = external_url

    return user_top_artist_data
```

Can you please help me out on what could have gone wrong? I am sure the API reference endpoint is correct since I verified it.
Originally created by @sk0903 on GitHub (Jun 30, 2021). Original GitHub issue: https://github.com/spotipy-dev/spotipy/issues/700 I am creating a user dashboard using plotly and flask to display the top tracks and top artists preferred by a user. My code has been working fine but suddenly I got this error. ![image](https://user-images.githubusercontent.com/86710304/123921426-a9f6b300-d98f-11eb-859c-7024db8fe675.png) These are the code blocks ```` def get_user_top_tracks_artists(self, entity_type="artists", limit=50,time_range="medium_term", offset=0): """ :param entity_type: artists or tracks :param limit: The number of entities to return. Limit is 50 :param time_range: Over what time frame the affinities are computed. Valid values: long_term (calculated from several years of data and including all new data as it becomes available), medium_term (approximately last 6 months), short_term (approximately last 4 weeks) :param offset: The index of the first entity to return. Default: 0 (i.e., the first track). Use with limit to get the next set of entities :return: json text """ endpoint = f"https://api.spotify.com/v1/me/top/{entity_type}?time_range={time_range}&limit={limit}&offset={offset}" track_artists = json.loads(requests.get(endpoint, headers=self.authorization_header).text) return track_artists` ``` ``` def df_get_user_top_track_artists(self, entity_type="artists", time_range="medium-term"): """ :return a pandas DataFrame """ total_top_entity = self.get_user_top_tracks_artists(entity_type=entity_type, limit=1,time_range=time_range, offset=0)["total"] print(total_top_entity) user_top_entity_data = pd.DataFrame() for i in range(int(total_top_entity/50)+1): temp_json = self.get_user_top_tracks_artists(entity_type=entity_type, limit=50, time_range=time_range, offset=i*50) if entity_type == "artists": temp = us.df_user_top_artists(temp_json) else: temp = us.df_user_top_tracks(temp_json) user_top_entity_data = pd.concat([user_top_entity_data, temp]) return user_top_entity_data ``` user_data.py code function ``` def df_user_top_artists(data): """ :param data: in json format :return pandas dataframe """ name, popularity, image_url, external_url, followers, genres = [], [], [], [], [], [] for artist in data['items']: name.append(artist['name']) popularity.append(artist['popularity']) try: image_url.append(artist['images'][1]['url']) except: try: image_url.append(artist['images'][0]['url']) except IndexError: image_url.append(np.nan) external_url.append(artist['external_urls']['spotify']) followers.append(artist['followers']['total']) genres.append(artist['genres']) user_top_artist_data = pd.DataFrame(columns=['name','followers','popularity','genres','image_url', 'external_url']) user_top_artist_data['name'] = name user_top_artist_data['followers'] = followers user_top_artist_data['popularity'] = popularity user_top_artist_data['genres'] = genres user_top_artist_data['image_url'] = image_url user_top_artist_data['external_url'] = external_url return user_top_artist_data ``` Can you please help me out on what could have gone wrong? I am sure the API reference endpoint is correct since I verified it.
kerem closed this issue 2026-02-27 23:22:29 +03:00
Author
Owner

@Peter-Schorn commented on GitHub (Jun 30, 2021):

You probably got an error because the access token expired. Why are you making the requests manually? That doesn't make any sense. Automatically refreshing the access token is something spotipy does for you. spotipy supports all Spotify web API endpoints. See Spotify.current_user_top_artists and Spotify.current_user_top_tracks.

<!-- gh-comment-id:871210732 --> @Peter-Schorn commented on GitHub (Jun 30, 2021): You probably got an error because the access token expired. Why are you making the requests manually? That doesn't make any sense. Automatically refreshing the access token is something spotipy does for you. spotipy supports all Spotify web API endpoints. See `Spotify.current_user_top_artists` and `Spotify.current_user_top_tracks`.
Author
Owner

@sk0903 commented on GitHub (Jun 30, 2021):

Oh okay. Yes I understand, Since I am new to using it, I'm initially familiarizing myself with the APIs and then work on in using spotipy.
Thanks

<!-- gh-comment-id:871268061 --> @sk0903 commented on GitHub (Jun 30, 2021): Oh okay. Yes I understand, Since I am new to using it, I'm initially familiarizing myself with the APIs and then work on in using spotipy. Thanks
Author
Owner

@sk0903 commented on GitHub (Jun 30, 2021):

Hi, also just a quick doubt, I was able to create a new playlist on spotify by extracting my past playlists through recommendations by using the spotify API directly but wasnt able to extract the user top tracks. Does that still have to do with an expired access token? I may have to read more on this but it would be great if you can help me on that.

<!-- gh-comment-id:871319767 --> @sk0903 commented on GitHub (Jun 30, 2021): Hi, also just a quick doubt, I was able to create a new playlist on spotify by extracting my past playlists through recommendations by using the spotify API directly but wasnt able to extract the user top tracks. Does that still have to do with an expired access token? I may have to read more on this but it would be great if you can help me on that.
Author
Owner

@Peter-Schorn commented on GitHub (Jun 30, 2021):

It's hard to say because you haven't provided enough information. In particular, I don't know how you're retrieving the authorization header. Once again, this is something spotipy can do for you. Using both spotipy and manual requests is likely going to cause more issues. Furthermore, if you receive a key error when trying to access a key in a dictionary, you need to print the entire dictionary to the console in order to see what data Spotify is returning. It it likely returning an error response that will provide you with more information.

<!-- gh-comment-id:871633068 --> @Peter-Schorn commented on GitHub (Jun 30, 2021): It's hard to say because you haven't provided enough information. In particular, I don't know how you're retrieving the authorization header. Once again, this is something spotipy can do for you. Using both spotipy and manual requests is likely going to cause more issues. Furthermore, if you receive a key error when trying to access a key in a dictionary, you need to print the entire dictionary to the console in order to see what data Spotify is returning. It it likely returning an error response that will provide you with more information.
Author
Owner

@sk0903 commented on GitHub (Jul 1, 2021):

Oh alright. I am posting my auth code so that you get an idea where the error could have occured . Again, I do understand that spotipy does it in an easier way but for learning purpose I incorporated the manual request as well. And, yes I will try to debug it in my console as well.

class SpotifyClient:
    # Spotify API URLS
    API_VERSION = "v1"
    SPOTIFY_AUTH_URL = "https://accounts.spotify.com/authorize"
    SPOTIFY_TOKEN_URL = "https://accounts.spotify.com/api/token"
    SPOTIFY_API_BASE_URL = "https://api.spotify.com"
    SPOTIFY_API_URL = f"{SPOTIFY_API_BASE_URL}/{API_VERSION}"

    #Server-side parameters
    STATE = ""
    SHOW_DIALOG_bool = True
    SHOW_DIALOG_str = str(SHOW_DIALOG_bool).lower()
    SCOPE = "playlist-modify-public playlist-modify-private playlist-read-private user-top-read"

    CLIENT_SIDE_URL = 'http://127.0.0.1'

    def __init__(self, client_id, client_secret, client_side_url=CLIENT_SIDE_URL, port=None):
        self.client_id = client_id
        self.client_secret = client_secret
        self.client_side_url = client_side_url
        self.port = port
        self._access_token = ''
        self.authorization_header = ''
        self.redirect_uri = f"{self.client_side_url}/callback/q" if port is None else f"{self.client_side_url}:{self.port}/callback/q"
    
    def get_auth_url(self):
        auth_query_parameters = {
            "response_type": "code",
            "redirect_uri": self.redirect_uri,
            "scope": self.SCOPE,
            "show_dialog": self.SHOW_DIALOG_str,
            "client_id": self.client_id
            #"state": STATE,
        }

        url_args = "&".join([f"{key}={quote(str(val))}" for key, val in auth_query_parameters.items()])
        return f"{self.SPOTIFY_AUTH_URL}/?{url_args}"
    
    def get_authorization(self, auth_token):
        """
        returning authorization data and setting the authorization_header
        :param auth_token:
        :return: dict
        """

        data = {
            "grant_type": "authorization_code",
            "code": str(auth_token),
            "redirect_uri": self.redirect_uri,
            'client_id': self.client_id,
            'client_secret': self.client_secret,
        }
        post_request = requests.post(self.SPOTIFY_TOKEN_URL, data=data)

        response_data = json.loads(post_request.text)
        self._access_token = response_data["access_token"]
        self.authorization_header = {"Authorization": f"Bearer {self._access_token}"}

        return dict(
            access_token=response_data["access_token"],
            refresh_token=response_data["refresh_token"],
            token_type=response_data["token_type"],
            expires_in=response_data["expires_in"],
        )
<!-- gh-comment-id:871946537 --> @sk0903 commented on GitHub (Jul 1, 2021): Oh alright. I am posting my auth code so that you get an idea where the error could have occured . Again, I do understand that spotipy does it in an easier way but for learning purpose I incorporated the manual request as well. And, yes I will try to debug it in my console as well. ``` class SpotifyClient: # Spotify API URLS API_VERSION = "v1" SPOTIFY_AUTH_URL = "https://accounts.spotify.com/authorize" SPOTIFY_TOKEN_URL = "https://accounts.spotify.com/api/token" SPOTIFY_API_BASE_URL = "https://api.spotify.com" SPOTIFY_API_URL = f"{SPOTIFY_API_BASE_URL}/{API_VERSION}" #Server-side parameters STATE = "" SHOW_DIALOG_bool = True SHOW_DIALOG_str = str(SHOW_DIALOG_bool).lower() SCOPE = "playlist-modify-public playlist-modify-private playlist-read-private user-top-read" CLIENT_SIDE_URL = 'http://127.0.0.1' def __init__(self, client_id, client_secret, client_side_url=CLIENT_SIDE_URL, port=None): self.client_id = client_id self.client_secret = client_secret self.client_side_url = client_side_url self.port = port self._access_token = '' self.authorization_header = '' self.redirect_uri = f"{self.client_side_url}/callback/q" if port is None else f"{self.client_side_url}:{self.port}/callback/q" def get_auth_url(self): auth_query_parameters = { "response_type": "code", "redirect_uri": self.redirect_uri, "scope": self.SCOPE, "show_dialog": self.SHOW_DIALOG_str, "client_id": self.client_id #"state": STATE, } url_args = "&".join([f"{key}={quote(str(val))}" for key, val in auth_query_parameters.items()]) return f"{self.SPOTIFY_AUTH_URL}/?{url_args}" def get_authorization(self, auth_token): """ returning authorization data and setting the authorization_header :param auth_token: :return: dict """ data = { "grant_type": "authorization_code", "code": str(auth_token), "redirect_uri": self.redirect_uri, 'client_id': self.client_id, 'client_secret': self.client_secret, } post_request = requests.post(self.SPOTIFY_TOKEN_URL, data=data) response_data = json.loads(post_request.text) self._access_token = response_data["access_token"] self.authorization_header = {"Authorization": f"Bearer {self._access_token}"} return dict( access_token=response_data["access_token"], refresh_token=response_data["refresh_token"], token_type=response_data["token_type"], expires_in=response_data["expires_in"], ) ```
Author
Owner

@dieser-niko commented on GitHub (May 1, 2024):

Do you still have an issue to resolve or can we close this?

<!-- gh-comment-id:2089080709 --> @dieser-niko commented on GitHub (May 1, 2024): Do you still have an issue to resolve or can we close this?
Author
Owner

@dieser-niko commented on GitHub (May 21, 2024):

It appears that @sk0903 has no other activity on his account besides this issue. Closing.

<!-- gh-comment-id:2123463367 --> @dieser-niko commented on GitHub (May 21, 2024): It appears that @sk0903 has no other activity on his account besides this issue. Closing.
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#414
No description provided.