The missing rate-limit wrapper for aiohttp. Effortlessly handle 429s, Retry-After headers, and domain throttling for scraping and data pipelines.
Project description
HTTP Wizz 🧙♂️
The missing rate-limit wrapper for aiohttp and asyncio.
HTTP Wizz handles the hard parts of web scraping and high-volume API consumption: Strict Rate Limiting (RPS), Automatic Retries, 429/503 Backoff, and Domain Throttling. Perfect for web crawlers, data processing pipelines, and microservices.
✨ Key Features
- Strict Global Rate Limiting: Enforce a precise Request Per Second (RPS) limit across all your concurrent tasks.
- Per-Domain Throttling: Set different rate limits for different domains (e.g., 50 RPS for Google, 1 RPS for a small site) within the same client.
- Smart Retries & Backoff: Automatically retries failed requests with exponential backoff.
- Respects
Retry-After: Automatically sleeps when a server sends a429 Too Many Requestsor503 Service Unavailablewith aRetry-Afterheader. - Custom Retry Logic: Define your own conditions for retrying (e.g., specific JSON content or headers).
- Drop-in
aiohttpReplacement: TheRateLimitedSessionis compatible with standardaiohttpusage, including proxies, cookies, and all HTTP verbs.
⚡ Why HTTP Wizz?
Whether you are building a web scraper or a data pipeline (e.g., geocoding 100k addresses), hitting rate limits is the #1 cause of failure. asyncio.gather is too aggressive, and requests is too slow.
| Feature | requests |
aiohttp (raw) |
http-wizz 🧙♂️ |
|---|---|---|---|
| Async / Non-blocking | ❌ | ✅ | ✅ |
| Strict Rate Limiting (RPS) | ❌ | ❌ | ✅ |
Handle Retry-After Header |
❌ | ❌ | ✅ |
| Domain-Specific Limits | ❌ | ❌ | ✅ |
| Auto-Retries with Backoff | ❌ | ❌ | ✅ |
| Data Pipeline Friendly | ❌ | ⚠️ | ✅ |
🚀 Installation
pip install http-wizz
(Optional) For progress bars in fetch_all and fetch_urls: pip install tqdm
🏃 Quick Start
Batch Processing (The Simple Way) Perfect for data processing pipelines where you just want to "fire and forget" a list of tasks at a safe speed.
from http_wizz import fetch_urls
urls = [f"https://api.geocoder.com/search?q={addr}" for addr in my_addresses]
# Process items at exactly 20 requests per second
results = fetch_urls(urls, requests_per_second=20, show_progress=True)
🛠 Advanced Usage
1. High-Performance Async Client
Best for modern async applications and microservices.
import asyncio
from http_wizz import WizzClient
async def main():
# 50 RPS limit for high-throughput pipelines
async with WizzClient(requests_per_second=50, burst_size=10) as client:
results = await client.fetch_all(["https://api.com/task/1", ...])
2. Fine-grained Control (RateLimitedSession)
A drop-in replacement for aiohttp.ClientSession. Use this for full control (headers, cookies, POST/PUT methods, proxies, etc.).
from http_wizz import RateLimitedSession
async with RateLimitedSession(requests_per_second=5) as session:
# Use proxies, headers, or any other aiohttp feature
async with session.post(
"https://api.com/update",
json={"id": 123},
proxy="http://user:pass@proxy.com:8080"
) as resp:
status = await resp.json()
3. Domain Throttling
Manage multiple services with different quotas simultaneously.
client = WizzClient(
requests_per_second=10, # Global Limit
domain_limits={
"maps.google.com": 50, # High quota
"legacy-service.local": 1 # Very fragile service
}
)
4. Custom Retry Logic
Retry not just on network errors, but also on specific application-level responses (e.g., a 200 OK that actually contains an error message).
def is_error_response(response, content):
# Retry if the JSON body contains "error": true
if isinstance(content, dict) and content.get("error"):
return True
return False
client = WizzClient(should_retry=is_error_response)
📖 Recipes & Examples
Check out the examples/ directory for ready-to-run scripts:
- Data Pipeline: Process batches of data at a fixed speed.
- Hacker News Scraper: Fetch top stories politely.
- Strict API Consumer: Handle APIs with tight limits (e.g., 2 RPS).
- Proxy Integration: Use rotating proxies with rate limiting.
- Benchmark: Compare Wizz vs Sequential vs Naive Async.
📚 API Reference
For a complete list of all parameters, flags, and advanced options, please see the Full API Reference.
🤝 Contributing
We love pull requests! If you have a feature idea or found a bug, please open an issue.
License: MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file http_wizz-1.0.2.tar.gz.
File metadata
- Download URL: http_wizz-1.0.2.tar.gz
- Upload date:
- Size: 11.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3a5f568cabb1f55db68693cc03ad2427eb568d58293bb136e110fcede57a3858
|
|
| MD5 |
65dfb1d427a3499a8f99fa93c25c874f
|
|
| BLAKE2b-256 |
29494f7462a97c89876311eaf3e0746a02c3d5dcbbc43786b7a42312e0f35c50
|
Provenance
The following attestation bundles were made for http_wizz-1.0.2.tar.gz:
Publisher:
publish.yml on TomMcKenna1/http-wizz
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
http_wizz-1.0.2.tar.gz -
Subject digest:
3a5f568cabb1f55db68693cc03ad2427eb568d58293bb136e110fcede57a3858 - Sigstore transparency entry: 872141063
- Sigstore integration time:
-
Permalink:
TomMcKenna1/http-wizz@f530330559fdb96bb30fb1515f93295e85e6fe4b -
Branch / Tag:
refs/tags/v1.0.2 - Owner: https://github.com/TomMcKenna1
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f530330559fdb96bb30fb1515f93295e85e6fe4b -
Trigger Event:
release
-
Statement type:
File details
Details for the file http_wizz-1.0.2-py3-none-any.whl.
File metadata
- Download URL: http_wizz-1.0.2-py3-none-any.whl
- Upload date:
- Size: 8.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fad8436db98449785ca5aceffa7e0b0abb8931027ed7fa6ea668e0ab6798be6d
|
|
| MD5 |
14b9e49dc9a3ade9d16bcc9648d7866a
|
|
| BLAKE2b-256 |
ba26934c2d6ac4f0c8d12d4189e601f321fb06c4f6c2ba9d80f38698802cc929
|
Provenance
The following attestation bundles were made for http_wizz-1.0.2-py3-none-any.whl:
Publisher:
publish.yml on TomMcKenna1/http-wizz
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
http_wizz-1.0.2-py3-none-any.whl -
Subject digest:
fad8436db98449785ca5aceffa7e0b0abb8931027ed7fa6ea668e0ab6798be6d - Sigstore transparency entry: 872141065
- Sigstore integration time:
-
Permalink:
TomMcKenna1/http-wizz@f530330559fdb96bb30fb1515f93295e85e6fe4b -
Branch / Tag:
refs/tags/v1.0.2 - Owner: https://github.com/TomMcKenna1
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@f530330559fdb96bb30fb1515f93295e85e6fe4b -
Trigger Event:
release
-
Statement type: