Crawlfox API

Authentication

Every request is authenticated with your secret API key, sent as a Bearer token in the Authorization header. Create and reveal your key from the dashboard.

code
Authorization: Bearer $CRAWLFOX_API_KEY

Keep it secret

Treat the key like a password — never ship it in client-side code. If it leaks, rotate it from the API Keys page; the old secret is invalidated immediately.

Crawlfox API

Limits & Credits

There is no per-minute request limit. Credits are the only meter — while your key has credits, you can spend them as fast as you like, so you don't need to build backoff for a rate limit that never fires.

Credits

Successful requests consume credits: 1 credit per page scraped (requesting multiple formats for one page is still 1 credit, and a cached page costs the same as a fresh one), and 1 credit per 10 requested search results (based on num). Failed calls are free.

Crawlfox API

Status Codes & Errors

Errors return a JSON envelope with a stable machine code, an HTTP status, whether the request is safe to retry, and a human remediation hint.

code
{
  "code": "UPSTREAM_TIMEOUT",
  "status": 504,
  "retryable": true,
  "title": "Request timed out",
  "message": "The target site did not respond in time.",
  "remediation": "Retry. If a URL consistently times out, try a more specific path."
}

Error codes

Switch on the stable `code` — statuses and messages may change, codes won't. Retryable errors are safe to retry with backoff.

CodeRetryableWhen
MISSING_URLNoThe request body has no url.
INVALID_URLNoThe URL isn't fully-qualified (https://…) or is malformed.
UPSTREAM_UNREACHABLEYesThe target site couldn't be reached.
UPSTREAM_NOT_FOUNDNoThe target site returned 404 for the URL.
UPSTREAM_TIMEOUTYesThe target site didn't respond in time.
UPSTREAM_RATE_LIMITEDYesThe target site is rate-limiting requests.
UPSTREAM_SERVER_ERRORYesThe target site returned a server error.
UPSTREAM_GEO_BLOCKEDNoThe target site refused the request on regional or legal grounds.
BOT_WALLNoThe page could not be retrieved.
NO_PUBLIC_CONTENTNoThe page loaded but had no readable content.
INTERNAL_ERRORYesAn unexpected error on our side — retry, then contact support with the request ID.
Crawlfox API

OpenAPI Spec

The whole public API is published as an OpenAPI 3.1 document. Point Swagger UI, Stoplight, an SDK generator, or an agent at it — it describes every live endpoint, request body, response shape and error code.

code
https://crawlfox.io/openapi.json

What it covers

Only endpoints that are live today. There is no separate extract endpoint — structured extraction is this scrape endpoint with jsonOptions, below — and search is /v1/search, with the engine as a request field. Map and crawl are not shipped yet.

Scrape

Scrape a URL

POSThttps://api-staging.crawlfox.io/v1/scrape
Consumes credits. 1 credit per page scraped — any number of formats for one page is still 1 credit, and a page served from cache costs the same as a fresh one. Failed calls are free.

Fetch a single URL and return clean, structured data. Blocked and JavaScript-heavy pages are handled for you by our bespoke in-house engine, so you get a result instead of a block. Choose one or more output formats.

Body params

