Announcements

Help Wizard

Step 1

NEXT STEP

401 No Token Provided Python

401 No Token Provided Python

I have been developing playlist tracker so that I can see the changes my loved playlists. In my development I get same error whenever I tried to use playlist_items function. 

I clear the cache files but no changes at all. I couldn't fix the issue here. Thank you for help. 

import os
import json
import time
from datetime import datetime
from dotenv import load_dotenv
import spotipy
from spotipy.oauth2 import SpotifyOAuth

# ================= CONFIG =================

load_dotenv()

CLIENT_ID = os.getenv('SPOTIFY_CLIENT_ID')
CLIENT_SECRET = os.getenv('SPOTIFY_CLIENT_SECRET')
REDIRECT_URI = os.getenv('SPOTIFY_REDIRECT_URI', 'http://127.0.0.1:8888/callback')

SCOPE = 'playlist-read-private playlist-read-collaborative'
CACHE_FILE = 'spotify_liked_playlists_cache.json'
LOG_DIR = 'playlist_changes'
RATE_LIMIT_DELAY = 0.5  # seconds

sp = spotipy.Spotify(
    auth_manager=SpotifyOAuth(
        client_id=CLIENT_ID,
        client_secret=CLIENT_SECRET,
        redirect_uri=REDIRECT_URI,
        scope=SCOPE,
        open_browser=True,
        cache_path=".cache"
    )
)

user_playlists = sp.current_user_playlists()

for idx, item in enumerate(user_playlists["items"]):
    playlist_id = item["id"]
    playlist_name = item["name"]
    print(f"\n{'='*60}")
    print(f"Playlist {idx}: {playlist_name}")
    print(f"Owner: {item['owner']['uri']}")
    print(f"{'='*60}")

    results = sp.playlist_items(playlist_id)
    tracks = results['items']

    
    while results['next']:
        time.sleep(RATE_LIMIT_DELAY)
        results = sp.next(results)
        tracks.extend(results['items'])
    
    # Print track information
    print(f"Total tracks: {len(tracks)}\n")
    for track_idx, track_item in enumerate(tracks, 1):
        if track_item['track'] is not None:  
            track = track_item['track']
            track_name = track['name']
            artists = ', '.join([artist['name'] for artist in track['artists']])
            album = track['album']['name']
            print(f"{track_idx}. {track_name} - {artists} (Album: {album})")
        else:
            print(f"{track_idx}. [Track unavailable]")
    
    time.sleep(RATE_LIMIT_DELAY)  

 

 

Reply
1 Reply

Hey @Kronos58!

 

I'm not too familiar with spotipy or why you would be getting the 401 error. However, I was able to convert your script to use a new Spotify SDK for Python I created recently and confirmed it worked for me:

 

1. Install spotify-sdk:

# using uv
uv pip install spotify-sdk

# using pip
python3 -m pip install spotify-sdk

 

2. Run the following script:

 

import os
import time

from dotenv import load_dotenv

from spotify_sdk import SpotifyClient
from spotify_sdk.auth import AuthorizationCode, FileTokenCache, authorize_local

# ================= CONFIG =================

load_dotenv()

CLIENT_ID = os.getenv("SPOTIFY_CLIENT_ID")
CLIENT_SECRET = os.getenv("SPOTIFY_CLIENT_SECRET")
REDIRECT_URI = os.getenv("SPOTIFY_REDIRECT_URI")

SCOPE = ("playlist-read-private", "playlist-read-collaborative")
CACHE_FILE = ".cache/spotify-sdk/token.json"
RATE_LIMIT_DELAY = 0.5  # seconds
PAGE_LIMIT = 50


def get_all_current_user_playlists(client: SpotifyClient):
    playlists = []
    offset = 0

    while True:
        page = client.playlists.get_for_current_user(
            limit=PAGE_LIMIT,
            offset=offset,
        )
        playlists.extend(page.items)

        if not page.next or not page.items:
            break

        offset += len(page.items)
        time.sleep(RATE_LIMIT_DELAY)

    return playlists


