API rate limits, 429 answers and Retry-After
The host.sh API rate limits: 10 tokenless lookups a minute per IP, no per-minute limit with a token, 100 addresses per batch, and how to retry a 429.
Without a token
Tokenless lookups of your own IP (/v2/lookup/ with no token) are limited to 10 requests a minute per client IP address, with short bursts of up to 10. A request over the limit gets 429 and a Retry-After header with the number of seconds to wait:
HTTP/2 429
retry-after: 6
content-type: application/json
{"errors":[{"code":429,"message":"Too many requests","reason":"TOO_MANY_REQUESTS","detail":"Too many requests without a token, retry after a few seconds or use a token"}]}
The headers are readable from a browser too (the API exposes Retry-After to cross-origin scripts). Wait at least that long before the next request, or send a token.
Not counted against this limit:
GET /v2/ip/, which only echoes your address and does no lookup- requests with a token
curl host.shin a terminal, which is answered by host.sh itself and keeps the answer for your IP for an hour
With a token
The API has no per-minute limit for requests with a token. Each lookup is counted for your token, and a batch counts one lookup per address. Which sections of the answer you get depends on your token's plan.
Size limits
| Limit | Value | Over it |
|---|---|---|
| Addresses per batch | 100 | 400, reason TOO_MANY_IPS |
| Request body | 64 KB | 413 (an HTML page from the web server, not JSON) |
callback name | 64 characters | 400, reason INVALID_CALLBACK |
Retrying
- On
429, waitRetry-Afterseconds, then retry. - On a network error or a
5xxanswer, retry with a growing delay (1, 2, 4 seconds and so on). - Don't retry
400,401,403or404: the same request fails the same way. See Errors.
import time
import requests
def lookup(url, attempts=5):
for attempt in range(attempts):
try:
r = requests.get(url, timeout=10)
except (requests.ConnectionError, requests.Timeout):
time.sleep(2 ** attempt)
continue
if r.status_code == 429:
time.sleep(int(r.headers.get("Retry-After", "6")))
continue
if r.status_code >= 500:
time.sleep(2 ** attempt)
continue
r.raise_for_status() # 400, 401, 403, 404, 413: retrying won't help
return r.json()
raise RuntimeError("host.sh API: too many retries")
print(lookup("https://api.host.sh/v2/lookup/?fields=connection.ip")["connection"]["ip"])
This page as Markdown: /docs/rate-limits/index.md