API error codes, reasons and how to fix them

Every error the host.sh IP lookup API returns: HTTP status, machine-readable reason, what causes it and how to fix it, with a request that triggers it.

An error is an HTTP status of 400 or more with a JSON body (except 413, which is an HTML page from the web server): an errors array holding one object with the numeric code (the same as the status), a short message, a machine-readable reason and a detail sentence. Match on reason; message and detail are for people and can change.

{"errors":[{"code":400,"message":"Bad request","reason":"INVALID_LANGUAGE","detail":"lang must be one of en, de, es, fr, ja, pt-BR, ru, zh-CN"}]}

In a batch an invalid address gets the same object as its item in results, and the batch itself still answers 200.

All errors

StatusReasonCause
400BAD_REQUESTA JSON body that isn't valid JSON
400INVALID_IP_ADDRESSip (or the address in the path) is not an IPv4 or IPv6 address
400INVALID_LANGUAGElang is not one of the supported languages
400INVALID_FORMATformat is not json or text, or format=text without exactly one single-value field
400INVALID_CALLBACKcallback is not a JavaScript identifier
400NO_IPSA batch with no addresses
400TOO_MANY_IPSA batch with more than 100 addresses
401TOKEN_MISSINGA batch without a token
403TOKEN_INVALIDThe token is unknown, disabled or has no permission for this endpoint
403TOKEN_REQUIREDA tokenless request asked for something other than your own IP
404(none)No such endpoint
405METHOD_NOT_ALLOWEDThe endpoint doesn't take this HTTP method
413(none)The request body is over 64 KB; the answer is an HTML page, not JSON
429TOO_MANY_REQUESTSOver the tokenless rate limit
5xx(none)A server error; retry later

400 Bad request

BAD_REQUEST

The body was sent as Content-Type: application/json but isn't valid JSON. Check the quoting, or let your HTTP library encode the body.

curl -H "Content-Type: application/json" -d '{bad' https://api.host.sh/v2/lookup/
{"errors":[{"code":400,"message":"Bad request","reason":"BAD_REQUEST","detail":"The request could not be parsed"}]}