def get_all_playlist_items(client: SpotifyClient, playlist_id: str):
    tracks = []
    offset = 0

    while True:
        page = client.playlists.get_items(
            playlist_id,
            limit=PAGE_LIMIT,
            offset=offset,
        )
        tracks.extend(page.items)

        if not page.next or not page.items:
            break

        offset += len(page.items)
        time.sleep(RATE_LIMIT_DELAY)

    return tracks


def main() -> None:
    if not CLIENT_ID or not CLIENT_SECRET:
        raise RuntimeError(
            "Missing Spotify credentials. Set SPOTIFY_CLIENT_ID and "
            "SPOTIFY_CLIENT_SECRET in your environment."
        )

    auth = AuthorizationCode(
        client_id=CLIENT_ID,
        client_secret=CLIENT_SECRET,
        redirect_uri=REDIRECT_URI,
        scope=SCOPE,
        token_cache=FileTokenCache(CACHE_FILE),
    )

    authorize_local(auth, open_browser=True)

    with SpotifyClient(auth_provider=auth) as client:
        user_playlists = get_all_current_user_playlists(client)

        for idx, item in enumerate(user_playlists):
            playlist_id = item.id
            playlist_name = item.name

            print(f"\n{'=' * 60}")
            print(f"Playlist {idx}: {playlist_name}")
            print(f"Owner: {item.owner.uri}")
            print(f"{'=' * 60}")

            tracks = get_all_playlist_items(client, playlist_id)

            print(f"Total tracks: {len(tracks)}\n")
            for track_idx, track_item in enumerate(tracks, 1):
                if track_item.track is not None:
                    track = track_item.track
                    track_name = track.name
                    artists = ", ".join(
                        artist.name for artist in track.artists
                    )
                    album = track.album.name
                    print(
                        f"{track_idx}. {track_name} - {artists} "
                        f"(Album: {album})"
                    )
                else:
                    print(f"{track_idx}. [Track unavailable]")

            time.sleep(RATE_LIMIT_DELAY)


if __name__ == "__main__":
    main()

Note: If you set SPOTIFY_SDK_CLIENT_ID, SPOTIFY_SDK_CLIENT_SECRET, and SPOTIFY_SDK_REDIRECT_URI in your environment, the SDK finds them automatically and you can clean up your script a bit.

 

Example Output:

...

============================================================
Playlist 7: House stuff
Owner: spotify:user:jonathang09
============================================================
Total tracks: 13

1. Assumptions - Sam Gellaitry (Album: Assumptions (Jengi Remix))
2. Rather Be (feat. Jess Glynne) - Clean Bandit, Jess Glynne (Album: New Eyes)
3. Honey Boy (feat. Nile Rodgers & Shenseea) - Purple Disco Machine, Benjamin Ingrosso, Nile Rodgers, Shenseea (Album: Honey Boy (feat. Nile Rodgers & Shenseea))
4. places to be - Fred again.., Anderson .Paak, CHIKA (Album: places to be)
5. Chihiro - Gravagerz (Album: Chihiro)
6. leavemealone - Fred again.., Baby Keem (Album: USB)
7. Saving Up - Dom Dolla (Album: Saving Up)
8. Intimidated (feat. H.E.R.) - KAYTRANADA, H.E.R. (Album: Intimidated)
9. BE YOUR GIRL - KAYTRANADA REMIX - Teedra Moses, KAYTRANADA (Album: BE YOUR GIRL (KAYTRANADA REMIX))
10. Relax My Eyes - ANOTR, Abel Balder (Album: Relax My Eyes)
11. She’s Gone, Dance On - Disclosure (Album: She’s Gone, Dance On)
12. Down4Me - jsilos (Album: Stay Inspired)
13. words - Higgo Remix - piri, Tommy Villiers, Higgo (Album: words (Higgo Remix))

 

You can find more information about this SDK in the official documentation site:

https://spotify-sdk.dev/

 

If you decide to go this route, feel free to provide any feedback you have for the SDK in GitHub!

Suggested posts

Let's introduce ourselves!

Hey there you,   Yeah, you! 😁   Welcome - we're glad you joined the Spotify Community!   While you here, let's have a fun game and get…

ModeratorStaff / Moderator/ 4 years ago  in Social & Random