- Published on
Using the Spotify Web API in a Python application
python- Authors
- Name
- Ndamulelo Nemakhavhani
- @ndamulelonemakh
Pre-requisites
- A Spotify Developer Account - Register here
- A Spotify developer Application(Take note of the ClientID and Client Secret)
- Flask - Install using pip
- requests - Install using pip
- Pipenv - Optional but recommended
Spotify provides different ways to authenticated and/or authorize users in order to access resources on their accounts. In this tutorial, we will look at the Authorization Code Flow method.
NB: This method is NOT suitable for public clients(i.e. Client-side Javascript or single page applications). Only use this for server applications which are not exposed to the public
- Here is a full working example on github
i. Step 1 - Create a flask application running on localhost
import os
import flask
import requests
HOST_IP_ADDRESS = '127.0.0.1'
HOST_PORT = 9000
# Create a flask application
app = flask.Flask('YOUR_APP_NAME')
# Create a default route
@app.route('/')
def index():
return 'It works!'
"""
$ This route will redirect the user to the spotify login page
$ Once the user is authenticated, spotify will send an Authorization Code to the specified REDIRECT_URI
$ NB: Make sure to specify all the required SCOPES for the services you intend to use
$ Reference: https://developer.spotify.com/documentation/web-api/tutorials/code-flow
"""
@app.route('/login')
def login():
authentication_request_params = {
'response_type': 'code',
'client_id': os.getenv('CLIENT_ID'),
'redirect_uri': os.getenv('REDIRECT_URI'), # In this case we set it to http://localhost:9000/callback
'scope': 'user-read-email user-read-private user-top-read',
'state': str(uuid.uuid4()),
'show_dialog': 'true'
}
auth_url = 'https://accounts.spotify.com/authorize/?' + urllib.urlencode(authentication_request_params)
# Opens the spotify login page using the default browser
webbrowser.open_new_tab(auth_url)
if __name__ == '__main__':
app.run(HOST_IP_ADDRESS, HOST_PORT)
ii. Step 2 - Add the authorization callback handler
# .....
def _get_access_token(authorization_code:str):
spotify_request_access_token_url = 'https://accounts.spotify.com/api/token/?'
body = {'grant_type': 'authorization_code',
'code': authorization_code,
'client_id': os.getenv('CLIENT_ID'),
'client_secret': os.getenv('CLIENT_SECRET'),
'redirect_uri': os.getenv('REDIRECT_URI')
}
response: requests.Response = requests.post(spotify_request_access_token_url, data=body)
if response.status_code == 200:
return response.json()
raise Exception(f'Failed to obtain Access token.Response: {response.text}')
"""Callback route
$ This is the url that the user will be REDIRECTED to after the spotify login screen
$ The URL must match the REDIRECT_URL setting on your spotify developer dashboard
$ Spotify will send back a code which is then used to request an access token through a 'back-chanel'
"""
@app.route('/callback')
def callback():
code = flask.request.args.get('code')
credentials = _get_access_token(authorization_code=code)
os.environ['token'] = credentials['access_token']
return f"Authentication successful. Access token: {credentials['access_token']}"
# ....
Step 3 - Test the API (Get Current User's top tracks)
- Check out the documentation for more usage info
# ....
@app.route('/top-tracks')
def top_tracks():
root_url = 'https://api.spotify.com/v1/me/top/{tracks}'
# NB: Add the access token to the request header
headers = {
'Authorization': f'Bearer {os.getenv("token")}'
}
request_params = {
'time_range': 'medium_term',
'limit': 20,
'offset': 0
}
# NOTE: This requires the scope 'user-top-read'
full_url = root_url + urllib.urlencode(request_params)
response = requests.get(full_url,
headers=headers,
params=request_params)
if response.status_code == 200:
return response.json()
raise Exception(f'API Call to {full_url} failed. {response.text}')
# .....
Conclusion
- Here is a full working example on github
- Suggested improvements:
- Verify the state value on the authentication callback handler
- Add a token refresh handler
- Check if token is expired before making a request
- etc.