Skip to main content

Endpoint

All requests require an X-API-Key header. See Authentication.

Request

Parameters

urls
string[]
required
URLs to fetch and extract. Maximum 10 URLs per request.All URLs must use http or https. Private IP addresses, localhost, and cloud metadata endpoints are rejected.
purpose
string
An optional short statement of why you are fetching these URLs — the underlying goal or task the content will be used for. Supplying the intent behind a fetch gives us additional signal to further inform and deliver better-quality results. When omitted, fetch behaves exactly as before. When supplied, the value must be non-empty (whitespace-only values are rejected). Maximum 2000 characters. For example, Compare pricing tiers across vendors for a procurement report.
format
string
default:"markdown"
Output format for the text field in each result. One of:
  • html — semantic HTML
  • markdown — clean Markdown, recommended for LLMs (default)
  • json — structured document tree
When true, include all <a href> URLs found on the page in the links field.
When true, include all <img src> URLs found on the page in the image_links field.
ttl
integer
default:"omitted"
Cache freshness tolerance in seconds.
  • Omit ttl to accept any cached entry.
  • Set ttl to 0 when you want a live fetch.
  • Set ttl to a positive integer to accept cached entries younger than that many seconds.
per_url_timeout_ms
integer
default:"omitted"
Per-URL wall-clock timeout budget in milliseconds. Must be between 1 and 110000.If a URL exceeds this budget, that URL returns a timeout error in errors[] while other URLs in the same request can still complete.
if_none_match
string
An ETag you saved from a prior fetch of this URL, forwarded verbatim as the If-None-Match header on the origin request. Single URL only — combining with a batch of URLs returns a 400.
if_modified_since
string
A Last-Modified value you saved from a prior fetch of this URL, forwarded verbatim as the If-Modified-Since header on the origin request. Single URL only — combining with a batch of URLs returns a 400.
include_etag_and_last_modified
boolean
default:"false"
When true, include etag and last_modified on each result so you can store them and replay them on your next fetch of the same URL. Works with a single URL or a batch.
Conditional requests are a stateless pass-through — Fetch does not store etag or last_modified for you. Save the values returned by include_etag_and_last_modified and replay them as if_none_match / if_modified_since on your next request to detect whether the page changed.
include_selectors
string[]
An array of CSS selectors (1–20 entries, each 1–1000 characters) that scopes extracted content (text, links, image_links) to elements matching any entry, concatenated in document order. Tag selectors cover semantic sections (main, article, nav); entries may themselves use CSS comma-grouping ("main, footer").Selected content is returned verbatim, converted to the requested format (scripts and styles stripped) — automatic boilerplate removal is bypassed. Page-level metadata (title, description, language, author, published_date) still comes from the full document.If some entries match and others don’t, the URL still succeeds with the matched content and the misses are listed in the result’s unmatched_selectors. If no entry matches anything, that URL fails with the per-URL error code selector_not_matched — there is no silent full-page fallback — and the error carries unmatched_selectors plus candidate_selectors retry hints. Invalid CSS selector syntax is rejected with a 422.
exclude_selectors
string[]
An array of CSS selectors (1–20 entries, each 1–1000 characters) for elements to remove before extraction. Applied before include_selectors scopes what remains, so it also prunes inside selected regions. Entries that match nothing are a no-op, never an error. Invalid CSS selector syntax is rejected with a 422.
Selectors are applied after the page is fetched — caching and routing are unchanged. URLs that resolve to direct PDF or CSV downloads have no HTML to scope, so sending include_selectors or exclude_selectors for them fails that URL with selector_unsupported.

Response

results[]

One entry per successfully fetched URL.
url
string
The original requested URL.
final_url
string
The URL after any redirects. May differ from url.
title
string | null
Page title, preferring og:title over <title>. null if not found.
description
string | null
Meta description, preferring og:description over <meta name="description">. null if not found.
language
string | null
Detected page language (e.g. "en"). null if undetectable.
author
string | null
Author from meta tags. null if not found.
published_date
string | null
Publication date, if detectable. null if not found.
text
string | object
Extracted page content. Format depends on the format request parameter:
  • string when format is "html" or "markdown"
  • object (document tree) when format is "json"
All <a href> URLs on the page, resolved to absolute URLs. Only present when links: true was requested.
All <img src> URLs on the page, resolved to absolute URLs. Only present when image_links: true was requested.
not_modified
boolean (optional)
Present and true only when the origin returned 304 Not Modified for your if_none_match or if_modified_since header — the content is unchanged and you can skip re-processing. Omitted otherwise.
etag
string (optional)
The origin’s current ETag validator. Save it and replay it as if_none_match on your next fetch of this URL. Present only when the origin sent one and you set include_etag_and_last_modified; omitted otherwise.
last_modified
string (optional)
The origin’s current Last-Modified validator. Save it and replay it as if_modified_since on your next fetch of this URL. Present only when the origin sent one and you set include_etag_and_last_modified; omitted otherwise.
unmatched_selectors
string[] (optional)
Partial-miss report for include_selectors: the entries that matched no elements on this page. Present only when some (but not all) entries matched — the result still carries the matched content. Omitted when every entry matched. A total miss is reported as a selector_not_matched entry in errors[] instead.
latency_ms
number | null
Time to fetch and extract this URL, in milliseconds. null if unavailable.
format
string
Output format used for the text field. Echoes the request format parameter ("markdown", "html", or "json").
Fields that could not be extracted (title, description, language, author, published_date) are returned as null.

errors[]

