Here's how to make HTTP requests in Python, from simple to advanced.
Using requests (Recommended)
Install: pip install requests
Basic Requests
import requests
# GET request
response = requests.get("https://api.example.com/users")
print(response.status_code) # 200
print(response.json()) # Parse JSON response
# POST request
response = requests.post(
"https://api.example.com/users",
json={"name": "Alice", "email": "alice@example.com"}
)
# Other methods
requests.put(url, json=data)
requests.patch(url, json=data)
requests.delete(url)
requests.head(url)Query Parameters
# Add query string parameters
response = requests.get(
"https://api.example.com/search",
params={"q": "python", "page": 1, "limit": 10}
)
# URL: https://api.example.com/search?q=python&page=1&limit=10Headers
headers = {
"Authorization": "Bearer your-token",
"Content-Type": "application/json",
"User-Agent": "MyApp/1.0"
}
response = requests.get(url, headers=headers)
# Access response headers
print(response.headers["Content-Type"])Request Body
# JSON body (most common)
requests.post(url, json={"key": "value"})
# Form data
requests.post(url, data={"field": "value"})
# Raw data
requests.post(url, data="raw content", headers={"Content-Type": "text/plain"})Authentication
# Basic auth
requests.get(url, auth=("username", "password"))
# Bearer token
requests.get(url, headers={"Authorization": "Bearer token"})
# Custom auth
from requests.auth import AuthBase
class TokenAuth(AuthBase):
def __init__(self, token):
self.token = token
def __call__(self, r):
r.headers["X-API-Key"] = self.token
return r
requests.get(url, auth=TokenAuth("my-api-key"))Response Handling
response = requests.get(url)
# Status
response.status_code # 200
response.ok # True if 200-299
response.raise_for_status() # Raises HTTPError if not ok
# Content
response.text # String content
response.json() # Parse JSON
response.content # Raw bytes
# Headers
response.headers # Response headers
# Request info
response.url # Final URL (after redirects)
response.request.headers # Request headers sentTimeouts
# Always use timeouts!
response = requests.get(url, timeout=10) # 10 seconds
# Separate connect and read timeouts
response = requests.get(url, timeout=(3, 10)) # 3s connect, 10s readError Handling
import requests
try:
response = requests.get(url, timeout=10)
response.raise_for_status()
data = response.json()
except requests.exceptions.Timeout:
print("Request timed out")
except requests.exceptions.ConnectionError:
print("Connection failed")
except requests.exceptions.HTTPError as e:
print(f"HTTP error: {e}")
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}")Sessions
Persist settings across requests:
session = requests.Session()
session.headers.update({"Authorization": "Bearer token"})
# All requests use the same headers
session.get(url1)
session.get(url2)
# With context manager
with requests.Session() as session:
session.get(url)File Upload
# Upload file
with open("file.txt", "rb") as f:
response = requests.post(url, files={"file": f})
# Multiple files
files = {
"file1": open("file1.txt", "rb"),
"file2": ("custom_name.txt", open("file2.txt", "rb"))
}
response = requests.post(url, files=files)Download Files
# Small files
response = requests.get(url)
with open("file.txt", "wb") as f:
f.write(response.content)
# Large files (streaming)
with requests.get(url, stream=True) as response:
with open("large_file.zip", "wb") as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)Using urllib (Standard Library)
from urllib.request import urlopen, Request
from urllib.parse import urlencode
import json
# Simple GET
with urlopen("https://api.example.com/data") as response:
data = json.loads(response.read())
# With headers
request = Request(
"https://api.example.com/data",
headers={"Authorization": "Bearer token"}
)
with urlopen(request) as response:
data = json.loads(response.read())
# POST with data
data = urlencode({"key": "value"}).encode()
request = Request("https://api.example.com/post", data=data)
with urlopen(request) as response:
result = response.read()Common Patterns
Retry logic
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
session = requests.Session()
retries = Retry(
total=3,
backoff_factor=0.5,
status_forcelist=[500, 502, 503, 504]
)
session.mount("https://", HTTPAdapter(max_retries=retries))
response = session.get(url)API client class
class APIClient:
def __init__(self, base_url, api_key):
self.base_url = base_url
self.session = requests.Session()
self.session.headers["Authorization"] = f"Bearer {api_key}"
def get(self, endpoint, **kwargs):
return self.session.get(f"{self.base_url}{endpoint}", **kwargs)
def post(self, endpoint, data, **kwargs):
return self.session.post(f"{self.base_url}{endpoint}", json=data, **kwargs)
client = APIClient("https://api.example.com", "my-key")
users = client.get("/users").json()Quick Reference
import requests
# Basic requests
requests.get(url)
requests.post(url, json=data)
# With options
requests.get(url,
params={"key": "value"}, # Query string
headers={"Auth": "token"}, # Headers
timeout=10, # Timeout
auth=("user", "pass"), # Basic auth
)
# Response
response.status_code
response.json()
response.text
response.raise_for_status()
# Session
with requests.Session() as s:
s.headers["Auth"] = "token"
s.get(url)Use requests for most HTTP work. It's simpler and handles edge cases better than urllib.
React to this post: