Grabber

Errors

Every error the Grabber API returns, with its HTTP status, its stable detail code and what to do next. Errors are never charged.

Last updated

Every error has the shape { status, message, detail }, plus a hint when there is something the caller can do about it. detail is a stable code to branch on; message is the HTTP reason phrase. Nothing is ever cached: every answer has Cache-Control: no-store.

You pay only for a page that was loaded, so no error is ever charged. A page whose own server answered 404 or 500 is not an error: it was loaded, so the answer is 200 and it is charged. Its status is in data.fetch.httpStatusCode.

Error codes

StatusdetailMeaning
400invalid_queryThe query is wrong, and hint says how.
400invalid_urlThe url is not http or https, has a username or password, or is too long.
400blocked_urlThe url points at a host that cannot be fetched.
401invalid_api_keyThe key is missing, malformed, unknown, or deleted.
402insufficient_creditsThe balance is below the price of this request. Nothing was charged and nothing was fetched.
404not_foundThe path is not /fetch.
405method_not_allowedThe method is not GET.
429rate_limitedMore than 60 requests in this minute for this key. Wait Retry-After seconds.
500internal_errorSomething failed on Grabber's side. Nothing was charged. Try again; if it keeps happening, it is not caused by your request.
502fetch_failedThe page could not be loaded.
502blocked_urlThe page redirected to a host that cannot be fetched.
502body_too_largeThe page is over 8 MiB.
502format_unavailableunwrap=true, and none of the requested formats can be produced for this content.
502upstream_unavailableGrabber could not get an answer from its fetching service.

Examples

{
  "status": 400,
  "message": "Bad Request",
  "detail": "invalid_query",
  "hint": "Give exactly one address to fetch, for example ?url=https://example.com/"
}

What to do

  • 400: the request itself is wrong, so sending it again gives the same answer. Read hint, fix the query or the URL, then retry.
  • 401: check that the key is sent as Authorization: Bearer gsh_… and still exists in the dashboard.
  • 402: add credit at the address in hint, or turn on auto top-up so the balance never runs out.
  • 429: wait the number of seconds in Retry-After, then retry. The limit is 60 requests per minute per key.
  • 500 and 502 upstream_unavailable: the problem is on Grabber's side. Retry with a growing delay, such as 1, 2, then 4 seconds.
  • 502 fetch_failed: the page did not load. Check the URL in a browser; if it opens there, try again later.
  • 502 format_unavailable: with unwrap=true, add a format this content can produce, such as raw, after the one you want.

Response headers

HeaderMeaning
X-Grabber-CostWhat this request cost, in US dollars: 0.001, 0.005, or 0 when nothing was charged.
X-Grabber-BalanceWhat is left of your credit after this request, in US dollars.
Cache-ControlAlways no-store. Answers are never cached.
WWW-AuthenticateAlways Bearer.
AllowAlways GET.
Retry-AfterSeconds until the next minute begins.