dark-req
A requests-compatible Python HTTP client that fixes everything requests
gets wrong — in the same lightweight footprint (only urllib3 + certifi).
import dark_req
# Works exactly like requests...
r = dark_req.get("https://api.example.com/users", timeout=10)
print(r.status_code, r.json())
# ...but with superpowers baked in
s = dark_req.Session(
base_url="https://api.example.com",
max_retries=3, # auto-retry on 429/5xx + connection errors
rate_limit=5, # max 5 req/sec per host (token bucket)
hooks={"on_error": [lambda e: print("failed:", e)]},
)
r = s.get("/users", params={"page": 2}) # -> https://api.example.com/users?page=2
r.raise_for_status()
# Downloads with progress, one line
s.download("https://example.com/big.zip", "big.zip",
progress=lambda done, total: print(f"{done}/{total}"))
# Async, same API
import asyncio
async def main():
async with dark_req.AsyncSession(base_url="https://api.example.com") as s:
users, repos = await asyncio.gather(s.get("/users"), s.get("/repos"))
asyncio.run(main())
Install
pip install dark-req
Requires Python 3.9+.
Why not just requests?
| Pain point | requests |
dark-req |
|---|---|---|
| Default timeout | ❌ none — hangs forever | ✅ connect=5s, read=30s |
| Retries | ❌ manual | ✅ auto-retry on 429/5xx + network errors, exponential backoff + jitter, honors Retry-After |
| Rate limiting | ❌ | ✅ per-host token bucket (rate_limit=5) |
base_url on sessions |
❌ | ✅ |
| Hooks | ❌ (only transport adapters) | ✅ on_request / on_response / on_error |
| Download with progress | ❌ manual streaming loop | ✅ session.download(url, path, progress=...) |
| Async | ❌ sync only | ✅ AsyncSession, same API |
| Bearer auth helper | ❌ | ✅ BearerAuth("token") / (user, pass) tuples |
raise_for_status message |
❌ bare status | ✅ includes URL + body snippet |
response.json() errors |
❌ cryptic JSONDecodeError |
✅ dark_req.JSONDecodeError (also a ValueError), carries request/response |
| Retry exhaustion | ❌ silent last response | ✅ RetryExhausted with attempts + last_exception |
codes |
✅ | ✅ dark_req.codes.ok == 200 |
Everything else stays familiar: get/post/put/patch/delete/head/options,
Session, Request/PreparedRequest/Response, HTTPBasicAuth,
and an exception hierarchy mirroring requests (so existing except
blocks keep working).
Sane defaults
dark_req.get("https://slow.example.com") # gives up after 5s connect / 30s read
dark_req.get("https://flaky.example.com") # 3 automatic retries with backoff
Override per call with timeout=... (seconds, (connect, read) tuple, or
timeout=None to wait indefinitely), max_retries=0 to disable retries,
verify=False to skip TLS verification.
Roadmap
files=multipart uploads- Proxy support from environment variables
- HTTP/2 transport option
- Connection-level metrics / tracing hooks
License
MIT
Metadata
Release files for dark-req 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| dark_req-0.1.0.tar.gz | 16.9 kB | Without provenance | Details for dark_req-0.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| dark_req-0.1.0-py3-none-any.whl | Python 3 | none | any | Details for dark_req-0.1.0-py3-none-any.whl |
Total release size: 32.7 kB
Release files / dark_req-0.1.0.tar.gz
| Download URL | dark_req-0.1.0.tar.gz |
|---|---|
| Size | 16.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5b274bba28bb4cc775fb12ac0ce9ca023e335d0d75585b247c057930fe10b19a
|
|
BLAKE2b-256 checksum How to use checksums |
4ccd6185dc61d329535d6396e0ab80852a20fb0211c19da2848fb354bc080c60
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / dark_req-0.1.0-py3-none-any.whl
| Download URL | dark_req-0.1.0-py3-none-any.whl |
|---|---|
| Size | 15.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c58bdd6447e5be433e88974b74b7be78006e963b90d2fa79e5dc7fd0ff473108
|
|
BLAKE2b-256 checksum How to use checksums |
6502e94913de01739aa78e10478aa16a21679c6b1b2e132c7156438144320b98
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Security for dark-req 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.