Site checks
When a target runs a bot check on the way to the page you asked for, FourA tells you. Every request that meets one comes back with a field naming the system, whether the check was cleared, and (on a clear) the clearance you can replay so the next call skips it.
This page is the reference for those fields. For strategy, see Protected sites.
Where the Field Lives
| Endpoint | Field | Present when |
|---|---|---|
POST /api/single/ |
defense (object) |
A bot check was recognised on the response |
POST /api/proxy/ |
defense (object) |
Same, reported by the attempt that answered |
POST /api/browser/ |
defenseSolved (boolean) and defenses (object) |
Always, on a page that loaded. defenseSolved is false and defenses is empty when nothing was recognised. |
POST /api/auto/ |
meta.solved (boolean) |
On every answer once the ladder has started. true when a check was cleared somewhere on the ladder. A body that fails validation or a host that doesn't resolve is answered before the ladder, without meta. |
Absence means nothing was recognised. Don't read a missing defense as a failure.
On Single and Proxy, reporting needs unblocker, which is on by default. With unblocker: false you asked for the page exactly as it came, so Single hands back the challenge untouched and Browser renders it without solving.
defense on Single and Proxy
{
"status": 200,
"data": "<!doctype html>...",
"total_time": 3.61,
"defense": {
"vendor": "sgcaptcha",
"solved": true,
"present": ["sgcaptcha"],
"ms": 3412,
"hashes": 1048576,
"complexity": 20,
"cookie": "_I_=<clearance>"
}
}
| Field | Type | Description |
|---|---|---|
vendor |
string | The system this record is about: the one that was cleared, or the main one met. See the vendor list below. |
solved |
boolean | true means the check was cleared and data is the real page. false means data may be the challenge page. |
present |
string[] | Every system recognised on this response. Can hold more names than vendor, and can hold names nobody clears yet. |
ms |
number | Milliseconds spent clearing the check. Only on a clear. |
hashes |
number | How much computational work the challenge asked for. Only on a clear. |
complexity |
number | The difficulty the challenge declared. Only on a clear, and only where the challenge reports one. |
answers |
number | How many accepted answers were supplied, for challenges that want several rather than one. Only on a clear. |
retry |
string | Present when the body came back from a retry rather than from a clear. Today the one value is refusal-cookies. See below. |
cookie |
string | The jar to replay: the clearance a clear earned, or the session a refusal handed out. |
solved: false is the case worth branching on. FourA never presents a challenge page as content, so the flag is your signal that the body needs escalation rather than parsing.
retry: "refusal-cookies"
Some sites don't run a puzzle. They refuse the first request, set cookies on the refusal, and serve the real page to anyone who sends those cookies back. eBay's item pages are the reference case.
When that happens, FourA sends them back for you and hands you the page. The response then carries retry: "refusal-cookies":
{
"status": 200,
"data": "<!doctype html>...",
"defense": {
"vendor": "akamai",
"solved": false,
"present": ["akamai"],
"retry": "refusal-cookies",
"cookie": "bm_sv=...; dp1=..."
}
}
Read it like this:
solvedstaysfalse. Answering a handshake isn't clearing a challenge, and it never changes what the call costs. You're billed for the request you made.datais real content, not a challenge page. This is the one case wheresolved: falsedoesn't mean the body needs escalation, which is why the field exists.cookieis the session the site handed out. Replay it the same way you'd replay a clearance and the follow-up pages skip the refusal.- A retry and a clear can both happen on one request. If the retry's answer turned out to be a challenge that FourA can clear, you get
solved: truewith the vendor's own fields andretry: "refusal-cookies"beside them.
vendor reads unknown when a retry produced the content and no system was recognised on the way. present is then an empty array.
defenses on Browser
{
"status": 200,
"body": "<!doctype html>...",
"userAgent": "Mozilla/5.0...",
"defenseSolved": true,
"defenses": {
"present": ["cloudflare"],
"cleared": ["cloudflare"]
}
}
| Field | Type | Description |
|---|---|---|
defenseSolved |
boolean | true when a system was met during the load and its clearance is held on the final page. This is the flag that decides whether the call costs 5 or 10 credits. |
defenses.present |
string[] | Every system recognised at any point during the page load, not just on the final response. A check is something that happened, and by the time the real page arrives the challenge response is long gone. |
defenses.cleared |
string[] | The systems whose clearance the final page holds. |
A name in present that never reaches cleared is a system FourA can recognise but not yet complete. Those never raise the price of a call.
Vendors
vendor value |
The system |
|---|---|
cloudflare |
Cloudflare challenges and bot management |
sgcaptcha |
SiteGround's site check |
datadome |
DataDome |
perimeterx |
PerimeterX |
akamai |
Akamai Bot Manager |
incapsula |
Imperva Incapsula |
awswaf |
AWS WAF challenge |
ebay-splashui |
eBay's own challenge |
reddit |
Reddit's own check and refusal pages |
amazon |
Amazon's robot check |
google |
Google Search's JavaScript check |
hcaptcha |
hCaptcha |
recaptcha |
reCAPTCHA |
unknown |
No system was recognised. Only appears alongside retry, where the record exists to report the retry rather than a vendor. |
What Gets Cleared Today
| Endpoint | Clears |
|---|---|
| Single, Proxy | sgcaptcha, ebay-splashui. Both are computational rather than visual, so no browser is involved. |
| Browser | cloudflare, sgcaptcha |
Everything else on the list is recognised and reported, and nothing more. That split moves as FourA learns to clear more of them, so read solved rather than assuming from this table.
Two notes on the edges:
hcaptchaandrecaptchaare also ordinary form widgets. They're only reported when the response actually blocked you (403, 429, or 503), so a checkout page with a verification widget in a form doesn't report a defense.- Being behind Cloudflare isn't a defense.
cloudflareappears when there's a real challenge or bot-management artifact on the response, not because a site uses Cloudflare.
Replaying a Clearance
defense.cookie is the whole point of the field. A clearance is bound to the exit that earned it and the User-Agent that earned it, so replay it through the same pair and the check doesn't run again.
import requests
API = "https://eu.api.foura.ai"
H = {"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"}
# 1) First call pays for the clear.
first = requests.post(f"{API}/api/proxy/", headers=H, json={
"maxTries": 5,
"request": {"method": "GET", "url": "https://example.com/catalog"},
}).json()
defense = first.get("defense", {})
if defense.get("solved"):
clearance = defense["cookie"]
exit_id = first["proxy"]
# 2) Follow-up pages skip the check: same exit, same clearance.
for page in range(2, 6):
r = requests.post(f"{API}/api/single/", headers=H, json={
"method": "GET",
"url": f"https://example.com/catalog?page={page}",
"proxy": exit_id,
"headers": [["Cookie", clearance]],
}).json()
print(page, r["status"])
The first call carries the cost of the clear. Every replay is an ordinary request at the ordinary price.
Three things break a replay:
- A different exit. Pin the proxy ID the clearing response returned. See Reuse a Proxy Across Requests.
- A different User-Agent. Browser responses return the
userAgentthey used. Send it back with the cookie. - Expiry. Clearances have their own lifetimes, set by the target. SiteGround's runs around 30 days for the whole site; a Cloudflare clearance is usually much shorter. Treat a clearance as a cache: when replays start returning challenges again, run one fresh call and take the new one.
What It Costs
A cleared check changes the price on Browser only:
| Engine | Base | Cleared defense |
|---|---|---|
| Single | 1 (2 with unblocker) |
No change |
| Proxy | 2 (4 with unblocker) |
No change |
| Browser | 5 | 10 |
Browser charges 10 only when the solver was on and a system was genuinely cleared. A system that was recognised and not cleared costs 5, the same as a page with no check on it at all.
A check page FourA recognises served with HTTP 200 (for example Amazon's robot check, Reddit's verification page or Google Search's JavaScript check) isn't billed on any endpoint; the response names it in X-FourA-Check-Page.
Pair It With validate
defense tells you a check was met. validate tells FourA what the real page looks like, which is what lets a request fail rather than hand you an interstitial that happens to carry HTTP 200.
{
"method": "GET",
"url": "https://example.com/product/42",
"validate": {
"data": {"accept": ["Add to cart"], "fail": ["Just a moment"]}
}
}
On POST /api/auto/, validate is what stops the ladder from accepting a challenge page and calling it done.
Related
- Protected sites: Which engine to reach for at each protection level
- API Endpoints: Request and response reference for all four endpoints
- Reuse a Proxy Across Requests: Pin the exit a clearance is bound to
- Smart Fetch (Auto): How
meta.solvedfits into the ladder - Response Headers: Where the credit cost of a call shows up