Announcements

Help Wizard

Step 1

NEXT STEP

FAQs

Please see below the most popular frequently asked questions.

Loading article...

Loading faqs...

VIEW ALL

Ongoing Issues

Please see below the current ongoing issues which are under investigation.

Loading issue...

Loading ongoing issues...

VIEW ALL

web API Forbidden 403 on PUT/DELETE Queue

Solved!

web API Forbidden 403 on PUT/DELETE Queue

Plan

Free

 

I successfully generated token for API and can make a POST requests with curl from my local machine on win10
and from my dedicated linux server without problems
for example:
curl -X GET https://api.spotify.com/v1/playlists/********** -H "Authorization: Bearer ***HASH***"

but when I trt to make PUT/DELETE requests for(Save Tracks for Current User) current user's 'Your Music' library like this

curl -X PUT https://api.spotify.com/v1/me/tracks?ids=7ouMYWpwJ422jRcDASZB7P%2C4VqPOruhp5EdPBeR92t6lQ%2C2takcwOaA... -H "Authorization: Bearer ***HASH***"

i got error:

"error" : {
"status" : 403,
"message" : "Forbidden."
}
If I executing this from page
https://developer.spotify.com/documentation/web-api/reference/save-albums-user
it's working fine

Why this happens? my API key have not right permissions?

 

 

Reply

Accepted Solutions
Marked as solution

I'm find out
for edit liked songs library need to use SCOPE:user-library-modify
everything working now!

 

View solution in original post

3 Replies

You have likely generated a token using Client Credentials, but to access and edit user data, you will need to generate a token through the Authorization Code Flow.

XimzendSpotify Star
Help others find this answer and click "Accept as Solution".
If you appreciate my answer, maybe give me a Like.
Note: I'm not a Spotify employee.

Thanks for advice but I still getting 403,"message" : "Forbidden." even after I generated access tokens from "code flow"

Here is my walkthrough Authorization Code Flow scheme in python :

1u_0-1698006130902.png

so for running I use 3 python files:
spo.py
refresh.py
access.py

Go to dir where spo.py file is located and run this in linux console:
uvicorn spo:app --host 0.0.0.0 --port 8000 2>&1 | tee -a uvicorn_access.log

then open in browser http://localhost:8000  complete autorisation wih your log&pass and then click on Authorize link
after that run once in console:
python3 refresh.py
and finally
python3 access.py
access_tokenS will be in accessT.txt
it have rights permissions as I can see

1u_1-1698008269251.png

after that I'm trying some API requests:

add-tracks-to-playlist : (WORKING)
curl -X POST 'https://api.spotify.com/v1/playlists/*****/tracks?uris=spotify%3Atrack%3A7hkYSZ1Ry7OeBGrTzLhg0c' -H "Authorization: Bearer $(tail -n 1 /PATH/accessT.txt)"

save-tracks-user : (NOT WORKING)
curl --request PUT 'https://api.spotify.com/v1/me/tracks?ids=7hkYSZ1Ry7OeBGrTzLhg0c' --header "Authorization: Bearer $(tail -n 1 /PATH/accessT.txt)"

getting 403,"message" : "Forbidden.
If I intentionally corrupt the token, it says the token is invalid
So could it be related to my free plan or not?
also I'm tryed access tokens*1 and *2 with same result it can see on my scheme upper
can anybody help me?
here is my source code files:
spo.py

 

 

from fastapi import FastAPI
from fastapi.responses import HTMLResponse
import requests
import uvicorn

client_id = "99493f576c2d43018***************"
client_secret = "8debd3e6994b4***************"
redirect_uri = "http://localhost:8000" # e.g. http://localhost:8000/callback/ --> you will have to whitelist this url in the spotify developer dashboard 

