Lightweight HTTP request/response logger for Python web frameworks. Designed for developers who need clear, structured debug output without writing print() everywhere.
- Auto-log every request & response via middleware
- Colorized terminal output with status color coding
- File output in JSON (NDJSON) or plain text format
- Configurable output mode: terminal, file, or both
- Auto-diff mode — detects response changes per endpoint automatically
- Filter log by route, method, or status code (whitelist & blacklist)
- Press
cto clear terminal while server is running - Authorization header auto-masking
pip install reqtrace-pyThe package is installed as
reqtrace-pybut imported asreqtrace.
from fastapi import FastAPI
from reqtrace import ReqTrace
from reqtrace.middleware import ReqTraceMiddleware
rt = ReqTrace(output="terminal")
app = FastAPI()
app.add_middleware(ReqTraceMiddleware, config=rt.config)That's it — every request will be logged automatically.
# Terminal only (default)
rt = ReqTrace(output="terminal")
# File only — JSON format
rt = ReqTrace(output="file", file_path="logs/trace.json")
# File only — plain text
rt = ReqTrace(output="file", file_path="logs/trace.txt", file_format="txt")
# Both terminal and file
rt = ReqTrace(output="both", file_path="logs/trace.json")
# Disabled (useful for production)
rt = ReqTrace(output="terminal", enabled=False)Control which requests are logged using whitelist or blacklist mode.
from reqtrace import ReqTrace, ReqTraceFilter
# Whitelist — only log errors
rt = ReqTrace(
output="terminal",
filters=ReqTraceFilter(
mode="whitelist",
status_codes=["4xx", "5xx"],
)
)
# Whitelist — only log specific methods
rt = ReqTrace(
output="terminal",
filters=ReqTraceFilter(
mode="whitelist",
methods=["POST", "PUT", "DELETE"],
)
)
# Blacklist — hide docs routes and all 200 responses
rt = ReqTrace(
output="terminal",
filters=ReqTraceFilter(
mode="blacklist",
routes=["/docs", "/redoc", "/openapi.json"],
status_codes=[200],
)
)Filter rules:
- whitelist — only log requests that match the filter. Empty whitelist logs nothing.
- blacklist — log everything except requests that match the filter. Empty blacklist logs everything.
- Filters can be combined:
routes,methods, andstatus_codesare evaluated with OR logic. status_codesaccepts specific codes (404) or ranges ("4xx","5xx"), or mixed ([404, "5xx"]).
Enable auto-diff to automatically compare each response against the previous one for the same endpoint. Useful for detecting unintended changes after modifying your code.
rt = ReqTrace(output="terminal", diff=True)
# With file output
rt = ReqTrace(output="both", file_path="logs/trace.json", diff=True)On the first request to an endpoint, reqtrace saves a snapshot. On every subsequent request to the same endpoint, it compares and displays what changed:
┌─ DIFF GET /users ────────────────────────────────────────────
+1 -0 ~0
+ data[2] {'id': 3, 'name': 'Diz', 'email': 'diz@example.com'}
└──────────────────────────────────────────────────────────────
Diff symbols:
+— field or item added-— field or item removed~— value or type changed
When there are no changes:
┌─ DIFF GET /users ────────────────────────────────────────────
No changes detected
└──────────────────────────────────────────────────────────────
┌─ REQUEST ────────────────────────────────────────────────────
POST /api/users
content-type: application/json
Body:
{
"name": "Diz",
"email": "diz@mail.com"
}
├─ RESPONSE ───────────────────────────────────────────────────
Status : 422 43.2ms
Body:
{
"detail": [{"loc": ["body", "email"], "msg": "value is not a valid email"}]
}
└──────────────────────────────────────────────────────────────
Status codes are color-coded:
- 🟢
2xx— green - 🟡
3xx— yellow - 🔴
4xx— red - 🟣
5xx— magenta
While the server is running, press c to clear the terminal output. The key can be customized or disabled:
# Custom key
rt = ReqTrace(output="terminal", clear_key="r")
# Disable
rt = ReqTrace(output="terminal", clear_key=None)Each log entry is one JSON object per line (NDJSON), easy to stream and parse:
{"timestamp": "2026-03-23T10:15:00+00:00", "method": "POST", "url": "/api/users", "status_code": 422, "latency_ms": 43.2, "request_headers": {...}, "request_body": {"name": "Diz"}, "response_body": {...}}Diff entries are written as a separate record with "type": "diff":
{"timestamp": "2026-03-23T10:16:00+00:00", "type": "diff", "method": "GET", "url": "/users", "changes": {"added": [{"path": "data[2]", "value": {...}}], "removed": [], "changed": []}, "has_changes": true}| Parameter | Type | Default | Description |
|---|---|---|---|
output |
"terminal" | "file" | "both" |
"terminal" |
Where to send log output |
file_path |
str |
None |
Log file path. Required if output is "file" or "both" |
file_format |
"json" | "txt" |
"json" |
Log file format |
enabled |
bool |
True |
Master on/off switch |
diff |
bool |
False |
Enable auto-diff per endpoint |
clear_key |
str | None |
"c" |
Terminal clear shortcut. None to disable |
filters |
ReqTraceFilter | None |
None |
Filter which requests are logged |
| Parameter | Type | Default | Description |
|---|---|---|---|
mode |
"whitelist" | "blacklist" |
"blacklist" |
Filter mode |
routes |
list[str] |
[] |
Routes to filter. Supports exact and prefix match |
methods |
list[str] |
[] |
HTTP methods to filter. Case-insensitive |
status_codes |
list[int | str] |
[] |
Status codes to filter. Accepts 404 or "4xx" |
- Python >= 3.10
- Starlette >= 0.27.0
- Filter log by route, method, and status code
- Whitelist and blacklist mode
status_codessupports specific codes and ranges ("4xx","5xx")
- Auto-diff mode (
diff=True) — compares responses per endpoint automatically - Diff output in both terminal and file
- Press
cto clear terminal (configurable viaclear_key) - Fix:
CTRL+Cnow works correctly whenclear_keyis active
- Initial release
- Request/response logging via middleware
- Terminal (colorized) and file (JSON/txt) output
v0.4.0— Flask/Django supportv0.4.0— Web UI log viewer
MIT