Skip to main content
Glama

Start with foura_auto: one URL in, typed content out. It chooses the appropriate fetch method and handles common blocks for you. Use foura_single, foura_proxy, or foura_browser when you want explicit control over the request path.

Start simple

Reach difficult pages

Build predictable agent flows

One default tool for most URLs

HTTP, proxy rotation, and full-browser rendering

Typed outputs, stable error codes, and six ready-made prompts

The included workflows cover product extraction, article cleanup, price monitoring, endpoint checks, and bulk URL fetching.

Use it from Claude Desktop, Claude Code, Cursor, Windsurf, VS Code, or any MCP client. Run the npm package locally or connect to the hosted Streamable HTTP endpoint with the same FourA API key.

Get an API key | Read the MCP docs | See the package on npm

One-click install:

Add to Cursor Install in VS Code

Both buttons pre-fill the config with a YOUR_FOURA_API_KEY placeholder - replace it with your key. Or by hand: claude mcp add foura -- npx -y @fouradata/mcp (set FOURA_API_KEY in env first). Full per-client setup below.

Create or reveal an API key at foura.ai/dashboard/#api-keys (format pk_live_...). Then drop this into your MCP client's config:

{
  "mcpServers": {
    "foura": {
      "command": "npx",
      "args": ["-y", "@fouradata/mcp"],
      "env": {
        "FOURA_API_KEY": "pk_live_..."
      }
    }
  }
}

Claude Desktop gotcha: fully quit Claude Desktop (Cmd+Q on macOS) before editing the config file. If the app is still running, it will overwrite your edits with its in-memory config on exit.

The npx command downloads the package on first launch and runs it as a subprocess of your MCP client. No global install needed. The same JSON works across MCP clients; only the config-file location changes:

Client

Where the config lives

Claude Desktop (macOS)

~/Library/Application Support/Claude/claude_desktop_config.json

Claude Desktop (Windows)

%APPDATA%\Claude\claude_desktop_config.json

Claude Code

claude mcp add foura -- npx -y @fouradata/mcp (set FOURA_API_KEY in env first)

Cursor

~/.cursor/mcp.json

Windsurf

~/.codeium/windsurf/mcp_config.json

VS Code (MCP extension)

.vscode/mcp.json in your workspace

Restart the client and foura_auto, foura_single, foura_proxy, foura_browser show up in your tool list, plus six prompts under /prompts.

Related MCP server: Bright Data MCP

Quick Start - hosted (Streamable HTTP)

If your client supports the Streamable HTTP transport, point it at the hosted endpoint instead of running a local subprocess:

{
  "mcpServers": {
    "foura": {
      "url": "https://mcp.foura.ai/mcp",
      "headers": {
        "Authorization": "Bearer pk_live_..."
      }
    }
  }
}

For Claude Desktop, use the stdio config above. You can also bridge the hosted endpoint through mcp-remote:

{
  "mcpServers": {
    "foura": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://mcp.foura.ai/mcp", "--header", "Authorization: Bearer pk_live_..."]
    }
  }
}

The Tools

foura_auto is the default - give it a URL and it returns the content, choosing the fetch method for you. The other three tools give you direct control over HTTP, proxy rotation, and browser rendering.

All four are marked readOnlyHint: true and openWorldHint: true per the MCP specification. Clients can use those annotations when deciding how to present or approve tool calls.

Every response carries human-readable text (content) plus a typed structuredContent JSON object validated against the tool's outputSchema. Your agent gets a predictable response contract instead of parsing prose.

foura_auto - smart fetch (the default)

Give it a URL and get the content back. Use this first when you don't want to choose between HTTP, proxy rotation, and browser rendering. It handles common bot challenges and keeps the client surface small, with no proxy-attempt tuning required.

{
  "url": "https://example.com",
  // optional: a substring the real page must contain, so auto can tell a
  // real page from a challenge page on protected targets
  "validate": { "data": { "accept": ["Example Domain"] } }
}

The client surface is intentionally minimal: url (required), plus optional method, headers, data, validate, returnSession (default true), forceProxy (default true), timeout_ms (5000-180000, default 120000), ignoreProxies, exitClass (standard or premium, as on foura_proxy).

structuredContent shape: {status, headers, data, meta, session}. meta is always present - {rung, solved, attempts, credits} - so your agent can see how the request completed and how many credits it used. session ({proxy, cookies, userAgent}) is returned by default for follow-up requests (pass session.proxy into the proxy field). Send returnSession: false to omit it. There is no total_time field on auto.

exitClass: "premium" lets auto escalate to a premium exit once the standard pool cannot reach the page, and the result's exitClass says which class delivered. The standard pool goes first; once the premium traffic in your plan is spent the call goes on in the standard pool and reports standard. Neither class is an error. On a plan without premium exits the call is refused with code: "plan_limit_premium". exitClass: "standard" keeps auto off premium exits.

foura_single - fast HTTP

One HTTP request, response back. Use it for static pages, JSON APIs, and server-rendered HTML. unblocker defaults to true, so the request already carries a full browser header set; set it to false for a plain HTTP request.

{
  "method": "GET",
  "url": "https://example.com"
}

Supports custom headers, a body, per-stage timeouts, redirect controls, JSON auto-parse, a binary-buffer mode, and built-in response validation (validate.status.accept, validate.data.fail, and so on). If foura_single comes back blocked - status 403/429, a captcha page, challenge response headers, or a known challenge title - try a different browser profile (below), then escalate to foura_proxy. Start with maxTries: 5; protected targets may need 25-30. If the page also needs JavaScript to render, pass foura_proxy's returned proxy ID to foura_browser.proxy.

structuredContent shape: {status, headers, data, total_time, ...}. When the target ran a bot check, the response also carries defense; defense.solved: false means the body may be a challenge page rather than the content you asked for.

Choosing which browser you present

By default a request presents the latest Google Chrome. Some targets accept one browser and refuse another, so foura_single and foura_proxy let you pick:

{
  "method": "GET",
  "url": "https://example.com",
  "browser": "Firefox",
  "os": "Windows"
}
  • browser - Chrome, Edge, Safari, Firefox, or Tor.

  • os - Windows, macOS, Android, or iOS. A family name accepts any of its versions; the exact labels in the catalogue narrow further.

  • version - any version the catalogue lists for that browser. The newest match wins when several fit.

  • profile - an exact id from the catalogue, when you already have one.

The full catalogue is public at api.foura.ai/api/profiles, no key required, and its default field names the profile a request gets when you ask for nothing. Selection needs unblocker on, which is the default. A combination that does not exist returns an error listing what is available, so a request is never quietly sent as a browser you did not choose.

foura_proxy - rotating proxies with retry

Same target shape as foura_single, but routed through rotating proxies with automatic retry on failure. Use it when a direct request is blocked or when the target requires a specific exit country.

{
  "maxTries": 5,
  "exitCountries": ["CZ", "GB"],
  "request": {
    "method": "GET",
    "url": "https://example.com/pricing",
    "browser": "Chrome",
    "os": "Windows"
  }
}

structuredContent adds proxy (the encoded ID of the proxy that succeeded) and total (outer timing including selection and retries). When the rotation had to move to another browser to get an answer, profile names the catalogue profile it settled on; pass it as profile to present the same browser on the next call. exitCountries is optional: values are trimmed, uppercased, and deduplicated; proxies with unknown exits are excluded; the request never falls back to an unrequested country. Selection uses the latest available country metadata, normally updated within ten minutes, and a scoped success returns that value as exitCountry. If no eligible proxy matches, the result uses code: "no_eligible_proxy".

The inner request takes the same browser-profile fields as foura_single: browser, os, version, or an exact profile.

exitClass - for a target the standard pool cannot reach. Set exitClass: "premium" and the request may escalate to a premium exit instead of only rotating within the standard pool. It is an allowance, not an instruction: the standard pool still races for the answer and usually wins, and a request it answers before any premium exit is tried costs no premium traffic. Once a premium exit has been tried, the traffic it carried counts toward your premium allowance even if that attempt failed; an attempt still running when another exit answered is stopped and not counted. The response reports exitClass back, premium or standard, so you can see per request which one served you. standard is also the answer once the premium traffic in your plan is spent, and it is a normal result, not an error. exitClass: "standard" forbids escalation outright. On a plan without premium exits the call is refused with code: "plan_limit_premium".

attemptReport - why a rotation ran out of tries. Every failed foura_proxy result carries it beside the error. summary is one sentence; the counts underneath separate causes with opposite fixes: noResponse (the exit never answered), defense (a bot check was recognised, named in vendors), contentRejected (HTTP 200, no bot check, rejected only by your own validate.data), statusRejected, and other. profilesTried lists the browsers the task sent, in first-use order, with default meaning the request went out exactly as written. A high contentRejected means the pages arrived and your own rule threw them away: fetch one with foura_single and no validate, look at it, and rewrite the rule.

For difficult WAF challenges, use maxTries: 25-30. For a country allowlist, set exitCountries instead of increasing attempts. If the target needs JavaScript rendering, pass the returned proxy ID to foura_browser.proxy.

foura_browser - full browser session

A real browser session. JavaScript runs, the DOM finishes rendering, cookies come back with the response. Use it when the page is a single-page app, when content lazy-loads after first paint, or when there's an anti-bot challenge that needs a real browser to clear.

{
  "url": "https://example.com/spa",
  "timeout_ms": 15000,
  "checkText": "data-table"
}

Use this when an HTTP response isn't enough. checkText validates the rendered HTML once navigation completes; it doesn't wait or poll. If the substring is missing, the call fails with an error envelope. This catches pages that return 200 without the content you need. unblocker defaults to true and handles supported anti-bot or captcha challenges along the way. Set it to false to return the page exactly as it loads, challenge included.

structuredContent shape is intentionally different from single/proxy: {status, headers (object, not array), body (not data), cookies (full browser cookie shape), userAgent}.

Built-in Prompts

Six workflow templates surfaced under /prompts in your MCP client. They orchestrate one or more tools without you spelling out the steps.

Prompt

Arguments

What it does

smart_fetch

url, must_contain?, extract?

Pick the method, handle bot protection, and return or extract content

scrape_product_page

url

Extract title, price, image, stock, and SKU as JSON in a browser session

extract_article

url

Fetch an article, retry through a proxy if needed, and remove page chrome

monitor_pricing

url, target_price?

Fetch the current price and compare it with a target

check_endpoint_health

url, expected_text?

Validate reachability, status, content, and timing

bulk_fetch_urls

urls (comma-separated)

Fetch URLs in parallel, retry blocked ones, and return metadata

Each prompt arrives as a templated user message your LLM executes with the right tools. The full prompt text enters the context only when you invoke it.

