CLI¶
Installing the package puts a smartratelimit command on your PATH. It exists mainly to answer two questions from a shell: what does this API advertise? and what quota does my app think it has left?
--storage comes before the subcommand
It is a global option, and it defaults to memory โ which is empty in a
fresh process. status and clear are only meaningful against the same
SQLite or Redis backend your application writes to.
probe¶
Send one request and show what came back, headers and all. This is the command you run before writing any configuration.
Probing https://api.github.com/users/octocat...
Response Status: 200
Rate Limit Headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 1734567890
Detected Rate Limit:
Limit: 60
Remaining: 59
Window: 0:59:31
Read it in two parts:
- Rate Limit Headers โ what the API actually sent, of the names the CLI prints
- Detected Rate Limit โ what the library made of it
If the first section shows limit-ish headers and the second says nothing was detected, the API uses names the detector doesn't know: give it a headers_map.
Probing writes to the chosen backend, so you can seed a shared database and inspect it afterwards:
probe issues a real GET. Don't point it at anything with side effects.
status¶
Read the stored quota for one endpoint.
Endpoint: https://api.github.com
Limit: 5000
Remaining: 4958
Utilization: 0.8%
Resets at: 2026-08-15 11:18:25.481203
Resets in: 2842 seconds
Exceeded: False
Nothing stored yet:
The endpoint argument is positional and required โ a bare domain works as well as a full URL, since both normalise to scheme://host. Times are UTC.
clear¶
Forget a stored quota, so the next request re-learns it from response headers.
smartratelimit --storage "sqlite:///ratelimit.db" clear "https://api.github.com" # one endpoint
smartratelimit --storage "sqlite:///ratelimit.db" clear # everything
With no argument it clears the whole backend โ including endpoints belonging to other applications sharing that database. Name the endpoint unless you mean all of it.
list¶
Currently a placeholder: enumerating stored endpoints isn't part of the storage interface yet, so the command prints a note pointing you at status.
A working loop¶
The CLI is only useful when it reads the same state your code writes, so give both a real backend:
# app.py
from smartratelimit import RateLimiter
limiter = RateLimiter(storage="sqlite:///ratelimit.db")
for name in ["Michael", "Sarah", "Alex"]:
r = limiter.request("GET", "https://api.agify.io", params={"name": name})
print(name, r.json()["age"])
Watching quota from cron¶
Because state is in the backend rather than the process, a monitoring job can check quota without touching the application:
*/5 * * * * smartratelimit --storage "redis://localhost:6379/0" \
status "https://api.github.com" >> /var/log/ratelimit.log 2>&1
For anything richer than a log line, read the same backend from Python and export metrics โ the CLI prints for humans, not for scrapers.