Referencia de endpoints de la API
Una referencia para todos los endpoints de la API de FourA con parámetros de request y formatos de response.
Base URL
https://eu.api.foura.ai/api
Autenticación
Cada request requiere tu API key en el header X-API-Key:
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"}'
Crea y gestiona claves de API en el Dashboard. Las claves usan el prefijo pk_live_.
Headers de respuesta
Las respuestas de /api/* incluyen dos headers de correlación:
| Header | Valor | Descripción |
|---|---|---|
X-FourA-Request-Id |
UUID | ID único asignado a la request. Se devuelve en cada respuesta, incluyendo 4xx y 5xx, excepto en un body que FourA no pueda leer en absoluto: 400 Invalid JSON in request body y 413 se rechazan antes de asignar un ID. Regístralo en tus logs. |
X-FourA-Credits |
entero | Créditos gastados en esta request. Se devuelve en cada respuesta que llegó a un motor, sea exitosa o fallida (el trabajo se realizó en ambos casos). Una llamada que FourA rechazó antes de que cualquier motor la ejecutara (una clave faltante o inválida, un límite de plan o plataforma, un ID de proxy o destino rechazado) no incluye ninguno. Consulta Resultados de la request para ver qué resultados son facturables. |
El mismo ID de request indexa la vista previa del payload de request y response en el Registro de actividad del Dashboard (se conserva 24 horas, las últimas 200 por clave), para que puedas buscar la request exacta más tarde y reproducirla desde Actividad directamente en el Playground. Inclúyelo cuando contactes a soporte y localizará la request en segundos.
$ 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
...
Consulta Response Headers para ver la lista completa y consejos de uso.
Endpoints
¿Usas estos endpoints mediante MCP? El servidor
@fouradata/mcpenvuelve los cuatro endpoints como herramientas MCP nativas (foura_auto,foura_single,foura_proxy,foura_browser) con las mismas estructuras de entrada, más una opciónoffload_largepara gestionar respuestas grandes optimizando el uso de tokens.
FourA ofrece cuatro endpoints de request, cada uno optimizado para un escenario diferente:
| Endpoint | Ideal para |
|---|---|
POST /auto/ |
Smart fetch. Envías una URL, FourA elige la ruta más económica que funcione (directa, proxy rotativo o browser) y recuerda lo que funciona por cada host. |
POST /single/ |
Requests HTTP rápidos, páginas estáticas, APIs |
POST /proxy/ |
Sitios protegidos con rotación automática de proxy, alcance opcional por país visible para el destino |
POST /browser/ |
Páginas renderizadas con JavaScript, SPAs |
GET /profiles |
El catálogo de perfiles de browser para single y proxy. Público, no requiere API key. |
Para ver un análisis detallado sobre cuál elegir en cada caso, consulta Choosing the Right Endpoint y la guía de Smart Fetch.
Restricciones de URL de destino
Los destinos que resuelven en rangos de IP privados, de loopback o reservados (RFC 5735, RFC 6598, bloques reservados de IPv6) se rechazan con un error 400 antes de que el request salga de FourA. Solo se reenvían hostnames e IPs públicos.
{ "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/
Pasas una URL más reglas opcionales de validate. FourA recorre una escala orientada a costos (sondeo directo económico, proxy rotado, navegador completo) y se detiene en el primer nivel que devuelve una respuesta aceptada por tus reglas. En llamadas repetidas al mismo host, se reproduce una sesión activa, haciendo que el segundo intento sea económico.
No necesitas ajustar reintentos, tamaños de grupos ni cantidad de proxies. FourA los aprende por host.
Request Body
| Parámetro | Tipo | Requerido | Por defecto | Descripción |
|---|---|---|---|---|
url |
string | Sí | - | URL de destino |
method |
string | No | "GET" |
Método HTTP |
headers |
[string, string][] | No | - | Headers personalizados como pares [nombre, valor] |
data |
any | No | - | Request body para requests que no sean GET |
validate |
object | No | - | Criterios de éxito, con la misma estructura que validate de Single Request (ver abajo). Indica a auto cómo es una página real para distinguir el contenido de una página de desafío. |
returnSession |
boolean | No | true |
Incluye la sesión ganadora (proxy, cookies, userAgent) en la respuesta para que puedas reproducirla mediante /api/single/ o /api/browser/. |
forceProxy |
boolean | No | true |
Enruta siempre a través de un proxy rotatorio. Establece false para permitir la ruta directa más económica cuando el destino lo permita (algunas defensas son más estrictas con el tráfico de proxy). |
timeout_ms |
integer | No | 120000 |
Presupuesto de tiempo total para toda la llamada, en milisegundos. Todos los subintentos se ejecutan dentro de este presupuesto. Mínimo 5000, máximo 180000. |
ignoreProxies |
string[] | No | - | IDs de proxy a evitar en cada subintento. Usa los IDs devueltos por respuestas previas de /api/auto/ o /api/proxy/. |
followRedirects |
integer | No | 5 |
Máximo de redirecciones a seguir en los niveles económicos de la escala. 0 para deshabilitar. Máximo 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..."
}
}
| Campo | Tipo | Descripción |
|---|---|---|
status |
number | Estado HTTP del objetivo. |
data |
string | Cuerpo de la respuesta como texto, sin importar qué nivel lo haya servido. Una página JSON se devuelve como texto JSON, por lo que debes parsearla tú mismo. |
headers |
array u object | Headers de respuesta del objetivo. Los niveles directos y de proxy devuelven un array de objetos de headers por salto; los niveles de navegador devuelven un objeto plano. |
meta.rung |
string | Nivel de la escala que entregó la respuesta. Uno de: probe (request directa económica), proxy (proxy rotativo), browser (renderizado completo de navegador), cache (sesión activa reutilizada), warmup (se obtuvo primero la página de entrada del sitio y sus cookies abrieron la URL profunda), o fail (ningún nivel produjo una respuesta aceptada). |
meta.solved |
boolean | Indica si la página necesitó un paso adicional (una página de desafío) y se completó durante esta llamada. |
meta.attempts |
number | Subintentos realizados antes de tener éxito. |
meta.credits |
number | Créditos totales gastados en esta llamada. Coincide con X-FourA-Credits. |
session.proxy |
string | ID codificado del proxy que entregó la respuesta. Reutilízalo en una request Single o Browser. Presente cuando returnSession es true. |
session.cookies |
array | Cookies del intento exitoso. Presente cuando returnSession es true. |
session.userAgent |
string | User-Agent utilizado en el intento exitoso. Presente cuando returnSession es true. |
error |
string | Mensaje de error si la llamada falló. |
Ejemplo
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"]}}
}'
Notas
- Auto es un coordinador. Llama a Single, Proxy o Browser internamente y reenvía tu API key a cada subllamada. La llamada Auto es una única request en tu Activity Log y en tu Overview, con la suma de los créditos de sus subllamadas; las subllamadas se listan debajo de ella como sus intentos y nunca cuentan como requests independientes.
- Pasa
validate.data.acceptcon una subcadena que solo la página real contenga. Sin esto, Auto no puede distinguir un 200 real de un intersticial de desafío devuelto con estado 200. timeout_mslimita toda la llamada. Un primer intento en frío a un sitio protegido puede tardar decenas de segundos; las sesiones activas reutilizadas suelen finalizar en menos de un segundo.
Single Request
POST /api/single/
Envía una HTTP request con características de red realistas similares a las de un navegador, sin levantar un navegador real. Este es el endpoint más rápido.
Request Body
| Parámetro | Tipo | Requerido | Por defecto | Descripción |
|---|---|---|---|---|
method |
string | Sí | - | Método HTTP: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS |
url |
string | Sí | - | URL de destino. Usa {ts} en cualquier parte de la URL para insertar la marca de tiempo actual y evitar la caché. |
headers |
[string, string][] | No | - | Headers personalizados como pares [nombre, valor] |
unblocker |
boolean | No | true |
Envía headers de navegador realistas (User-Agent, Sec-Ch-Ua, Sec-Fetch-*, Accept-Encoding). Activado por defecto. Establece false para enviar una firma de cliente básica. |
timeout_ms |
number | No | 15000 | Timeout total en ms (máx: 120000) |
connect_timeout_ms |
number | No | 5000 | Timeout de conexión en ms |
accept_timeout_ms |
number | No | 5000 | Timeout de aceptación en ms (tiempo de espera para la aceptación de la conexión) |
server_response_timeout_ms |
number | No | 15000 | Timeout de respuesta del servidor en ms (tiempo de espera para el primer byte) |
dns_cache_timeout_sec |
number | No | 120 | TTL de la caché DNS en segundos (máx: 240) |
followRedirects |
number | No | disabled | Número máximo de redirecciones a seguir (0-20). Omítelo para desactivar. |
tryJsonData |
boolean | No | false | Parsea el cuerpo de la respuesta como JSON si es posible |
returnBuffer |
boolean | No | false | Devuelve el buffer en bruto en lugar de la cadena decodificada |
data |
any | No | - | Cuerpo de la request (cadena u objeto, serializado automáticamente a JSON) |
proxy |
string | No | - | ID de proxy de una respuesta anterior para fijar la misma salida. Pasa de vuelta la cadena opaca exactamente igual. Una dirección de proxy en bruto se rechaza con 400 Invalid proxy format. Algunos IDs no se pueden fijar: consulta Fijar una salida. |
browser |
string | No | Chrome | Navegador a presentar: Chrome, Edge, Safari, Firefox o Tor. Consulta Perfiles de navegador. |
os |
string | No | - | Sistema operativo a presentar: Windows, macOS, Android o iOS. Un nombre de familia acepta cualquiera de sus versiones. |
version |
string | No | newest | Versión del navegador a presentar, según la lista del catálogo. Si coinciden varias, se usa la más reciente. |
profile |
string | No | - | ID exacto del perfil desde GET /api/profiles, en lugar de los tres campos anteriores. |
validate |
object | No | - | Reglas de validación de respuesta (ver más abajo) |
Perfiles de navegador
Por defecto, una request presenta el último Google Chrome. Algunos destinos aceptan un navegador y rechazan otro, por lo que browser, os y version filtran un catálogo de perfiles medidos, y profile selecciona uno por id.
{
"method": "GET",
"url": "https://example.com",
"browser": "Firefox",
"os": "Windows"
}
Reglas:
- La selección requiere
unblocker(activado por defecto). Conunblockerdesactivado no se envían headers de navegador, por lo que la request se rechaza en lugar de aplicarse a medias. - Cuando varios perfiles coinciden, se elige la versión más reciente.
- Una combinación que el catálogo no puede ofrecer devuelve un error indicando lo que está disponible. La request nunca se envía como un navegador diferente.
- Los mismos cuatro campos están disponibles dentro del objeto
requestdePOST /proxy/.
GET /api/profiles devuelve el catálogo completo y no necesita API key:
{
"profiles": [
{ "id": "...", "browser": "Chrome", "version": "...", "os": "...", "osFamily": "macOS" }
],
"default": "..."
}
osFamily es el valor para filtrar al compilar un selector; os mantiene el nombre de la versión para mostrarlo en pantalla.
Reglas de validación
El objeto validate te permite definir condiciones de éxito y error. Si coincide una condición fail, la request se trata como fallida. Si se definen condiciones accept, solo las responses que coincidan se tratarán como exitosas.
{
"validate": {
"status": { "accept": [200, 201], "fail": [403, 503] },
"headers": { "accept": {"content-type": "application/json"} },
"data": { "accept": ["product"], "fail": ["captcha", "blocked"] }
}
}
| Campo | Tipo | Descripción |
|---|---|---|
validate.status.accept |
number[] | Códigos de estado HTTP a aceptar |
validate.status.fail |
number[] | Códigos de estado HTTP a rechazar |
validate.headers.accept |
object | Pares clave-valor de headers que deben estar presentes |
validate.headers.fail |
object | Pares clave-valor de headers que provocan un fallo |
validate.data.accept |
string[] | Cadenas que deben aparecer en el cuerpo de la response |
validate.data.fail |
string[] | Cadenas en el cuerpo de la response que provocan un fallo |
Ejemplo
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"
}
Cuando el objetivo ejecuta una verificación de bots antes de entregar el body, la response también incluye un objeto defense que indica el proveedor y si se superó la verificación:
{
"status": 200,
"data": "<!doctype html>...",
"total_time": 3.61,
"defense": {
"vendor": "sgcaptcha",
"solved": true,
"present": ["sgcaptcha"],
"ms": 3412,
"cookie": "_I_=<clearance>"
}
}
| Campo | Tipo | Descripción |
|---|---|---|
status |
number | Código de estado HTTP devuelto por el destino |
headers |
array | Un objeto por cada salto de redirección. Cada uno incluye un campo result con la línea de estado y todos los response headers. Los headers con múltiples valores (Set-Cookie, Link, WWW-Authenticate) se devuelven como arrays de strings. |
data |
string/object | Response body (JSON si tryJsonData es true) |
total_time |
number | Tiempo total de la request en segundos |
proxy |
string | ID codificado del proxy utilizado para la request (solo cuando se proporcionó proxy en la request). Reutilízalo en llamadas posteriores para fijar la misma salida. |
defense |
object | Presente cuando el destino ejecutó una verificación de bots en esta request, o cuando un reintento con las cookies del propio sitio produjo el body. defense.solved indica si se superó una verificación, defense.retry indica si un reintento obtuvo el contenido. Consulta Site checks para ver todos los campos y la lista completa de sistemas. |
error |
string | Mensaje de error si la request falló |
Proxy Request
POST /api/proxy/
Enruta tu request a través de proxies rotatorios con reintento automático en caso de fallo. Opcionalmente, puedes limitar la selección a un conjunto de países de salida visibles para el destino.
Request Body
| Parámetro | Tipo | Obligatorio | Por defecto | Descripción |
|---|---|---|---|---|
request |
object | Sí | - | El body de una sola request (los mismos campos que en Single Request arriba) |
timeout_ms |
number | No | 45000 | Timeout general para todos los intentos en ms (máx: 120000) |
maxTries |
number | No | 5 | Número máximo de intentos de rotación de proxy (máx: 90) |
ignoreProxies |
string[] | No | - | IDs de proxy para excluir de la rotación (usa los IDs devueltos por respuestas previas) |
exitCountries |
string[] | No | - | Allowlist estricta de códigos de país de dos letras visibles por el destino (ej. ["CZ", "GB"]). Los valores se limpian de espacios, se convierten a mayúsculas y se deduplican. Los proxies con salidas desconocidas se excluyen y la request nunca recurre a un país no solicitado. |
exitClass |
string | No | - | standard o premium. premium permite que la request escale a una salida premium cuando el pool estándar tiene dificultades con un destino protegido. Requiere un plan que incluya salidas premium. |
Alcance de exitCountries
La selección utiliza los metadatos más recientes de país visible por el destino, que normalmente se actualizan en unos diez minutos. No es una búsqueda de geolocalización en tiempo real durante la request. No deduzcas el país emisor a partir de la dirección del host del proxy.
Si el pool actual no tiene coincidencias para los países solicitados, la respuesta devuelve HTTP 200 con un contenedor de error:
{
"error": "No eligible proxy found for exit countries: CZ, GB",
"code": "no_eligible_proxy",
"details": { "exitCountries": ["CZ", "GB"] },
"total": 0.084
}
Conserva el scope solicitado y reintenta más tarde. Cámbialo o amplíalo solo cuando el requisito de país de tu flujo de trabajo cambie explícitamente.
Ejemplo
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
}
| Campo | Tipo | Descripción |
|---|---|---|
proxy |
string | Identificador codificado del proxy utilizado. Reutilízalo en una request Single o Browser pasándolo como el campo proxy, u omítelo en la siguiente request Proxy mediante ignoreProxies. |
exitCountry |
string | Código de país de dos letras visible para el destino del proxy que atendió la request. Solo está presente cuando la request configuró exitCountries. Verifica siempre que sea uno de los códigos que solicitaste antes de confiar en la response. |
exitClass |
string | Clase de salida que atendió esta request, presente en una response exitosa cuando la request especificó una. premium significa que una salida premium devolvió el cuerpo; standard significa que lo hizo el pool estándar. Una llamada fallida no atendió nada, por lo que no incluye exitClass; consulta su attemptReport para ver con qué se encontraron los intentos. |
total |
number | Duración total transcurrida en segundos (float). Incluye la selección de proxy, los reintentos y el intento exitoso. total_time corresponde únicamente a la request interna; total siempre es >= total_time. |
profile |
string | El perfil de navegador que eligió la rotación, presente solo cuando no fue el que solicitaste. Su ausencia significa que la request se envió exactamente como se indicó. Devuelve el id como profile en llamadas posteriores para mantener el navegador que funcionó. |
error |
string | Mensaje de error si la request falló. Si no coincide el scope, code es no_eligible_proxy y details.exitCountries refleja el scope normalizado. |
attemptReport |
object | Presente en cada llamada Proxy fallida. Cuenta los problemas con los que se encontraron los intentos, evitando que un pool bloqueado, un pool inactivo o una regla validate que nunca coincidió se interpreten como el mismo error. Consulta a continuación. |
También se incluyen todos los campos de response de Single Request, entre ellos defense: un intento de proxy que encontró una verificación de bot lo reporta del mismo modo que Single.
Por qué falló una llamada Proxy
Download maxTry limit reached devuelve lo mismo sin importar el resultado de los intentos, por lo que cada response de Proxy fallida incluye un attemptReport junto al error:
{
"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
}
| Campo | Tipo | Descripción |
|---|---|---|
total |
integer | Intentos realizados |
noResponse |
integer | La salida nunca respondió, por lo que nunca se alcanzó el sitio |
defense |
integer | El sitio respondió y se reconoció una verificación de bots en esa respuesta |
contentRejected |
integer | HTTP 200, sin verificación de bots, rechazado únicamente por tu validate.data |
statusRejected |
integer | El sitio respondió, sin verificación de bots, rechazado por tu validate.status |
other |
integer | Respondió, y ninguno de los anteriores |
vendors |
string[] | Proveedores de verificación de bots reconocidos en cualquier parte de la tarea |
profilesTried |
string[] | Perfiles de navegador enviados por la tarea, en orden de primer uso. default significa que tu request salió sin modificaciones. |
summary |
string | Una sola frase generada a partir de los recuentos, segura para registrar en logs |
El string error no cambia, por lo que un cliente que coincida con él seguirá funcionando. Qué hacer con cada recuento: Por qué un Proxy Request se quedó sin intentos.
exitClass
Algunos destinos rechazan las salidas del pool estándar sin importar cuántas se intenten. exitClass: premium le indica a Proxy que puede escalar dicha request a una salida premium además del pool estándar, en lugar de rotar únicamente dentro de él.
{
"exitClass": "premium",
"request": { "method": "GET", "url": "https://example.com/report" }
}
Vale la pena saber tres cosas antes de enviarlo.
Es una autorización, no una instrucción. El pool estándar sigue compitiendo por la respuesta y suele ganar. Una salida premium solo interviene cuando el pool ha consumido un presupuesto breve en la request o el destino la ha rechazado visiblemente. Una request que el pool estándar responde antes de que se haya intentado cualquier salida premium es un éxito normal y no te cuesta tráfico premium. Una vez que se prueba una salida premium, su tráfico cuenta, como se describe a continuación.
La response te dice qué te atendió realmente. Cuando defines una clase, la response devuelve exitClass:
{
"status": 200,
"exitClass": "premium",
"proxy": "Y2QXVK",
"data": "..."
}
premium significa que una salida premium devolvió el cuerpo. standard significa que lo hizo el pool estándar, que es la respuesta que también obtienes cuando no se pudo obtener una salida premium y cuando el tráfico premium incluido en tu plan (más cualquier compra adicional) se ha agotado para el periodo de facturación. Ninguno de los dos es un error, y puedes conciliar tu tráfico premium con estos valores por request en lugar de hacerlo contra una cifra mensual. El mismo valor viaja en el header de response X-FourA-Exit-Class (consulta Response Headers).
El tráfico premium se mide en la red. Un intento premium contabiliza lo enviado y recibido al cruzar la red, comprimido y cifrado sobre la marcha, devuelva o no tu página. Un intento que aún se estaba ejecutando cuando otra salida respondió se detiene de inmediato y no se contabiliza. El tráfico premium cuenta para tu límite premium y también dentro de tu ancho de banda total: son los mismos bytes, reportados dos veces, nunca sumados entre sí. Cuando una salida premium entrega la página, su tráfico representa todo el tráfico del request, por lo que la página no se vuelve a contar como tráfico estándar. Tu página de Uso y Límites muestra el tráfico total, la porción premium del mismo y el límite premium contra el que se te mide.
Omitir el campo no es lo mismo que enviar standard. Omitirlo deja la decisión sin definir; enviar standard indica explícitamente que este request nunca debe escalar, que es la forma de mantener un trabajo específico completamente fuera del tráfico premium.
Agotar el límite no es un error. Un request que especifica premium después de haber agotado el límite sigue funcionando: el pool estándar lo atiende y la response indica standard. Ningún trabajo se detiene por un límite agotado.
exitClass: premium requiere un plan que incluya salidas premium. En un plan que no las incluye, el request nunca consume una salida premium: se rechaza con un 403 que incluye X-FourA-Limit: plan_limit_premium (consulta Rate Limits) o se atiende desde el pool estándar con exitClass: standard en la response. Gestiona ambos casos.
Browser Profile Rotation
Proxy rota las salidas. Cuando un sitio rechaza el navegador que FourA presentó en lugar de la salida de la que provino, Proxy también cambia a otra familia de navegadores del catálogo. No añade ningún intento: la rotación cambia lo que envía un reintento, nunca si este se produce o no.
Proxy también recuerda, durante un tiempo, la familia que un sitio aceptó por última vez, para que una llamada posterior al mismo sitio pueda comenzar con esa familia en lugar de la predeterminada. La response la nombra en profile, como hace con cualquier familia elegida por la rotación.
Un valor explícito de profile, browser, os o version en tu request interno nunca se sobrescribe, como tampoco se sobrescribe un request que lleve su propio header User-Agent o Cookie, porque una autorización está vinculada a la firma que la obtuvo.
Browser Request
POST /api/browser/
Abre tu URL en una instancia del navegador Chrome. La página se carga, JavaScript se ejecuta y obtienes el HTML completamente renderizado junto con el cookie jar.
Request Body
| Parámetro | Tipo | Requerido | Predeterminado | Descripción |
|---|---|---|---|---|
url |
string | Sí | - | URL de destino |
headers |
object | No | - | Headers personalizados como pares clave-valor |
cookies |
array | No | - | Cookies para configurar: [{name, value, domain?}] |
userAgent |
string | No | - | Cadena de User-Agent personalizada |
unblocker |
boolean | No | true |
Completa la comprobación que solicita una página antes de cargarse (una página de desafío o un filtro similar). Activado por defecto. Establece false para renderizar lo que devuelva la página, incluida una página de desafío, tal como llegó. |
proxy |
string | No | - | ID de proxy de una respuesta anterior, para fijar la misma salida. Devuelve la cadena opaca textualmente. Una dirección de proxy sin procesar se rechaza con 400 Invalid proxy format. |
exitCountry |
string | No | - | Código de país de dos letras (ISO 3166-1 alpha-2) del país por el que sale la request. Ajusta el reloj del navegador a una zona horaria coincidente. Consulta Ajustar el reloj del navegador a la salida. |
timeout_ms |
number | No | 30000 | Tiempo de espera de carga de la página en ms (máx.: 120000) |
checkStatus |
number | No | - | Estado HTTP esperado (la request falla si es diferente) |
checkText |
string | No | - | Texto que debe aparecer en la página renderizada |
Ajustar el reloj del navegador a la salida
Una página puede leer la zona horaria del navegador y compararla con el país de la IP que detecta. Una discrepancia es una de las señales más sencillas que tiene un detector de bots, y no te cuesta nada eliminarla.
Configura exitCountry con el país por el que sale tu tráfico y el navegador reportará una zona horaria correspondiente:
{
"url": "https://example.com",
"proxy": "A1B2C3",
"exitCountry": "BR"
}
Reglas:
- El valor es el país de salida, es decir, el país que ve el destino, no donde está alojado el proxy. Ambos difieren con suficiente frecuencia como para importar.
- Si lo omites, FourA usa el país de salida cuando lo conoce y, de lo contrario, no modifica el reloj del navegador en lugar de adivinar.
- Un código de país que FourA no reconoce se trata igual que omitir el campo. No es un error.
- Solo el reloj sigue al país.
Accept-Languagey el contenido que sirve el sitio no se modifican, por lo que la página no cambiará de idioma inesperadamente.
El parámetro userAgent
Envía userAgent y esa cadena exacta será lo que vean la página, sus workers y el destino. FourA también deriva de ella los client hints correspondientes (sec-ch-ua, sec-ch-ua-platform, navigator.platform y los valores de alta entropía que un detector solicita por nombre), evitando que la request declare un navegador en el header y otro en JavaScript.
El userAgent en la response es el que se presentó. Esto importa cuando reproduces una autorización: una cookie cf_clearance está vinculada a la salida y al User-Agent que la obtuvo, así que reenvía la cadena que reportó la response, no la que crees que se usó. Consulta Site checks.
Si envías una cadena que no sea de Chromium (por ejemplo, un User-Agent de Firefox), se presenta tal cual, sin ninguna lista de marcas de Chromium adjunta.
Ejemplo
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"
}'
Respuesta:
{
"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"
}
| Campo | Tipo | Descripción |
|---|---|---|
status |
number | Código de estado HTTP del destino |
headers |
object | Headers de la respuesta |
body |
string or object | Contenido de la página renderizado por completo. String HTML cuando el content-type es HTML; object cuando la página devolvió JSON y fue parseado automáticamente. |
cookies |
array | Objetos cookie completos de la página. Cada cookie incluye name, value, domain, path, expires, httpOnly, secure, sameSite y otras propiedades de cookie. |
userAgent |
string | User-Agent del navegador utilizado |
defenseSolved |
boolean | true si se encontró una protección antibot y se superó exitosamente en esta llamada. Ausente en caso contrario. Determina si la llamada cuesta 5 o 10 créditos. |
defenses |
object | present lista todos los proveedores reconocidos durante la carga de la página, cleared lista aquellos cuya autorización conserva la página final. Un proveedor puede aparecer en present y nunca en cleared. Consulta Comprobaciones del sitio. |
proxy |
string | ID codificado del proxy por el que pasó la solicitud (solo cuando se proporcionó un proxy en la solicitud). Reutilízalo en llamadas posteriores para mantener la misma salida. |
error |
string | Mensaje de error si la solicitud falló |
Fijar una salida
Un valor proxy en una solicitud Single o Browser fija la salida que utilizó una llamada anterior. Devuelve el ID opaco exactamente como llegó, nunca una dirección de proxy.
Se rechazan tres valores, todos con un 400:
| Error | Significado |
|---|---|
Invalid proxy format |
El valor no es un ID emitido por FourA. Una dirección de proxy sin procesar cae aquí. |
Proxy not found |
El ID se decodificó, pero ya no resuelve a una salida activa. Obtén uno nuevo desde una llamada nueva. |
Managed exit: this proxy id cannot be pinned to a request |
La salida existe, pero no es una que FourA mantendrá abierta para una solicitud específica. El ID de una salida premium cae aquí cuando tu plan no tiene tráfico premium restante disponible. Reutiliza la sesión en la que se devolvió o ejecuta la llamada a través de POST /api/proxy/ y toma la salida que elija. |
Una salida premium fijada se tarifa como tráfico premium. La respuesta incluye X-FourA-Exit-Class: premium para que puedas verlo por solicitud, y el tráfico que cursó la salida cuenta para el tráfico premium en tu página de Uso y límites así como para tu ancho de banda total, independientemente de si el sitio devolvió la página deseada o no. Fijar salidas requiere salidas premium en tu plan y cuota disponible; de lo contrario, el ID se rechaza con el 400 de salida administrada mencionado arriba.
Códigos de estado HTTP
| Código | Significado |
|---|---|
| 200 | Request completado (revisa el status interno para ver la response de destino) |
| 400 | Request body o parámetros no válidos, IP de destino en un rango privado/reservado, o un proxy ID que no se puede fijar |
| 401 | API key faltante o no válida |
| 403 | El endpoint o un parámetro no está en tu plan. X-FourA-Limit lo especifica: plan_limit_feature o plan_limit_premium. |
| 404 | Not Found: no existe ningún endpoint en esa ruta. |
| 413 | El JSON request body supera los 100 KB. La respuesta no es JSON y no contiene X-FourA-Request-Id. |
| 429 | Un límite de plan (X-FourA-Limit definido) o el límite compartido por minuto de la plataforma (sin header) |
| 500 | Error interno del servidor |
| 502 | Upstream unavailable. FourA se conectó con su motor pero la respuesta no fue utilizable. Reintenta. |
| 503 | Servicio deshabilitado temporalmente o al límite de capacidad, o Backend service unavailable mientras se reinicia un motor |
| 504 | Upstream timeout. El motor no terminó dentro del tiempo límite para este request. Aumenta timeout_ms o reintenta. |
Próximos pasos
- Smart Fetch (Auto): Cuándo dejar que FourA elija la ruta por ti
- Elegir el endpoint correcto: Cuándo elegir Single, Proxy o Browser manualmente
- Autenticación: Administra tus API keys
- Manejo de errores: Maneja errores de forma controlada
- Verificaciones del sitio: Lee el campo
defensey reproduce una autorización - Por qué un request por proxy agotó los intentos: Lee
attemptReporty actúa en consecuencia - Rate Limits: Comprende los límites de requests
- Inicio rápido: Tu primer request en 30 segundos