Expand AI logo
DocsDocs
Glow Active
API Reference
Login

Documentation

Get Started

OverviewMCP ServerQuickstartWhy ExpandWays to Use Expand

Fetch

OverviewHow Fetch WorksOutput ModelProgressive DisclosureInclude OptionsDocumentsYouTubeBrowser BehaviorHighlightsPlayground & ReplayBatched Fetch

Reference

MCP Tools & ResourcesCLI, Skill & HooksCLI CommandsAPI ReferenceTypeScript SDK

Account & Billing

Pricing & UsageTiersFAQ

Machine-Readable Docs

start.mdllms.txtllms-full.txtDocs as Markdown
Browse docs

Get Started

OverviewMCP ServerQuickstartWhy ExpandWays to Use Expand

Fetch

OverviewHow Fetch WorksOutput ModelProgressive DisclosureInclude OptionsDocumentsYouTubeBrowser BehaviorHighlightsPlayground & ReplayBatched Fetch

Reference

MCP Tools & ResourcesCLI, Skill & HooksCLI CommandsAPI ReferenceTypeScript SDK

Account & Billing

Pricing & UsageTiersFAQ

Machine-Readable Docs

start.mdllms.txtllms-full.txtDocs as Markdown

Browser Behavior

How Fetch renders pages before producing Markdown and evidence.

Fetch renders live pages before extraction. It runs JavaScript, observes the page, captures browser state, and returns agent-ready Markdown, State JSON, screenshots when requested, and replayable evidence.

Public Fetch keeps browser controls small on purpose. Today, browserConfig.scrollFullPage is the only public browser behavior option.

curl https://api.expand.ai/v1/fetch \
  -H "x-expand-api-key: $EXPAND_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://stripe.com/pricing",
    "browserConfig": { "scrollFullPage": true }
}'

See Include Options

Choose Markdown, screenshot, JSON, and response output.

Debug in Playground

Replay what Fetch saw at capture time.

Open API Reference

See exact request and response schemas.

What Fetch does in the browser

Fetch does more than download HTML. It opens the page in a browser, lets client-side JavaScript run, observes the rendered page, and then extracts the content and state that matter for agents.

That difference matters on pages where raw HTML misses the useful content:

  • JavaScript-rendered docs that hydrate after load;
  • dashboards and app shells backed by JSON state;
  • pricing pages, tables, and grids where layout carries meaning;
  • icon-heavy pages where the icons are the signal.

Fetch reads and preserves page context. It is not a public browser-automation engine. This page does not promise that Fetch can fill forms, click through multi-step flows, or drive arbitrary page interactions.

Readiness and timing

Fetch decides when the page is ready internally. Public Fetch does not currently expose timeout, wait selector, network-idle, or custom readiness controls.

What that means in practice:

  • pages are rendered before extraction, not captured as raw source;
  • a page that never settles may be captured partially;
  • captures that fail or are refused surface as errors or blocked outcomes;
  • when output looks off, replay shows what Fetch actually saw.

The capture ceiling

Synchronous Fetch has one 150-second budget per request. It starts when the request is accepted and covers everything that follows: queueing, navigation, rendering, settling, optional scrolling, snapshot production, and delivering the result. Internal retries never get a fresh window.

  • If the budget runs out and the capture had started, the API returns 504 FetchCaptureTimeout. It does not prove the target page caused the timeout. timeoutMs reports the configured request ceiling (150000 by default). The SDKs do not retry this tag automatically, so an Expand-side incident is not amplified; a deliberate manual retry may still be appropriate.
  • If the budget runs out while the request was still waiting for capacity and had never started, the API returns 529 FetchCapacityTimeout with Retry-After: 5. This is a retryable Expand capacity condition, not a page verdict; both SDKs retry it.
  • A capture that started and then failed to finish stays a 504, because the capture was attempted.
  • Use a 180-second synchronous client timeout. After the 150-second budget, Expand takes at most five more seconds to decide the outcome, so a typed 504 or 529 arrives by 155 seconds. That leaves 25 seconds for the response to reach you. The TypeScript SDK's timeoutMs defaults to 60 seconds and therefore aborts long captures client-side; see TypeScript SDK.
  • Batched Fetch gives each item its own 150-second budget when that item is scheduled. An item that never started before its budget expired records the retryable 529; one that started records 504. Time spent accepting and preparing the batch is outside the per-item budget, because batched results are polled rather than held on one request.
  • Playground fetches use the same budget and the same outcome rules. Streamed playground requests deliver the outcome through the event stream rather than as a typed response on the initial request.

