Skip to content

Fix breaking changes from Spotify API February 2026 update#168

Open
beberry wants to merge 1 commit into
spotify2tidal:mainfrom
beberry:fix/spotify-api-feb-2026
Open

Fix breaking changes from Spotify API February 2026 update#168
beberry wants to merge 1 commit into
spotify2tidal:mainfrom
beberry:fix/spotify-api-feb-2026

Conversation

@beberry
Copy link
Copy Markdown

@beberry beberry commented Feb 16, 2026

Problem

On 02/06 Spotify made breaking changes to their Web API (changelog).

The endpoint GET /playlists/{playlist_id}/tracks has been deprecated and
replaced with GET /playlists/{playlist_id}/items. The new API includes the
following breaking changes:

  • The tracks key in playlist responses has been renamed to items
    (i.e. item['track'] -> item['item'])
  • external_ids has been deprecated and removed from the
    GET /playlists/{playlist_id}/items response, but is still available from
    GET /me/tracks (saved/favorite tracks)

These changes currently affect only new developer apps, but will apply to all existing
apps starting 03/09/2026.

Solution

  • Update playlist fetch method from playlist_tracks to playlist_items
  • Rename playlist item access from track to item in response parsing
  • Update fields query parameter to match new schema
  • Handle missing external_ids gracefully in isrc_match instead of crashing
  • Refactor _fetch_all_from_spotify_in_chunks to return raw paginated responses,
    letting callers handle item extraction (playlist items use item key, favorites use track key)
  • Extract _get_tracks_from_spotify_favorites into a standalone async function
  • Add unit tests for isrc_match, _fetch_all_from_spotify_in_chunks,
    playlist track fetching, and favorites fetching

Verification

  • Unit tests
  • I was able to sync a playlist using a new developer account

Fixes #167

@deathwishofashellfish
Copy link
Copy Markdown

deathwishofashellfish commented Feb 16, 2026

I have cloned this fixed directory and tried it again but I still receive the same 403 error.
The only apparent difference in the log is that the spotify link ends differently (the part "%2Cepisode" is new)

HTTP Error for GET to https://api.spotify.com/v1/playlists/1NShSKsJHfpFGzYwdgUpst/tracks with Params: {'limit': 100, 'offset': 0, 'fields': 'next,total,limit,items(item(name,album(name,artists),artists,track_number,duration_ms,id,external_ids(isrc))),type', 'market': None, 'additional_types': 'track,episode'} returned 403 due to Forbiddenhttp status: 403, code: -1 - https://api.spotify.com/v1/playlists/1NShSKsJHfpFGzYwdgUpst/tracks?limit=100&offset=0&fields=next%2Ctotal%2Climit%2Citems%28item%28name%2Calbum%28name%2Cartists%29%2Cartists%2Ctrack_number%2Cduration_ms%2Cid%2Cexternal_ids%28isrc%29%29%29%2Ctype&additional_types=track%2Cepisode:

Would I have to deinstall the previous installation before trying this one?

Edit: I deinstalled the old version with the uninstall prompt and installed the new version but there still seems to be more or less the same problem. Now the log looks like this:
HTTP Error for GET to https://api.spotify.com/v1/playlists/1NShSKsJHfpFGzYwdgUpst/tracks with Params: {'limit': 100, 'offset': 0, 'fields': 'next,total,limit,items(track(name,album(name,artists),artists,track_number,duration_ms,id,external_ids(isrc))),type', 'market': None, 'additional_types': 'track'} returned 403 due to Forbidden
http status: 403, code: -1 - https://api.spotify.com/v1/playlists/1NShSKsJHfpFGzYwdgUpst/tracks?limit=100&offset=0&fields=next%2Ctotal%2Climit%2Citems%28track%28name%2Calbum%28name%2Cartists%29%2Cartists%2Ctrack_number%2Cduration_ms%2Cid%2Cexternal_ids%28isrc%29%29%29%2Ctype&additional_types=track:

I would be really grateful for advice.

Thank you

@beberry
Copy link
Copy Markdown
Author

beberry commented Feb 16, 2026

@deathwishofashellfish according to the Spotify documentation the /v1/playlists/{playlist_id}/items api 403s unless you are the owner of the playlist or a collaborator.

