Guides

Errors

ByteKit error response shape, common error codes, and retry guidance.

All errors from the ByteKit API follow a consistent envelope shape so you can handle them programmatically.

Error response shape

Every 4xx/5xx response across the API uses one unified envelope. status is always the literal string "failed", so you can branch on the response body alone.

{
  "status": "failed",
  "error": {
    "code": "rate_limited",
    "message": "Too many requests. Retry after 2 seconds.",
    "httpStatus": 429,
    "failedAt": "2026-06-16T19:38:02.084Z",
    "details": {}
  }
}
FieldDescription
statusAlways "failed" on an error response — the top-level discriminator
error.codeMachine-readable string identifier
error.messageHuman-readable explanation
error.httpStatusMirrors the HTTP response status (useful for logged or replayed bodies)
error.failedAtISO-8601 UTC timestamp of when the error was produced
error.detailsOptional object with additional context (e.g. which field failed validation)

Common error codes

HTTP statusCodeMeaning
400invalid_urlA supplied URL (including webhook_url) is malformed or uses an unsupported scheme
401unauthorizedMissing or malformed Authorization header
401invalid_api_keyAPI key is present but not valid
402quota_exceededAccount has exceeded its plan quota
403forbiddenKey is valid but lacks permission for this action
422validation_errorMalformed JSON or a request field failed validation
429rate_limitedToo many requests; back off and retry
500internal_errorThe upstream fetch or browser render failed

Webhook URLs Must Use HTTPS

All webhook URLs submitted to the ByteKit API must use HTTPS. Plain HTTP URLs (e.g. http://example.com/webhook) are rejected with a 400 invalid_url error.

Why HTTPS only? Webhook payloads may contain sensitive data (API keys, session tokens, scrape results). HTTPS encryption protects this data in transit.

Request with an invalid webhook URL:

{
  "webhook_url": "http://example.com/webhook"
}

Response (HTTP 400) — the same unified envelope as every other error; error.details names the offending field and reason:

{
  "status": "failed",
  "error": {
    "code": "invalid_url",
    "message": "url is not a valid HTTP(S) URL: scheme_unsupported",
    "httpStatus": 400,
    "failedAt": "2026-06-16T19:38:02.340Z",
    "details": {
      "url": "http://example.com/webhook",
      "field": "webhook_url",
      "reason": "scheme_unsupported"
    }
  }
}

Working example:

{
  "webhook_url": "https://example.com/webhook"
}

This applies to all endpoints that accept a webhook_url parameter: /v1/scrape (async), /v1/scrape/bulk, /v1/fetch/bulk, /v1/bulk, /v1/monitors, and /v1/sitemap.

Retry guidance

Not all errors are retryable. Use this table to decide:

CodeRetry?Guidance
invalid_urlNoFix the URL before retrying
validation_errorNoFix the request body before retrying
unauthorized / invalid_api_keyNoCheck your API key
quota_exceededNoUpgrade your plan or wait for quota reset
forbiddenNoYou do not have access to this resource
rate_limitedYesExponential backoff; honour the Retry-After header
internal_errorYesExponential backoff; most resolve on retry

For retriable errors, start with a 1-second delay and double on each subsequent failure, up to a maximum of 60 seconds. Respect the Retry-After header value when it is present on 429 responses.

Example: handling errors in curl

response=$(curl -s -w "\n%{http_code}" -X POST https://api.bytekit.com/v1/scrape \
  -H "Authorization: Bearer sk_live_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com"}')

http_code=$(echo "$response" | tail -1)
# Body is everything except the trailing status-code line — drop only the last
# line so multi-line JSON responses survive intact.
body=$(echo "$response" | sed '$d')

if [ "$http_code" -ge 400 ]; then
  echo "Error $http_code: $body"
fi

Next steps

  • Rate Limits — quota model, concurrency slots, rate limit headers
  • Scraping — when 500 internal_error occurs and how fallback works
  • API Reference — per-endpoint error codes