Search code examples
pythonpython-3.xapispotipylibspotify

I want to make a playlist from all my liked songs on spotify with spotipy library


Since my liked songs aren't public I want spotipy to get a list from all the songs and add them to my playlist, but when I try to do that with a loop it says that the uri is incorrect, I don't know if I should use another method.

client_credentials_manager = SpotifyClientCredentials(client_id=cid, client_secret=secret)
scope = 'user-library-read playlist-modify-public'
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager,auth_manager=SpotifyOAuth(scope=scope))
def show_tracks(results):
    for item in results['items']:
        track = item['track']
        #print("%32.32s %s" % (track['artists'][0]['name'], track['name']))
        sp.playlist_add_items(playlist_id, track['uri'])

results = sp.current_user_saved_tracks()
show_tracks(results)

while results['next']:
    results = sp.next(results)
    show_tracks(results)

The error is

HTTP Error for POST to https://api.spotify.com/v1/playlists/5ZzsovDgANZfiXgRrwq5fw/tracks returned 400 due to Invalid track uri: spotify:track:s
Traceback (most recent call last):
  File "C:\Users\ferch\AppData\Local\Programs\Python\Python37\lib\site-packages\spotipy\client.py", line 245, in _internal_call
    response.raise_for_status()
  File "C:\Users\ferch\AppData\Local\Programs\Python\Python37\lib\site-packages\requests\models.py", line 941, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://api.spotify.com/v1/playlists/5ZzsovDgANZfiXgRrwq5fw/tracks

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "make_playlists.py", line 23, in <module>
    show_tracks(results)
  File "make_playlists.py", line 20, in show_tracks
    sp.playlist_add_items(playlist_id, track['uri'])
  File "C:\Users\ferch\AppData\Local\Programs\Python\Python37\lib\site-packages\spotipy\client.py", line 1025, in playlist_add_items
    position=position,
  File "C:\Users\ferch\AppData\Local\Programs\Python\Python37\lib\site-packages\spotipy\client.py", line 296, in _post
    return self._internal_call("POST", url, payload, kwargs)
  File "C:\Users\ferch\AppData\Local\Programs\Python\Python37\lib\site-packages\spotipy\client.py", line 266, in _internal_call
    headers=response.headers,
spotipy.exceptions.SpotifyException: http status: 400, code:-1 - https://api.spotify.com/v1/playlists/5ZzsovDgANZfiXgRrwq5fw/tracks:
 Invalid track uri: spotify:track:s, reason: None

I think this problem is because of the type of variable of track['uri']


Solution

  • playlist_add_items is expecting a list of URIs, URLs, or IDs to add to the playlist, but right now you're passing a single URI, which is a string like this: spotify:track:2t7rS8BHF5TmnBR5PmnnSU. The code for the spotipy library is likely doing a loop for item in items..., so when you pass it a string, it considers each character in the string as a different item. So it encounters the first character, s and tries to make a URI out of it resulting in spotify:track:s. This isn't a valid URI, so the request fails.

    You can try wrapping the uri in a list like so:

    for item in results['items']:
            track = item['track']
            # Note brackets around track['uri']
            sp.playlist_add_items(playlist_id, [track['uri']])  
    

    This will handle the issue you're getting now, but you may have issues down the line making one request per track you want to add to the playlist. You could run into rate limiting issues, so I recommend trying to build a list of 100 URIs at a time, which is the max that can be sent in one request.

    Keeping this in mind, we could try something like this:

    def show_tracks(results):
        for idx in range(0, len(results['items']), 100):
             uris = [item['track']['uri'] for item in results['items'][idx:idx+100]]
             sp.playlist_add_items(playlist_id, uris)