Skip to main content
POST /v1/fetch returns rendered page text. Long-running requests can run as jobs, with results available through GET /v1/job/{job_id}. For other output formats, see Extract. Scrape & crawl supports reads without a caller-managed session.

POST /v1/fetch

Load a URL in the session’s browser and return its text. The request attempts challenge recovery and reports whether usable content was delivered. Use /v1/extract for Markdown output. For protected pages, fetch combines block detection, challenge solving, and exit recovery with a typed response. Disconnect the main CDP client and any native Playwright or VNC client before calling it. CDP observers can remain connected; coordinate their commands with the fetch. On a custom-proxy session, recovery never switches the proxy exit. Auth: Bearer API key. Request: expect_url, expect_text and no_results_url are limited to 512 characters each. Invalid or unsafe regular expressions answer 422. A plain request:
Response: The Wikipedia page (text cut):
A settled read of a news front page, with a selector and the DOM returned. The request was {"session_id": "...", "url": "https://www.bbc.com/news", "settle_ms": 500, "wait_ms": 8000, "wait_for_selector": "h1", "include_html": true} (trimmed to the fields that differ from the plain example):
A blocked page, with the recovery report. The fetch spent its response budget on two more exits and gave up, answering 200 with status: "blocked". settle is null because no page was delivered:
Reading recovery: attempts and actions at the top level are the in-page heals on your own session. ladder is the escalation across exits: outcome is delivered, exhausted or no_results; attempts counts the tries that ran; each entry in rungs names the tier (direct, residential, isp, mobile, …), its result, how long it took and, when it is a plain slug, a reason; delivered_by names the tier that delivered the page, exhausted_reason why the ladder stopped, and answered_by the tier whose page was the site’s own answer. budget is the clock the fetch ran on: kind is sync (55 s) or async (900 s), elapsed_s what was used, and spent where the seconds went by phase (heal, chain, warm_entry, persist, report). A budget result on a rung means the tier was started but the clock ran out before it answered; on a 900 second job clock the same page gets many more tries. Async mode and polling. {"session_id": "...", "url": "https://en.wikipedia.org/wiki/HTTP", "async_mode": true} answers at once:
(The other fields are present with their null or default values.) A second fetch on the same session while that job runs is refused:
on_deadline: "continue". On a page that delivers in time the answer is a normal 200. When the page has not delivered at 55 seconds the route answers 202 instead, with status: "pending", the job_id, and job: {"poll": "/v1/job/<job_id>", "may_run_s": <seconds the job may still run>, "ends_by": <unix seconds>}; the work continues on the 900 second job clock and the page is read from GET /v1/job/{job_id}. On a session whose ttl cannot hold a 900 second job the request is refused:
Redirects. requested_url is what you asked for and final_url is where the page landed. https://wikipedia.org/ lands on https://www.wikipedia.org/ with redirected: false, because a www prefix is not counted as a move; a change of host or path is. Errors: Notes:
  • Timing: the response limit is 55 seconds; a job runs up to 900 seconds. Plain pages return in 0.5 to 3 seconds. A challenged page spends most of the limit on alternative exits, so a page you know is protected is better run with async_mode: true or on_deadline: "continue".
  • One job per session at a time. Parallel fetches need parallel sessions.
  • A finished job stays pollable for at least 20 minutes after it ends, even after the session is released.
  • Billing for credit-funded accounts: the action is charged for a successful delivery and waived on blocked, empty, incomplete or error outcomes. Egress can still be charged on undelivered pages, at the datacenter or premium rate for the exit used. Solves and session time are charged separately. Developer and Team have no per-call wallet debits.
  • The page stays open in the session’s current tab after a successful fetch, so a following /act, screenshot or extract works on it and the live view shows it.

GET /v1/job/{job_id}

Poll any job: a fetch (async_mode, or a continue handed over at the limit), an extract, an inspect, a search, a solve, an agent task or a template. The job id is the one the starting call returned. Auth: Bearer API key. No body. Response: While pending:
Done (text cut):
Errors: 404 no such job for an unknown id, an id that belongs to another account, or a record that has expired. A 503 job_worker_unavailable includes Retry-After; the job may still be running, so retry the poll rather than starting duplicate work. Notes:
  • Poll every 1 to 2 seconds with backoff. A job that has ended can be polled for at least 20 minutes afterwards; the session may already be gone by then and the poll still answers.
  • GET /v1/fetch/job/{job_id} also works for fetch jobs and answers the bare fetch response instead of the envelope. Prefer /v1/job/{job_id}, which covers every kind.