Making Requests¶
This guide covers everything you need to know about making HTTP requests with httpr.
HTTP Methods¶
httpr supports all standard HTTP methods:
import httpr
client = httpr.Client()
# GET - Retrieve data
response = client.get("https://httpbin.org/get")
# POST - Create/submit data
response = client.post("https://httpbin.org/post", json={"key": "value"})
# PUT - Update/replace data
response = client.put("https://httpbin.org/put", json={"key": "value"})
# PATCH - Partial update
response = client.patch("https://httpbin.org/patch", json={"key": "value"})
# DELETE - Remove data
response = client.delete("https://httpbin.org/delete")
# HEAD - Get headers only (no body)
response = client.head("https://httpbin.org/get")
# OPTIONS - Get supported methods
response = client.options("https://httpbin.org/get")
You can also use the generic request() method:
import httpr
client = httpr.Client()
response = client.request("GET", "https://httpbin.org/get")
response = client.request("POST", "https://httpbin.org/post", json={"key": "value"})
Query Parameters¶
Add query parameters to the URL using the params argument:
import httpr
# Using params dict
response = httpr.get(
"https://httpbin.org/get",
params={"search": "python", "page": 1, "limit": 10}
)
# Result: https://httpbin.org/get?search=python&page=1&limit=10
print(response.json()["args"])
# {"search": "python", "page": "1", "limit": "10"}
Automatic String Conversion
All parameter values are automatically converted to strings. Numbers, booleans, and other types work seamlessly.
Default Parameters¶
Set default query parameters on the client that are included in every request:
import httpr
# API key included in all requests
client = httpr.Client(params={"api_key": "your-api-key"})
response = client.get("https://api.example.com/users")
# URL: https://api.example.com/users?api_key=your-api-key
response = client.get("https://api.example.com/posts", params={"page": 1})
# URL: https://api.example.com/posts?api_key=your-api-key&page=1
Request Headers¶
Set custom headers for individual requests or as client defaults:
Per-Request Headers¶
import httpr
response = httpr.get(
"https://httpbin.org/headers",
headers={
"X-Custom-Header": "my-value",
"Accept": "application/json",
"User-Agent": "my-app/1.0"
}
)
Default Headers¶
Set headers that are sent with every request:
import httpr
client = httpr.Client(
headers={
"Authorization": "Bearer token123",
"Accept": "application/json"
}
)
# All requests include these headers
response = client.get("https://api.example.com/data")
Modifying Client Headers¶
client.headers is a live, mutable view — in-place changes are applied to the
client and included in subsequent requests:
import httpr
client = httpr.Client()
# Replace all headers
client.headers = {"X-Api-Key": "secret"}
# Mutate in place
client.headers["Accept"] = "application/json"
client.headers.update({"X-Trace-Id": "abc123"})
del client.headers["X-Api-Key"]
# Read current headers
print(client.headers) # contains "accept" and "x-trace-id" (x-api-key removed)
Header Case
Headers are stored in lowercase internally (HTTP/2 requirement) but can be accessed case-insensitively.
Cookies are preserved
Modifying headers — including full replacement via client.headers = {...} — never affects cookies. Manage cookies via client.cookies.
Request Body¶
httpr supports multiple ways to send data in the request body. These options are mutually exclusive - use only one per request.
JSON Data¶
The most common way to send structured data:
import httpr
response = httpr.post(
"https://httpbin.org/post",
json={
"name": "John Doe",
"email": "john@example.com",
"tags": ["python", "rust"],
"metadata": {"version": 1}
}
)
# Content-Type is automatically set to application/json
print(response.json()["json"])
Form Data¶
Send URL-encoded form data:
import httpr
response = httpr.post(
"https://httpbin.org/post",
data={
"username": "john",
"password": "secret",
"remember": "true"
}
)
# Content-Type: application/x-www-form-urlencoded
print(response.json()["form"])
# {"username": "john", "password": "secret", "remember": "true"}
Binary Data¶
Send raw bytes directly:
import httpr
# Send raw bytes
response = httpr.post(
"https://httpbin.org/post",
content=b"raw binary data"
)
# Send string as bytes
response = httpr.post(
"https://httpbin.org/post",
content="text data".encode("utf-8")
)
File Uploads¶
Upload files using multipart/form-data:
import httpr
response = httpr.post(
"https://httpbin.org/post",
files={
"document": "/path/to/document.pdf",
"image": "/path/to/photo.jpg"
}
)
The files dictionary maps form field names to file paths. Files are read and uploaded automatically.
File Paths
The files argument expects file paths as strings, not file objects. The files must exist on disk.
Timeouts¶
Control how long to wait for responses:
Request Timeout¶
import httpr
# Wait up to 10 seconds for this request
response = httpr.get("https://httpbin.org/delay/2", timeout=10)
Client Default Timeout¶
import httpr
# Default timeout for all requests
client = httpr.Client(timeout=30)
# Uses 30 second timeout
response = client.get("https://httpbin.org/get")
# Override for specific request
response = client.get("https://httpbin.org/delay/5", timeout=60)
Timeout Behavior¶
- The default timeout is 30 seconds;
timeout=Nonedisables it - The timeout bounds how long the server may keep you waiting, not how long a request may take: it applies to the wait for the response headers and then to the wait for each chunk of the body, and every chunk that arrives resets it. A large download or a long-lived stream that keeps delivering data is never cut off; a server that goes silent for longer than the timeout is
- When it is exceeded,
httpr.ReadTimeout(aTimeoutException) is raised - Assigning
client.timeoutapplies to the next request - Timeout of
0or very small values may cause immediate timeout
import httpr
try:
response = httpr.get("https://httpbin.org/delay/10", timeout=1)
except Exception as e:
print(f"Request timed out: {e}")
Redirects¶
By default, httpr follows HTTP redirects automatically:
import httpr
# Follows up to 20 redirects by default
response = httpr.get("https://httpbin.org/redirect/3")
print(response.url) # Final URL after redirects
Configuring Redirects¶
import httpr
# Disable redirects
client = httpr.Client(follow_redirects=False)
response = client.get("https://httpbin.org/redirect/1")
print(response.status_code) # 302
# Limit number of redirects
client = httpr.Client(max_redirects=5)
Protocol Options¶
HTTPS Only¶
Restrict to secure connections only:
import httpr
client = httpr.Client(https_only=True)
# Works
response = client.get("https://example.com")
# Fails - HTTP not allowed
# response = client.get("http://example.com")
HTTP/2¶
Enable HTTP/2 only mode:
import httpr
# Use only HTTP/2
client = httpr.Client(http2_only=True)
response = client.get("https://example.com")
Note
When http2_only=False (default), httpr uses HTTP/1.1. Set to True for HTTP/2.
Complete Example¶
Here's a complete example showing various request options:
import httpr
# Create a configured client
client = httpr.Client(
headers={"User-Agent": "my-app/1.0"},
params={"api_version": "v2"},
timeout=30,
follow_redirects=True,
max_redirects=10,
)
# GET request with query params
response = client.get(
"https://httpbin.org/get",
params={"search": "python"},
headers={"Accept": "application/json"}
)
print(f"Status: {response.status_code}")
print(f"URL: {response.url}")
# POST with JSON
response = client.post(
"https://httpbin.org/post",
json={"message": "Hello, World!"},
timeout=60 # Override timeout for this request
)
print(response.json())
# Cleanup
client.close()
Next Steps¶
- Response Handling - Learn to work with response data
- Authentication - Add authentication to your requests