Skip to main content
Some calls finish in the moment; others run long enough to hand back a job you follow up on. Hydrafetch keeps the shape predictable: a synchronous result comes back as { data }, and a job comes back as an id you poll — or a webhook that calls you when it’s done.

Scrape: synchronous by default

A scrape waits for the result and returns it inline. You get { data } with the formats you asked for.
If a scrape runs past the synchronous wait — or if you set async: true — it returns a job id instead, with a 201:
Poll it until it’s done:
The status response reports the job state and, once finished, the page:
string
waiting, active, completed, or failed.
object
The scraped page, present when status is completed.
string
Set when status is failed.
Set async: true up front when you know a page is heavy — a JavaScript-rendered app, a long settle time — so your request never blocks waiting for it.

Crawl and batch: always async

A crawl (discover and scrape a whole site) and a batch (scrape an explicit list of URLs) always run as background jobs. Starting one returns an id immediately with a 201:
You then track it one of two ways.
Request the job’s status endpoint for live progress and per-page results:
Batches use GET /v1/web/batch/{id}. Both return the same status shape:
status moves through running to completed (or failed / cancelled). Each entry in pages carries its own status and, once done, its scraped data.

Verifying a webhook

Your webhook endpoint is a public URL, so anyone who finds it can POST to it. Set a webhook.secret and we sign every callback, letting you prove a request came from us and reject anything that didn’t. Each signed delivery carries these headers: To verify, recompute the HMAC over the raw request body — not a re-serialized version of the parsed JSON, which may produce different bytes and never match:
Compare signatures in constant time (hmac.compare_digest, crypto.timingSafeEqual) — a plain == leaks timing information. And always check the timestamp: a signature alone stays valid forever, so without a freshness window a captured delivery can be replayed at you.
The timestamp is signed along with the body, so an attacker cannot take a real delivery and re-send it under a fresh timestamp. If you don’t set a secret, callbacks are still sent — just unsigned.

Which calls return what

Next: Errors

The structured error model and every status you’ll see.