Using query parameters with requests
Query parameters
When making requests for data relating to a particular track or album, the URL itself (with the {id} at the end of the endpoint) is sufficient to specify the data we want returned:
https://api.spotify.com/v1/albums/1To7kv722A8SpZF789MZy7
However, we often need or want to be more specific, for example:
- making a search for data with specific features
- fetching a subset of data from a given collection
APIs tend to be structed to handle such requests through the use of query parameters.
Example requiring query parameters
Take a look at the API documentation for Search.
You'll notice that values for the q (short for 'query') and type parameters are required - our request will fail if we don't provide them.
Fear not - requests is here to make life easier for us.
Code walkthrough
First, fork the repl.
Access Token
Remember that you'll need to enter your own valid access_token, which you can generate by forking this repl and adding your own Spotify API credentials to a .env file.
Run the repl, copy your access_token from the console, and and paste it into main.py in the repl for the walkthrough.
import requests
headers = {'Authorization': f'Bearer {access_token}'}
base_url = 'https://api.spotify.com/v1'
search_endpoint = '/search'
search_url = f'{base_url}{search_endpoint}'
params = {'q': 'waterfall', 'type': 'track'}
response = requests.get(search_url, headers=headers, params=params)
The params keyword argument
Having covered authorization and endpoints in the MixTape tutorial, we'll skip straight to the relevant code for query parameters:
params = {'q': 'waterfall', 'type': 'track'}
response = requests.get(search_url, headers=headers, params=params)
- we assigned a dictionary containing the
parameter:valuepairs toparams - we used our
paramsdictionary as theparamsargument in theGETrequest
Examining the response
After running the repl, you can try out the following code snippets in the console.
data = response.json()
type(data)
dict
list(data.keys())
['tracks']
- the top-level dictionary has only one key; perhaps at some stage,
typewasn't a required query parameter and so the returned dataset could also have contained albums, artists, etc
More nested data...
list(data['tracks'].keys())
['href', 'items', 'limit', 'next', 'offset', 'previous', 'total']
- the keys in the next level relate to the search itself, including data on relevant tracks
- the
itemsvalue is a list of dictionaries, each containing data about a given track
- the
- each item in this list is a dictionary, some of whose values are also data structures
We have to go deep into the JSON structure to find our individual track data:
print(list(data['tracks']['items'][0].keys()))
['album', 'artists', 'available_markets', 'disc_number', 'duration_ms', 'explicit', 'external_ids', 'external_urls', 'href', 'id', 'is_local', 'name', 'popularity', 'preview_url', 'track_number', 'type', 'uri']
len(data['tracks']['items'])
20
- our request has returned 20
items, but there are many more tracks which were identified by our search...
Result and rate limits on API requests
APIs will not typically return all items if there are a large number of matches; instead, further calls to the API will be required. You may also encounter limits on the frequency or volume of requests to an API or particular endpoint.
print(waterfall_tracks['tracks']['total'])
print(waterfall_tracks['tracks']['limit'])
print(waterfall_tracks['tracks']['next'])
97307
20
https://api.spotify.com/v1/search?query=waterfall&type=track&offset=20&limit=20
- given the total number of results, we can see why there is a limit rather than returning all of them :)
- the Spotify API conveniently provides us with an endpoint for the next block of tracks
Your turn...
Spend some time using requests.get() to fetch data from endpoints listed under Albums, Artists, Browse, Search, and Tracks in the documentation; all of these can be done using the Client Credentials access_token you created earlier.
See if you can create some reuable functions, to do things such as:
- fetching data for a given track, using an
access_tokenand a trackidas arguments - searching for artists, using an
access_tokenand a string of keywords as arguments
For now, don't worry about automatically renewing the access_token or diving too deep into the nested data - we'll be looking at that later on.