- Explain the parts of an HTTP request and response, the main methods and the status codes
- Send GET requests with parameters and POST requests with a JSON body using
requests - Write robust code with timeouts,
raise_for_statusand exceptions, and keep API keys secret
The weather forecast on your phone, a bank's exchange rates, a route on a map — programs get all this data from servers through an API (Application Programming Interface). The Educora apps also load lessons from the website's API. A web API is a simple agreement: you send an HTTP request to a certain address, and the server usually returns a JSON response. In Python the most popular tool for this is the requests library.
HTTP in brief
A request has four parts: the method (what to do), the URL (where), the headers (extra information: format, key) and the body (the data being sent, for example JSON). A response consists of a status code, headers and a body. The part of the URL after ? holds the query parameters (the query string): ?city=Baku&units=metric.
GET /v1/weather?city=Baku&units=metric HTTP/1.1
Host: api.example.com
Accept: application/json
HTTP/1.1 200 OK
Content-Type: application/json
{"city": "Baku", "temp": 24.5, "wind": 7.2, "description": "sunny"}api.example.com is an example address reserved for documentation — all the responses in this lesson are illustrative.| Method | Meaning | Example |
|---|---|---|
GET | read data | GET /v1/tasks |
POST | create a new object | POST /v1/tasks |
PUT / PATCH | replace / partly update an object | PATCH /v1/tasks/42 |
DELETE | delete an object | DELETE /v1/tasks/42 |
| Code | Meaning |
|---|---|
| 200, 201, 204 | success: OK, Created, No Content |
| 301, 302 | redirect — look at another address |
| 400, 401, 403, 404 | client error: bad request, not logged in, forbidden, not found |
| 429 | too many requests — the limit is exceeded, wait |
| 500, 503 | server error, service unavailable |
Requests with requests
Install the library on your computer: pip install requests. Python in the browser cannot send network requests, so the code in this lesson is not runnable here — try it on your own computer. requests.get returns a response object: status_code, headers, text, json(). Do not glue parameters into the URL by hand: the params dictionary encodes them correctly, for example “Sumqayıt” becomes Sumqay%C4%B1t.
import requests
url = 'https://api.example.com/v1/weather'
params = {'city': 'Baku', 'units': 'metric'}
headers = {'Accept': 'application/json'}
response = requests.get(url, params=params, headers=headers, timeout=10)
print(response.status_code)
print(response.url)
print(response.headers['Content-Type'])
data = response.json()
print(data['city'], data['temp'])200 https://api.example.com/v1/weather?city=Baku&units=metric application/json Baku 24.5
response.json() turns the JSON body into a Python dictionary. The output is an example: a real API would return a different temperature.To create a new object we send a POST. The json= argument converts the dictionary to JSON and adds the Content-Type: application/json header by itself. On successful creation the server usually returns code 201 and the new object (with its identifier).
import requests
new_task = {'title': 'Finish the pandas lesson', 'done': False}
r = requests.post('https://api.example.com/v1/tasks', json=new_task, timeout=10)
print(r.status_code)
print(r.json())
print(r.request.headers['Content-Type'])201
{'id': 42, 'title': 'Finish the pandas lesson', 'done': False}
application/jsonErrors, timeouts and raise_for_status
Careful: a 404 or 500 response is not an error for requests — the code quietly continues. raise_for_status() raises an HTTPError for 4xx and 5xx codes. Network problems are separate exceptions: Timeout and ConnectionError; all of them derive from requests.exceptions.RequestException.
import requests
def get_json(url, **params):
try:
r = requests.get(url, params=params, timeout=5)
r.raise_for_status()
return r.json()
except requests.exceptions.Timeout:
print('The server did not answer in time')
except requests.exceptions.HTTPError as e:
print('HTTP error:', e.response.status_code)
except requests.exceptions.RequestException as e:
print('Network problem:', type(e).__name__)
return None
print(get_json('https://api.example.com/v1/weather', city='Atlantis'))HTTP error: 404 None
RequestException); otherwise they would never be reached.Keeping API keys safe
Most APIs identify you by a key (an API key or token). A key is like a password: anyone who knows it can send requests in your name, use up your limit and even run up charges. The rules:
- Never write the key in your code or commit it to Git — keep it in an environment variable.
- If you use a
.envfile, add it to.gitignore. - If the API allows it, send the key in a header, not in the URL: URLs end up in logs and browser history.
- Do not put a secret key into browser or mobile app code — any user can extract it; send such requests through your own server.
- If a key leaks, revoke it immediately and create a new one.
# Linux / macOS
export WEATHER_API_KEY='paste-your-key-here'
# Windows PowerShell
$env:WEATHER_API_KEY = 'paste-your-key-here'.env file.import os
import requests
api_key = os.environ.get('WEATHER_API_KEY')
if not api_key:
raise SystemExit('Set the WEATHER_API_KEY environment variable first')
session = requests.Session()
session.headers.update({'Authorization': f'Bearer {api_key}'})
r = session.get('https://api.example.com/v1/weather', params={'city': 'Baku'}, timeout=10)
r.raise_for_status()
print(r.json()['description'])sunny
Session adds it to the header of every request. The exact header name (Authorization, X-API-Key, etc.) is given in the API's documentation.Key points
- An HTTP request: method, URL, headers, body; a response: status code, headers, body (often JSON).
- GET reads, POST creates, PUT/PATCH update, DELETE deletes; 2xx is success, 4xx a client error, 5xx a server error.
requests.get(url, params=..., headers=..., timeout=...)andrequests.post(url, json=...); get the result withr.json().- Always pass
timeoutand callraise_for_status(); catch exceptions from specific to general. - An API key lives in an environment variable, travels in a header and never goes into Git; if it leaks, revoke it.
Check yourself
10 questions. Every correct answer earns XP.
requests.get(...) do?