Requests
01 / 02

Basic Requests, JSON & Error Handling

Requests: Basic Requests, JSON & Error Handling

Requests is Python's "HTTP for Humans" library -- an ergonomic API layered on top of urllib3's connection pooling/retry primitives, the de facto standard for making HTTP requests in Python. Built on urllib3: simplicity on top, robustness underneath.

Basic Requests & JSON

import requests

# GET with query parameters -- properly URL-encoded automatically
response = requests.get(
    'https://api.example.com/search',
    params={'q': 'python', 'page': 2},
    timeout=5,  # NO default timeout exists -- can hang forever without this
)

data = response.json()  # shorthand for json.loads(response.text)

# POST with a JSON body -- json= serializes AND sets
# Content-Type: application/json automatically
response = requests.post(
    'https://api.example.com/users',
    json={'name': 'Alice', 'email': 'alice@example.com'},
    headers={'Authorization': f'Bearer {token}'},
    timeout=5,
)

# GOTCHA: data= sends application/x-www-form-urlencoded, NOT JSON --
# a common source of confusion when an API expects json=
requests.post(url, data={'username': 'alice'})  # form-encoded
requests.post(url, json={'username': 'alice'})   # JSON body

Error Handling

try:
    response = requests.get(url, timeout=5)
    response.raise_for_status()  # raises HTTPError for 4xx/5xx, no-op on success
except requests.exceptions.Timeout:
    print('Server took too long to respond')
except requests.exceptions.ConnectionError:
    print('Could not reach the server at all')
except requests.exceptions.HTTPError as e:
    print(f'Server responded with an error: {e}')

# .content (raw bytes) vs .text (decoded string) -- use .content
# for binary data like images/PDFs, .text for actual text content
with open('photo.jpg', 'wb') as f:
    f.write(requests.get(image_url).content)

Response Inspection

response.status_code       # 200, 404, 500, etc.
response.headers['Content-Type']  # case-insensitive dict-like object
response.url                # final URL after following any redirects

# allow_redirects=True is the GET default -- follows 3xx automatically.
# Set False to inspect the redirect response itself instead.
response = requests.get(url, allow_redirects=False)

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free