Full recipe text + manual fallback prompts: foura.ai/docs/mcp/recipes. For the full error code list, see foura.ai/docs/mcp/errors.

Authentication

Use FOURA_API_KEY in stdio mode or an Authorization: Bearer pk_live_... header with the hosted endpoint. One key authenticates all four tools.

Keys are managed in the dashboard, where you can create, reveal, rotate, or deactivate them. See foura.ai/docs/getting-started/authentication for the full key-management walkthrough.

Error envelope - typed contract for agent retries

Every error (isError: true) carries a structuredContent envelope with at minimum these three fields:

{
  "service": "auto" | "single" | "proxy" | "browser",
  "code": "ssrf_blocked" | "auth_failed" | "rate_limited" | ...,
  "error": "Human-readable message"
}

Where the upstream returned a status, you also get status (HTTP code) and on rate-limit / capacity errors the FourA API envelope adds retryAfter, current.{concurrency, rpm}, limits.{maxConcurrency, maxRpm}.

code

When

Retry safe?

ssrf_blocked

Target resolves to a private or reserved address

No - change the URL

upstream_non_json

Upstream returned malformed body

Maybe - investigate

bad_request (400)

Input shape rejected by FourA

No - fix arguments

auth_failed (401)

Key missing, invalid, or deactivated

No - fix the key

forbidden (403)

Authenticated but not allowed

No

not_found (404)

Target / endpoint doesn't exist

No

rate_limited (429)

RPM cap hit

Yes - wait retryAfter

at_capacity (503)

Concurrency cap hit

Yes - wait retryAfter

service_disabled (503)

Maintenance window

Yes - wait retryAfter

service_unavailable (503)

Generic 503

Yes - short backoff

upstream_error (>=500)

Upstream 5xx

Yes - exponential backoff

upstream_client_error (4xx)

Other 4xx

Usually no

no_eligible_proxy

No proxy matches the requested exitCountries

No - change the country scope

plan_limit_* (403/429)

Your own FourA plan refused the call, not the target

Only retryAfter clears it - see below

A plan_limit_ code names which of your plan's limits refused the call: credits, bandwidth, rate, concurrency, browser_daily, premium, or feature. It is not the target blocking you, so retrying the same work through another tool spends the rest of the allowance for nothing. Wait out retryAfter where there is one, or change the plan.

LLM agents can read code directly for retry logic without parsing prose. Spec reference: foura.ai/docs/api/errors.

What every result carries

Beside the tool's own fields, each result reports what the call cost and how to trace it:

  • credits - credits this call spent, on failures as well, because the work was done either way;

  • request_id - FourA's id for the call. Quote it in a support request;

  • exitClass - premium when a premium exit served the call. On foura_single and foura_browser that happens when proxy replays a premium exit that foura_proxy or foura_auto found; on foura_proxy and foura_auto it is reported whenever the request named an exitClass.

Combining the tools - reuse the same exit

The lower-level tools compose. foura_proxy returns the base36 ID of the exit it used. Pass that ID into foura_single.proxy or foura_browser.proxy to reuse the same exit for the next request.

// 1. Find a working exit. Difficult protected targets may need maxTries:25-30.
const r = await foura_proxy({
  maxTries: 30,
  request: { method: "GET", url: "https://probe.example.com" }
});
// Returns { status: 200, proxy: "4DZ3VE", ... }

// 2. Reuse it for follow-up HTTP
await foura_single({ method: "GET", url: "https://target/api", proxy: r.proxy });

// 3. Or render JavaScript through the same exit.
await foura_browser({ url: "https://target/spa", proxy: r.proxy });

For a protected JavaScript page, find a working route with foura_proxy before calling foura_browser. Starting in the browser can return the challenge page before the real content loads.

