spicrawlspicrawlDocs

Response headers

Every header Spicrawl returns on /v1/scrape: request id, credits, engine, target status, proxy, cache state, limits and X-Warning codes.

A /v1/scrape response tells you what ran, what it cost and what the site said, in headers, whatever the body format. Read them with curl -D - (dump headers) or from your HTTP client's response object.

curl -sS -D - -o page.md "https://api.spicrawl.com/v1/scrape" \
  -H "Authorization: Bearer $SPICRAWL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/products/42", "response_format": "markdown"}'
HTTP/2 200
content-type: text/markdown; charset=utf-8
x-request-id: 01M0HF5WFWE7PRE8KZHDTNETWN
x-credits-charged: 1
x-request-cost: 1
x-credits-remaining: 987
x-engine: fetch
x-proxy-source: direct
x-target-status: 200
x-final-url: https://example.com/products/42
x-ratelimit-limit: 10
x-ratelimit-remaining: 9
concurrency-limit: 5
concurrency-remaining: 4
cache-state: miss

Two statuses

The HTTP status line is the platform's. The site's status is X-Target-Status.

HTTP statusX-Target-StatusMeaningCredits
200200The site returned the page.charged
200404 or 410The site said the page does not exist. The call succeeded.charged
200403, 500, …The site refused or failed. You get its body. The call still succeeded.0
4xx/5xx with application/problem+jsonabsentSpicrawl could not complete the request. Read code.0

Always check X-Target-Status (or envelope status) before trusting the body. A 200 with X-Target-Status: 403 is a block page, not your content. original_status=true moves the target's status onto the HTTP status line; avoid it unless a client requires it, because a target 404 then looks like an API error.

Header reference

HeaderValuesMeaning
X-Request-IdULIDThis request's id, on every response including errors. Quote it to support; pass it to GET /v1/requests/{id} for the trace.
X-Credits-ChargedintegerCredits actually billed. 0 on any failure, cache hit or non-billable target status.
X-Request-CostintegerPrice of the engine and proxy tier that ran. 0 on a cache hit. Differs from X-Credits-Charged exactly when nothing was billed.
X-Credits-RemainingintegerCredits left in your organization's monthly allowance after this request's charge, rounded down. Counts credits held by running batch jobs and open browser sessions. Never negative. On a 402 it can be above 0: less than the request needed. Absent when your organization has no monthly limit, when the request was refused before the credit check (a validation error, a rate or concurrency limit), or when the balance could not be read. See Credits.
X-Enginefetch, obscura, chromiumEngine that ran. Under mode=auto, the rung that produced the result.
X-Proxy-Sourcecustom, direct, poolWhose exit carried the request: your proxy, no proxy, or the managed pool Coming soon.
X-Proxy-EndpointstringIdentifier of the managed pool exit that served (managed pool Coming soon). Absent for custom and direct.
X-Target-StatusintegerThe site's HTTP status. Absent when no document was retrieved.
X-Final-UrlURLURL after redirects, when known.
X-RateLimit-LimitintegerRequests per second allowed for this key.
X-RateLimit-RemainingintegerTokens left in the rate-limit bucket.
X-RateLimit-ResetintegerSeconds until a retry is allowed. Sent only when the limiter imposed a wait.
Concurrency-LimitintegerConcurrent in-flight requests allowed for your organization.
Concurrency-RemainingintegerConcurrent slots left.
Cache-Statehit, miss, bypassResult-cache outcome. Always present on a completed scrape.
X-WarningCODE: messageA non-fatal decision the platform made for you. Repeated, one header per warning.
Retry-AfterintegerOn retryable errors: seconds to wait before retrying.
Content-Typesee belowShape of the body.

Content-Type follows response_format: text/html (html, the default), text/markdown (markdown), text/plain (text), application/json (json, and any request that forces the envelope), application/pdf (pdf). Errors are always application/problem+json.

Cache-State

ValueMeaningCredits
hitServed from a stored result younger than cache_ttl. Nothing was fetched.0
missThe request was eligible for the cache, nothing fresh was stored, so it was fetched now. A billable success is stored for next time.normal price
bypassThe request was not eligible: cache=false or cache_ttl=0, a session_id, actions, a method other than GET, or caching is off on this deployment.normal price

The default cache_ttl is 172800 seconds (48 hours). Set cache: false for time-sensitive data. See Caching.

X-Warning codes

Each X-Warning header is CODE: message. Switch on the code; the message is for humans. The JSON envelope's warnings array carries the messages only.

CodeWhen you see itWhat to do
PROXY_FLAG_IGNOREDYou set proxy together with a managed-pool flag (premium_proxy or proxy_country Coming soon). Your own proxy wins and the pool flags were ignored.Remove the ignored flags.
FORMAT_COERCEDYou asked for html, markdown or text, but extract, autoparse, links, ai_extract, network_capture or screenshot needs the JSON envelope, so response_format became json.Send response_format: "json" explicitly, or drop the flag. Markdown is in the envelope's content.
CACHE_TTL_CLAMPEDcache_ttl was above the deployment's maximum (48 hours by default) and was lowered to it.Send a smaller cache_ttl.
ENGINE_SUBSTITUTEDYou asked for a browser render without pinning engine, and this deployment served it on a different render engine than the default. X-Engine names the engine that ran, and X-Request-Cost its price.Pin engine if you need a specific one; a pinned engine is never substituted.
RENDER_DEGRADEDThe browser returned the page but could not deliver something you asked for, for example a wait_for selector that never appeared.Check the selector, or raise wait_for_timeout.
ESCALATEDA cheaper rung was tried and abandoned before the one that answered: under mode=auto, or when a bot challenge on your own proxy moved the request to Camoufox Coming soon. One header per abandoned rung, sent on success too, so you can see why the price rose.Under mode=auto, send the engine that worked (js_render=true) next time to skip the failed rung.

Warnings also appear in an error body's warnings array when a request fails.

Read the headers in code

curl -sS -D headers.txt -o page.md "https://api.spicrawl.com/v1/scrape" \
  -H "Authorization: Bearer $SPICRAWL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/products/42", "response_format": "markdown"}'
grep -i -E '^(x-target-status|x-credits-charged|x-engine|cache-state|x-warning):' headers.txt

On this page