One entry per URL that could not be fetched. Always present, may be empty. Per-URL failures do not affect the rest of the batch.
url
string
The URL that failed.
error
string
Structured error code identifying the failure type. One of: target_http_error, page_not_found, target_unreachable, timeout, bot_blocked, empty_content, invalid_url, invalid_redirect_url, proxy_error, conditional_unsupported, selector_not_matched, selector_unsupported.
status
number (optional)
Upstream HTTP status code. Present when error is target_http_error or page_not_found.
unmatched_selectors
string[] (optional)
The include_selectors entries that matched no elements on the fetched page. Present only when error is selector_not_matched.
candidate_selectors
string[] (optional)
Cheap retry hints (max 10), present only when error is selector_not_matched: landmark tags found on the page (e.g. main, article, nav) plus #id selectors of content-heavy elements. Agents can retry the fetch with include_selectors drawn from this list.

SDK Methods


Error Codes

HTTP-level errors apply to the entire request.
StatusMeaning
400Invalid request — missing urls, too many URLs (max 10), bad parameter value, or if_none_match/if_modified_since combined with a batch of URLs
401Missing or invalid API key
422Invalid CSS selector syntax in include_selectors / exclude_selectors
429Rate limit exceeded
500Internal server error
Per-URL errors appear in errors[] alongside a 200 response. The error field is one of these codes:
Error codestatus fieldMeaning
target_http_errorHTTP status code (e.g. 403, 500)Target server returned a non-2xx HTTP response other than 404/410
page_not_found404 or 410Target URL does not exist (HTTP 404 Not Found or 410 Gone)
target_unreachableConnection refused, TLS failure, DNS failure, or other network error
timeoutPage did not finish loading within the request deadline
bot_blockedSite returned a bot-protection challenge (Cloudflare, Incapsula)
empty_contentBrowser returned HTML but no extractable text found
invalid_urlURL rejected before fetch (private IP, invalid scheme, disallowed host)
invalid_redirect_urlRedirect target rejected before fetch (private IP or disallowed host)
proxy_errorProxy tunnel failed — site may be reachable directly
conditional_unsupportedURL requires browser rendering — conditional requests (if_none_match / if_modified_since) are supported on the fast path only
selector_not_matchedNo elements matching any include_selectors entry remained after exclude_selectors was applied (total miss); the error carries unmatched_selectors + candidate_selectors retry hints. A partial miss is not an error — it’s reported on the result’s unmatched_selectors
selector_unsupportedinclude_selectors / exclude_selectors sent for a URL that resolves to a direct PDF/CSV download — no HTML to scope
Per-URL fetch failures are not HTTP errors. They appear as entries in errors[] alongside a 200 response.
Each URL has a 110-second backend timeout. If the page doesn’t respond within 110 seconds, that URL returns a timeout error in errors[] while the rest of the batch continues. Requests are also subject to a 120-second CDN ceiling for the full batch. Set your client-side timeout to at least 150 seconds to receive CDN timeout errors cleanly.

Supported Content Types

Content TypeBehavior
HTMLFull text extraction with formatting
PDFText content extracted
JSONRaw JSON returned as text
Plain textFull text returned
Images (PNG, JPG)Not supported — returns an error indicating no extractable content

Usage Endpoint

Retrieve a paginated history of your fetch operations.
All requests require an X-API-Key header. See Authentication.

Query Parameters

start_after
string (ISO 8601)
Filter results created after this timestamp. Example: 2026-01-01T00:00:00Z
end_before
string (ISO 8601)
Filter results created before this timestamp. Example: 2026-02-01T00:00:00Z
status
string
Filter by result status. One of: completed, failed.
limit
integer
default:"100"
Maximum number of items per page. Range: 1-1000.
page
integer
default:"1"
Page number for pagination.

Response

items[]

id
string
Unique identifier for the fetch result.
url
string
The original requested URL.
final_url
string
The URL after any redirects.
title
string | null
Page title, if detected.
description
string | null
Meta description, if detected.
language
string | null
Detected page language (e.g. "en").
author
string | null
Page author, if detected.
published_date
string | null
Published date, if detected.
format
string
The format used for extraction: markdown, html, or json.
status
string
Result status: completed or failed.
request_origin
string
Where the request originated: api, cli, python-sdk, js-sdk, mcp, etc.
request_id
string | null
The request ID that grouped this URL with others in a batch.
text_length
integer | null
Length of the extracted text content in characters. The full text is not included in usage responses.
Number of links found on the page.
Number of image links found on the page.
latency_ms
number | null
Time taken to fetch and extract the page, in milliseconds.
not_modified
boolean (optional)
Present and true only when that fetch was a conditional request that returned 304 Not Modified. Omitted otherwise.
etag
string (optional)
The origin’s ETag validator captured at fetch time. Present only when include_etag_and_last_modified was set on that request and the origin returned one; omitted otherwise.
last_modified
string (optional)
The origin’s Last-Modified validator captured at fetch time. Present only when include_etag_and_last_modified was set on that request and the origin returned one; omitted otherwise.
created_at
string (ISO 8601)
Timestamp when the fetch was executed.
error
string | null
Error message if the fetch failed. null for successful fetches.

Error Codes

StatusMeaning
400Invalid query parameters
401Missing or invalid API key
500Internal server error

Rate Limits

Limits apply per API key, measured in URLs per minute across all requests.
PlanURLs / minute
Free150
Pay As You Go150
Starter300
Pro600
When the limit is exceeded, the API returns HTTP 429.

Billing

Fetch does not use credits.

Fetch Overview

First request, response shape, and product routing

Authentication

API key setup and troubleshooting

Error Codes

Full list of API error codes