Note: This endpoint is only accessible for playlists owned by the current user or playlists the user is a collaborator of. A 403 Forbidden status code will be returned if the user is neither the owner nor a collaborator of the playlist.

This might be the reason why you are getting the error. Alternatively, you might've not authenticated properly? I'm able to sync my playlists.

@nateha1984
Copy link
Copy Markdown

@beberry i tried the branch locally with --sync-favorites (new app just created today) and i get this error:

  File "/Users/***/dev/spotify_to_tidal/src/spotify_to_tidal/sync.py", line 340, in sync_favorites
    spotify_tracks = await get_tracks_from_spotify_favorites()
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/***/dev/spotify_to_tidal/src/spotify_to_tidal/sync.py", line 326, in get_tracks_from_spotify_favorites
    tracks = await repeat_on_request_error( _fetch_all_from_spotify_in_chunks, _get_favorite_tracks)
    
  File "/Users/natehall/dev/spotify_to_tidal/src/spotify_to_tidal/sync.py", line 141, in repeat_on_request_error
    return await function(*args, **kwargs)
    
  File "/Users/***/dev/spotify_to_tidal/src/spotify_to_tidal/sync.py", line 165, in _fetch_all_from_spotify_in_chunks
    output.extend([item['item'] for item in results['items'] if item['item']['type'] == 'track'])
                                                                ~~~~^^^^^^^^
KeyError: 'item'

First time using the tool so it may be an unrelated issue, but fyi

@beberry
Copy link
Copy Markdown
Author

beberry commented Feb 17, 2026

@nateha1984 I just checked the favorites functionality and you're right - it's broken. Spotify did not change me/tracks api which still uses the old format and does not depend on the item subkey. I'll try to find some time to fix this.

@beberry beberry marked this pull request as draft February 17, 2026 02:22
- Use playlist_items instead of playlist_tracks, rename 'track' key to 'item'
- Refactor _fetch_all_from_spotify_in_chunks to return raw pages, letting
  callers handle their own response parsing
- Extract _get_tracks_from_spotify_favorites as standalone function
- Make isrc_match handle missing external_ids gracefully
- Add unit tests for pagination, playlist fetching, and favorites fetching
@beberry beberry force-pushed the fix/spotify-api-feb-2026 branch from 3cbb6fc to c4d7c30 Compare February 17, 2026 07:36
@deathwishofashellfish
Copy link
Copy Markdown

@deathwishofashellfish according to the Spotify documentation the /v1/playlists/{playlist_id}/items api 403s unless you are the owner of the playlist or a collaborator.

Note: This endpoint is only accessible for playlists owned by the current user or playlists the user is a collaborator of. A 403 Forbidden status code will be returned if the user is neither the owner nor a collaborator of the playlist.

This might be the reason why you are getting the error. Alternatively, you might've not authenticated properly? I'm able to sync my playlists.

Thank you, I get the same error I got with the previous version, before your fix. That is why I think there might be some residual problems from my first installation even though I uninstalled it and renamed the folder. When I first ran your version of the program there were tidal and spotify logins opening in the browser and I could log in successfully.

I will try reinstalling python and then spotify to tidal once more.

@timrae
Copy link
Copy Markdown
Collaborator

timrae commented Feb 17, 2026 via email

@deathwishofashellfish
Copy link
Copy Markdown

You can try deleting the two cache files, they should be in the directory you run the script from. .cache-username or something like that

