Skip to content

Errors — Shotvik API error responses

Errors return a non-2xx status, Content-Type: application/json, Cache-Control: no-store and this body:

{
"error": {
"code": "url_blocked",
"message": "this URL cannot be rendered",
"request_id": "req_3f9c2a71b0d4e8a6",
"reason": "private_ip"
}
}
Field Always present Description
code yes Machine-readable error code (table below). Use this in your code, not message.
message yes Human-readable explanation. The wording may change.
request_id yes Same as the X-Request-Id header. Include it when you contact support@shotvik.com.
reason no A fixed reason: the block reason on url_blocked (see below), key_suspended on key_suspended, and account_frozen on account_frozen.
retry_after no Seconds to wait before retrying. Also sent as the Retry-After header on 429 and 503.
Status Code Meaning What to do
400 invalid_request A parameter is missing, has the wrong type or range, or is unknown (e.g. jpeg_quality without format: "jpeg", or both/neither of template and html). Fix the request; message names the field.
400 api_key_in_url An API key was sent in the query string (api_key, key, apikey, access_key or token). Use the Authorization header, or a signed URL for public links.
401 unauthorized No API key was sent. Send Authorization: Bearer <key> or X-API-Key.
401 invalid_api_key The key isn’t valid. Check the key.
401 api_key_revoked The key has been revoked. Create a new key.
401 invalid_signature The signed URL’s signature is missing or wrong, or a parameter appears twice. Re-sign the URL; see Signed URLs.
403 signature_expired The signed URL’s exp has passed. Sign a new URL.
403 url_blocked The page URL (or a redirect of it) was refused. reason says why. Refused sub-resources (images, fonts, scripts) don’t cause this error; they’re dropped and the render continues. See block reasons below. Contact support if you think it’s wrong.
403 key_suspended The key is temporarily blocked (abuse protection). Contact support@shotvik.com.
403 account_frozen The account is temporarily blocked. Contact support@shotvik.com.
403 free_tier_paused The free plan is temporarily paused. Try again later.
404 not_found Unknown path. Check the endpoint.
404 template_not_found The OG template ID doesn’t exist in your account. Check GET /v1/templates.
413 payload_too_large The request body or HTML is too large (html and css together max 1,048,576 bytes). Make the input smaller.
429 rate_limited Your per-minute rate limit was exceeded. Wait Retry-After seconds.
429 too_many_concurrent_requests Too many of your requests are running at once. Retry after Retry-After; lower your parallelism.
429 target_rate_limited Too many renders of this target domain right now, across all customers (30 per minute). Retry after Retry-After.
429 monthly_quota_exceeded Your monthly quota is used up (hard limit). Wait for the next period. Retry-After gives the seconds until the reset.
429 queue_full The render queue is full. Retry after Retry-After.
500 render_failed The render failed on our side. Retry with backoff.
500 internal_error Unexpected error on our side. Retry with backoff; contact support with the request_id if it persists.
502 target_unreachable The target page couldn’t be loaded (e.g. connection failed). No image is returned. Check that the site is up and publicly reachable.
503 queue_timeout No render slot became free in time. Retry after Retry-After.
503 service_paused Rendering is temporarily paused. Retry after Retry-After.
503 url_rendering_disabled URL rendering is temporarily disabled; HTML and OG rendering still work. Retry after Retry-After.
504 render_timeout The render didn’t finish within 30 s (including delay_ms). Lower delay_ms, use a faster wait_until, or avoid full-page captures of very long pages.

A target site’s own 4xx/5xx is not an error. You get the rendered page with 200, the target’s status in X-Target-Status, and it counts. None of the errors above count toward your quota, because no image or PDF is returned. See How usage is counted.

Reason Meaning
private_ip, loopback, link_local, metadata_ip, own_infra The URL or a redirect resolves to a private, loopback, link-local, cloud-metadata or Shotvik-internal address.
redirect_to_private A redirect points to such an address.
dns_rebinding, ip_encoding_trick The hostname resolved differently between checks, or the address is written in an unusual encoding.
bad_scheme, bad_port, bad_hostname, invalid_url, credentials_in_url Not http/https; a port other than 80 or 443 (also after a redirect); a local or single-label hostname; an invalid URL; or a username/password in the URL.
dns_failure The hostname couldn’t be resolved.
too_many_redirects More than 5 redirects.
size_limit, request_limit The page exceeded the per-render budget of 25 MiB downloaded or 400 requests.
phishing_database The URL, its domain or its IP address is on the Phishing.Database list.
own_blocklist The URL is on Shotvik’s own blocklist.
reputation_unavailable Shotvik’s copy of Phishing.Database is more than 48 hours old, so URL renders are refused to be safe. Retry later.

key_suspended errors carry reason: "key_suspended", and account_frozen errors carry reason: "account_frozen".

Fonts and images that are refused or over budget don’t cause an error. They’re skipped, and the response lists them in the X-Shotvik-Warnings header (see Skipped fonts and images).

  • Respect Retry-After on 429 and 503.
  • Use exponential backoff for 500 and 503.
  • Don’t retry 400, 401, 403 or 413 unchanged.

Shotvik is in private beta. Request access: support@shotvik.com · Privacy