app = FastAPI()
def get_access_token(auth_code: str):
    response = requests.post(
        "https://accounts.spotify.com/api/token",
        data={
            "grant_type": "authorization_code",
            "code": auth_code,
            "redirect_uri": redirect_uri,
	    # not work"state: state": state
        },
        auth=(client_id, client_secret),
    )
    access_token = response.json()["access_token"]
    return {"Authorization": "Bearer "**bleep**("/")
async def auth():
    scope = ["playlist-modify-private", "playlist-modify-public"]  #Permissions
    auth_url = f"https://accounts.spotify.com/authorize?response_type=code&client_id={client_id}&redirect_uri={redirect_uri}&scope={' '.join(scope)}"
    return HTMLResponse(content=f'<a href="{auth_url}">Authorize</a>')
#if __name__ == "__main__":
#    uvicorn.run(app)
#RUN in console =>> uvicorn spo:app --host 0.0.0.0 --port 8000 2>&1 | tee -a uvicorn_access.log

 

 

 

refresh.py

 

 

import re
import requests
import base64
import json

# Spotify API credentials
client_id = "99493f576c2d430******"
client_secret = "8debd3e6994******"
redirect_uri = "http://localhost:8000"
# Define the URL for the /api/token endpoint
token_url = "https://accounts.spotify.com/api/token"

#Read last line from uvicorn_access.log for hash CODE
###########################################################
with open("/PATH/uvicorn_access.log", "r") as log_file:
    # Read the last line from the log file
    lines = log_file.read().splitlines()
    last_line = lines[-1]

    # Use regular expression to find the code in the last line
    code_match = re.search(r'code=([^&\s"]+)', last_line)

    if code_match:
        code = code_match.group(1)
        #print(f"{code}")
    else:
        print("Code not found in the last line.")
###########################################################
# Prepare the data for the request body
data = {
    #"code": "TEST_HASH",
    "code": code, # from uvicorn_access.log
    "redirect_uri": redirect_uri,
    "grant_type": "authorization_code"
}

encoded = base64.b64encode((client_id + ":" + client_secret).encode("ascii")).decode("ascii")
# Prepare the headers for the request
headers = {
    "Content-Type": "application/x-www-form-urlencoded",
    "Authorization": "Basic " + encoded
}

# Send the POST request
response = requests.post(token_url, data=data, headers=headers)

# Check the response
if response.status_code == 200:
    response_data = response.json()
    print("Full JSON Response:")
    print(json.dumps(response_data, indent=4))
    refresh_token = response_data["refresh_token"]
    access_token = response_data["access_token"]
######SAVE TO LOGS
    # Append the refresh_token to the end of the log file
    with open("/PATH/uvicorn_access.log", "a") as log_file:
        log_file.write(f"refresh_token: {refresh_token}\n")

    # Append the access_tokenS to the end of the log file
    with open("/PATH/accessT.txt", "a") as log_file:
        log_file.write(f"{access_token}\n")
#########
else:
    print(f"Error: {response.status_code}, {response.text}")

 

 

 

access.py

 

 

import re
import requests
import base64
import json

# Spotify API credentials
client_id = "99493f576c2d43***********"
client_secret = "8debd3e699***********"
# Define the URL for the /api/token endpoint
token_url = "https://accounts.spotify.com/api/token"

#Read last line from uvicorn_access.log for hash of refresh_token
###########################################################
with open("/PATH/uvicorn_access.log", "r") as log_file:
    # Read the last line from the log file
    lines = log_file.read().splitlines()
    last_line = lines[-1]

    # Use regular expression to find the code in the last line
    token_match = re.search(r'refresh_token: ([^\s]+)', last_line)

    if token_match:
        refresh_token = token_match.group(1)
        #print(f"{refresh_token}")
    else:
        print("Refresh Token not found in the last line.")
###########################################################
# Prepare the data for the request body
data = {
    "grant_type": "refresh_token",
    "refresh_token": refresh_token, # from uvicorn_access.log
}

encoded = base64.b64encode((client_id + ":" + client_secret).encode("ascii")).decode("ascii")
# Prepare the headers for the request
headers = {
    "Content-Type": "application/x-www-form-urlencoded",
    "Authorization": "Basic " + encoded
}

# Send the POST request
response = requests.post(token_url, data=data, headers=headers)

if response.status_code == 200:
    response_data = response.json()
    print("Full JSON Response:")
    print(json.dumps(response_data, indent=4))
    access_token = response_data["access_token"]
    #print(f"Access Token: {access_token}")

    # Append the access_tokenS to the end of the log file
    with open("/PATH/accessT.txt", "a") as log_file:
        log_file.write(f"{access_token}\n")
else:
    print(f"Error: {response.status_code}, {response.text}")

 

 

 







 

 

Marked as solution

I'm find out
for edit liked songs library need to use SCOPE:user-library-modify
everything working now!

 

Suggested posts