On Tue, 17 Feb 2026, 20:41 deathwishofashellfish, @.> wrote: deathwishofashellfish left a comment (spotify2tidal/spotify_to_tidal#168) <#168 (comment)> @deathwishofashellfish https://github.com/deathwishofashellfish according to the Spotify documentation https://developer.spotify.com/documentation/web-api/reference/get-playlists-items the /v1/playlists/{playlist_id}/items api 403s unless you are the owner of the playlist or a collaborator. Note: This endpoint is only accessible for playlists owned by the current user or playlists the user is a collaborator of. A 403 Forbidden status code will be returned if the user is neither the owner nor a collaborator of the playlist. This might be the reason why you are getting the error. Alternatively, you might've not authenticated properly? I'm able to sync my playlists. Thank you, I get the same error I got with the previous version, before your fix. That is why I think there might be some residual problems from my first installation even though I uninstalled it and renamed the folder. When I first ran your version of the program there were tidal and spotify logins opening in the browser and I could log in successfully. I will try reinstalling python and then spotify to tidal once more. — Reply to this email directly, view it on GitHub <#168 (comment)>, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAVQBYRT42S4NH25RP6P6JL4MNVGHAVCNFSM6AAAAACVHRVXNOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTSMJWG4ZTANBXGY . You are receiving this because you are subscribed to this thread.Message ID: @.>

I tried, but still the same result. I can login to both spotify and tidal and then it starts loading the playlists but gives the same 403 error as before. They are all playlists created by me, so I don't why the forbidden code appears. I put the same username in the config file that I use to login to spotify.

@beberry
Copy link
Copy Markdown
Author

beberry commented Feb 18, 2026

@nateha1984 I force pushed a fix last night. Now both regular playlist & favorites sync should work. Can you please pull the latest change and see if works for you?

@nateha1984
Copy link
Copy Markdown

@beberry worked fine for me, thanks!

@elainetripleu
Copy link
Copy Markdown

Thanks for the fix! I was able to load one Spotify playlist before getting the following message:
Your application has reached a rate/request limit. Retry will occur after: 80901 s

Is there an easy fix for this? Trying to avoid waiting 22 hours for another debugging session 🥲 Any help appreciated!

@TrainingArc
Copy link
Copy Markdown

TrainingArc commented Feb 18, 2026

@beberry I tried uninstalling Python using RevoUninstaller and reinstalled it using the python manager. Then I downloaded https://github.com/beberry/spotify_to_tidal/tree/fix/spotify-api-feb-2026 your code. I followed the directions for installing the dependencies and changing the ID name. When running the python3 -m spotify_to_tidal command, the browser doesn't open and I'm still receiving the following error

HTTP Error for GET to https://api.spotify.com/v1/playlists/31xr3sldTQdr1qU6ZIXiwq/tracks with Params: {'limit': 100, 'offset': 0, 'fields': 'next,total,limit,items(item(name,album(name,artists),artists,track_number,duration_ms,id,external_ids(isrc))),type', 'market': None, 'additional_types': 'track,episode'} returned 403 due to Forbidden
http status: 403, code: -1 - https://api.spotify.com/v1/playlists/31xr3sldTQdr1qU6ZIXiwq/tracks?limit=100&offset=0&fields=next%2Ctotal%2Climit%2Citems%28item%28name%2Calbum%28name%2Cartists%29%2Cartists%2Ctrack_number%2Cduration_ms%2Cid%2Cexternal_ids%28isrc%29%29%29%2Ctype&additional_types=track%2Cepisode:
Forbidden, reason: None occurred

Did I simply uninstall it incorrectly? Or is there something else at play here? Thank you for any help you can provide and apologies for the ping.

EDIT: I also deleted the .cache files as suggested by timrae, but was still unable to run the code successfully and received the same error despite the playlists being mine, and verifying my login details with what I had put in the config file

You can try deleting the two cache files, they should be in the directory
you run the script from. .cache-username or something like that

@beberry beberry marked this pull request as ready for review February 22, 2026 01:21
@beberry
Copy link
Copy Markdown
Author

beberry commented Feb 22, 2026

@TrainingArc I'm not sure if your issue is related to this PR / initially reported problem. I would suggest creating a separate issue for tracking purposes.

@timrae I marked this ready for a review whenever you have chance.

@adb-sh
Copy link
Copy Markdown

adb-sh commented Mar 1, 2026

well turns out spotipy is still using the /tracks endpoint in the new playlist_items function xD
https://github.com/spotipy-dev/spotipy/blob/c52a29f6d255c8f1b9b0ff5c2ebf566174db2cb5/spotipy/client.py#L733

@adb-sh
Copy link
Copy Markdown

adb-sh commented Mar 1, 2026

ah well, they're already on it:
spotipy-dev/spotipy#1228

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

403 error on new developer app after reopening API

7 participants