A batch body that starts with [ or { but isn't valid JSON gets the same reason with the detail The body is not valid JSON.

INVALID_IP_ADDRESS

ip, or the address in /v2/lookup/{ip}, is not an IPv4 or IPv6 address. Host names are not looked up; resolve them first. Leading and trailing spaces are ignored.

curl -H "Authorization: Bearer YOUR_TOKEN" "https://api.host.sh/v2/lookup/?ip=1.2.3"
{"errors":[{"code":400,"message":"Bad request","reason":"INVALID_IP_ADDRESS","detail":"ip must be an IPv4 or IPv6 address"}]}

Without a token, ip= gets TOKEN_REQUIRED first.

INVALID_LANGUAGE

lang must be one of en, de, es, fr, ja, pt-BR, ru or zh-CN, written exactly like that.

curl "https://api.host.sh/v2/lookup/?lang=xx"
{"errors":[{"code":400,"message":"Bad request","reason":"INVALID_LANGUAGE","detail":"lang must be one of en, de, es, fr, ja, pt-BR, ru, zh-CN"}]}

INVALID_FORMAT

format must be json or text, and format=text needs fields with exactly one path to a single value (not an object). There are three details:

curl "https://api.host.sh/v2/lookup/?format=xml"
{"errors":[{"code":400,"message":"Bad request","reason":"INVALID_FORMAT","detail":"format must be json or text"}]}
curl "https://api.host.sh/v2/lookup/?format=text"
{"errors":[{"code":400,"message":"Bad request","reason":"INVALID_FORMAT","detail":"format=text needs exactly one field, e.g. fields=geo.country.code"}]}
curl "https://api.host.sh/v2/lookup/?format=text&fields=geo.country"
{"errors":[{"code":400,"message":"Bad request","reason":"INVALID_FORMAT","detail":"format=text needs a field with a single value, not an object"}]}

INVALID_CALLBACK

A JSONP callback must be a JavaScript identifier, or identifiers joined by dots such as app.onIp: letters, digits, _ and $, not starting with a digit, not a reserved word like function, at most 64 characters.

curl "https://api.host.sh/v2/lookup/?callback=1abc"
{"errors":[{"code":400,"message":"Bad request","reason":"INVALID_CALLBACK","detail":"callback must be a JavaScript identifier"}]}

NO_IPS

A batch body that is empty or holds no addresses. Send a JSON array, an object with an ips array, or addresses as text.

curl -H "Authorization: Bearer YOUR_TOKEN" -d '[]' https://api.host.sh/v2/lookup/batch/
{"errors":[{"code":400,"message":"Bad request","reason":"NO_IPS","detail":"Send a JSON array of addresses, e.g. [\"8.8.8.8\", \"1.1.1.1\"]"}]}

TOO_MANY_IPS

A batch takes at most 100 addresses. Split longer lists into several requests.

{"errors":[{"code":400,"message":"Bad request","reason":"TOO_MANY_IPS","detail":"Send at most 100 addresses per request"}]}

401 Unauthorized

TOKEN_MISSING

The batch endpoint needs a token, as a Bearer header or ?token=. A token in the body is not read there, because the body is the list of addresses.

curl -d '["8.8.8.8"]' https://api.host.sh/v2/lookup/batch/
{"errors":[{"code":401,"message":"Unauthorized","reason":"TOKEN_MISSING","detail":"Send a token as ?token=, a JSON body field or an Authorization: Bearer header"}]}

403 Forbidden

TOKEN_INVALID

The token is unknown, has been disabled, or its plan doesn't include this endpoint. Check that it is copied whole, with no spaces or quotes around it. When a request has a token in more than one place, the one the API reads first counts; see Authentication.

curl -H "Authorization: Bearer not-a-token" https://api.host.sh/v2/lookup/
{"errors":[{"code":403,"message":"Forbidden","reason":"TOKEN_INVALID","detail":"The token is unknown, disabled or has no permission for this endpoint"}]}

TOKEN_REQUIRED

Without a token the API only looks up your own IP. Asking for another address with ip= or /v2/lookup/{ip}, or sending ua= or al=, needs a token.

curl "https://api.host.sh/v2/lookup/?ip=8.8.8.8"
{"errors":[{"code":403,"message":"Forbidden","reason":"TOKEN_REQUIRED","detail":"Looking up anything but your own IP needs a token"}]}

404, 405 and 413

404 Not found

There is no endpoint at this path. The answer has no reason. Check the version prefix and the trailing slash: /v2/lookup/ and /v2/lookup/batch/ end with one.

curl https://api.host.sh/v2/nothing/
{"errors":[{"code":404,"message":"Not found"}]}

METHOD_NOT_ALLOWED

Lookups take GET, HEAD and POST, the batch endpoint only POST, and /v2/ip/ only GET and HEAD. OPTIONS, a browser's CORS preflight, gets 204 everywhere.

curl -X DELETE https://api.host.sh/v2/lookup/
{"errors":[{"code":405,"message":"Not allowed","reason":"METHOD_NOT_ALLOWED","detail":"This endpoint does not support the request method"}]}

413 Request Entity Too Large

The request body is over 64 KB. The web server answers before the API sees the request, so the body is a short HTML page, not JSON. A batch of 100 addresses is far below the limit.

429 Too many requests

TOO_MANY_REQUESTS

More than 10 tokenless requests a minute from one IP address. Wait the number of seconds in the Retry-After header, or send a token. See Rate limits.

{"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"}]}

5xx Server errors

A 500 ({"errors":[{"code":500,"message":"Internal server error"}]}) is a fault on the host.sh side, and 502 to 504 can come from the network in between. Retry with a growing delay.

This page as Markdown: /docs/errors/index.md