requests
¶Most APIs require users to identify themselves, and have limits on the volume and frequency of requests each user can make, in order to:
This typically requires users to register, upon which they're provided with credentials, typically in the form of a unique id
and an accompanying key
or secret
.
We'll be using the Spotify API throughout the tutorial. In order to use it, you'll need a Spotify account.
Follow CREATE AN APP
from the Dashboard, then copy your Client ID
and Client Secret
to somewhere handy.
In addition to the id
and secret
we've just gathered, Spotify requires us to authenticate prior to requesting data.
There are several options available; we'll be using the Client Credentials Flow. This will give us access to masses of data about the contents of the Spotify catalogue, but without access to personalized information such as user playlists.
We'll send the id
and secret
to the API using a POST
request, and be sent an access_token
in the response.
access_token
¶The documentation tells us that we'll need to:
POST
request to https://accounts.spotify.com/api/token
'grant_type': 'client_credentials'
in the request body'Authorization' : 'Basic [base64 encoded client_id:client_secret]'
in the headerFortunately, the requests.post()
and HTTPBasicAuth
functions will simplify this for us.
First of all, fork the repl. Next, create a new file called .env
, and then enter your credentials in the format shown in .env.example
.
.env
files aren't shared when a fork of a repl is made; they allow you to store values you don't want to sharemain.py
will be executed when you hit Run
. If all is well, you should see a dictionary printed in the console at the bottom.
!!! warning "Access Token"
**Take a copy of your `access_token`** from your repl's console; you'll need it later to get data from the API.
Tokens are **valid for one hour**, so come back to your fork of the repl to generate another one if needed later on.
import requests
from requests.auth import HTTPBasicAuth
import os
client_id = os.getenv("CLIENT_ID")
client_secret = os.getenv("CLIENT_SECRET")
requests
and os
packages, and the HTTPBasicAuth
submodule.getenv()
method to collect our credentials from the .env
fileWe can use the Python help()
function to see the docstring for requests.post()
:
help(requests.post)
Help on function post in module requests.api: post(url, data=None, json=None, **kwargs) Sends a POST request. :param url: URL for the new :class:`Request` object. :param data: (optional) Dictionary, list of tuples, bytes, or file-like object to send in the body of the :class:`Request`. :param json: (optional) json data to send in the body of the :class:`Request`. :param \*\*kwargs: Optional arguments that ``request`` takes. :return: :class:`Response <Response>` object :rtype: requests.Response
url = 'https://accounts.spotify.com/api/token'
data = {'grant_type': 'client_credentials'}
auth=HTTPBasicAuth(client_id, client_secret)
url
is the one given by the API documentationdata
is the parameter:value
pair required to be in the bodyauth
is an optional keyword argumentHTTPBasicAuth
method has done the required encoding and formatting of the credentials for usPOST
request¶response = requests.post(url, data=data, auth=auth)
response.ok
we used the .post()
method of requests
with the arguments we had defined, assigning the returned object to response
the .ok
attribute of the Response
object is True
, meaning that the response was successful
response.json()
{'access_token': 'BQA5XobojGmQ22qGfcf1XSX1xTJD6pH6oeltC5HtX5fML8ps_uDp1U74ybc5M45CmmRf8DX8FAFjOivOae4', 'token_type': 'Bearer', 'expires_in': 3600, 'scope': ''}
.json()
method of the response
object returned by the API converts the included JSON object into a Python dictionarykey:value
pairs include the access_token
we need; highlight and right-click it to copy (usual shortcuts don't work in the console)expires_in
value - this is the time in seconds (i.e. one hour) that the token will remain usable forresponse.status_code
200
The .status_code
attribute indicates whether the request was successful, and if not, what went wrong.
200
is good news, as is anything in the 200
s 400
s typcially indicate an issue with your code or parameters500
s indicate something is malfunctioning on the serverJSON (JavaScript Object Notation) is the most popular data format used by web APIs.
Fortunately for Python programmers, it is fairly straightforward to map JSON to equivalent Python data structures, data types and values (and as shown above, modules which can do this for us).
key:value
pairs inside {
braces }
[
brackets ]
The JSON values true
, false
and null
are equivalent to the Python values True
, False
and None
respectively.