Getting 400 Bearer Authentication Error with Python Spotify Web API

Hey everyone! I’m working on a Python project to connect to the Spotify Web API and I keep running into this annoying 400 error. The authentication part seems to work fine, but when I try to make a search request I get an error saying “Only valid bearer authentication supported”.

Here’s my code:

import base64, requests
import datetime
from urllib.parse import urlencode

app_id = "your_app_id"
app_secret = "your_app_secret"

class MusicAPI(object):
    token = None
    token_expires = datetime.datetime.now()
    token_expired = True
    app_id = None
    app_secret = None
    auth_url = "https://accounts.spotify.com/api/token"

    def __init__(self, app_id, app_secret, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.app_id = app_id
        self.app_secret = app_secret

    def encodeCredentials(self):
        app_id = self.app_id
        app_secret = self.app_secret
        
        if app_id is None or app_secret is None:
            raise Exception('App ID and secret are required')
        
        credentials = f"{app_id}:{app_secret}"
        encoded_creds = base64.b64encode(credentials.encode())
        return encoded_creds.decode()

    def buildAuthHeader(self):
        encoded_creds = self.encodeCredentials()
        return {
            'Authorization': f"Basic {encoded_creds}"
        }

    def buildTokenData(self):
        return {
            "grant_type": "client_credentials"
        }

    def authenticate(self):
        auth_url = self.auth_url
        token_data = self.buildTokenData()
        auth_header = self.buildAuthHeader()
        
        response = requests.post(auth_url, data=token_data, headers=auth_header)
        
        if response.status_code not in range(200, 299):
            return False
        
        current_time = datetime.datetime.now()
        response_data = response.json()
        token = response_data['access_token']
        expires_in = response_data['expires_in']
        expiry_time = current_time + datetime.timedelta(seconds=expires_in)
        self.token = token
        self.token_expires = expiry_time
        self.token_expired = expiry_time < current_time
        
        return True

music_client = MusicAPI(app_id, app_secret)
print(music_client.authenticate())
current_token = music_client.token

request_header = {
    "Authorization": f"Bearer {current_token}"
}
search_endpoint = "https://api.spotify.com/v1/search"
query_params = urlencode({"q": "Love", "type": "track"})

full_url = f"{search_endpoint}?{query_params}"

response = requests.get(full_url, headers=request_header)
print(response.json())

The authentication returns True so that part works, but then I get this error: {'error': {'status': 400, 'message': 'Only valid bearer authentication supported'}}. Can someone help me figure out what I’m doing wrong? Thanks!

Had this exact problem building a similar integration. Your token validation probably happens after you’ve already extracted it. Add a method to check if the token’s valid before making API calls - something like datetime.datetime.now() < self.token_expires. I found the authentication step sometimes completes but corrupts the token during assignment. Spotify’s error messages are misleading too - I’ve gotten “Only valid bearer authentication supported” when the token format was right but expired or invalid. Try calling authenticate() again right before your search request for a fresh token.

Your token extraction is probably broken. I hit this same issue with Spotify’s API - the JSON response structure wasn’t what I expected and response_data['access_token'] kept returning None or getting corrupted. Throw a print(response.text) right after your auth request to see what’s actually coming back. Also, your token_expired logic is bugged - you’re setting it to True right after getting a fresh token. Fix that to actually track expiration properly. And check if your app_id and app_secret have invisible characters messing up the base64 encoding.

Your token timing logic is off. I had the same issue where token_expired wasn’t getting set right after authentication. You’re doing self.token_expired = expiry_time < current_time right after getting the token, which immediately marks it expired since current_time equals the time you just grabbed.

Just change that to self.token_expired = False after successful auth, or delete the line completely since you’ve already got expiry_time for later checks. Also throw in a quick validation before the search request to make sure the token isn’t None or empty. I’ve seen auth look successful but token extraction fail silently.

I encountered a similar 400 error with the Spotify Web API, and it turned out to be an issue with how the token was used in the request. Make sure to double-check the token before utilizing it in your API call. A common oversight is inadvertently including whitespace in the token string. You can verify this by printing the token just before the request. Additionally, ensure that the request header accurately reflects the required format. If you’ve confirmed the token is correct but still face issues, consider examining the scope associated with your app. The permissions specified might not align with the API actions you’re trying to perform.

You’re not checking if authentication actually worked before using the token. Even if authenticate() returns true, the token could still be None or malformed. Add print(f"Token: {current_token}") right before your search request to see what’s actually being sent. Also check for extra spaces or newlines in your app credentials - that can mess up the base64 encoding.