API Endpoints Referenz
Eine Referenz für alle FourA-API-Endpoints mit Request-Parametern und Response-Formaten.
Base-URL
https://eu.api.foura.ai/api
Authentifizierung
Jeder Request erfordert deinen API-Key im 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"}'
Erstelle und verwalte API-Keys im Dashboard. Keys nutzen das Präfix pk_live_.
Response Headers
Responses von /api/* enthalten zwei Korrelations-Header:
| Header | Value | Description |
|---|---|---|
X-FourA-Request-Id |
UUID | Eindeutige ID, die dem Request zugewiesen wird. Wird bei jeder Response zurückgegeben, einschließlich 4xx und 5xx, außer bei einem Body, den FourA überhaupt nicht lesen kann: 400 Invalid JSON in request body und 413 werden abgelehnt, bevor eine ID zugewiesen wird. Logge sie auf deiner Seite. |
X-FourA-Credits |
integer | Für diesen Request verbrauchte Credits. Wird bei jeder Response zurückgegeben, die eine Engine erreicht hat, egal ob Erfolg oder Fehler (die Arbeit wurde in beiden Fällen ausgeführt). Ein Aufruf, den FourA abgelehnt hat, bevor eine Engine ihn ausgeführt hat (ein fehlender oder ungültiger Key, ein Plan- oder Plattform-Limit, eine abgelehnte Ziel- oder Proxy-ID), enthält keinen. Unter Request-Ergebnisse siehst du, welche Ergebnisse abrechenbar sind. |
Dieselbe Request-ID dient als Schlüssel für die Vorschau der Request- und Response-Payloads im Activity Log des Dashboards (24 Stunden aufbewahrt, die letzten 200 pro Key). So kannst du den genauen Request später nachschlagen und direkt aus dem Activity Log im Playground erneut ausführen. Gib sie an, wenn du den Support kontaktierst, damit der Request in Sekundenschnelle gefunden werden kann.
$ 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
...
Siehe Response Headers für die vollständige Liste und Nutzungstipps.
Endpoints
Verwendest du diese Endpoints über MCP? Der
@fouradata/mcpServer verpackt alle vier Endpoints als native MCP-Tools (foura_auto,foura_single,foura_proxy,foura_browser) mit denselben Eingabeformaten plus einemoffload_largeOpt-in für token-effizientes Handling großer Responses.
FourA bietet vier Request-Endpoints, jeweils optimiert für ein anderes Szenario:
| Endpoint | Best for |
|---|---|
POST /auto/ |
Smart Fetch. Du übergibst eine URL, FourA wählt den günstigsten funktionierenden Pfad (direkt, rotierter Proxy oder Browser) und speichert, was pro Host funktioniert. |
POST /single/ |
Schnelle HTTP-Requests, statische Seiten, APIs |
POST /proxy/ |
Geschützte Seiten mit automatischer Proxy-Rotation, optionalem zielseitig sichtbarem Länder-Scoping |
POST /browser/ |
JavaScript-gerenderte Seiten, SPAs |
GET /profiles |
Der Browser-Profil-Katalog für single und proxy. Öffentlich, kein API-Key. |
Einen detaillierteren Leitfaden zur Auswahl findest du unter Choosing the Right Endpoint und im Smart Fetch guide.
Target URL Restrictions
Ziele, die zu privaten, Loopback- oder reservierten IP-Bereichen auflösen (RFC 5735, RFC 6598, reservierte IPv6-Blöcke), werden mit einem 400 abgelehnt, bevor der Request FourA verlässt. Nur öffentliche Hostnames und IPs werden weitergeleitet.
{ "error": "Refusing to fetch <target>: target resolves to a private or reserved IP range. The FourA scraping API only forwards requests to public internet hosts." }
Smart Fetch (Auto)
POST /api/auto/
Du uebergibst eine URL sowie optionale validate Regeln. FourA durchlaeuft eine kostenoptimierte Eskalationsstufe (guenstiger Direkt-Probe, rotierter Proxy, vollstaendiger Browser) und stoppt auf der ersten Stufe, die eine Antwort liefert, die deine Regeln akzeptieren. Bei wiederholten Aufrufen desselben Hosts wird stattdessen eine warme Session wiederverwendet, sodass der zweite Aufruf guenstig ist.
Du musst Retries, Pool-Groessen oder Proxy-Anzahlen nicht optimieren. FourA lernt diese pro Host.
Request Body
| Parameter | Typ | Erforderlich | Standard | Beschreibung |
|---|---|---|---|---|
url |
string | Ja | - | Ziel-URL |
method |
string | Nein | "GET" |
HTTP-Methode |
headers |
[string, string][] | Nein | - | Benutzerdefinierte Header als [name, value]-Paare |
data |
any | Nein | - | Request-Body fuer Nicht-GET-Requests |
validate |
object | Nein | - | Erfolgskriterien, gleiche Struktur wie validate bei Single Request (siehe unten). Gib auto an, wie eine echte Seite aussieht, damit Content von einer Challenge-Seite unterschieden werden kann. |
returnSession |
boolean | Nein | true |
Fuege die erfolgreiche Session (proxy, cookies, userAgent) in die Response ein, damit du sie ueber /api/single/ oder /api/browser/ erneut abspielen kannst. |
forceProxy |
boolean | Nein | true |
Immer ueber einen rotierenden Proxy leiten. Setze false, um den guenstigeren direkten Pfad zu erlauben, wenn das Ziel dies zulaesst (einige Schutzmechanismen sind bei Proxy-Traffic strenger). |
timeout_ms |
integer | Nein | 120000 |
Gesamtzeitbudget fuer den gesamten Aufruf in Millisekunden. Alle Unterversuche laufen innerhalb dieses Budgets. Min 5000, max 180000. |
ignoreProxies |
string[] | Nein | - | Proxy-IDs, die bei jedem Unterversuch vermieden werden sollen. Verwende IDs aus vorherigen /api/auto/- oder /api/proxy/-Responses. |
followRedirects |
integer | Nein | 5 |
Maximale Anzahl an Redirects, denen auf den guenstigen Stufen gefolgt wird. 0 zum Deaktivieren. 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..."
}
}
| Feld | Typ | Beschreibung |
|---|---|---|
status |
number | HTTP-Status des Ziels. |
data |
string | Response-Body als Text, unabhängig von der ausführenden Stufe. Eine JSON-Seite wird als JSON-Text zurückgegeben, den du selbst parsen musst. |
headers |
array or object | Response-Header des Ziels. Single- und Proxy-Stufen geben ein Array von Header-Objekten pro Hop zurück; Browser-Stufen liefern ein flaches Objekt. |
meta.rung |
string | Gibt an, welche Stufe die Response geliefert hat. Einer der folgenden Werte: probe (günstiger direkter Request), proxy (rotierender Proxy), browser (vollständiges Browser-Rendering), cache (erneutes Abspielen einer aktiven Session), warmup (die Startseite der Website wurde zuerst abgerufen und ihre Cookies öffneten die Deep-URL) oder fail (keine Stufe lieferte eine akzeptierte Response). |
meta.solved |
boolean | Gibt an, ob die Seite einen zusätzlichen Schritt erforderte (eine Challenge-Seite) und dieser während dieses Aufrufs abgeschlossen wurde. |
meta.attempts |
number | Anzahl der Teilversuche vor dem Erfolg. |
meta.credits |
number | Gesamte verbrauchte Credits für diesen Aufruf. Entspricht X-FourA-Credits. |
session.proxy |
string | Encodierte ID des Proxys, der die Response geliefert hat. Kannst du bei einem Single- oder Browser-Request wiederverwenden. Vorhanden, wenn returnSession gleich true ist. |
session.cookies |
array | Cookies aus dem erfolgreichen Versuch. Vorhanden, wenn returnSession gleich true ist. |
session.userAgent |
string | User-Agent, der beim erfolgreichen Versuch verwendet wurde. Vorhanden, wenn returnSession gleich true ist. |
error |
string | Fehlermeldung, falls der Aufruf fehlgeschlagen ist. |
Beispiel
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"]}}
}'
Hinweise
- Auto fungiert als Koordinator. Es ruft intern Single, Proxy oder Browser auf und leitet deinen API-Key an jeden Unteraufruf weiter. Der Auto-Aufruf zählt als ein Request in deinem Activity Log und in deiner Overview, mit der Summe der Credits seiner Unteraufrufe. Die Unteraufrufe werden darunter als Versuche aufgeführt und zählen niemals als eigene Requests.
- Übergib
validate.data.acceptmit einem Substring, den nur die echte Seite enthält. Ohne ihn kann Auto einen echten 200-Status nicht von einer Challenge-Zwischenseite mit Status 200 unterscheiden. timeout_msbegrenzt den gesamten Aufruf. Ein erster Cold-Aufruf einer geschützten Website kann zig Sekunden dauern; wiederverwendete Warm-Sessions sind meist in unter einer Sekunde fertig.
Single Request
POST /api/single/
Sendet einen HTTP-Request mit realistischen, browserähnlichen Wire-Eigenschaften, ohne einen echten Browser zu starten. Dies ist der schnellste Endpoint.
Request Body
| Parameter | Typ | Erforderlich | Standard | Beschreibung |
|---|---|---|---|---|
method |
string | Ja | - | HTTP-Methode: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS |
url |
string | Ja | - | Ziel-URL. Verwende {ts} an beliebiger Stelle in der URL, um den aktuellen Zeitstempel für Cache-Busting einzufügen. |
headers |
[string, string][] | Nein | - | Benutzerdefinierte Header als [name, value]-Paare |
unblocker |
boolean | Nein | true |
Realistische Browser-Header senden (User-Agent, Sec-Ch-Ua, Sec-Fetch-*, Accept-Encoding). Standardmäßig aktiviert. Setze false, um eine einfache Client-Signatur zu senden. |
timeout_ms |
number | Nein | 15000 | Gesamt-Timeout in ms (max: 120000) |
connect_timeout_ms |
number | Nein | 5000 | Verbindungs-Timeout in ms |
accept_timeout_ms |
number | Nein | 5000 | Accept-Timeout in ms (Wartezeit auf Verbindungsannahme) |
server_response_timeout_ms |
number | Nein | 15000 | Serverantwort-Timeout in ms (Wartezeit auf erstes Byte) |
dns_cache_timeout_sec |
number | Nein | 120 | DNS-Cache-TTL in Sekunden (max: 240) |
followRedirects |
number | Nein | disabled | Max. Weiterleitungen (0-20). Weglassen zum Deaktivieren. |
tryJsonData |
boolean | Nein | false | Response-Body wenn möglich als JSON parsen |
returnBuffer |
boolean | Nein | false | Roh-Buffer statt decodiertem String zurückgeben |
data |
any | Nein | - | Request-Body (String oder Objekt, automatisch nach JSON serialisiert) |
proxy |
string | Nein | - | Proxy-ID aus einer früheren Response, um denselben Exit zu pinnen. Übergib den opaken String unverändert. Eine rohe Proxy-Adresse wird mit 400 Invalid proxy format abgelehnt. Manche IDs können nicht gepinnt werden: siehe Pinning an exit. |
browser |
string | Nein | Chrome | Vorzutäuschender Browser: Chrome, Edge, Safari, Firefox oder Tor. Siehe Browser profiles. |
os |
string | Nein | - | Vorzutäuschendes Betriebssystem: Windows, macOS, Android oder iOS. Ein Familienname akzeptiert jede seiner Versionen. |
version |
string | Nein | newest | Vorzutäuschende Browser-Version gemäß Katalog. Bei mehreren Treffern gewinnt der neueste. |
profile |
string | Nein | - | Exakte Profil-ID aus GET /api/profiles anstelle der drei obigen Felder. |
validate |
object | Nein | - | Response-Validierungsregeln (siehe unten) |
Browser profiles
Standardmäßig verwendet ein Request das neueste Google Chrome. Manche Ziele akzeptieren einen bestimmten Browser und blockieren andere. Mit browser, os und version schränkst du einen Katalog vermessener Profile ein; profile wählt eines direkt per ID aus.
{
"method": "GET",
"url": "https://example.com",
"browser": "Firefox",
"os": "Windows"
}
Regeln:
- Die Auswahl erfordert
unblocker(standardmäßig aktiviert). Wennunblockerdeaktiviert ist, werden keine Browser-Header gesendet; der Request wird daher abgelehnt statt unvollständig angewendet. - Wenn mehrere Profile übereinstimmen, gewinnt die neueste Version.
- Eine Kombination, die der Katalog nicht bereitstellen kann, gibt einen Fehler zurück, der die verfügbaren Optionen nennt. Der Request wird niemals als anderer Browser gesendet.
- Dieselben vier Felder sind im
request-Objekt vonPOST /proxy/verfügbar.
GET /api/profiles gibt den vollständigen Katalog zurück und benötigt keinen API-Key:
{
"profiles": [
{ "id": "...", "browser": "Chrome", "version": "...", "os": "...", "osFamily": "macOS" }
],
"default": "..."
}
osFamily ist der Wert zum Filtern beim Erstellen eines Pickers; os behält den Release-Namen für die Anzeige.
Validierungsregeln
Mit dem Objekt validate kannst du Bedingungen für Erfolg und Fehler definieren. Wenn eine fail-Bedingung zutrifft, wird der Request als fehlgeschlagen gewertet. Wenn accept-Bedingungen festgelegt sind, werden nur übereinstimmende Responses als erfolgreich gewertet.
{
"validate": {
"status": { "accept": [200, 201], "fail": [403, 503] },
"headers": { "accept": {"content-type": "application/json"} },
"data": { "accept": ["product"], "fail": ["captcha", "blocked"] }
}
}
| Feld | Typ | Beschreibung |
|---|---|---|
validate.status.accept |
number[] | Zu akzeptierende HTTP-Statuscodes |
validate.status.fail |
number[] | Abzuweisende HTTP-Statuscodes |
validate.headers.accept |
object | Header-Schlüssel-Wert-Paare, die vorhanden sein müssen |
validate.headers.fail |
object | Header-Schlüssel-Wert-Paare, die einen Fehler auslösen |
validate.data.accept |
string[] | Zeichenketten, die im Response-Body enthalten sein müssen |
validate.data.fail |
string[] | Zeichenketten im Response-Body, die einen Fehler auslösen |
Beispiel
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": "...", "set-cookie": ["session=abc", "tracker=xyz"]}],
"data": "<!doctype html>...",
"total_time": 0.342,
"proxy": "A1B2C3"
}
Wenn das Ziel vor der Auslieferung des Body einen Bot-Check durchführt, enthält die Response auch ein defense-Objekt, das den Anbieter nennt und angibt, ob der Check bestanden wurde:
{
"status": 200,
"data": "<!doctype html>...",
"total_time": 3.61,
"defense": {
"vendor": "sgcaptcha",
"solved": true,
"present": ["sgcaptcha"],
"ms": 3412,
"cookie": "_I_=<clearance>"
}
}
| Feld | Typ | Beschreibung |
|---|---|---|
status |
number | HTTP-Statuscode des Ziels |
headers |
array | Ein Objekt pro Redirect-Hop. Jedes enthält ein Feld result mit der Statuszeile und allen Response-Headern. Multi-Value-Header (Set-Cookie, Link, WWW-Authenticate) werden als String-Arrays zurückgegeben. |
data |
string/object | Response-Body (JSON, wenn tryJsonData true ist) |
total_time |
number | Gesamte Request-Dauer in Sekunden |
proxy |
string | Encodierte ID des Proxys, über den der Request lief (nur wenn beim Request ein proxy übergeben wurde). Verwende sie bei Folgeaufrufen wieder, um denselben Exit festzuhalten. |
defense |
object | Vorhanden, wenn das Ziel bei diesem Request einen Bot-Check ausgeführt hat oder wenn ein Retry mit den Cookies der Website den Body geliefert hat. defense.solved gibt an, ob ein Check gelöst wurde, defense.retry gibt an, ob ein Retry den Inhalt geliefert hat. Siehe Site-Checks für alle Felder und die vollständige Liste der Systeme. |
error |
string | Fehlermeldung, falls der Request fehlgeschlagen ist |
Proxy Request
POST /api/proxy/
Leitet deinen Request über rotierende Proxys mit automatischem Retry bei Fehlern weiter. Die Auswahl kann optional auf bestimmte zielseitig sichtbare Exit-Länder eingeschränkt werden.
Request Body
| Parameter | Typ | Erforderlich | Standard | Beschreibung |
|---|---|---|---|---|
request |
object | Ja | - | Ein einzelner Request-Body (dieselben Felder wie bei Single Request oben) |
timeout_ms |
number | Nein | 45000 | Gesamt-Timeout für alle Versuche in ms (max: 120000) |
maxTries |
number | Nein | 5 | Maximale Proxy-Rotationsversuche (max: 90) |
ignoreProxies |
string[] | Nein | - | Proxy-IDs, die von der Rotation ausgeschlossen werden sollen (IDs aus vorherigen Responses verwenden) |
exitCountries |
string[] | Nein | - | Strikte Allowlist aus zweistelligen, zielseitig sichtbaren Ländercodes (z. B. ["CZ", "GB"]). Werte werden getrimmt, in Großbuchstaben umgewandelt und dedupliziert. Proxys mit unbekannten Exits werden ausgeschlossen und der Request weicht niemals auf ein nicht angefordertes Land aus. |
exitClass |
string | Nein | - | standard oder premium. premium erlaubt die Eskalation auf einen Premium-Exit, wenn der Standard-Pool bei einem geschützten Ziel scheitert. Erfordert einen Plan mit Premium-Exits. |
exitCountries-Scoping
Die Auswahl nutzt die neuesten verfügbaren zielseitig sichtbaren Ländermetadaten, die üblicherweise etwa alle zehn Minuten aktualisiert werden. Es handelt sich nicht um ein Live-Geolocation-Lookup während des Requests. Leite das bereitstellende Land nicht aus der Proxy-Hostadresse ab.
Wenn der aktuelle Pool keine Übereinstimmung für die angeforderten Länder hat, gibt die Response HTTP 200 mit einem Error-Envelope zurück:
{
"error": "No eligible proxy found for exit countries: CZ, GB",
"code": "no_eligible_proxy",
"details": { "exitCountries": ["CZ", "GB"] },
"total": 0.084
}
Behalte den angeforderten Scope bei und versuche es später erneut. Ändere oder erweitere ihn nur, wenn sich die Länderanforderung deines Workflows explizit ändert.
Beispiel
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,
"exitCountries": ["CZ", "GB"],
"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",
"exitCountry": "CZ",
"total": 2.341
}
| Feld | Typ | Beschreibung |
|---|---|---|
proxy |
string | Codierte Kennung des verwendeten Proxys. Verwende sie bei einem Single- oder Browser-Request wieder, indem du sie als Feld proxy übergibst, oder überspringe sie beim nächsten Proxy-Request via ignoreProxies. |
exitCountry |
string | Für das Ziel sichtbarer zweistelliger Ländercode des Proxys, der den Request verarbeitet hat. Nur vorhanden, wenn der Request exitCountries gesetzt hat. Prüfe immer, ob es sich um einen der von dir angeforderten Codes handelt, bevor du der Response vertraust. |
exitClass |
string | Gibt an, welche Exit-Klasse diesen Request verarbeitet hat. Bei erfolgreicher Response vorhanden, wenn der Request eine angegeben hat. premium bedeutet, dass ein Premium-Exit den Body zurückgegeben hat; standard bedeutet, dass dies der Standard-Pool war. Ein fehlgeschlagener Aufruf hat nichts verarbeitet und enthält daher kein exitClass; lies attemptReport aus, um zu erfahren, worauf die Versuche gestoßen sind. |
total |
number | Gesamte reale Laufzeit in Sekunden (Float). Beinhaltet Proxy-Auswahl, Retries und den erfolgreichen Versuch. total_time betrifft nur den inneren Request; total ist immer >= total_time. |
profile |
string | Das von der Rotation gewählte Browser-Profil. Nur vorhanden, wenn es nicht das von dir angeforderte war. Fehlt der Wert, wurde der Request exakt wie angegeben ausgeführt. Übergib die ID bei Folgeaufrufen als profile zurück, um den funktionierenden Browser beizubehalten. |
error |
string | Fehlermeldung, falls der Request fehlschlägt. Bei einem Scope-Miss ist code gleich no_eligible_proxy und details.exitCountries gibt den normalisierten Scope aus. |
attemptReport |
object | Bei jedem fehlgeschlagenen Proxy-Aufruf vorhanden. Zählt die aufgetretenen Probleme der Versuche, damit ein blockierter Pool, ein toter Pool und eine validate-Regel ohne Treffer nicht als derselbe Fehler gewertet werden. Siehe unten. |
Alle Response-Felder von Single Request sind ebenfalls enthalten, darunter defense: Ein Proxy-Versuch, der auf einen Bot-Check stößt, meldet dies genauso wie Single.
Warum ein Proxy-Aufruf fehlschlug
Download maxTry limit reached sieht unabhängig vom Ausgang der Versuche gleich aus, daher enthält jede fehlgeschlagene Proxy-Response neben dem Fehler ein attemptReport:
{
"error": "Download maxTry limit reached",
"attemptReport": {
"total": 25,
"noResponse": 0,
"defense": 0,
"contentRejected": 25,
"statusRejected": 0,
"other": 0,
"vendors": [],
"profilesTried": ["default"],
"summary": "25 attempt(s): 25 returned HTTP 200 with no defense present and were rejected only by your validate.data - the page was fetched, your content rule did not match it"
},
"total": 34.812
}
| Feld | Typ | Beschreibung |
|---|---|---|
total |
integer | Durchgeführte Versuche |
noResponse |
integer | Der Exit hat nie geantwortet, die Website wurde also nie erreicht |
defense |
integer | Die Website hat geantwortet und bei dieser Antwort wurde ein Bot-Check erkannt |
contentRejected |
integer | HTTP 200, kein Bot-Check, nur durch deine validate.data abgelehnt |
statusRejected |
integer | Die Website hat geantwortet, kein Bot-Check, durch deine validate.status abgelehnt |
other |
integer | Beantwortet und keines der oben genannten |
vendors |
string[] | Bot-Check-Anbieter, die an beliebiger Stelle im Task erkannt wurden |
profilesTried |
string[] | Browser-Profile, die der Task gesendet hat, in der Reihenfolge der ersten Verwendung. default bedeutet, dass dein Request unverändert gesendet wurde. |
summary |
string | Ein aus den Zählern erstellter Satz, sicher zu loggen |
Der String error bleibt unverändert, sodass ein Client, der darauf matcht, weiterhin funktioniert. Was bei jedem Zähler zu tun ist: Warum ein Proxy-Request keine Versuche mehr übrig hatte.
exitClass
Manche Ziele lehnen die Exits im Standard-Pool ab, egal wie viele probiert werden. exitClass: premium teilt Proxy mit, dass ein solcher Request zusätzlich zum Standard-Pool zu einem Premium-Exit eskaliert werden darf, anstatt nur innerhalb dieses Pools zu rotieren.
{
"exitClass": "premium",
"request": { "method": "GET", "url": "https://example.com/report" }
}
Drei Dinge solltest du wissen, bevor du den Request sendest.
Es ist ein Kontingent, keine Anweisung. Der Standard-Pool versucht weiterhin zuerst zu antworten und gewinnt meistens. Ein Premium-Exit schaltet sich erst ein, wenn der Pool ein kurzes Zeitbudget für den Request aufgebraucht hat oder das Ziel ihn sichtbar abgelehnt hat. Ein Request, den der Standard-Pool beantwortet, bevor ein Premium-Exit versucht wurde, gilt als normaler Erfolg und kostet dich keinen Premium-Traffic. Sobald ein Premium-Exit versucht wurde, zählt dessen Traffic wie unten beschrieben.
Die Response zeigt dir, was dich tatsächlich bedient hat. Wenn du eine Klasse angibst, liefert die Response exitClass zurück:
{
"status": 200,
"exitClass": "premium",
"proxy": "Y2QXVK",
"data": "..."
}
premium bedeutet, dass ein Premium-Exit den Body zurückgegeben hat. standard bedeutet, dass der Standard-Pool dies getan hat. Das ist auch die Antwort, wenn kein Premium-Exit bezogen werden konnte oder das in deinem Plan enthaltene Premium-Traffic-Kontingent (plus zusätzlich gekaufte Mengen) für den Abrechnungszeitraum aufgebraucht ist. Beides ist kein Fehler, und du kannst deinen Premium-Traffic pro Request statt über Monatswerte abgleichen. Derselbe Wert wird im X-FourA-Exit-Class Response-Header übertragen (siehe Response Headers).
Premium-Traffic wird auf Netzwerkebene gemessen. Ein Premium-Versuch zählt die gesendeten und empfangenen Bytes während der Übertragung über das Netzwerk, komprimiert und verschlüsselt, unabhängig davon, ob deine Seite zurückgegeben wurde. Ein Versuch, der noch lief, als ein anderer Exit geantwortet hat, wird sofort gestoppt und nicht gezählt. Premium-Traffic zählt zu deinem Premium-Kontingent und zu deiner gesamten Bandbreite: dieselben Bytes, doppelt ausgewiesen, nie summiert. Wenn ein Premium-Exit die Seite geliefert hat, entspricht sein Traffic dem gesamten Traffic des Requests, sodass die Seite nicht noch einmal als Standard-Traffic gezählt wird. Deine Seite Usage & Limits zeigt den Gesamttraffic, den Premium-Anteil daran und das Premium-Kontingent, an dem du gemessen wirst.
Das Weglassen des Felds ist nicht dasselbe wie das Senden von standard. Weglassen lässt die Entscheidung offen; das Senden von standard legt explizit fest, dass dieser Request niemals eskalieren darf. So hältst du einen bestimmten Job vollständig von Premium-Traffic fern.
Das Aufbrauchen des Kontingents ist kein Fehler. Ein Request mit premium funktioniert nach Verbrauch des Kontingents weiter: Der Standard-Pool bedient ihn und die Response meldet standard. Kein Job bricht wegen eines aufgebrauchten Kontingents ab.
exitClass: premium erfordert einen Plan mit Premium-Exits. In einem Plan ohne Premium-Exits verbraucht der Request niemals einen Premium-Exit: Er wird entweder mit 403 und X-FourA-Limit: plan_limit_premium abgelehnt (siehe Rate Limits) oder aus dem Standard-Pool mit exitClass: standard in der Response bedient. Fange beides ab.
Browser Profile Rotation
Proxy rotiert Exits. Wenn eine Website den von FourA präsentierten Browser statt des Exits ablehnt, wechselt Proxy zudem zu einer anderen Browser-Familie aus dem Katalog. Dabei wird kein zusätzlicher Versuch erzeugt: Die Rotation ändert nur, was ein Retry sendet, nicht, ob einer stattfindet.
Proxy speichert zudem temporär die Browser-Familie, die eine Website zuletzt akzeptiert hat. Ein späterer Aufruf derselben Website kann so direkt mit dieser Familie statt mit dem Standard beginnen. Die Response nennt sie in profile, genau wie jede durch die Rotation gewählte Familie.
Ein explizites profile, browser, os oder version in deinem inneren request wird nie überschrieben. Das gilt auch für Requests mit eigenem User-Agent- oder Cookie-Header, da eine Freigabe an die Signatur gebunden ist, mit der sie erlangt wurde.
Browser Request
POST /api/browser/
Öffnet deine URL in einer Chrome-Browser-Instanz. Die Seite lädt, JavaScript wird ausgeführt und du erhältst das vollständig gerenderte HTML sowie den Cookie-Jar.
Request Body
| Parameter | Typ | Erforderlich | Standard | Beschreibung |
|---|---|---|---|---|
url |
string | Ja | - | Ziel-URL |
headers |
object | Nein | - | Benutzerdefinierte Header als Key-Value-Paare |
cookies |
array | Nein | - | Zu setzende Cookies: [{name, value, domain?}] |
userAgent |
string | Nein | - | Benutzerdefinierter User-Agent-String |
unblocker |
boolean | Nein | true |
Schließt die Prüfung ab, die eine Seite vor dem Laden verlangt (eine Challenge-Seite oder ein ähnliches Gate). Standardmäßig aktiviert. Setze false, um die Rückgabe der Seite inklusive einer Challenge-Seite unverändert zu rendern. |
proxy |
string | Nein | - | Proxy-ID aus einer früheren Response, um denselben Exit beizubehalten. Übergib den opaken String unverändert zurück. Eine reine Proxy-Adresse wird mit 400 Invalid proxy format abgewiesen. |
exitCountry |
string | Nein | - | Zwei-Buchstaben-Ländercode (ISO 3166-1 alpha-2) des Landes, über das der Request ausgeht. Setzt die Browser-Uhr auf eine passende Zeitzone. Siehe Browser-Uhr an den Exit anpassen. |
timeout_ms |
number | Nein | 30000 | Timeout für das Laden der Seite in ms (max: 120000) |
checkStatus |
number | Nein | - | Erwarteter HTTP-Status (Request schlägt fehl, falls abweichend) |
checkText |
string | Nein | - | Text, der auf der gerenderten Seite vorkommen muss |
Browser-Uhr an den Exit anpassen
Eine Seite kann die Zeitzone des Browsers auslesen und mit dem Land der erkannten IP abgleichen. Eine Abweichung ist eines der einfachsten Signale für einen Bot-Detektor, und es kostet dich nichts, sie zu vermeiden.
Setze exitCountry auf das Land, über das dein Traffic ausgeht, und der Browser meldet eine dazu passende Zeitzone:
{
"url": "https://example.com",
"proxy": "A1B2C3",
"exitCountry": "BR"
}
Regeln:
- Der Wert ist das Exit-Land, also das Land, das das Ziel sieht, nicht der Host-Standort des Proxys. Beide weichen oft genug voneinander ab.
- Wenn du ihn weglässt, nutzt FourA das Exit-Land, sofern bekannt. Andernfalls bleibt die Browser-Uhr unverändert, anstatt zu raten.
- Ein Ländercode, den FourA nicht erkennt, wird wie ein weggelassenes Feld behandelt. Das ist kein Fehler.
- Nur die Uhr folgt dem Land.
Accept-Languageund der vom Server gelieferte Inhalt bleiben unberührt, sodass die Seite nicht unerwartet die Sprache wechselt.
Der Parameter userAgent
Sende userAgent und genau dieser String wird der Seite, ihren Workern und dem Ziel bereitgestellt. FourA leitet daraus auch die passenden Client Hints ab (sec-ch-ua, sec-ch-ua-platform, navigator.platform sowie die High-Entropy-Werte, die ein Detector namentlich abfragt). So behauptet der Request nicht einen Browser im Header und einen anderen in JavaScript.
Der userAgent in der Response ist der tatsächlich verwendete. Das ist wichtig beim Replay einer Clearance: Ein cf_clearance-Cookie ist an den Exit und den User-Agent gebunden, der ihn erhalten hat. Sende daher genau den String zurück, den die Response gemeldet hat, nicht den, von dem du glaubst, dass er verwendet wurde. Siehe Site checks.
Sendest du einen Nicht-Chromium-String (etwa einen Firefox-User-Agent), wird er unverändert übergeben, ohne angehängte Chromium-Brand-Liste.
Beispiel
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,
"defenses": {"present": ["cloudflare"], "cleared": ["cloudflare"]},
"proxy": "A1B2C3"
}
| Feld | Typ | Beschreibung |
|---|---|---|
status |
number | HTTP-Statuscode vom Ziel |
headers |
object | Response-Header |
body |
string or object | Vollständig gerenderter Seiteninhalt. String-HTML, wenn Content-Type HTML ist; Objekt, wenn die Seite JSON zurückgegeben hat und dieses automatisch geparst wurde. |
cookies |
array | Vollständige Cookie-Objekte der Seite. Jedes Cookie enthält name, value, domain, path, expires, httpOnly, secure, sameSite und weitere Cookie-Eigenschaften. |
userAgent |
string | Verwendeter Browser-User-Agent |
defenseSolved |
boolean | true, wenn bei diesem Aufruf ein Bot-Schutz erkannt und erfolgreich überwunden wurde. Andernfalls nicht vorhanden. Bestimmt, ob der Aufruf 5 oder 10 Credits kostet. |
defenses |
object | present listet alle beim Laden der Seite erkannten Anbieter auf, cleared listet diejenigen auf, deren Freigabe die finale Seite behält. Ein Anbieter kann in present auftauchen und nie in cleared. Siehe Site checks. |
proxy |
string | Encodierte ID des Proxys, über den der Request lief (nur wenn beim Request ein proxy übergeben wurde). Verwende sie bei Folgeaufrufen wieder, um denselben Exit beizubehalten. |
error |
string | Fehlermeldung, falls der Request fehlgeschlagen ist |
Einen Exit anheften
Ein proxy-Wert bei einem Single- oder Browser-Request heftet den Exit an, den ein vorheriger Aufruf verwendet hat. Übergib die opaque ID exakt so zurück, wie sie empfangen wurde, niemals eine Proxy-Adresse.
Drei Werte werden abgelehnt, alle mit einem 400:
| Fehler | Bedeutung |
|---|---|
Invalid proxy format |
Der Wert ist keine von FourA ausgestellte ID. Eine reine Proxy-Adresse führt hierher. |
Proxy not found |
Die ID wurde dekodiert, verweist aber nicht mehr auf einen aktiven Exit. Hole dir einen neuen über einen frischen Aufruf. |
Managed exit: this proxy id cannot be pinned to a request |
Der Exit existiert, wird von FourA aber nicht für einen benannten Request offengehalten. Die ID eines Premium-Exits führt hierher, wenn dein Plan kein Premium-Guthaben mehr hat. Verwende die Session wieder, mit der er zurückkam, oder führe den Aufruf über POST /api/proxy/ aus und nimm den Exit, der automatisch gewählt wird. |
Ein angehefteter Premium-Exit wird als Premium-Traffic abgerechnet. Die Response enthält X-FourA-Exit-Class: premium, damit du dies pro Request einsehen kannst, und der über den Exit geführte Traffic zählt sowohl für den Premium-Traffic auf deiner Seite Usage & Limits als auch für deine gesamte Bandbreite, unabhängig davon, ob die Website die gewünschte Seite zurückgegeben hat. Das Anheften erfordert Premium-Exits in deinem Plan sowie verbleibendes Kontingent; andernfalls wird die ID mit dem oben genannten Managed-Exit-400 abgelehnt.
HTTP-Statuscodes
| Code | Bedeutung |
|---|---|
| 200 | Request abgeschlossen (prüfe inneres status auf Ziel-Response) |
| 400 | Ungültiger Request-Body, Parameter, Ziel-IP in einem privaten/reservierten Bereich oder eine Proxy-ID, die nicht gepinnt werden kann |
| 401 | Fehlender oder ungültiger API-Key |
| 403 | Der Endpoint oder ein Parameter ist nicht in deinem Plan enthalten. X-FourA-Limit nennt ihn: plan_limit_feature oder plan_limit_premium. |
| 404 | Not Found: Unter diesem Pfad existiert kein Endpoint. |
| 413 | Der JSON-Request-Body ist größer als 100 KB. Die Antwort ist kein JSON und enthält kein X-FourA-Request-Id. |
| 429 | Ein Plan-Limit (X-FourA-Limit gesetzt) oder das geteilte Minutenkontingent der Plattform (kein Header) |
| 500 | Interner Serverfehler |
| 502 | Upstream unavailable. FourA hat seine Engine erreicht, aber die Antwort war unbrauchbar. Erneut versuchen. |
| 503 | Service vorübergehend deaktiviert oder ausgelastet, oder Backend service unavailable während eines Engine-Neustarts |
| 504 | Upstream timeout. Die Engine wurde nicht innerhalb des Zeitlimits für diesen Request fertig. Erhöhe timeout_ms oder versuche es erneut. |
Nächste Schritte
- Smart Fetch (Auto): Wann du FourA den Pfad wählen lassen solltest
- Den richtigen Endpoint wählen: Wann du Single, Proxy oder Browser manuell wählst
- Authentifizierung: Verwalte deine API-Keys
- Fehlerbehandlung: Fehler sauber behandeln
- Site-Checks: Lies das Feld
defenseaus und spiele eine Clearance erneut ab - Warum ein Proxy-Request keine Versuche mehr hatte: Lies
attemptReportaus und reagiere darauf - Rate Limits: Request-Limits verstehen
- Schnellstart: Dein erster Request in 30 Sekunden