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:value
pairs toparams
- we used our
params
dictionary as theparams
argument in theGET
request
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,
type
wasn'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
items
value 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_token
and a trackid
as arguments - searching for artists, using an
access_token
and 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.