Python Tutorial menu

Python Working With APIs (requests)

An API lets your program talk to another program over the internet, and the requests library makes that conversation easy.

What is a Web API?

When a weather app shows Karachi's temperature, it did not measure it. It asked a weather service's API. The app sends a request to a web address (an endpoint), and the service sends back a response, usually in JSON.

PartMeaning
EndpointThe URL you call, e.g. https://api.example.com/users/1
MethodWhat you want: GET to read, POST to create, PUT/PATCH to change, DELETE to remove
Status codeA number that says how it went, e.g. 200 OK
HeadersExtra information, like the content type or an API key
BodyThe data itself, often JSON

Install requests

requests is not built in. Install it inside your virtual environment:

Example

bash
pip install requests

The examples below use JSONPlaceholder, a free practice API with fake data. It needs no sign-up and no key.

A GET Request

Example

python
import requests

response = requests.get("https://jsonplaceholder.typicode.com/todos/1", timeout=10)

print(response.status_code)
print(response.headers["Content-Type"])
print(response.text)
Output
200
application/json; charset=utf-8
{
  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false
}

response.text is the raw text. Usually you want Python objects instead, so call .json():

Example

python
import requests

response = requests.get("https://jsonplaceholder.typicode.com/users/1", timeout=10)
user = response.json()

print(type(user))
print(user["name"])
print(user["email"])
print(user["address"]["city"])
Output
<class 'dict'>
Leanne Graham
Sincere@april.biz
Gwenborough

Always pass a timeout. Without it, your program can wait forever if the server never answers.

Query Parameters

Many APIs let you filter results with ?key=value at the end of the URL. Let requests build that part for you with params:

Example

python
import requests

response = requests.get(
    "https://jsonplaceholder.typicode.com/posts",
    params={"userId": 1},
    timeout=10,
)
posts = response.json()

print("Posts by user 1:", len(posts))
print("First post id:", posts[0]["id"])
print("Every post is by user 1:", all(p["userId"] == 1 for p in posts))
Output
Posts by user 1: 10
First post id: 1
Every post is by user 1: True

requests turns params={"userId": 1} into ?userId=1 and also handles spaces and special characters safely.

Status Codes

CodeMeaning
200OK, here is your data
201Created (after a successful POST)
400Bad request: your data is wrong
401 / 403Not logged in / not allowed
404Not found
429Too many requests, slow down
500The server has a problem

Codes in the 200s mean success. response.ok is True for any code below 400.

A POST Request

To send data, use requests.post() with json=. requests converts your dictionary to JSON and sets the right header.

Example

python
import requests

new_post = {"title": "Python class timings", "body": "Mon to Thu, 6 pm", "userId": 1}
response = requests.post("https://jsonplaceholder.typicode.com/posts", json=new_post, timeout=10)

print(response.status_code)
created = response.json()
print(created["id"], created["title"])
Output
201
101 Python class timings

JSONPlaceholder pretends to save the post and gives it the id 101. A real API would store it.

Handling Errors

Things go wrong on networks: no internet, a slow server, a wrong URL. Use raise_for_status() to turn bad codes (400 and above) into exceptions, and catch them with try...except.

Example

python
import requests

def get_json(url):
    try:
        response = requests.get(url, timeout=5)
        response.raise_for_status()
        return response.json()
    except requests.exceptions.HTTPError as err:
        print("HTTP error:", err.response.status_code)
    except requests.exceptions.ConnectionError:
        print("Could not connect. Check your internet.")
    except requests.exceptions.Timeout:
        print("The server took too long.")
    return None

print(get_json("https://jsonplaceholder.typicode.com/todos/1")["title"])
print(get_json("https://jsonplaceholder.typicode.com/posts/99999"))
Output
delectus aut autem
HTTP error: 404
None

Headers and API Keys

Real APIs usually need a key to know who is calling. You send it in a header. Keep the key out of your code by reading it from an environment variable.

Example

python
import os
import requests

api_key = os.environ.get("WEATHER_API_KEY", "")
headers = {"Authorization": f"Bearer {api_key}", "Accept": "application/json"}

response = requests.get("https://api.example.com/v1/weather", params={"city": "Karachi"}, headers=headers, timeout=10)

Never put API keys or passwords directly in your code, and never upload them to GitHub. Anyone who sees the key can use your account.

Sessions

If you call the same API many times, a Session reuses the connection and remembers headers, which is faster.

Example

python
import requests

with requests.Session() as s:
    s.headers.update({"Accept": "application/json"})
    for n in [1, 2, 3]:
        r = s.get(f"https://jsonplaceholder.typicode.com/users/{n}", timeout=10)
        print(n, r.status_code)

Exercise

Exercise

Which line turns a JSON response into a Python dictionary?

Learn Python with a teacher

Join the Python Programming course at Workownix, online or in Orangi Town, Karachi, and get a certificate.

See the course Ask on WhatsApp