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

3.7k views Asked by At

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']

2

There are 2 answers

1
Montgomery Watts On BEST ANSWER

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)
0
poolebenjamin24 On

Another way to do this would be to create a list with all the uris/ids of the tracks you want to add, and then pass that list into the sp.playlist_add_items() function. This could be useful if you need the list of uris again further down the line. Like so :

uris = []        

for item in results['items']:
    track = item['track']
    uris.append(track['uri'])

sp.playlist_add_items(playlist_id, uris)

Bear in mind, sp.playlist_add_items only lets you add <= 100 tracks at a time. i created this loop to handle adding a list of tracks no matter the size: (where songIDs is a list of song ids / uris)

i = 0
increment = 99
while i < len(songIDS)+increment:
    try:
        sp.playlist_add_items(playlistID, songIDS[i: i+increment])
    except spotipy.exceptions.SpotifyException:
        pass

    i += increment

Hope this helps, i've only been using spotipy for a week myself