150 seconds bounds the budget, but it is not a target. Most captures finish in a few seconds. A result that arrives while Expand is deciding the outcome is still returned successfully; otherwise you get a typed 504 or 529 by 155 seconds at the latest. Every timing constant beneath the 150-second budget, including readiness waits and settle budgets, is internal, not a stable public contract, and can change.

Scrolling

scrollFullPage is the one public browser behavior control. It defaults to false. When true, Fetch attempts to scroll the page before capture to trigger lazy-loaded content, then returns to the top before capturing.

{
  "url": "https://example.com",
  "browserConfig": {
    "scrollFullPage": true
  }
}

The scroll pass is best-effort. It does not guarantee that every infinite-scroll page is fully exhausted, and a scroll that fails is logged and does not fail the request.

Use scrollFullPage when important content appears only after scrolling.

scrollFullPage: false -> capture the initial rendered page
scrollFullPage: true  -> scroll to trigger lazy content -> return to top -> capture

Screenshots

Screenshots are requested through include.screenshot, not browserConfig.

{
  "url": "https://example.com",
  "include": {
    "screenshot": true
  }
}

Screenshots are opt-in. A requested screenshot defaults to full-page. Set include.screenshot.fullPage: false for a viewport screenshot instead. Fetch returns one screenshot per request, not both a full-page and a viewport image.

fullPage: true  -> one full-page screenshot
fullPage: false -> one viewport screenshot

The response carries a screenshot URL and a fullPage boolean. The exact schema belongs to Output Model and the API Reference; see Include Options for the full request surface.

Redirects and response metadata

If your application needs to know what happened at the HTTP layer, request response metadata.

{
  "url": "https://example.com",
  "include": {
    "response": {
      "includeHeaders": true
    }
  }
}

Response metadata can report:

  • the final URL Fetch landed on;
  • the originally requested URL when it differs;
  • origin status;
  • redirect status;
  • headers, only when include.response.includeHeaders is true.

The full response schema lives in Output Model and the API Reference.

Blocked pages

Fetch renders through a real browser and handles many sites where raw HTTP fails, but it does not promise to bypass every block, CAPTCHA, auth wall, or bot-protection system.

  • A blocked page may return FetchBlocked.
  • Synchronous POST /v1/fetch can surface this as HTTP 403.
  • Some retry behavior is internal; Fetch may retry retryable block classes on its own.
  • Proxy behavior is internal and is not a public request option.
  • When a capture result is surprising, inspect replay or the error details before assuming the page is unreachable.

Browser controls that are not public

This is the full set of public browser behavior today. The rest of the table exists so you do not hunt for options that Fetch does not expose.

ControlPublic today?Notes
scrollFullPageYesBest-effort scroll before capture.
TimeoutNoReadiness is managed internally. Synchronous Fetch enforces one 150 s budget per request; batched items get their own when scheduled. Internal retries never reset it.
Proxy / locationNo

If any of these become public, this page and the API Reference change together.

Debug with replay

When output looks incomplete or surprising, replay shows what Fetch saw at capture time.

  • Replay helps debug missing or lazy-loaded content.
  • Replay lets you inspect citations and evidence.
  • Replay separates page behavior (what the site rendered) from extraction behavior (what Fetch kept).

The common failure modes to look for: timeout, blocked, auth wall, CAPTCHA, missing lazy content, and unexpected redirects. Playground & Replay covers the inspection workflow in full.

Next steps

  • Include Options: control which artifacts Fetch returns.
  • Output Model: see the response fields and schemas.
  • Playground & Replay: inspect evidence visually.
  • How Fetch Works: the capture mental model.
PreviousYouTube
NextHighlights

On This Page

What Fetch does in the browserReadiness and timingThe capture ceilingScrollingScreenshotsRedirects and response metadataBlocked pagesBrowser controls that are not publicDebug with replayNext steps
Proxy retry behavior is internal.
Viewport / deviceNoNot a public Fetch option.
User agentNoNot a public Fetch option.
Cookies / session authNoAuthenticated browsing is not owned by this page.
GeolocationNoNot a public Fetch option.
Wait selector / action stepsNoFetch is not a public browser-actions API today.
Bot detector bypassNoInternal-only; not a public option.