urlstringrequired
The URL to scrape. Must include the scheme (https://).
formatsstring[]
Any of markdown, html, rawHtml, text, json, links, images, emails. Defaults to markdown.
extractMainContentboolean
Strip nav/header/footer/sidebar and return just the article body.
skipCacheboolean
Force a fresh fetch instead of serving a cached result.
timeoutinteger
How long to wait for the page, in milliseconds. Defaults to 30000. Below 1000 the request is rejected; a value above 90000 is capped at 90000 rather than refused.
jsonOptionsobject
Structured extraction. With "json" among formats, maps output keys to CSS selectors and returns the result as data.json — deterministic, no AI. This is how extraction works; there is no separate extract endpoint.
Language
Credentials
Bearer$CRAWLFOX_API_KEY
request.sh
curl --request POST \
  --url https://api-staging.crawlfox.io/v1/scrape \
  --header "Authorization: Bearer $CRAWLFOX_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{"url":"https://example.com/","formats":["markdown","html","links"]}'
200 OKresponse.json
{
  "success": true,
  "data": {
    "markdown": "# Example Domain\n...",
    "html": "<html>...</html>",
    "links": ["https://www.iana.org/domains/example"],
    "metadata": {
      "title": "Example Domain",
      "description": "Example Domain for use in documents.",
      "language": "en",
      "sourceURL": "https://example.com/",
      "statusCode": 200
    }
  }
}
Batch

Batch scrape

POSThttps://api-staging.crawlfox.io/v1/batch
Consumes credits. 1 credit per page scraped, billed per URL, cached or fresh. Failed URLs are free.

Scrape many URLs in one call. Each URL is processed independently with the same formats, and results come back in the same order as the input array.

Body params

urlsstring[]required
The list of URLs to scrape — up to 100 per request.
formatsstring[]
Output formats applied to every URL. Defaults to markdown.
extractMainContentboolean
Strip nav/header/footer/sidebar from every page and return just the article body.
skipCacheboolean
Force a fresh fetch for every URL instead of serving cached results.
timeoutinteger
How long to wait for the page, in milliseconds. Defaults to 30000. Below 1000 the request is rejected; a value above 90000 is capped at 90000 rather than refused. Applies to each URL on its own, not to the batch as a whole — a batch of slow pages can take longer than this in total.
Language
Credentials
Bearer$CRAWLFOX_API_KEY
request.sh
curl --request POST \
  --url https://api-staging.crawlfox.io/v1/batch \
  --header "Authorization: Bearer $CRAWLFOX_API_KEY" \
  --header 'Content-Type: application/json' \
  --data '{"urls":["https://example.com/","https://example.org/"],"formats":["markdown"]}'
200 OKresponse.json
{
  "success": true,
  "count": 2,
  "results": [
    { "success": true, "data": { "markdown": "# Example Domain\n...", "metadata": { "sourceURL": "https://example.com/", "statusCode": 200 } } },
    { "success": true, "data": { "markdown": "# Example Domain\n...", "metadata": { "sourceURL": "https://example.org/", "statusCode": 200 } } }
  ]
}
MCP Server

CrawlFox MCP server

Give any MCP-compatible client — Claude Desktop, Claude Code, Cursor — first-class tools to read the web: scrape a page to clean Markdown, search Google, Bing or DuckDuckGo, batch-fetch, and pull structured fields out of HTML.

It is a faithful adapter over the same public CrawlFox REST API documented here — the same bespoke engine does the work, so a protected page comes back as content rather than as a block. There is nothing new to learn about the underlying behaviour, and tool calls spend credits at the same rate as the equivalent REST call.

What you need

A CrawlFox account. The server requires an OAuth token — the sign-in your client opens is the same one you use for the dashboard. No API key is ever pasted into, or stored by, the client.

MCP Server

Endpoint and authentication

Point your client at this URL:

server url
https://mcp.crawlfox.io/mcp
Value
URLhttps://mcp.crawlfox.io/mcp
TransportStreamable HTTP
AuthOAuth 2.1 — your client runs the flow, no key to paste

OAuth 2.1

Your client registers itself dynamically (DCR) with PKCE and opens a browser for you to sign in and approve access. There is no client ID to request from us and no key to paste.

Discovery

A spec-compliant client discovers everything it needs from these two documents. An unauthenticated call to /mcp returns 401 with a WWW-Authenticate header pointing at them — that response starts the flow.

discovery
GET /.well-known/oauth-protected-resource/mcp   # RFC 9728
GET /.well-known/oauth-authorization-server     # RFC 8414
MCP Server

Client setup

These shapes genuinely differ between clients: Claude Desktop adds remote servers through Connectors (its config file only launches local stdio servers), Cursor takes a bare url, and Claude Code requires an explicit type.

Claude Desktop · Connectors

Remote servers are added through Connectors, not claude_desktop_config.json — that file only launches local stdio servers.

server url
https://mcp.crawlfox.io/mcp
  1. Open Settings → Connectors → Add custom connector.
  2. Paste the URL above, save, then click Connect to run the OAuth sign-in.

Cursor · mcp.json

Add to ~/.cursor/mcp.json for every project, or .cursor/mcp.json for just one.

~/.cursor/mcp.json
{
  "mcpServers": {
    "crawlfox": {
      "url": "https://mcp.crawlfox.io/mcp"
    }
  }
}
  1. Open Settings → MCP and sign in when Cursor prompts.

Claude Code · CLI

Add it from the terminal, or write the entry by hand. The type field is required — an entry with a url and no type is read as stdio and fails.

terminal
claude mcp add --transport http crawlfox https://mcp.crawlfox.io/mcp
.mcp.json
{
  "mcpServers": {
    "crawlfox": {
      "type": "http",
      "url": "https://mcp.crawlfox.io/mcp"
    }
  }
}
  1. Run /mcp, pick crawlfox, then Authenticate.
  2. A browser opens for sign-in; the session reconnects authenticated.

Any MCP host · Spec

A spec-compliant client discovers everything it needs from these two documents. Registration is dynamic (DCR) with PKCE, so there is no client ID to request from us.

discovery
GET /.well-known/oauth-protected-resource/mcp   # RFC 9728
GET /.well-known/oauth-authorization-server     # RFC 8414
  1. An unauthenticated call to /mcp returns 401 with a WWW-Authenticate header pointing at the metadata above — that response starts the flow.
MCP Server

Tools (13)

Choose a tool

Every tool the server registers, in registration order. Eight of them are single-purpose shortcuts over a scrape restricted to one output format — they exist so a model can ask for exactly what it needs without reasoning about the format list.

JobToolUse it when
Fetch one URL as clean, LLM-ready content — Markdown, HTML, text, links, images or emails. Handles JavaScript-rendered and protected pages.crawlfox_scrapeYou know the URL and want the page content.
Web search via Google, Bing, or DuckDuckGo, returning ranked organic results.crawlfox_searchYou do not have a URL yet and need to find pages.
Scrape several URLs in one call, returning one result per page.crawlfox_batch_scrapeYou have a list of URLs and want them all.
Pull named fields out of a page into JSON using CSS selectors — deterministic, no AI in the loop.crawlfox_extractYou want specific fields, not the whole page.
Return only page metadata: title, description, and status.crawlfox_metadataYou want to know what a page is without reading it.
Extract every link on a page.crawlfox_linksYou are mapping where a page points.
Extract every image URL on a page.crawlfox_imagesYou want a page's images.
Extract every email address on a page.crawlfox_emailsYou are collecting contact details from a page.
Return a page as plain text.crawlfox_textYou want prose with no markup.
Return a page as clean HTML.crawlfox_htmlYou need the markup itself.
Lightweight GET scrape of a URL, for quick one-off fetches.crawlfox_scrape_getYou want the cheapest possible read of one page.
Look up the status and timing of a past request by its id.crawlfox_get_logYou want to know how an earlier call went. Free.
Retrieve the full stored result of a past scrape by id.crawlfox_log_resultYou want an earlier result back without paying for it twice. Free.

Arguments

Every argument each tool accepts. Your client also shows these from the server's own schema; this table is here so you can read them before connecting. Only url-style arguments are required unless marked otherwise.

crawlfox_scrape

Fetch one URL as clean, LLM-ready content — Markdown, HTML, text, links, images or emails. Handles JavaScript-rendered and protected pages. Maps to POST /v1/scrape.

ArgumentTypeRequiredDescription
urlstringyesAbsolute URL to fetch, including the scheme (http:// or https://).
formatsstring[]Any of markdown, html, rawHtml, text, json, links, images, emails. Defaults to markdown.
onlyMainContentbooleanStrip nav, header, footer and sidebar and keep the main article only.
skipCachebooleanBypass the cache and force a fresh fetch.
timeoutintegerGive up on this page after this many milliseconds. Defaults to 30000. Below 1000 the request is rejected; a value above 90000 is capped at 90000 rather than refused. Worth setting for slow or JavaScript-heavy pages.

crawlfox_search

Web search via Google, Bing, or DuckDuckGo, returning ranked organic results. Maps to POST /v1/search.

ArgumentTypeRequiredDescription
querystringyesThe search query.
enginestringgoogle, bing or duckduckgo. Defaults to google.
countintegerHow many results to return, from 1 to 100.
offsetintegerSkip this many results before returning any — 0 or above, for paging.
countrystringTwo-letter country code, e.g. us.
languagestringTwo-letter language code, e.g. en.

crawlfox_batch_scrape

Scrape several URLs in one call, returning one result per page. Maps to POST /v1/batch.

ArgumentTypeRequiredDescription
urlsstring[]yesBetween 1 and 50 absolute URLs. This tool caps lower than the REST endpoint.
formatsstring[]Any of markdown, html, rawHtml, text, json, links, images, emails. Defaults to markdown.
onlyMainContentbooleanStrip nav, header, footer and sidebar and keep the main article only.
skipCachebooleanBypass the cache and force a fresh fetch.

crawlfox_extract

Pull named fields out of a page into JSON using CSS selectors — deterministic, no AI in the loop. Maps to POST /v1/scrape.

ArgumentTypeRequiredDescription
urlstringyesAbsolute URL to fetch, including the scheme (http:// or https://).
selectorsobjectyesField name to CSS selector, e.g. { "title": "h1", "price": ".price" }.
onlyMainContentbooleanStrip nav, header, footer and sidebar and keep the main article only.
skipCachebooleanBypass the cache and force a fresh fetch.

crawlfox_metadata

Return only page metadata: title, description, and status. Maps to POST /v1/scrape.

ArgumentTypeRequiredDescription
urlstringyesAbsolute URL to fetch, including the scheme (http:// or https://).
onlyMainContentbooleanStrip nav, header, footer and sidebar and keep the main article only.

crawlfox_links

Extract every link on a page. Maps to POST /v1/scrape.

ArgumentTypeRequiredDescription
urlstringyesAbsolute URL to fetch, including the scheme (http:// or https://).
onlyMainContentbooleanStrip nav, header, footer and sidebar and keep the main article only.

crawlfox_images

Extract every image URL on a page. Maps to POST /v1/scrape.

ArgumentTypeRequiredDescription
urlstringyesAbsolute URL to fetch, including the scheme (http:// or https://).
onlyMainContentbooleanStrip nav, header, footer and sidebar and keep the main article only.

crawlfox_emails

Extract every email address on a page. Maps to POST /v1/scrape.

ArgumentTypeRequiredDescription
urlstringyesAbsolute URL to fetch, including the scheme (http:// or https://).
onlyMainContentbooleanStrip nav, header, footer and sidebar and keep the main article only.

crawlfox_text

Return a page as plain text. Maps to POST /v1/scrape.

ArgumentTypeRequiredDescription
urlstringyesAbsolute URL to fetch, including the scheme (http:// or https://).
onlyMainContentbooleanStrip nav, header, footer and sidebar and keep the main article only.
skipCachebooleanBypass the cache and force a fresh fetch.

crawlfox_html

Return a page as clean HTML. Maps to POST /v1/scrape.

ArgumentTypeRequiredDescription
urlstringyesAbsolute URL to fetch, including the scheme (http:// or https://).
onlyMainContentbooleanStrip nav, header, footer and sidebar and keep the main article only.
skipCachebooleanBypass the cache and force a fresh fetch.

crawlfox_scrape_get

Lightweight GET scrape of a URL, for quick one-off fetches. Maps to GET /v1/scrape/:url.

ArgumentTypeRequiredDescription
urlstringyesAbsolute URL to fetch, including the scheme (http:// or https://).
formatsstring[]Any of markdown, html, rawHtml, text, json, links, images, emails. Defaults to markdown.

crawlfox_get_log

Look up the status and timing of a past request by its id. Maps to GET /v1/logs/:id.

ArgumentTypeRequiredDescription
idstringyesThe id returned by an earlier call.

crawlfox_log_result

Retrieve the full stored result of a past scrape by id. Maps to GET /v1/logs/:id/result.

ArgumentTypeRequiredDescription
idstringyesThe id returned by an earlier call.
MCP Server

Worked examples

Once the server is connected you do not call these tools by hand — you ask in plain language and the client picks the tool. These are the shapes that work well, with the call each one produces.

Read one page

The most common case. The model picks crawlfox_scrape and gets Markdown back.

prompt
You: Summarise https://example.com/pricing for me.

→ crawlfox_scrape { "url": "https://example.com/pricing" }

Research a topic across sources

Search first, then read the results. Ask for the search explicitly when you want breadth before depth, otherwise a client may scrape the first URL it can guess.

prompt
You: Find three recent write-ups on Rust async runtimes and
     summarise what they disagree about.

→ crawlfox_search        { "query": "rust async runtime comparison", "count": 10 }
→ crawlfox_scrape        { "url": "<first result>" }
→ crawlfox_scrape        { "url": "<second result>" }

Pull specific fields out of a page

When you want data rather than prose, name the fields. Selectors are CSS, matched against the fetched DOM, and the result comes back as JSON — the same deterministic extraction the REST API does, with no model in the loop guessing values.

prompt
You: From https://example.com/product/42 get me the title, price
     and stock status.

→ crawlfox_extract {
    "url": "https://example.com/product/42",
    "selectors": { "title": "h1", "price": ".price", "stock": "[data-stock]" }
  }

Read many pages at once

Batch when you already have the list. One call, one result per page, in the order you gave them.

prompt
You: Scrape these five docs pages and tell me which mention rate limits.

→ crawlfox_batch_scrape { "urls": ["https://…/a", "https://…/b",] }

When a page is slow

A page that renders slowly can exceed the default time budget. Ask for more time and the model passes timeout through. It defaults to 30000 ms; below 1000 the call is rejected, and above 90000 it is capped at 90000 rather than refused.

prompt
You: Scrape https://example.com/heavy — give it more time than usual.

→ crawlfox_scrape { "url": "https://example.com/heavy", "timeout": 60000 }

Costs

Tool calls spend credits at exactly the same rate as the REST call behind them — 1 credit per page scraped, 1 per 10 requested search results. Looking up a past request or its stored result is free. Failed calls are free.