API Endpoints Reference
A reference for all FourA API endpoints with request parameters and response formats.
Base URL
https://eu.api.foura.ai/api
Authentication
Every request requires your API key in the X-API-Key header:
curl -X POST https://eu.api.foura.ai/api/single/ \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"method": "GET", "url": "https://example.com"}'
Create and manage API keys in the Dashboard. Keys use the pk_live_ prefix.
Response Headers
Every response from /api/* carries two correlation headers:
| Header | Value | Description |
|---|---|---|
X-FourA-Request-Id |
UUID | Unique ID assigned to the request. Returned on every response, including 4xx and 5xx. Log it on your side. |
X-FourA-Credits |
integer | Credits spent on this request. Returned on success and on failure (the work was done either way). See Request Outcomes for which outcomes are billable. |
The same request ID keys the request and response payload preview in the Dashboard's Activity Log (kept 24 hours, last 200 per key), so you can look up the exact request later and replay it from Activity straight into the Playground. Include it when you contact support, and it pinpoints the request in seconds.
$ curl -i -X POST https://eu.api.foura.ai/api/single/ \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"method": "GET", "url": "https://example.com"}'
HTTP/2 200
content-type: application/json
x-foura-request-id: 8f3e2a14-7b6c-4d1a-9e2f-5a3b8c1d4e7f
x-foura-credits: 2
...
See Response Headers for the full list and usage tips.
Endpoints
Using these endpoints via MCP? The
@fouradata/mcpserver wraps all four endpoints as native MCP tools (foura_auto,foura_single,foura_proxy,foura_browser) with the same input shapes plus anoffload_largeopt-in for token-friendly large-response handling.
FourA provides four request endpoints, each optimized for a different scenario:
| Endpoint | Best for |
|---|---|
POST /auto/ |
Smart fetch. You pass a URL, FourA picks the cheapest path that works (direct, rotated proxy, or browser) and remembers what works per host. |
POST /single/ |
Fast HTTP requests, static pages, APIs |
POST /proxy/ |
Protected sites with automatic proxy rotation |
POST /browser/ |
JavaScript-rendered pages, SPAs |
For a deeper walkthrough of when to pick each, see Choosing the Right Endpoint and the Smart Fetch guide.
Target URL Restrictions
Targets that resolve to private, loopback, or reserved IP ranges (RFC 5735, RFC 6598, IPv6 reserved blocks) are refused with a 400 before the request leaves FourA. Only public hostnames and IPs are forwarded.
{ "error": "Target <ip> resolves to a private/reserved IP" }
Smart Fetch (Auto)
POST /api/auto/
You pass a URL plus optional validate rules. FourA walks a cost-aware ladder (cheap direct probe, rotated proxy, full browser) and stops at the first rung that returns a response your rules accept. On repeat calls to the same host, a warm session is replayed instead, so the second hit is cheap.
You don't tune retries, pool sizes, or proxy counts. FourA learns them per host.
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
url |
string | Yes | - | Target URL |
method |
string | No | "GET" |
HTTP method |
headers |
[string, string][] | No | - | Custom headers as [name, value] pairs |
data |
any | No | - | Request body for non-GET requests |
validate |
object | No | - | Success criteria, same shape as Single Request's validate (see below). Tell auto what a real page looks like so it can tell content from a challenge page. |
returnSession |
boolean | No | true |
Include the winning session (proxy, cookies, userAgent) in the response so you can replay it through /api/single/ or /api/browser/. |
forceProxy |
boolean | No | true |
Always route through a rotating proxy. Set false to allow the cheaper direct path when the target permits it (some defenses are stricter on proxy traffic). |
timeout_ms |
integer | No | 120000 |
Total time budget for the whole call, in milliseconds. All sub-attempts run inside this budget. Min 5000, max 180000. |
ignoreProxies |
string[] | No | - | Proxy IDs to avoid on every sub-attempt. Use IDs returned by previous /api/auto/ or /api/proxy/ responses. |
followRedirects |
integer | No | 5 |
Max redirects to follow on the cheap ladder rungs. 0 to disable. Max 20. |
Response
{
"status": 200,
"data": "<!doctype html>...",
"headers": [{"content-type": "text/html"}],
"meta": {
"rung": "cache",
"solved": false,
"attempts": 1,
"credits": 2
},
"session": {
"proxy": "A1B2C3",
"cookies": [{"name": "session", "value": "abc", "domain": "example.com"}],
"userAgent": "Mozilla/5.0..."
}
}
| Field | Type | Description |
|---|---|---|
status |
number | HTTP status from the target. |
data |
string or object | Response body. |
headers |
array or object | Target response headers. Single and proxy rungs return an array of per-hop header objects; browser rungs return a flat object. |
meta.rung |
string | Which ladder rung delivered the response. One of: probe (cheap direct request), proxy (rotating proxy), browser (full browser render), cache (warm session replayed), or fail (no rung produced an accepted response). |
meta.solved |
boolean | Whether a bot challenge was solved during this call. |
meta.attempts |
number | Sub-attempts made before success. |
meta.credits |
number | Total credits spent on this call. Matches X-FourA-Credits. |
session.proxy |
string | Encoded ID of the proxy that delivered the response. Reuse it on a Single or Browser request. Present when returnSession is true. |
session.cookies |
array | Cookies from the winning attempt. Present when returnSession is true. |
session.userAgent |
string | User-Agent used on the winning attempt. Present when returnSession is true. |
error |
string | Error message if the call failed. |
Example
curl -X POST https://eu.api.foura.ai/api/auto/ \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/product/42",
"validate": {"data": {"accept": ["Add to cart"]}}
}'
Notes
- Auto is a coordinator. It calls Single, Proxy, or Browser internally and forwards your API key to each sub-call. Each sub-call appears in your Activity Log; the outer
/api/auto/call doesn't add a separate billable row. - Pass
validate.data.acceptwith a substring that only the real page contains. Without it, auto can't tell a real 200 from a challenge interstitial returned with status 200. timeout_mscaps the whole call. A cold first hit to a protected site can take tens of seconds; reused warm sessions usually finish in under a second.
Single Request
POST /api/single/
Sends an HTTP request with realistic browser-like wire characteristics, without spinning up a real browser. This is the fastest endpoint.
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
method |
string | Yes | - | HTTP method: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS |
url |
string | Yes | - | Target URL. Use {ts} anywhere in the URL to insert the current timestamp for cache-busting. |
headers |
[string, string][] | No | - | Custom headers as [name, value] pairs |
unblocker |
boolean | No | true |
Send realistic browser headers (User-Agent, Sec-Ch-Ua, Sec-Fetch-*, Accept-Encoding). On by default. Set false to send a plain client signature. |
timeout_ms |
number | No | 15000 | Overall timeout in ms (max: 120000) |
connect_timeout_ms |
number | No | 5000 | Connection timeout in ms |
accept_timeout_ms |
number | No | 5000 | Accept timeout in ms (time to wait for connection acceptance) |
server_response_timeout_ms |
number | No | 15000 | Server response timeout in ms (time to wait for first byte) |
dns_cache_timeout_sec |
number | No | 120 | DNS cache TTL in seconds (max: 240) |
followRedirects |
number | No | disabled | Max redirects to follow (0-20). Omit to disable. |
tryJsonData |
boolean | No | false | Parse response body as JSON if possible |
returnBuffer |
boolean | No | false | Return raw buffer instead of decoded string |
data |
any | No | - | Request body (string or object, auto-serialized to JSON) |
proxy |
string | No | - | Proxy URL (http, socks4, or socks5) or a proxy ID returned by a previous response |
validate |
object | No | - | Response validation rules (see below) |
Validation Rules
The validate object lets you define conditions for success and failure. If a fail condition matches, the request is treated as failed. If accept conditions are set, only matching responses are treated as successful.
{
"validate": {
"status": { "accept": [200, 201], "fail": [403, 503] },
"headers": { "accept": {"content-type": "application/json"} },
"data": { "accept": ["product"], "fail": ["captcha", "blocked"] }
}
}
| Field | Type | Description |
|---|---|---|
validate.status.accept |
number[] | HTTP status codes to accept |
validate.status.fail |
number[] | HTTP status codes to reject |
validate.headers.accept |
object | Header key-value pairs that must be present |
validate.headers.fail |
object | Header key-value pairs that trigger failure |
validate.data.accept |
string[] | Strings that must appear in the response body |
validate.data.fail |
string[] | Strings in the response body that trigger failure |
Example
curl -X POST https://eu.api.foura.ai/api/single/ \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"method": "GET",
"url": "https://example.com/products",
"timeout_ms": 10000
}'
Response:
{
"status": 200,
"headers": [{"result": {"version": "HTTP/2", "code": 200, "reason": ""}, "content-type": "text/html", "server": "nginx", "set-cookie": ["session=abc", "tracker=xyz"]}],
"data": "<!doctype html>...",
"total_time": 0.342,
"proxy": "A1B2C3"
}
| Field | Type | Description |
|---|---|---|
status |
number | HTTP status code from the target |
headers |
array | One object per redirect hop. Each has a result field with the status line plus every response header. Multi-value headers (Set-Cookie, Link, WWW-Authenticate) come back as arrays of strings. |
data |
string/object | Response body (JSON if tryJsonData is true) |
total_time |
number | Total request time in seconds |
proxy |
string | Encoded ID of the proxy the request went through (only when a proxy was supplied on the request). Reuse it on a follow-up call to pin the same exit. |
error |
string | Error message if the request failed |
Proxy Request
POST /api/proxy/
Routes your request through rotating proxies with automatic retry on failure.
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
request |
object | Yes | - | A single request body (same fields as Single Request above) |
timeout_ms |
number | No | 45000 | Overall timeout for all attempts in ms (max: 120000) |
maxTries |
number | No | 5 | Maximum proxy rotation attempts (max: 90) |
ignoreProxies |
string[] | No | - | Proxy IDs to exclude from rotation (use IDs returned by previous responses) |
Example
curl -X POST https://eu.api.foura.ai/api/proxy/ \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"maxTries": 3,
"request": {
"method": "GET",
"url": "https://example.com/prices"
}
}'
Response:
{
"status": 200,
"headers": [{"result": {"code": 200}, "content-type": "text/html", "set-cookie": ["a=1", "b=2"]}],
"data": "<!doctype html>...",
"total_time": 1.204,
"proxy": "A1B2C3",
"total": 2.341
}
| Field | Type | Description |
|---|---|---|
proxy |
string | Encoded identifier of the proxy used. Reuse it on a Single or Browser request by passing it as the proxy field, or skip it on the next Proxy request via ignoreProxies. |
total |
number | Outer wall-clock duration in seconds (float). Includes proxy selection, retries, and the successful attempt. total_time is the inner request only; total is always >= total_time. |
error |
string | Error message if the request failed |
All Single Request response fields are also included.
Browser Request
POST /api/browser/
Opens your URL in a Chrome browser instance. The page loads, JavaScript executes, and you get the fully rendered HTML plus the cookie jar.
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
url |
string | Yes | - | Target URL |
headers |
object | No | - | Custom headers as key-value pairs |
cookies |
array | No | - | Cookies to set: [{name, value, domain?}] |
userAgent |
string | No | - | Custom User-Agent string |
unblocker |
boolean | No | true |
Auto-solve common bot challenges (Cloudflare clearance, similar gates) during page load. On by default. Set false to render whatever the page returns, including a challenge page, without solving. |
proxy |
string | No | - | Proxy URL or a proxy ID returned by a previous response |
timeout_ms |
number | No | 30000 | Page load timeout in ms (max: 120000) |
checkStatus |
number | No | - | Expected HTTP status (request fails if different) |
checkText |
string | No | - | Text that must appear in the rendered page |
Example
curl -X POST https://eu.api.foura.ai/api/browser/ \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/spa-app",
"timeout_ms": 15000,
"checkText": "product-list"
}'
Response:
{
"status": 200,
"headers": {"content-type": "text/html"},
"body": "<!doctype html>...",
"cookies": [{"name": "session", "value": "abc123", "domain": "example.com", "path": "/", "expires": 1735689600, "httpOnly": true, "secure": true, "sameSite": "Lax"}],
"userAgent": "Mozilla/5.0...",
"defenseSolved": true,
"proxy": "A1B2C3"
}
| Field | Type | Description |
|---|---|---|
status |
number | HTTP status code from the target |
headers |
object | Response headers |
body |
string or object | Fully rendered page content. String HTML when content-type is HTML; object when the page returned JSON and was auto-parsed. |
cookies |
array | Full cookie objects from the page. Each cookie includes name, value, domain, path, expires, httpOnly, secure, sameSite, and other cookie properties. |
userAgent |
string | Browser User-Agent used |
defenseSolved |
boolean | true if a bot defense (Cloudflare clearance or similar) was solved on this call. Absent otherwise. |
proxy |
string | Encoded ID of the proxy the request went through (only when a proxy was supplied on the request). Reuse it on follow-up calls to keep the same exit. |
error |
string | Error message if the request failed |
HTTP Status Codes
| Code | Meaning |
|---|---|
| 200 | Request completed (check inner status for target response) |
| 400 | Invalid request body, parameters, or target IP in a private/reserved range |
| 401 | Missing or invalid API key |
| 429 | Rate limit exceeded |
| 500 | Internal server error |
| 503 | Service temporarily disabled or at capacity |
Next Steps
- Smart Fetch (Auto): When to let FourA pick the path for you
- Choosing the Right Endpoint: When to pick Single, Proxy, or Browser by hand
- Authentication: Manage your API keys
- Error Handling: Handle errors gracefully
- Rate Limits: Understand request limits
- Quick Start: Your first request in 30 seconds