To choose a different proxy on the next foura_proxy call, pass the previous ID as ignoreProxies: ["4DZ3VE"]. The proxy field on foura_single and foura_browser also accepts raw URLs (http://host:port, socks5://...) if you have your own list.

Large responses - offload_large (default: inline)

By default (since v0.2.0), full response bodies are returned inline in structuredContent regardless of size. This works in every MCP client.

If your client supports MCP resources/read (and you want to save tokens on big pages), pass offload_large: true per tool call. Responses of 50 KB or more are returned as a resource_link, and your client fetches the body only when it needs it. The resource remains available for one hour.

{
  "method": "GET",
  "url": "https://en.wikipedia.org/wiki/Web_scraping",
  "offload_large": true   // opt in for token savings
}

Support for MCP resource links varies by client. Leave offload_large at its default false if your client can't read resource_link blocks.

Only the API key that created an offloaded resource can read it back.

Limits and responsible use

  • Private targets are refused. Requests to private or reserved addresses are blocked at the MCP layer. Only public-internet hosts are forwarded.

  • Rate limits are enforced by the FourA API per service. Concurrency + RPM. Details at foura.ai/docs/api/rate-limits.

Use FourA only for public content you are authorized to access and in accordance with the target site's terms and applicable law.

Run it yourself

Run the stdio server directly from npm with npx -y @fouradata/mcp, or build the included Dockerfile for the Streamable HTTP transport.

Configurable environment:

Variable

Default

Purpose

PORT

3076

HTTP listen port

FOURA_API_BASE

https://api.foura.ai/api

Upstream FourA REST base URL

FOURA_MCP_PAYLOADS_DIR

/data/payloads

Where responses of 50 KB or more are cached on disk

See DEVELOPMENT.md for the local build and test workflow.

License

MIT. See LICENSE.

Available Tools

4 tools
foura_autoFourA - auto (smart fetch, picks the method for you)A
Read-only
Inspect

Give it a public URL and get the content back. Use it when only the content matters and not how it is fetched: it escalates from a direct request to a rotating proxy to a full browser only as far as the target forces, and returns the session that worked so the next call can replay it. On protected targets, or whenever HTTP 200 may still be a challenge or an incomplete page, pass validate.data.accept with text unique to the real content; auto makes bounded attempts and returns either validated content or a failure, and cannot guarantee a match. It owns its own retry settings, so there is no maxTries here, and timeout_ms is the budget for every attempt together rather than for one. What it cannot do is the reason to reach for another tool: a strict exit country, a pinned exit and a premium exit live on foura_proxy (auto can only avoid exits, through ignoreProxies); choosing which browser is presented to the target lives on foura_single and foura_proxy; a scripted browser session lives on foura_browser. A request that names any of those belongs there rather than here. One FourA API key authenticates every call, the result reports the credits it spent, which is the sum of the attempts it made, and a refusal by your own plan arrives as a plan_limit_ code with retryAfter rather than as a block by the target.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesPublic target URL. Private or reserved targets return `ssrf_blocked`. Use {ts} in the URL to insert the current Unix timestamp. Example: https://example.com/page.
dataNoRequest body for non-GET methods. Strings sent as-is; objects auto-serialized to JSON.
methodNoHTTP method for the target request (default GET).
headersNoCustom HTTP headers as [name, value] tuples. Example: [["Accept", "application/json"], ["Authorization", "Bearer ..."]]
validateNoPost-fetch response validation. When the response fails these checks foura_auto returns an error envelope.
forceProxyNoRequire proxy routing for every target request. Default true. Send false to allow direct HTTP when suitable.
timeout_msNoTotal time budget in ms for the whole operation. Every attempt must fit inside it. Default 120000, max 180000.
ignoreProxiesNoExits to avoid - base36 proxy IDs (like "4DZ3VE") or proxy URLs. Use this to rotate away from an exit that was just blocked.
offload_largeNoIf true, response bodies of 50 KB or more are returned as a resource_link instead of inlined. Default false. Read the returned offloaded_resource_uri with resources/read.
returnSessionNoReturn reusable {proxy, cookies, userAgent} values for follow-up calls. Default true. Send false for a leaner response when you only need the content.
followRedirectsNoFollow up to N redirects for HTTP and proxy requests. Default 5; 0 means don't follow. Browser navigation handles redirects itself.

Output Schema

ParametersJSON Schema
NameRequiredDescription
codeNoStable error code for retry classification. auth_failed means the FourA API key was rejected; verify that key, not target-site credentials. Other codes: ssrf_blocked, upstream_non_json, output_validation_failed, bad_request (400), forbidden (403), not_found (404), rate_limited (429), at_capacity (503), service_disabled (503), service_unavailable (503), upstream_error (>=500), upstream_client_error (other 4xx), upstream_unknown (defensive). A plan_limit_* code is the caller's own FourA plan refusing (credits, bandwidth, rate, concurrency, browser_daily, premium, feature), not the target: wait out retryAfter or change the plan, never retry the same work through another tool.
dataNoDecoded response body of the delivered page. String by default; object when the body parsed as JSON. Omitted when offloaded.
metaNoCompletion details: rung, solved, attempts, and credits. Always present.
errorNoHuman-readable error message when the request could not deliver content within the budget.
limitsNoPer-service limits at error time
statusNoHTTP status code from the request that delivered the content. `0` means no HTTP response was received; check `error`.
creditsNoCredits this call spent. Reported on failures too: the work was done either way.
currentNoCaller's current usage at error time
headersNoResponse headers from the successful request, as an array of objects. Each entry has `result.{version, code, reason}` plus header-name keys. The last entry is the final response.
serviceNo
sessionNoReusable {proxy, cookies, userAgent} values for follow-up calls. For plain HTTP, call foura_single with session.proxy as proxy, session.userAgent as a User-Agent header, and session.cookies serialized as a Cookie header. For JavaScript, pass the three values to foura_browser fields. Present by default; send returnSession:false to omit.
attemptsNoTotal attempts when the request failed (also present inside `meta`).
request_idNoFourA's id for this call, for a support request.
retryAfterNoSeconds to wait before retrying a 429 or 503 response
size_bytesNoTotal offloaded body size in bytes
offloaded_resource_uriNofoura-mcp://payload/<uuid>. Pass this URI to resources/read to retrieve the offloaded body.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already signal read-only, non-destructive behavior, and the description adds substantial behavioral context beyond that: escalation strategy, bounded attempts, validation semantics, shared timeout budget, no maxTries, session replay, credit reporting, and plan-limit error behavior. It also openly discloses the limitation that exact-match validation 'cannot guarantee a match,' which is valuable honesty.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense and long, but it is front-loaded with the core purpose and then logically progresses through escalation, validation, exclusions, and operational details. It earns most of its length, though a few points (e.g., timeout budget) repeat schema information, keeping it just short of a perfect score.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 11 parameters, nested validation objects, and an output schema, the description covers everything an agent needs to call this tool correctly: when to use it, what it cannot do, which siblings handle those cases, how validation works, cost/credits behavior, and error semantics. The output schema handles return-shape documentation, so nothing critical is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real parameter-level meaning: it explains validate.data.accept usage on protected targets, clarifies that timeout_ms is the budget for all attempts combined, notes that auto can only control exits via ignoreProxies, and explains that no maxTries exists because retry settings are internal. This goes beyond the schema without replacing it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a concrete verb and resource: 'Give it a public URL and get the content back,' then explains the auto-escalation from direct request to proxy to browser. It also distinguishes itself from foura_proxy, foura_single, and foura_browser by naming exactly which capabilities belong to which sibling, so an agent can select it unambiguously.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly states when to use this tool: 'Use it when only the content matters and not how it is fetched.' It then provides clear when-not-to-use guidance: strict exit country, pinned/premium exits, browser-choice control, and scripted browser sessions belong on other tools, and 'a request that names any of those belongs there rather than here.' This is exemplary routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

foura_browserFourA - full browser navigationA
Read-only
Inspect

Load a public URL in a full browser session. JavaScript runs, the DOM renders, and cookies come back with the response. Use it for single-page apps, lazy-loaded content, or supported browser challenges. You can set your own headers, cookies and userAgent, and checkStatus or checkText turn a navigation that rendered the wrong page into a failure instead of returning it as content. For a protected page, call foura_proxy first and pass its returned proxy ID here to reuse that same exit, instead of starting a new selection here; with no proxy the session leaves from one fixed address. Set unblocker:false when you want the page exactly as it loads, challenge included. It is the most expensive of the four tools and the slowest, so prefer foura_single or foura_proxy whenever the content is already in the HTML. One FourA API key authenticates every call, the result reports the credits it spent, and a refusal by your own plan arrives as a plan_limit_ code, including plan_limit_browser_daily when the daily browser allowance is spent.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesPublic URL to load in a full browser session. Private or reserved targets return `ssrf_blocked`. Example: https://shop.example.com/product/123.
proxyNoOptional proxy. Three forms: (1) URL `http://user:pass@host:port` or `socks5://host:port`; (2) base36 ID from foura_proxy (e.g. `4DZ3VE`) to reuse the same exit; (3) omit to use the default route.
cookiesNoCookies to set before navigation: [{ name, value, domain? }]
headersNoCustom HTTP headers as a key-value object rather than [name, value] tuples. Example: {"Referer": "https://google.com/"}
checkTextNoValidate the rendered HTML once navigation completes. This is a substring check, not a waiter, and it doesn't poll. A missing substring returns an error envelope. Example: "add to cart" for a product page.
unblockerNoHandle supported anti-bot or captcha challenges during navigation. Default true. Set false to return the page exactly as it loads, including any challenge page.
userAgentNoOverride the browser's User-Agent string
timeout_msNoPage load timeout in ms (default 30000, max 120000)
checkStatusNoExpected HTTP status code. A different status returns an error envelope carrying the actual value. Example: 200 for a product page.
offload_largeNoIf true, response bodies of 50 KB or more are returned as a resource_link instead of inlined. Default false. Read the returned offloaded_resource_uri with resources/read.

Output Schema

ParametersJSON Schema
NameRequiredDescription
bodyNoFully-rendered page content. String HTML when content-type is HTML; object when the page returned JSON and it was auto-parsed. Field is named `body`, not `data`. Omitted when offloaded.
codeNoStable error code for retry classification. auth_failed means the FourA API key was rejected; verify that key, not target-site credentials. Other codes: ssrf_blocked, upstream_non_json, output_validation_failed, bad_request (400), forbidden (403), not_found (404), rate_limited (429), at_capacity (503), service_disabled (503), service_unavailable (503), upstream_error (>=500), upstream_client_error (other 4xx), upstream_unknown (defensive). A plan_limit_* code is the caller's own FourA plan refusing (credits, bandwidth, rate, concurrency, browser_daily, premium, feature), not the target: wait out retryAfter or change the plan, never retry the same work through another tool.
errorNoHuman-readable error message
limitsNo
statusNoHTTP status code from the target page. `0` indicates the navigation failed before any HTTP response (DNS / connection refused / timeout) - check the `error` field for the underlying reason.
cookiesNoFull cookie objects collected after navigation, including name, value, domain, path, expiry, and same-site settings.
creditsNoCredits this call spent. Reported on failures too: the work was done either way.
currentNo
headersNoResponse headers as a flat key-value object. Values are typically strings but may be arrays for repeated headers.
serviceNo
exitClassNo`premium` when a premium exit served this call, which happens when `proxy` replays one from foura_proxy.
userAgentNoThe User-Agent the browser session presented
request_idNoFourA's id for this call, for a support request.
retryAfterNo
size_bytesNoTotal offloaded body size in bytes
offloaded_resource_uriNofoura-mcp://payload/<uuid>. Pass this URI to resources/read to retrieve the offloaded body.

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark it read-only, open-world, and non-destructive, so the bar is lower, yet the description still adds substantial context: JavaScript execution and DOM rendering, cookie return, fixed source address without a proxy, unblocker:false behavior, cost/slowness relative to the other tools, and plan_limit_browser_daily refusal behavior. No contradiction with the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense and front-loaded, with the core behavior first and cost/alternative guidance later. It is long, but every sentence carries useful facts; however, the single wall-of-text paragraph could be lightly structured. It earns its length given the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 10-parameter tool with an output schema and rich annotations, the description covers the important operational context: when to use it versus cheaper siblings, proxy reuse, failure behavior, auth/credits, and plan-limit error codes. The output schema handles return-value details, so nothing needed for correct invocation appears missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers 100% of parameters, so the baseline is 3, but the description adds meaning beyond the field docs: checkStatus/checkText convert a wrong-page render into a failure, proxy IDs from foura_proxy reuse the same exit, and unblocker:false returns the page exactly as loaded including challenges. It does not individually re-document every parameter, which is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb-resource pair, 'Load a public URL in a full browser session,' and immediately clarifies what makes it distinct: JavaScript runs, the DOM renders, and cookies come back. It also differentiates itself from siblings by naming foura_single and foura_proxy as cheaper alternatives for content already present in HTML.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit indications: use for single-page apps, lazy-loaded content, or supported browser challenges, and prefer foura_single or foura_proxy when content is already in the HTML. It even prescribes a workflow: call foura_proxy for protected pages and pass its proxy ID here to reuse the same exit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

foura_proxyFourA - HTTP request via rotating proxiesA
Read-only
Inspect

Route an HTTP request through rotating proxies, retrying on another exit until one delivers. Use it when foura_single is blocked, and whenever the exit itself matters: this is the only tool that takes a strict exit-country allowlist (exitCountries, which never falls back to another country), presents a named browser family per attempt, excludes exits you already know are dead (ignoreProxies), and may escalate to a premium exit (exitClass, an allowance rather than an instruction). maxTries bounds how many exits are tried and timeout_ms bounds the whole rotation, so a short timeout can end it before maxTries is reached; protected targets often need 25 to 30. validate decides what counts as delivered, and an attempt it rejects is retried on the next exit. The response returns the id of the exit that succeeded: pass that returned id to foura_single.proxy or foura_browser.proxy to send the next request from the same exit. A failed rotation returns attemptReport, which separates exits that never answered from exits a bot check refused from pages your own rule threw away. Use foura_browser when the page needs JavaScript. Rotation costs several times a single request. One FourA API key authenticates every call, the result reports the credits it spent, and a refusal by your own plan arrives as a plan_limit_ code with retryAfter rather than as a block by the target.

ParametersJSON Schema
NameRequiredDescriptionDefault
requestYesThe inner HTTP request to send through each proxy attempt. Validation rules here determine when a proxy is treated as failed and retried.
maxTriesNoMaximum rotation attempts before giving up (default 5, max 90). Difficult protected targets may need 25-30. Use exitCountries for country scope.
exitClassNoAllow escalation to a premium exit for a target the standard pool cannot deliver. An allowance, not an instruction: the pool still races and usually wins, and the response reports which class served. `standard` forbids escalation. Without premium exits in the plan the call is refused with code plan_limit_premium.
timeout_msNoOverall timeout across all rotation attempts in ms (default 45000, max 120000). Must be positive.
exitCountriesNoOptional target-visible proxy countries as two-letter provider codes, for example ["CZ", "GB"]. Use codes supplied by the user or target requirements. When geography matters, do not guess codes or substitute unscoped rotation. Values are trimmed, uppercased, and deduplicated. Unknown exits are excluded and the request never falls back to another country.
ignoreProxiesNoEncoded proxy IDs (base36 strings like "4DZ3VE") or proxy URLs to exclude from rotation.
offload_largeNoIf true, response bodies of 50 KB or more are returned as a resource_link instead of inlined. Default false. Read the returned offloaded_resource_uri with resources/read.

Output Schema

ParametersJSON Schema
NameRequiredDescription
codeNoStable error code for retry classification. auth_failed means the FourA API key was rejected; verify that key, not target-site credentials. no_eligible_proxy means the strict exitCountries scope had no match. Keep that scope and retry later; do not propose or perform an unscoped fallback. A plan_limit_* code is the caller's own FourA plan refusing (credits, bandwidth, rate, concurrency, browser_daily, premium, feature), not the target: wait out retryAfter or change the plan, never retry the same work through another tool.
dataNoDecoded response body. Omitted when offloaded.
errorNoHuman-readable error message
proxyNoBase36 ID of the exit that succeeded (e.g. `4DZ3VE`). Pass it to foura_single.proxy or foura_browser.proxy to reuse that exit, or to foura_proxy.ignoreProxies to skip it on future rotations.
totalNoOuter total time in seconds (proxy selection + retries + the successful inner attempt). Float.
limitsNo
statusNoHTTP status code from the target (from the succeeding proxy attempt). `0` indicates every attempt failed before any HTTP response (DNS / connection refused / timeout) - check the `error` field for the underlying reason.
creditsNoCredits this call spent. Reported on failures too: the work was done either way.
currentNo
defenseNoPresent when the target ran a bot check. When solved is false the body may be a challenge page: retry with a different browser, os, or version, or move to foura_browser.
detailsNoStructured no_eligible_proxy context containing the normalized requested country scope. Preserve this scope and retry later. Do not propose or perform an unscoped fallback; change it only after the user explicitly changes the requirement.
headersNoResponse headers per redirect hop, as an array of objects. Each entry has `result.{version, code, reason}` plus arbitrary header-name keys whose values are strings (or arrays of strings for multi-value headers like Set-Cookie / Link).
profileNoThe browser family rotation moved to after the target refused the one this request sent. Absent means it went out as written; when present, replay with it or repeat the version that failed.
requestNoEchoed PrRequest from upstream PrResponseError
serviceNo
exitClassNoWhich class delivered, when the request named exitClass. `standard` means the standard pool answered first, which is also the answer once the premium allowance is spent. Neither is an error.
request_idNoFourA's id for this call, for a support request.
retryAfterNo
size_bytesNoTotal offloaded body size in bytes
total_timeNoPer-attempt wall-clock duration of the succeeding inner request
exitCountryNoLatest available two-letter target-visible exit-country code used for selection. Present on successful requests that use exitCountries.
attemptReportNoWhy a failed rotation ran out of tries. Read `summary` first. Counts over `total` attempts: noResponse (the exit never answered), defense (a bot check was recognised, named in `vendors`), contentRejected (HTTP 200, no bot check, rejected only by your validate.data), statusRejected (rejected by your validate.status), other. `profilesTried` lists the browsers sent, `default` meaning the request went out as written. High contentRejected means the pages arrived and your own rule threw them away: fetch once with foura_single and no validate, then rewrite it.
offloaded_resource_uriNofoura-mcp://payload/<uuid>. Pass this URI to resources/read to retrieve the offloaded body.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnly/openWorld/destructive annotations, the description adds substantial behavioral detail: retry semantics ('retrying on another exit until one delivers'), exitClass as 'an allowance rather than an instruction', timeout interactions ('a short timeout can end it before maxTries is reached'), validation-driven retries, the response's exit id for follow-up requests, attemptReport on failure, cost implications, and plan-limit error behavior. This far exceeds annotation coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Long but every sentence carries distinct operational knowledge. It is front-loaded with the core purpose, then flows to when-to-use, parameter interactions, response handling, cost, and auth. There is no filler, repetition, or fluff. The length is justified by the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Together with a 100%-covered schema and an output schema, the description covers the full decision space: when to choose this tool over siblings, how retries and validation work, how timeouts bound rotation, what the response contains (exit id, attemptReport), cost and authentication, and plan-limit error behavior. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds interpretive value: exitCountries 'never falls back', exitClass is 'an allowance rather than an instruction', maxTries 'bounds how many exits are tried', timeout_ms 'bounds the whole rotation', and validate determines retry. It also clarifies the interaction between maxTries and timeout_ms, which is not inferable from individual schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb+resource: 'Route an HTTP request through rotating proxies, retrying on another exit until one delivers.' It explicitly contrasts itself with foura_single and foura_browser, so an agent can distinguish it without opening the schema. The title reinforces the purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the exact condition for use: 'Use it when foura_single is blocked, and whenever the exit itself matters.' It also names the alternative for JavaScript-heavy pages: 'Use foura_browser when the page needs JavaScript.' This is explicit when/when-not guidance with named alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

foura_singleFourA - single HTTP requestA
Read-only
Inspect

Send one HTTP request and return the response. Use it for static pages, JSON APIs, and server-rendered HTML, with your own headers, body and cookies. Set browser, os, or version when a target refuses the default Chrome. Pass a proxy id returned by foura_proxy to leave from that same exit. validate decides what counts as success, so a response it rejects comes back as a failure instead of as content; the timeouts nest, with timeout_ms bounding the whole request and the connect, accept and server_response ones bounding stages inside it. Switch to foura_proxy when the response is blocked or the exit country matters, and to foura_browser when the page needs JavaScript. One FourA API key authenticates every call, the result reports the credits it spent, and a refusal by your own plan arrives as a plan_limit_ code with retryAfter rather than as a block by the target.

ParametersJSON Schema
NameRequiredDescriptionDefault
osNoOperating system to present: Windows, macOS, Android, or iOS. A family name accepts any of its versions.
urlYesPublic target URL. Private or reserved targets return `ssrf_blocked`. Use {ts} in the URL to insert the current Unix timestamp. Example: https://api.example.com/v1/users.
dataNoRequest body. Strings sent as-is; objects auto-serialized to JSON. Example: {"query": "hello"} for POST APIs.
proxyNoOptional proxy. Two forms: (1) URL `http://host:port` or `socks5://host:port`; (2) base36 ID from foura_proxy (e.g. `4DZ3VE`) to reuse the same exit. For rotation, use foura_proxy.
methodYesHTTP method (GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS, or any WebDAV verb like PROPFIND/MKCOL)
browserNoBrowser to present: Chrome, Edge, Safari, Firefox, or Tor. Omit every profile field and the request presents the latest Google Chrome.
headersNoCustom HTTP headers as [name, value] tuples. Example: [["Accept", "application/json"], ["Referer", "https://google.com/"]]
profileNoExact profile id from the public catalogue at https://api.foura.ai/api/profiles. Use browser/os/version when you do not have an id.
versionNoBrowser version to present, as listed in the catalogue. The newest match wins when several fit. An impossible combination returns an error listing what is available; no other browser is substituted.
validateNoPost-fetch response validation. When the response fails these checks the tool returns an error envelope.
unblockerNoSend a full browser header set, including User-Agent and Sec-Ch-Ua. Default true. Set false for a plain HTTP request; profile selection needs it on and errors when it is off.
timeout_msNoOverall request timeout in ms (max 120000, default 15000)
tryJsonDataNoIf true, attempt JSON.parse on the response body. On success, `data` is the parsed value (typically object or array). On parse failure, `data` silently stays as the original string - no error, no warning. Set false (or omit) when you need to detect parse failures explicitly.
returnBufferNoReturn raw bytes as a serialized Buffer JSON shape (`{type:"Buffer", data:[byte, ...]}`, bytes 0-255) instead of decoded string. Use for binary responses (images, protobuf). Reconstruct: `Buffer.from(data.data)` in Node, `new Uint8Array(data.data)` elsewhere.
offload_largeNoIf true, response bodies of 50 KB or more are returned as a resource_link instead of inlined. Default false. Read the returned offloaded_resource_uri with resources/read.
followRedirectsNoMax number of redirects to follow (0-20). Omit to disable redirect following.
accept_timeout_msNoTimeout in ms to receive the first response byte after the request is sent (0-120000). Omit for the default.
connect_timeout_msNoTimeout in ms for establishing the TCP/TLS connection (0-120000). Omit to use the default.
dns_cache_timeout_secNoHow long (seconds) to cache the target's resolved DNS (0-240). Omit for the default.
server_response_timeout_msNoTimeout in ms for the server to send the complete response (0-120000). Omit for the default.

Output Schema

ParametersJSON Schema
NameRequiredDescription
codeNoStable error code for retry classification. auth_failed means the FourA API key was rejected; verify that key, not target-site credentials. Other codes: ssrf_blocked, upstream_non_json, output_validation_failed, bad_request (400), forbidden (403), not_found (404), rate_limited (429), at_capacity (503), service_disabled (503), service_unavailable (503), upstream_error (>=500), upstream_client_error (other 4xx), upstream_unknown (defensive). A plan_limit_* code is the caller's own FourA plan refusing (credits, bandwidth, rate, concurrency, browser_daily, premium, feature), not the target: wait out retryAfter or change the plan, never retry the same work through another tool.
dataNoDecoded response body. String by default; object when tryJsonData=true and the body parsed as JSON; serialized Buffer JSON shape (`{type:"Buffer", data:[byte, ...]}`, bytes 0-255) when returnBuffer=true - reconstruct with `Buffer.from(data.data)` in Node, `new Uint8Array(data.data)` elsewhere. Omitted when offloaded.
errorNoHuman-readable error message
limitsNoPer-service limits at error time
statusNoHTTP status code from the target. `0` indicates the request failed before any HTTP response (DNS failure, connection refused, timeout) - check the `error` field for the underlying reason.
creditsNoCredits this call spent. Reported on failures too: the work was done either way.
currentNoCaller's current usage at error time
defenseNoPresent when the target ran a bot check. When solved is false the body may be a challenge page: retry with a different browser, os, or version, or move to foura_proxy or foura_browser.
headersNoResponse headers per redirect hop, as an array of objects. Each entry has `result.{version, code, reason}` plus arbitrary header-name keys whose values are strings (or arrays of strings for multi-value headers like Set-Cookie / Link). Last array entry is the final response.
serviceNo
exitClassNo`premium` when a premium exit served this call, which happens when `proxy` replays one from foura_proxy.
request_idNoFourA's id for this call, for a support request.
retryAfterNoSeconds to wait before retrying (429/503)
size_bytesNoTotal offloaded body size in bytes
total_timeNoWall-clock request duration in seconds. Number when present; string in some variants; null when the request never started.
offloaded_resource_uriNofoura-mcp://payload/<uuid>. Pass this URI to resources/read to retrieve the offloaded body.

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already declare readOnlyHint true and destructiveHint false, and the description adds valuable behavior beyond that: validate changes what counts as success, timeouts nest with timeout_ms bounding the whole request, plan refusals arrive as plan_limit_ codes with retryAfter, and one API key authenticates every call. It also explains default Chrome behavior and proxy exit reuse, making the call semantics transparent for an HTTP tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact despite covering a 20-parameter tool. Every sentence adds information: core action first, then use cases, routing to siblings, then nuanced semantics like nested timeouts, validation, and plan limits. There is no filler or repetition of schema details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex tool with 20 parameters, an output schema, and annotations, this description is complete: it explains when to use it, when not to, what the success/failure semantics are, how timeouts behave, how authentication and credit reporting work, and what error variants look like. Nothing essential for correct selection or invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is already 100%, so the baseline is 3, but the description goes further by explaining the meaning behind the parameters semantically: it frames proxy reuse, validate failure handling, timeout nesting, and the browser/os/version fallback strategy. This materially helps an agent decide which parameters to set and why.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Send one HTTP request and return the response.' It then enumerates the exact use cases (static pages, JSON APIs, server-rendered HTML) and contrasts itself with foura_proxy and foura_browser, so the agent can distinguish it from its siblings without inspecting schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use guidance: static pages, JSON APIs, and server-rendered HTML, and it states clear switch conditions: use foura_proxy when blocked or exit country matters, and foura_browser when JavaScript is needed. This is actionable routing guidance rather than implied usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv0.7.3
    • Changedfoura_auto4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedInput schema / properties / headers / items / additionalItems
        Removed value: -false
      • changedInput schema / properties / headers / items / items
        Previous value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "string"
        -  }
        -]New value: +{
        +  "type": "string"
        +}
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedfoura_browser2 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedfoura_proxy4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedInput schema / properties / request / properties / headers / items / additionalItems
        Removed value: -false
      • changedInput schema / properties / request / properties / headers / items / items
        Previous value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "string"
        -  }
        -]New value: +{
        +  "type": "string"
        +}
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
    • Changedfoura_single4 fields changed
      • removedInput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
      • removedInput schema / properties / headers / items / additionalItems
        Removed value: -false
      • changedInput schema / properties / headers / items / items
        Previous value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "string"
        -  }
        -]New value: +{
        +  "type": "string"
        +}
      • removedOutput schema / $schema
        Removed value: -"http://json-schema.org/draft-07/schema#"
  2. 4 tool updatesv0.7.2
    • Changedfoura_auto6 fields changed
      • addedInput schema / properties / headers / items / additionalItems
        Added value: +false
      • addedInput schema / properties / headers / items / maxItems
        Added value: +2
      • addedInput schema / properties / headers / items / minItems
        Added value: +2
      • changedOutput schema / properties / code / description
        Previous value: -"Stable error code for retry classification. auth_failed means the FourA API key was rejected; verify that key, not target-site credentials. Other codes: ssrf_blocked, upstream_non_json, output_validation_failed, bad_request (400), forbidden (403), not_found (404), rate_limited (429), at_capacity (503), service_disabled (503), service_unavailable (503), upstream_error (>=500), upstream_client_error (other 4xx), upstream_unknown (defensive)."New value: +"Stable error code for retry classification. auth_failed means the FourA API key was rejected; verify that key, not target-site credentials. Other codes: ssrf_blocked, upstream_non_json, output_validation_failed, bad_request (400), forbidden (403), not_found (404), rate_limited (429), at_capacity (503), service_disabled (503), service_unavailable (503), upstream_error (>=500), upstream_client_error (other 4xx), upstream_unknown (defensive). A plan_limit_* code is the caller's own FourA plan refusing (credits, bandwidth, rate, concurrency, browser_daily, premium, feature), not the target: wait out retryAfter or change the plan, never retry the same work through another tool."
      • addedOutput schema / properties / credits
        Added value: +{
        +  "description": "Credits this call spent. Reported on failures too: the work was done either way.",
        +  "type": "number"
        +}
      • addedOutput schema / properties / request_id
        Added value: +{
        +  "description": "FourA's id for this call, for a support request.",
        +  "type": "string"
        +}
    • Changedfoura_browser4 fields changed
      • changedOutput schema / properties / code / description
        Previous value: -"Stable error code for retry classification. auth_failed means the FourA API key was rejected; verify that key, not target-site credentials. Other codes: ssrf_blocked, upstream_non_json, output_validation_failed, bad_request (400), forbidden (403), not_found (404), rate_limited (429), at_capacity (503), service_disabled (503), service_unavailable (503), upstream_error (>=500), upstream_client_error (other 4xx), upstream_unknown (defensive)."New value: +"Stable error code for retry classification. auth_failed means the FourA API key was rejected; verify that key, not target-site credentials. Other codes: ssrf_blocked, upstream_non_json, output_validation_failed, bad_request (400), forbidden (403), not_found (404), rate_limited (429), at_capacity (503), service_disabled (503), service_unavailable (503), upstream_error (>=500), upstream_client_error (other 4xx), upstream_unknown (defensive). A plan_limit_* code is the caller's own FourA plan refusing (credits, bandwidth, rate, concurrency, browser_daily, premium, feature), not the target: wait out retryAfter or change the plan, never retry the same work through another tool."
      • addedOutput schema / properties / credits
        Added value: +{
        +  "description": "Credits this call spent. Reported on failures too: the work was done either way.",
        +  "type": "number"
        +}
      • addedOutput schema / properties / exitClass
        Added value: +{
        +  "description": "`premium` when a premium exit served this call, which happens when `proxy` replays one from foura_proxy.",
        +  "enum": [
        +    "standard",
        +    "premium"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / request_id
        Added value: +{
        +  "description": "FourA's id for this call, for a support request.",
        +  "type": "string"
        +}
    • Changedfoura_proxy12 fields changed
      • addedInput schema / properties / exitClass
        Added value: +{
        +  "description": "Allow escalation to a premium exit for a target the standard pool cannot deliver. An allowance, not an instruction: the pool still races and usually wins, and the response reports which class served. `standard` forbids escalation. Without premium exits in the plan the call is refused with code plan_limit_premium.",
        +  "enum": [
        +    "standard",
        +    "premium"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / request / properties / headers / items / additionalItems
        Added value: +false
      • addedInput schema / properties / request / properties / headers / items / maxItems
        Added value: +2
      • addedInput schema / properties / request / properties / headers / items / minItems
        Added value: +2
      • addedOutput schema / properties / attemptReport
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Why a failed rotation ran out of tries. Read `summary` first. Counts over `total` attempts: noResponse (the exit never answered), defense (a bot check was recognised, named in `vendors`), contentRejected (HTTP 200, no bot check, rejected only by your validate.data), statusRejected (rejected by your validate.status), other. `profilesTried` lists the browsers sent, `default` meaning the request went out as written. High contentRejected means the pages arrived and your own rule threw them away: fetch once with foura_single and no validate, then rewrite it.",
        +  "properties": {
        +    "contentRejected": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "defense": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "noResponse": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "other": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "profilesTried": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    },
        +    "statusRejected": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "summary": {
        +      "type": "string"
        +    },
        +    "total": {
        +      "maximum": 9007199254740991,
        +      "minimum": -9007199254740991,
        +      "type": "integer"
        +    },
        +    "vendors": {
        +      "items": {
        +        "type": "string"
        +      },
        +      "type": "array"
        +    }
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / properties / code / description
        Previous value: -"Stable error code for retry classification. auth_failed means the FourA API key was rejected; verify that key, not target-site credentials. no_eligible_proxy means the strict exitCountries scope had no match. Keep that scope and retry later; do not propose or perform an unscoped fallback."New value: +"Stable error code for retry classification. auth_failed means the FourA API key was rejected; verify that key, not target-site credentials. no_eligible_proxy means the strict exitCountries scope had no match. Keep that scope and retry later; do not propose or perform an unscoped fallback. A plan_limit_* code is the caller's own FourA plan refusing (credits, bandwidth, rate, concurrency, browser_daily, premium, feature), not the target: wait out retryAfter or change the plan, never retry the same work through another tool."
      • addedOutput schema / properties / credits
        Added value: +{
        +  "description": "Credits this call spent. Reported on failures too: the work was done either way.",
        +  "type": "number"
        +}
      • addedOutput schema / properties / exitClass
        Added value: +{
        +  "description": "Which class delivered, when the request named exitClass. `standard` means the standard pool answered first, which is also the answer once the premium allowance is spent. Neither is an error.",
        +  "enum": [
        +    "standard",
        +    "premium"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / profile
        Added value: +{
        +  "description": "The browser family rotation moved to after the target refused the one this request sent. Absent means it went out as written; when present, replay with it or repeat the version that failed.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / request_id
        Added value: +{
        +  "description": "FourA's id for this call, for a support request.",
        +  "type": "string"
        +}
      • removedOutput schema / properties / total_time / anyOf
        Removed value: -[
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / total_time / type
        Added value: +[
        +  "number",
        +  "string",
        +  "null"
        +]
    • Changedfoura_single9 fields changed
      • addedInput schema / properties / headers / items / additionalItems
        Added value: +false
      • addedInput schema / properties / headers / items / maxItems
        Added value: +2
      • addedInput schema / properties / headers / items / minItems
        Added value: +2
      • changedOutput schema / properties / code / description
        Previous value: -"Stable error code for retry classification. auth_failed means the FourA API key was rejected; verify that key, not target-site credentials. Other codes: ssrf_blocked, upstream_non_json, output_validation_failed, bad_request (400), forbidden (403), not_found (404), rate_limited (429), at_capacity (503), service_disabled (503), service_unavailable (503), upstream_error (>=500), upstream_client_error (other 4xx), upstream_unknown (defensive)."New value: +"Stable error code for retry classification. auth_failed means the FourA API key was rejected; verify that key, not target-site credentials. Other codes: ssrf_blocked, upstream_non_json, output_validation_failed, bad_request (400), forbidden (403), not_found (404), rate_limited (429), at_capacity (503), service_disabled (503), service_unavailable (503), upstream_error (>=500), upstream_client_error (other 4xx), upstream_unknown (defensive). A plan_limit_* code is the caller's own FourA plan refusing (credits, bandwidth, rate, concurrency, browser_daily, premium, feature), not the target: wait out retryAfter or change the plan, never retry the same work through another tool."
      • addedOutput schema / properties / credits
        Added value: +{
        +  "description": "Credits this call spent. Reported on failures too: the work was done either way.",
        +  "type": "number"
        +}
      • addedOutput schema / properties / exitClass
        Added value: +{
        +  "description": "`premium` when a premium exit served this call, which happens when `proxy` replays one from foura_proxy.",
        +  "enum": [
        +    "standard",
        +    "premium"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / request_id
        Added value: +{
        +  "description": "FourA's id for this call, for a support request.",
        +  "type": "string"
        +}
      • removedOutput schema / properties / total_time / anyOf
        Removed value: -[
        -  {
        -    "type": "number"
        -  },
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / total_time / type
        Added value: +[
        +  "number",
        +  "string",
        +  "null"
        +]
  3. 2 tool updatesv0.6.0
    • Changedfoura_proxy6 fields changed
      • addedInput schema / properties / request / properties / browser
        Added value: +{
        +  "description": "Browser to present: Chrome, Edge, Safari, Firefox, or Tor. Omit every profile field and the request presents the latest Google Chrome.",
        +  "type": "string"
        +}
      • addedInput schema / properties / request / properties / os
        Added value: +{
        +  "description": "Operating system to present: Windows, macOS, Android, or iOS. A family name accepts any of its versions.",
        +  "type": "string"
        +}
      • addedInput schema / properties / request / properties / profile
        Added value: +{
        +  "description": "Exact profile id from the public catalogue at https://api.foura.ai/api/profiles. Use browser/os/version when you do not have an id.",
        +  "type": "string"
        +}
      • changedInput schema / properties / request / properties / unblocker / description
        Previous value: -"Add common browser headers such as User-Agent, Sec-Ch-Ua, and Accept-Encoding. Default false. Enable it for targets that reject basic HTTP requests."New value: +"Send a full browser header set, including User-Agent and Sec-Ch-Ua. Default true. Set false for a plain HTTP request; profile selection needs it on and errors when it is off."
      • addedInput schema / properties / request / properties / version
        Added value: +{
        +  "description": "Browser version to present, as listed in the catalogue. The newest match wins when several fit. An impossible combination returns an error listing what is available; no other browser is substituted.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / defense
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the target ran a bot check. When solved is false the body may be a challenge page: retry with a different browser, os, or version, or move to foura_browser.",
        +  "properties": {
        +    "solved": {
        +      "description": "True when the check was met and `data` is the real page.",
        +      "type": "boolean"
        +    }
        +  },
        +  "type": "object"
        +}
    • Changedfoura_single6 fields changed
      • addedInput schema / properties / browser
        Added value: +{
        +  "description": "Browser to present: Chrome, Edge, Safari, Firefox, or Tor. Omit every profile field and the request presents the latest Google Chrome.",
        +  "type": "string"
        +}
      • addedInput schema / properties / os
        Added value: +{
        +  "description": "Operating system to present: Windows, macOS, Android, or iOS. A family name accepts any of its versions.",
        +  "type": "string"
        +}
      • addedInput schema / properties / profile
        Added value: +{
        +  "description": "Exact profile id from the public catalogue at https://api.foura.ai/api/profiles. Use browser/os/version when you do not have an id.",
        +  "type": "string"
        +}
      • changedInput schema / properties / unblocker / description
        Previous value: -"Add common browser headers such as User-Agent, Sec-Ch-Ua, and Accept-Encoding. Default false. Enable it for targets that reject basic HTTP requests."New value: +"Send a full browser header set, including User-Agent and Sec-Ch-Ua. Default true. Set false for a plain HTTP request; profile selection needs it on and errors when it is off."
      • addedInput schema / properties / version
        Added value: +{
        +  "description": "Browser version to present, as listed in the catalogue. The newest match wins when several fit. An impossible combination returns an error listing what is available; no other browser is substituted.",
        +  "type": "string"
        +}
      • addedOutput schema / properties / defense
        Added value: +{
        +  "additionalProperties": {},
        +  "description": "Present when the target ran a bot check. When solved is false the body may be a challenge page: retry with a different browser, os, or version, or move to foura_proxy or foura_browser.",
        +  "properties": {
        +    "solved": {
        +      "description": "True when the check was met and `data` is the real page.",
        +      "type": "boolean"
        +    }
        +  },
        +  "type": "object"
        +}
  4. 4 tool updatesv0.5.0
    • Changedfoura_auto30 fields changed
      • changedInput schema / properties / followRedirects / description
        Previous value: -"Follow up to N redirects on the cheap (direct / proxy) rungs so a 301/302 lands on the real content instead of being returned as-is. Default 5; 0 = don't follow. The browser rung follows redirects natively."New value: +"Follow up to N redirects for HTTP and proxy requests. Default 5; 0 means don't follow. Browser navigation handles redirects itself."
      • changedInput schema / properties / forceProxy / description
        Previous value: -"Always reach the target through a rotating proxy, never from FourA's own egress. Default true (the target never sees FourA's origin IP). Send false to allow the cheaper direct path - but note some trust-gated defenses actually resolve more easily from the direct egress, so forcing a proxy can make those targets harder (more attempts / credits)."New value: +"Require proxy routing for every target request. Default true. Send false to allow direct HTTP when suitable."
      • changedInput schema / properties / headers / description
        Previous value: -"Custom HTTP headers to send to the TARGET, as [name, value] tuples. Example: [[\"Accept\", \"application/json\"], [\"Authorization\", \"Bearer ...\"]]"New value: +"Custom HTTP headers as [name, value] tuples. Example: [[\"Accept\", \"application/json\"], [\"Authorization\", \"Bearer ...\"]]"
      • changedInput schema / properties / ignoreProxies / description
        Previous value: -"Exits to AVOID - base36 proxy ids (like \"4DZ3VE\") or proxy URLs. Auto skips a warm session on one of these and tells its internal proxy search to avoid them too. Use to rotate away from an exit that just got blocked."New value: +"Exits to avoid - base36 proxy IDs (like \"4DZ3VE\") or proxy URLs. Use this to rotate away from an exit that was just blocked."
      • changedInput schema / properties / offload_large / description
        Previous value: -"If true, response bodies >= 50KB are written to disk and returned as a resource_link instead of inlined. Saves token context but requires a client that supports `resources/read`. Default false."New value: +"If true, response bodies of 50 KB or more are returned as a resource_link instead of inlined. Default false. Read the returned offloaded_resource_uri with resources/read."
      • changedInput schema / properties / returnSession / description
        Previous value: -"Return the {proxy, cookies, userAgent} session triple of the winning session so you can replay it through foura_single / foura_proxy later. Default true. Send false for a leaner response when you only need the content."New value: +"Return reusable {proxy, cookies, userAgent} values for follow-up calls. Default true. Send false for a leaner response when you only need the content."
      • changedInput schema / properties / timeout_ms / description
        Previous value: -"Total time budget in ms for the WHOLE operation - auto fires several internal attempts and they must all fit inside this. Default 120000, max 180000. Auto portions the budget across its attempts; it does not hand the whole budget to one attempt."New value: +"Total time budget in ms for the whole operation. Every attempt must fit inside it. Default 120000, max 180000."
      • changedInput schema / properties / url / description
        Previous value: -"Target URL. Public hosts only - private/reserved ranges (RFC 1918 10/8, 172.16/12, 192.168/16, loopback 127/8, link-local, IPv6 ULA fc00::/7, IPv6 loopback ::1, plus *.local mDNS) are refused with code `ssrf_blocked`. Example: https://example.com/page. Use {ts} anywhere in the URL to insert the current Unix timestamp for cache-bust."New value: +"Public target URL. Private or reserved targets return `ssrf_blocked`. Use {ts} in the URL to insert the current Unix timestamp. Example: https://example.com/page."
      • addedInput schema / properties / validate / description
        Added value: +"Post-fetch response validation. When the response fails these checks foura_auto returns an error envelope."
      • addedInput schema / properties / validate / properties / data / description
        Added value: +"Body validation: pass when the body contains an expected substring (accept), fail when it contains a blocked one (fail)."
      • changedInput schema / properties / validate / properties / data / properties / accept / description
        Previous value: -"Substrings the final body MUST contain for the fetch to count as solved (CASE-SENSITIVE). Strongly recommended on protected targets so auto can tell a real page from a challenge page."New value: +"Case-sensitive substrings the final body must contain. Use this on protected targets to distinguish the real page from a challenge page."
      • changedInput schema / properties / validate / properties / data / properties / fail / description
        Previous value: -"Substrings the final body must NOT contain"New value: +"Substrings the final body must not contain"
      • addedInput schema / properties / validate / properties / headers / description
        Added value: +"Header validation: pass when an accepted header matches, fail when a blocklisted header matches."
      • changedInput schema / properties / validate / properties / headers / properties / accept / description
        Previous value: -"Map of header-name-substring → header-value-substring (case-insensitive). PASSES if at least one entry matches a response header."New value: +"Case-insensitive header substring rules. The response passes when at least one name/value pair matches."
      • changedInput schema / properties / validate / properties / headers / properties / fail / description
        Previous value: -"Map of header-name-substring → header-value-substring (case-insensitive). FAILS if any entry matches a response header (use to reject challenge / block headers)."New value: +"Case-insensitive header substring rules that reject the response when any name/value pair matches."
      • addedInput schema / properties / validate / properties / status / description
        Added value: +"Status-code validation: which HTTP status codes count as success (accept) or failure (fail)."
      • changedOutput schema / properties / attempts / description
        Previous value: -"Total sub-call attempts when the ladder failed (also present inside `meta`)."New value: +"Total attempts when the request failed (also present inside `meta`)."
      • changedOutput schema / properties / code / description
        Previous value: -"Stable error code for retry classification. One of: ssrf_blocked, upstream_non_json, output_validation_failed, bad_request (400), auth_failed (401), forbidden (403), not_found (404), rate_limited (429), at_capacity (503), service_disabled (503), service_unavailable (503), upstream_error (>=500), upstream_client_error (other 4xx), upstream_unknown (defensive)."New value: +"Stable error code for retry classification. auth_failed means the FourA API key was rejected; verify that key, not target-site credentials. Other codes: ssrf_blocked, upstream_non_json, output_validation_failed, bad_request (400), forbidden (403), not_found (404), rate_limited (429), at_capacity (503), service_disabled (503), service_unavailable (503), upstream_error (>=500), upstream_client_error (other 4xx), upstream_unknown (defensive)."
      • changedOutput schema / properties / error / description
        Previous value: -"Human-readable error message when the ladder could not deliver the content within the budget."New value: +"Human-readable error message when the request could not deliver content within the budget."
      • changedOutput schema / properties / headers / description
        Previous value: -"Response headers from the delivering rung, as an array of objects. Each entry has `result.{version, code, reason}` plus arbitrary header-name keys whose values are strings (or arrays of strings for multi-value headers like Set-Cookie / Link). Last array entry is the final response."New value: +"Response headers from the successful request, as an array of objects. Each entry has `result.{version, code, reason}` plus header-name keys. The last entry is the final response."
      • changedOutput schema / properties / meta / description
        Previous value: -"Trace of what the ladder did: rung, solved, attempts, credits. Always present."New value: +"Completion details: rung, solved, attempts, and credits. Always present."
      • changedOutput schema / properties / meta / properties / attempts / description
        Previous value: -"Total internal sub-call attempts across the whole ladder."New value: +"Total fetch attempts made for this request."
      • changedOutput schema / properties / meta / properties / credits / description
        Previous value: -"Total credits spent (sum of every internal sub-call). A cold solve is expensive; a subsequent warm replay amortizes to the cheap-fetch cost."New value: +"Total credits spent across all attempts."
      • changedOutput schema / properties / meta / properties / rung / description
        Previous value: -"Which rung delivered the content (e.g. probe / proxy / browser / cache). `cache` means a warm session was replayed cheaply."New value: +"Which method delivered the content (e.g. probe / proxy / browser / cache). `cache` means a reusable session was used."
      • changedOutput schema / properties / offloaded_resource_uri / description
        Previous value: -"foura-mcp://payload/<uuid>"New value: +"foura-mcp://payload/<uuid>. Pass this URI to resources/read to retrieve the offloaded body."
      • changedOutput schema / properties / retryAfter / description
        Previous value: -"Seconds to wait before retrying (429/503 from the gateway)"New value: +"Seconds to wait before retrying a 429 or 503 response"
      • changedOutput schema / properties / session / description
        Previous value: -"The {proxy, cookies, userAgent} triple of the winning session, for DIY replay through foura_single / foura_proxy. Present by default (send returnSession:false to omit)."New value: +"Reusable {proxy, cookies, userAgent} values for follow-up calls. For plain HTTP, call foura_single with session.proxy as proxy, session.userAgent as a User-Agent header, and session.cookies serialized as a Cookie header. For JavaScript, pass the three values to foura_browser fields. Present by default; send returnSession:false to omit."
      • changedOutput schema / properties / session / properties / cookies / description
        Previous value: -"Cookies accumulated by the winning session - replay them on a follow-up request."New value: +"Cookie objects accumulated by the winning session. For foura_single, serialize their name/value pairs into a Cookie header; pass the array directly to foura_browser.cookies."
      • changedOutput schema / properties / session / properties / userAgent / description
        Previous value: -"User-Agent string the winning session used - send the same one when replaying."New value: +"User-Agent used by the winning session. Send it as a User-Agent header to foura_single or as foura_browser.userAgent."
      • changedOutput schema / properties / status / description
        Previous value: -"HTTP status code from the target on the rung that delivered the content. `0` indicates the whole ladder failed before any HTTP response - check `error`."New value: +"HTTP status code from the request that delivered the content. `0` means no HTTP response was received; check `error`."
    • Changedfoura_browser13 fields changed
      • changedInput schema / properties / checkStatus / description
        Previous value: -"Expected HTTP status code. If the page returns a different status → tool returns an error envelope with the actual status carried in the envelope. Example: 200 for product pages, or 404 to assert a soft-404 didn't leak through."New value: +"Expected HTTP status code. A different status returns an error envelope carrying the actual value. Example: 200 for a product page."
      • changedInput schema / properties / checkText / description
        Previous value: -"One-shot post-render validator - substring search on the rendered HTML AFTER navigation completes. NOT a waiter: does not poll, does not block until the substring appears. If the substring is missing, the tool returns an error envelope. Use to catch silent failures like a 200 response that captured a challenge page or empty SPA shell. Example: \"add to cart\" for product pages."New value: +"Validate the rendered HTML once navigation completes. This is a substring check, not a waiter, and it doesn't poll. A missing substring returns an error envelope. Example: \"add to cart\" for a product page."
      • addedInput schema / properties / cookies / items / properties / domain / description
        Added value: +"Cookie domain (e.g. .example.com). Omit to scope it to the navigated URL's host."
      • addedInput schema / properties / cookies / items / properties / name / description
        Added value: +"Cookie name."
      • addedInput schema / properties / cookies / items / properties / value / description
        Added value: +"Cookie value."
      • changedInput schema / properties / headers / description
        Previous value: -"Custom HTTP headers as a key-value object (NOT [name, value] tuples). Example: {\"Referer\": \"https://google.com/\"}"New value: +"Custom HTTP headers as a key-value object rather than [name, value] tuples. Example: {\"Referer\": \"https://google.com/\"}"
      • changedInput schema / properties / offload_large / description
        Previous value: -"If true, response bodies >= 50KB are written to disk and returned as a resource_link instead of inlined. Default false."New value: +"If true, response bodies of 50 KB or more are returned as a resource_link instead of inlined. Default false. Read the returned offloaded_resource_uri with resources/read."
      • changedInput schema / properties / proxy / description
        Previous value: -"Optional proxy. Three forms: (1) URL `http://user:pass@host:port` or `socks5://host:port`; (2) base36 ID from foura_proxy (e.g. `4DZ3VE`) - same pool exit IP; (3) omit → fixed container egress."New value: +"Optional proxy. Three forms: (1) URL `http://user:pass@host:port` or `socks5://host:port`; (2) base36 ID from foura_proxy (e.g. `4DZ3VE`) to reuse the same exit; (3) omit to use the default route."
      • changedInput schema / properties / unblocker / description
        Previous value: -"Actively SOLVE an anti-bot / captcha challenge (Cloudflare Turnstile and similar) encountered during navigation, instead of just rendering it. Default true. Set false to render and return the page exactly as it loads - including a challenge page - without attempting to solve; cheaper when you already know the target is open or you want the raw challenge page."New value: +"Handle supported anti-bot or captcha challenges during navigation. Default true. Set false to return the page exactly as it loads, including any challenge page."
      • changedInput schema / properties / url / description
        Previous value: -"Target URL to load in a full browser session. Public hosts only - private/reserved ranges (RFC 1918 + loopback + link-local + IPv6 ULA/loopback + *.local mDNS) are refused with code `ssrf_blocked`. Example: https://shop.example.com/product/123 or any single-page-app URL."New value: +"Public URL to load in a full browser session. Private or reserved targets return `ssrf_blocked`. Example: https://shop.example.com/product/123."
      • changedOutput schema / properties / code / description
        Previous value: -"Stable error code for retry classification. One of: ssrf_blocked, upstream_non_json, output_validation_failed, bad_request (400), auth_failed (401), forbidden (403), not_found (404), rate_limited (429), at_capacity (503), service_disabled (503), service_unavailable (503), upstream_error (>=500), upstream_client_error (other 4xx), upstream_unknown (defensive)."New value: +"Stable error code for retry classification. auth_failed means the FourA API key was rejected; verify that key, not target-site credentials. Other codes: ssrf_blocked, upstream_non_json, output_validation_failed, bad_request (400), forbidden (403), not_found (404), rate_limited (429), at_capacity (503), service_disabled (503), service_unavailable (503), upstream_error (>=500), upstream_client_error (other 4xx), upstream_unknown (defensive)."
      • changedOutput schema / properties / cookies / description
        Previous value: -"Full cookie objects collected after navigation (name, value, domain, path, expires, httpOnly, secure, session, sameSite, …)"New value: +"Full cookie objects collected after navigation, including name, value, domain, path, expiry, and same-site settings."
      • changedOutput schema / properties / offloaded_resource_uri / description
        Previous value: -"foura-mcp://payload/<uuid>"New value: +"foura-mcp://payload/<uuid>. Pass this URI to resources/read to retrieve the offloaded body."
    • Changedfoura_proxy26 fields changed
      • addedInput schema / properties / exitCountries
        Added value: +{
        +  "description": "Optional target-visible proxy countries as two-letter provider codes, for example [\"CZ\", \"GB\"]. Use codes supplied by the user or target requirements. When geography matters, do not guess codes or substitute unscoped rotation. Values are trimmed, uppercased, and deduplicated. Unknown exits are excluded and the request never falls back to another country.",
        +  "items": {
        +    "pattern": "^[A-Z]{2}$",
        +    "type": "string"
        +  },
        +  "minItems": 1,
        +  "type": "array"
        +}
      • changedInput schema / properties / ignoreProxies / description
        Previous value: -"Encoded proxy IDs (base36 strings like \"4DZ3VE\") OR proxy URLs to exclude from rotation. Both forms are accepted."New value: +"Encoded proxy IDs (base36 strings like \"4DZ3VE\") or proxy URLs to exclude from rotation."
      • changedInput schema / properties / maxTries / description
        Previous value: -"Maximum proxy rotation attempts before giving up (default 5, max 90). Default 5 is sized for lightly-blocked sites. Raise to 25-30 for tier-1 WAF challenges (Vercel Security Checkpoint, Cloudflare 'Just a moment', Akamai Bot Manager) - most rotations on these targets need this range. If still blocked after 30 attempts, the gate is likely country / ASN allowlist (not solvable by rotation) - pivot strategy instead of climbing to 60."New value: +"Maximum rotation attempts before giving up (default 5, max 90). Difficult protected targets may need 25-30. Use exitCountries for country scope."
      • changedInput schema / properties / offload_large / description
        Previous value: -"If true, response bodies >= 50KB are written to disk and returned as a resource_link instead of inlined. Default false."New value: +"If true, response bodies of 50 KB or more are returned as a resource_link instead of inlined. Default false. Read the returned offloaded_resource_uri with resources/read."
      • addedInput schema / properties / request / properties / accept_timeout_ms / description
        Added value: +"Timeout in ms to receive the first response byte after the request is sent (0-120000). Omit for the default."
      • addedInput schema / properties / request / properties / connect_timeout_ms / description
        Added value: +"Timeout in ms for establishing the connection to the target through the proxy (0-120000). Omit for the default."
      • addedInput schema / properties / request / properties / dns_cache_timeout_sec / description
        Added value: +"How long (seconds) to cache the target's resolved DNS (0-240). Omit for the default."
      • changedInput schema / properties / request / properties / headers / description
        Previous value: -"Custom HTTP headers as [name, value] tuples. Example: "New value: +"Custom HTTP headers as [name, value] tuples. Example: [[\"Accept\", \"application/json\"]]"
      • addedInput schema / properties / request / properties / returnBuffer / description
        Added value: +"Return raw bytes as a serialized Buffer JSON shape ({type:\"Buffer\", data:[byte, ...]}) instead of a decoded string. Use for binary responses (images, protobuf)."
      • addedInput schema / properties / request / properties / server_response_timeout_ms / description
        Added value: +"Timeout in ms for the server to send the complete response (0-120000). Omit for the default."
      • addedInput schema / properties / request / properties / tryJsonData / description
        Added value: +"If true, attempt JSON.parse on the response body; on success `data` is the parsed value, otherwise it stays the original string. Omit to keep the body as-is."
      • changedInput schema / properties / request / properties / unblocker / description
        Previous value: -"Inject realistic browser headers (User-Agent, Sec-Ch-Ua, Accept-Encoding, …) and make the request look like it's coming from a real browser at the wire level. Default false - STRONGLY recommended on proxy paths since most sites that need a proxy also have wire-level anti-bot (Cloudflare, Akamai, PerimeterX, Datadome). Cheap to leave on for production scrapes."New value: +"Add common browser headers such as User-Agent, Sec-Ch-Ua, and Accept-Encoding. Default false. Enable it for targets that reject basic HTTP requests."
      • changedInput schema / properties / request / properties / url / description
        Previous value: -"Target URL the proxy should fetch. Public hosts only - private/reserved ranges (RFC 1918 + loopback + link-local + IPv6 ULA/loopback + *.local mDNS) are refused with code `ssrf_blocked`. Example: https://shop.example.com/pricing for blocked sites. {ts} placeholder is replaced with current Unix timestamp."New value: +"Public target URL. Private or reserved targets return `ssrf_blocked`. Use {ts} in the URL to insert the current Unix timestamp. Example: https://shop.example.com/pricing."
      • addedInput schema / properties / request / properties / validate / description
        Added value: +"Per-attempt response validation. A proxy attempt that fails these checks is treated as failed and the next proxy is tried."
      • addedInput schema / properties / request / properties / validate / properties / data / description
        Added value: +"Body validation: pass when the body contains an expected substring (accept), fail when it contains a blocked one (fail)."
      • addedInput schema / properties / request / properties / validate / properties / data / properties / accept / description
        Added value: +"Substrings the response body must contain to pass."
      • addedInput schema / properties / request / properties / validate / properties / data / properties / fail / description
        Added value: +"Substrings that, if present in the body, mark the response as failed."
      • addedInput schema / properties / request / properties / validate / properties / headers / description
        Added value: +"Header validation: pass when an accepted header matches, fail when a blocklisted header matches."
      • changedInput schema / properties / request / properties / validate / properties / headers / properties / accept / description
        Previous value: -"Map of header-name-substring → header-value-substring (both case-insensitive). Response PASSES if AT LEAST ONE entry matches (header name contains the key AND value contains the value). Checked across all redirect hops. Empty / omitted = no header requirement."New value: +"Case-insensitive header substring rules. The response passes when at least one name/value pair matches across the redirect chain."
      • changedInput schema / properties / request / properties / validate / properties / headers / properties / fail / description
        Previous value: -"Map of header-name-substring → header-value-substring (both case-insensitive). Response is treated as FAILURE if ANY entry matches a response header. Use to reject challenge / block headers, e.g. {\"x-blocked\": \"bot\", \"server\": \"cloudflare\"}."New value: +"Case-insensitive header substring rules that reject the response when any name/value pair matches."
      • addedInput schema / properties / request / properties / validate / properties / status / description
        Added value: +"Status-code validation: which HTTP status codes count as success (accept) or failure (fail)."
      • changedOutput schema / properties / code / description
        Previous value: -"Stable error code for retry classification. One of: ssrf_blocked, upstream_non_json, output_validation_failed, bad_request (400), auth_failed (401), forbidden (403), not_found (404), rate_limited (429), at_capacity (503), service_disabled (503), service_unavailable (503), upstream_error (>=500), upstream_client_error (other 4xx), upstream_unknown (defensive)."New value: +"Stable error code for retry classification. auth_failed means the FourA API key was rejected; verify that key, not target-site credentials. no_eligible_proxy means the strict exitCountries scope had no match. Keep that scope and retry later; do not propose or perform an unscoped fallback."
      • addedOutput schema / properties / details
        Added value: +{
        +  "additionalProperties": false,
        +  "description": "Structured no_eligible_proxy context containing the normalized requested country scope. Preserve this scope and retry later. Do not propose or perform an unscoped fallback; change it only after the user explicitly changes the requirement.",
        +  "properties": {
        +    "exitCountries": {
        +      "items": {
        +        "pattern": "^[A-Z]{2}$",
        +        "type": "string"
        +      },
        +      "minItems": 1,
        +      "type": "array"
        +    }
        +  },
        +  "required": [
        +    "exitCountries"
        +  ],
        +  "type": "object"
        +}
      • addedOutput schema / properties / exitCountry
        Added value: +{
        +  "description": "Latest available two-letter target-visible exit-country code used for selection. Present on successful requests that use exitCountries.",
        +  "pattern": "^[A-Z]{2}$",
        +  "type": "string"
        +}
      • changedOutput schema / properties / offloaded_resource_uri / description
        Previous value: -"foura-mcp://payload/<uuid>"New value: +"foura-mcp://payload/<uuid>. Pass this URI to resources/read to retrieve the offloaded body."
      • changedOutput schema / properties / proxy / description
        Previous value: -"Base36 ID of the pool exit that succeeded (e.g. `4DZ3VE`). Reuse on next call: pass to foura_single.proxy or foura_browser.proxy → same exit IP. Pass to foura_proxy.ignoreProxies → skip this exit on future rotations."New value: +"Base36 ID of the exit that succeeded (e.g. `4DZ3VE`). Pass it to foura_single.proxy or foura_browser.proxy to reuse that exit, or to foura_proxy.ignoreProxies to skip it on future rotations."
    • Changedfoura_single17 fields changed
      • addedInput schema / properties / accept_timeout_ms / description
        Added value: +"Timeout in ms to receive the first response byte after the request is sent (0-120000). Omit for the default."
      • addedInput schema / properties / connect_timeout_ms / description
        Added value: +"Timeout in ms for establishing the TCP/TLS connection (0-120000). Omit to use the default."
      • addedInput schema / properties / dns_cache_timeout_sec / description
        Added value: +"How long (seconds) to cache the target's resolved DNS (0-240). Omit for the default."
      • changedInput schema / properties / offload_large / description
        Previous value: -"If true, response bodies >= 50KB are written to disk and returned as a resource_link instead of inlined. Saves token context but requires a client that supports `resources/read`. Default false."New value: +"If true, response bodies of 50 KB or more are returned as a resource_link instead of inlined. Default false. Read the returned offloaded_resource_uri with resources/read."
      • changedInput schema / properties / proxy / description
        Previous value: -"Optional proxy. Two forms: (1) URL `http://host:port` or `socks5://host:port`; (2) base36 ID from foura_proxy (e.g. `4DZ3VE`) - same exit IP. For rotation, use foura_proxy."New value: +"Optional proxy. Two forms: (1) URL `http://host:port` or `socks5://host:port`; (2) base36 ID from foura_proxy (e.g. `4DZ3VE`) to reuse the same exit. For rotation, use foura_proxy."
      • addedInput schema / properties / server_response_timeout_ms / description
        Added value: +"Timeout in ms for the server to send the complete response (0-120000). Omit for the default."
      • changedInput schema / properties / unblocker / description
        Previous value: -"Inject realistic browser headers (User-Agent, Sec-Ch-Ua, Accept-Encoding, …) and make the request look like it's coming from a real browser at the wire level. Default false - set true for any target with anti-bot or WAF (Cloudflare, Akamai, PerimeterX, Datadome). Cheap to leave on for production scrapes."New value: +"Add common browser headers such as User-Agent, Sec-Ch-Ua, and Accept-Encoding. Default false. Enable it for targets that reject basic HTTP requests."
      • changedInput schema / properties / url / description
        Previous value: -"Target URL. Public hosts only - private/reserved ranges (RFC 1918 10/8, 172.16/12, 192.168/16, loopback 127/8, link-local, IPv6 ULA fc00::/7, IPv6 loopback ::1, plus *.local mDNS) are refused with code `ssrf_blocked`. Example: https://example.com/page or https://api.example.com/v1/users. Use {ts} anywhere in the URL to insert current Unix timestamp for cache-bust."New value: +"Public target URL. Private or reserved targets return `ssrf_blocked`. Use {ts} in the URL to insert the current Unix timestamp. Example: https://api.example.com/v1/users."
      • addedInput schema / properties / validate / description
        Added value: +"Post-fetch response validation. When the response fails these checks the tool returns an error envelope."
      • addedInput schema / properties / validate / properties / data / description
        Added value: +"Body validation: pass when the body contains an expected substring (accept), fail when it contains a blocked one (fail)."
      • changedInput schema / properties / validate / properties / data / properties / fail / description
        Previous value: -"Substrings the response body must NOT contain"New value: +"Substrings the response body must not contain"
      • addedInput schema / properties / validate / properties / headers / description
        Added value: +"Header validation: pass when an accepted header matches, fail when a blocklisted header matches."
      • changedInput schema / properties / validate / properties / headers / properties / accept / description
        Previous value: -"Map of header-name-substring → header-value-substring (both case-insensitive). Response PASSES if AT LEAST ONE entry matches (header name contains the key AND value contains the value). Checked across all redirect hops. Empty / omitted = no header requirement."New value: +"Case-insensitive header substring rules. The response passes when at least one name/value pair matches across the redirect chain."
      • changedInput schema / properties / validate / properties / headers / properties / fail / description
        Previous value: -"Map of header-name-substring → header-value-substring (both case-insensitive). Response is treated as FAILURE if ANY entry matches a response header. Use to reject challenge / block headers, e.g. {\"x-blocked\": \"bot\", \"server\": \"cloudflare\"}."New value: +"Case-insensitive header substring rules that reject the response when any name/value pair matches."
      • addedInput schema / properties / validate / properties / status / description
        Added value: +"Status-code validation: which HTTP status codes count as success (accept) or failure (fail)."
      • changedOutput schema / properties / code / description
        Previous value: -"Stable error code for retry classification. One of: ssrf_blocked, upstream_non_json, output_validation_failed, bad_request (400), auth_failed (401), forbidden (403), not_found (404), rate_limited (429), at_capacity (503), service_disabled (503), service_unavailable (503), upstream_error (>=500), upstream_client_error (other 4xx), upstream_unknown (defensive)."New value: +"Stable error code for retry classification. auth_failed means the FourA API key was rejected; verify that key, not target-site credentials. Other codes: ssrf_blocked, upstream_non_json, output_validation_failed, bad_request (400), forbidden (403), not_found (404), rate_limited (429), at_capacity (503), service_disabled (503), service_unavailable (503), upstream_error (>=500), upstream_client_error (other 4xx), upstream_unknown (defensive)."
      • changedOutput schema / properties / offloaded_resource_uri / description
        Previous value: -"foura-mcp://payload/<uuid>"New value: +"foura-mcp://payload/<uuid>. Pass this URI to resources/read to retrieve the offloaded body."
  5. 4 tool updatesv0.3.2
    • First observedfoura_auto
    • First observedfoura_browser
    • First observedfoura_proxy
    • First observedfoura_single

TDQS

A4.8/5.0

Scored across 4 tools

Disambiguation4/5

Each tool targets a distinct fetch mode (single request, rotating proxy, browser, auto-escalation), and the descriptions explicitly cross-reference when to switch. foura_single and foura_proxy could be confused since both send HTTP requests, but proxy's exit-country and rotation role is clearly delineated.

Naming Consistency5/5

All four tools follow the exact foura_<mode> pattern with no mixed conventions. The naming is predictable and makes the escalation ladder immediately understandable.

Tool Count5/5

Four tools map cleanly to the fetch escalation ladder: direct request, rotating proxy, full browser, and automatic fallback. Each tool earns its place with a distinct responsibility, and the count is well-scoped for the server's purpose.

Completeness4/5

The set covers direct requests, proxy rotation, JavaScript rendering, and automatic escalation, with proxy IDs shared across tools for sticky sessions. Minor gaps such as a dedicated credit/plan status inspection tool exist, but credits are reported per response and core workflows are fully supported.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    F
    maintenance
    A scraper tool that leverages the Oxylabs Web Scraper API to fetch and process web content with flexible options for parsing and rendering pages, enabling efficient content extraction from complex websites.
    10
    2,283 PyPI
    104
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Official Bright Data server for the Model Context Protocol that enables AI assistants like Claude Desktop to reference and make decisions based on real-time public web data.
    5
    14,541 npm
    2,673
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Scrape any webpage and return clean markdown, HTML, or structured JSON. Bypasses anti-bot protection, renders JavaScript (React/Vue/Angular), supports premium residential proxies and CSS extraction. Works with any MCP client — no local install required.
    1
    1,065 npm
    19
    MIT