
The requests module can be used to issue a REST API request.
- DELETE request
- GET request
- PATCH request (typically used to update an existing resource)
- POST request (this article - typically used to create a new resource)
- PUT request (typically used to update an existing resource)
Here is how you can make a POST request.
Notice in this example that json={"foo": "hello world"} is being used. This automatically set header "Content-Type": "application/json" and serializes the dictionary {"foo": "hello world"} into a JSON string.
#!/usr/bin/python3
import requests
try:
response = requests.post(
"http://www.example.com/api",
json={"foo": "hello world"}
)
except requests.exceptions.Timeout:
print(f"POST request timed out")
except Exception as exception:
print(f"requests.post raised the following exception: {exception}")
else:
print("requests.post appears to have been successful")
Sometimes, you may want (or need to) instead use "data". Almost always, this is going to require that you set header "Content-Type": "application/json" and to also use json.dumps to convert the payload dictionary into a JSON string. It is also fairly common to include "Accept": "application/json" to let the API know that JSON is being used in the POST request.
#!/usr/bin/python3
import requests
url = "http://www.example.com/api"
headers = { "Content-Type": "application/json" }
payload = {"foo": "hello world"}
data = json.dumps(payload)
try:
response = requests.post(url, headers=headers, data=data)
except requests.exceptions.Timeout:
print(f"POST request timed out")
except Exception as exception:
print(f"requests.post raised the following exception: {exception}")
else:
print("requests.post appears to have been successful")
Perhaps this helps to visualize this, where we can see that "a" is a dictionary whereas "b" is a string.
#!/usr/bin/python
import json
a = {"foo": "hello world"}
b = json.dumps(a)
print(f"a type = {type(a)}")
print(f"b type = {type(b)}")
With this output.
a type = <class 'dict'>
b type = <class 'str'>
verify=False can be used to ignore SSL issues, such as when using a self-signed certificate. This is like using the --insecure flag in curl.
response = requests.post(url, json=payload, headers=headers, verify=False)
timeout can be used to specify how many seconds should elapse before the PUT request is timed out.
response = requests.put(url, json=payload, headers=headers, timeout=10)
Here is how you can include a username and password if basic authentication is required.
#!/usr/bin/python3
import requests
url = "http://www.example.com/api"
payload = { "foo": "hello", "bar": "world" }
headers = { "Content-Type": "application/json" }
session = requests.Session()
try:
session.auth = ("john.doe", "itsasecret")
except Exception as exception:
print(f"session.auth raised the following exception: {exception}")
else:
print("session.auth appears to have been successful")
try:
response = session.post(url, data=payload, headers=headers)
except requests.exceptions.Timeout:
print(f"POST request timed out")
except Exception as exception:
print(f"session.post raised the following exception: {exception}")
else:
print("session.post appears to have been successful")
There are a number of different objects that can be used to return useful information.
print(f"response = {response}")
print(f"response.status_code = {response.status_code}")
print(f"response.ok = {response.ok}")
print(f"response.content = {response.content}")
print(f"response.text = {response.text}")
print(f"response.json = {response.json()}")
print(f"response.headers = {response.headers}")
Since each API has it's own unique response, the response you get back will different between APIs. However, I typically expect to get some sort of response that let's me know if the request was successful or if it failed.
response = <Response [200]>
response.status_code = 200
response.ok = True
response.content = {"result":{"success":true}}
response.text = {"result":{"success":true}}
response.json = {u'result': {u'success': True}}
If some issue occurs, you may want to set logging to DEBUG to view the full request and response.
#!/usr/bin/python
import logging
try:
import http.client as http_client
except ImportError:
import httplib as http_client
http_client.HTTPConnection.debuglevel = 1
logging.basicConfig()
logging.getLogger().setLevel(logging.DEBUG)
requests_log = logging.getLogger("requests.packages.urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True
Did you find this article helpful?
If so, consider buying me a coffee over at