Getting continuous 429 rate limit errors with Spotify Web API through spotipy library

I’m building a music app that needs to fetch playlist data from Spotify using the spotipy Python library. Yesterday I was making tons of API calls and hit the rate limit. My program just froze when trying to make requests. After waiting overnight, I rewrote my code to handle rate limiting better but now I’m stuck with a weird issue.

I can only make one successful API call, then every subsequent request throws a 429 error. Even when I wait several minutes between attempts, the same pattern happens. One success, then all failures. This doesn’t make sense since Spotify’s rate limit is supposed to reset every 30 seconds.

Here’s my current implementation:

import spotipy
from spotipy.oauth2 import SpotifyOAuth
import time

def setup_spotify_client():
    client = spotipy.Spotify(
        retries=0,
        auth_manager=SpotifyOAuth(
            client_id='client_id_here',
            client_secret='secret_here', 
            scope='playlist-read-private playlist-modify-public',
            redirect_uri='http://localhost:8888/callback'
        )
    )
    return client

class SpotifyAPI:
    def __init__(self, username):
        self.last_call_time = time.time()
        self.client = setup_spotify_client()
        self.username = username
        
    def fetch_tracks_from_playlist(self, playlist_id, start_index, attempt_count=0):
        time_since_last = time.time() - self.last_call_time
        
        if time_since_last >= 1:
            try:
                result = self.client.user_playlist_tracks(
                    self.username, playlist_id, 
                    offset=start_index, limit=100
                )
                self.last_call_time = time.time()
                return result
            except spotipy.exceptions.SpotifyException as error:
                if error.http_status == 429:
                    wait_time = (2 ** attempt_count) * 5
                    print(f"Rate limited. Waiting {wait_time} seconds...")
                    time.sleep(wait_time)
                    return self.fetch_tracks_from_playlist(playlist_id, start_index, attempt_count + 1)
                else:
                    raise error
        else:
            time.sleep(1 - time_since_last)
            return self.fetch_tracks_from_playlist(playlist_id, start_index)

spotify_handler = SpotifyAPI('my_username')

def collect_all_tracks(playlist_id):
    all_tracks = []
    current_offset = 0
    
    while True:
        print("Making API request...")
        batch_result = spotify_handler.fetch_tracks_from_playlist(playlist_id, current_offset)
        print("Response received")
        
        for item in batch_result['items']:
            all_tracks.append(item['track'])
            
        if not batch_result["next"]:
            break
        current_offset += 100
            
    return all_tracks

if __name__ == '__main__':
    track_list = collect_all_tracks('playlist_id_here')
    print(f"Total tracks: {len(track_list)}")

I’ve tried using different app credentials from my Spotify developer dashboard but get the same behavior. The rate limiting should allow multiple requests per 30 second window, so waiting 2+ minutes between calls should definitely work.

Why can I only make one successful request before getting blocked? Is there something wrong with my retry logic or authentication handling?

I encountered a similar issue previously while developing a tool that interacted with the Spotify API. Your approach to handling rate limiting appears solid, but it seems that the core issue lies in how you manage your OAuth session. Each time you initialize spotipy, it’s possible that a new authorization is being requested, which can conflict with the rate limits imposed by Spotify. It’s advisable to create your Spotify client instance once and reuse it throughout your application, thereby maintaining a consistent authenticated session. Additionally, keep in mind that Spotify enforces stricter limits for newer developer accounts. Make sure to review your app status in the developer dashboard. Lastly, consider using user_playlist_tracks without the username, as this parameter has been deprecated in some updates. A helpful hint: when you receive a 429 error, the retry-after header can provide a precise wait time, which can be more effective than the exponential backoff approach you are currently using.

This topic was automatically closed 4 days after the last reply. New replies are no longer allowed.