Skip to main content
Glama

FourA - HTTP request via rotating proxies

foura_proxy
Read-only

Route blocked HTTP requests through rotating proxy exits, retrying until one passes validation. Choose strict exit countries, ignore dead proxies, and escalate premium exits when needed.

Instructions

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.

Input Schema

TableJSON 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

TableJSON Schema
NameRequiredDescriptionDefault
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.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed12 schema fields changedv0.7.2
    • 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"
      +]
  2. Changed6 schema fields changedv0.6.0
    • 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"
      +}
  3. Changed26 schema fields changedv0.5.0
    • 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."
  4. First observedv0.3.2

TDQS

A5/5.0
Behavior5/5

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

Description discloses extensive behaviors beyond annotations: never falls back on exitCountries, presents named browser family, excludes dead exits, escalates to premium as allowance, timeout bounds whole rotation, validate defines delivered, response returns exit id for reuse, and reports credits and plan refusals. No contradiction with readOnlyHint/openWorldHint.

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 earns its place, with core purpose and key constraints front-loaded. No filler; complex rotation behavior is explained efficiently without redundancy.

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 tool with 7 params, nested objects, and output schema, the description covers all critical operational aspects: rotation logic, validation, retries, failure reporting, credits, plan limits, and how to chain with sibling tools. 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?

Though schema covers all parameters (100%), the description adds crucial interplay semantics: how timeout_ms can end rotation before maxTries, exitClass is an allowance not instruction, exitCountries never falls back, ignoreProxies excludes known-dead exits, and validate triggers retry. It explains the returned id's reuse, enriching schema meaning.

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?

Clearly states the tool routes HTTP requests through rotating proxies with retry on different exits, and explicitly contrasts it with foura_single (when blocked) and foura_browser (when JS needed). Verb+resource+scope are precise, making it easily distinguishable from siblings.

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?

Explicitly names when to use this tool (foura_single blocked, exit matters), when not to (foura_browser for JS), and notes rotation costs. Gives concrete conditions like strict exit-country allowlist and premium escalation, leaving no ambiguity about selection.

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

Deploy Server

Other Tools