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 bodyError 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