API Endpoint 참조
request 파라미터 및 response 형식이 포함된 모든 FourA API endpoint 레퍼런스입니다.
Base URL
https://eu.api.foura.ai/api
인증
모든 request는 X-API-Key header에 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"}'
대시보드에서 API key를 생성하고 관리할 수 있습니다. 키에는 pk_live_ 접두사가 사용됩니다.
Response Headers
/api/*의 응답에는 두 개의 correlation header가 포함됩니다.
| Header | Value | Description |
|---|---|---|
X-FourA-Request-Id |
UUID | 요청에 할당된 고유 ID입니다. FourA가 본문을 전혀 읽을 수 없는 경우를 제외하고 4xx 및 5xx를 포함한 모든 응답에 반환됩니다. 400 Invalid JSON in request body 및 413은 ID가 할당되기 전에 거부됩니다. 사용자 측 로그에 기록하십시오. |
X-FourA-Credits |
integer | 이 요청에 사용된 크레딧입니다. 성공 여부와 관계없이 엔진에 도달한 모든 응답에 반환됩니다(작업이 수행되었으므로 청구됨). 엔진이 실행되기 전에 FourA가 거부한 호출(누락되었거나 유효하지 않은 키, 플랜 또는 플랫폼 제한, 거부된 대상 또는 proxy ID)에는 포함되지 않습니다. 과금 대상 결과에 대해서는 Request Outcomes를 참조하십시오. |
동일한 요청 ID가 대시보드의 Activity Log(24시간 동안 유지, 키당 최근 200개)에서 요청 및 응답 페이로드 미리보기의 키로 사용되므로, 나중에 정확한 요청을 조회하고 Activity에서 Playground로 직접 재생할 수 있습니다. 고객 지원팀에 문의할 때 이 ID를 포함하면 요청을 신속하게 식별할 수 있습니다.
$ 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
...
전체 목록과 사용 팁은 Response Headers를 참고하세요.
Endpoints
MCP를 통해 이 endpoint들을 사용하시나요?
@fouradata/mcpserver는 4개의 endpoint를 모두 네이티브 MCP 도구(foura_auto,foura_single,foura_proxy,foura_browser)로 래핑하여 동일한 입력 형태를 제공하며, 토큰 친화적인 대용량 응답 처리를 위한offload_large옵트인을 지원합니다.
FourA는 각각 다른 시나리오에 최적화된 4개의 request endpoint를 제공합니다.
| Endpoint | Best for |
|---|---|
POST /auto/ |
스마트 fetch. URL을 전달하면 FourA가 동작하는 가장 저렴한 경로(direct, rotated proxy 또는 browser)를 선택하고 호스트별 성공 경로를 기억합니다. |
POST /single/ |
빠른 HTTP request, 정적 페이지, API |
POST /proxy/ |
자동 proxy rotation이 적용된 보호 사이트, 대상 기준 국가 범위 지정(선택 사항) |
POST /browser/ |
JavaScript 렌더링 페이지, SPA |
GET /profiles |
single 및 proxy용 브라우저 프로필 카탈로그. 공개 endpoint이며 API key가 필요하지 않습니다. |
각 endpoint의 선택 기준에 대한 자세한 안내는 Choosing the Right Endpoint 및 Smart Fetch guide를 참고하세요.
Target URL Restrictions
사설, 루프백 또는 예약된 IP 범위(RFC 5735, RFC 6598, IPv6 예약 블록)로 확인되는 대상은 FourA에서 request를 전송하기 전에 400 오류와 함께 거부됩니다. 공개 호스트 이름과 IP만 전달됩니다.
{ "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/
URL과 선택적 validate 규칙을 전달합니다. FourA는 비용 인식 사다리 단계(저렴한 직접 프로브, 순환 proxy, 전체 브라우저)를 거치며 규칙에 부합하는 응답을 반환하는 첫 번째 단계에서 중단합니다. 동일한 호스트에 대한 반복 호출 시에는 웜 세션이 재사용되므로 두 번째 요청부터는 비용이 적게 듭니다.
재시도 횟수, 풀 크기, proxy 수를 직접 조정할 필요가 없습니다. FourA가 호스트별로 이를 학습합니다.
Request Body
| 매개변수 | 유형 | 필수 | 기본값 | 설명 |
|---|---|---|---|---|
url |
string | 예 | - | 대상 URL |
method |
string | 아니요 | "GET" |
HTTP 메서드 |
headers |
[string, string][] | 아니요 | - | [name, value] 쌍 형태의 커스텀 header |
data |
any | 아니요 | - | GET 이외의 요청을 위한 Request body |
validate |
object | 아니요 | - | 성공 기준이며, Single Request의 validate와 형태가 동일합니다(아래 참조). auto 모드가 챌린지 페이지와 실제 콘텐츠를 구분할 수 있도록 정상 페이지의 형태를 지정합니다. |
returnSession |
boolean | 아니요 | true |
/api/single/ 또는 /api/browser/을 통해 재사용할 수 있도록 응답에 성공한 세션 정보(proxy, cookies, userAgent)를 포함합니다. |
forceProxy |
boolean | 아니요 | true |
항상 순환 proxy를 통해 라우팅합니다. 대상 서버가 허용할 때 비용이 더 저렴한 직접 경로를 사용하려면 false로 설정합니다(일부 방어 시스템은 proxy 트래픽에 더 엄격합니다). |
timeout_ms |
integer | 아니요 | 120000 |
전체 호출에 대한 총 시간 예산(밀리초 단위)입니다. 모든 하위 시도는 이 시간 예산 내에서 실행됩니다. 최소 5000, 최대 180000. |
ignoreProxies |
string[] | 아니요 | - | 모든 하위 시도에서 제외할 proxy ID 목록입니다. 이전 /api/auto/ 또는 /api/proxy/ 응답에서 반환된 ID를 사용합니다. |
followRedirects |
integer | 아니요 | 5 |
저비용 사다리 단계에서 따를 최대 리디렉션 수입니다. 비활성화하려면 0로 설정합니다. 최대 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 상태 코드입니다. |
data |
string | 응답 본문 텍스트입니다. 어떤 rung에서 처리했든 텍스트로 반환됩니다. JSON 페이지는 JSON 텍스트로 반환되므로 직접 파싱해야 합니다. |
headers |
array or object | 대상 response header 목록입니다. Single 및 proxy rung은 홉별 header 객체 배열을 반환하며, browser rung은 평면 객체를 반환합니다. |
meta.rung |
string | 응답을 전달한 ladder rung입니다. 다음 중 하나입니다: probe (저비용 직접 request), proxy (rotating proxy), browser (전체 브라우저 렌더링), cache (웜 세션 재생), warmup (사이트 진입 페이지를 먼저 가져온 후 해당 cookie로 딥 URL 접근), fail (어떤 rung에서도 유효한 응답을 생성하지 못함). |
meta.solved |
boolean | 페이지에 추가 단계(challenge 페이지)가 필요했는지 및 이번 호출 중에 완료되었는지 여부입니다. |
meta.attempts |
number | 성공 전까지 시도한 하위 시도 횟수입니다. |
meta.credits |
number | 이번 호출에 사용된 총 크레딧입니다. X-FourA-Credits와 일치합니다. |
session.proxy |
string | 응답을 전달한 proxy의 인코딩된 ID입니다. Single 또는 Browser request에서 재사용할 수 있습니다. returnSession 값이 true일 때 포함됩니다. |
session.cookies |
array | 성공한 시도에서 얻은 cookie 목록입니다. returnSession 값이 true일 때 포함됩니다. |
session.userAgent |
string | 성공한 시도에 사용된 User-Agent입니다. returnSession 값이 true일 때 포함됩니다. |
error |
string | 호출 실패 시 오류 메시지입니다. |
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"]}}
}'
참고 사항
- Auto는 코디네이터입니다. 내부적으로 Single, Proxy 또는 Browser를 호출하고 각 하위 호출로 API 키를 전달합니다. Auto 호출은 하위 호출 크레딧의 합계와 함께 Activity Log 및 Overview에 단일 요청으로 기록됩니다. 하위 호출은 해당 호출 하위의 시도 내역으로 나열되며, 개별 요청으로 계산되지 않습니다.
- 실제 페이지만 포함하는 하위 문자열과 함께
validate.data.accept을 전달하십시오. 이 값이 없으면 Auto는 실제 200 응답과 상태 코드 200으로 반환된 챌린지 전면 페이지를 구별할 수 없습니다. timeout_ms는 전체 호출에 대한 상한을 설정합니다. 보호된 사이트에 대한 첫 콜드 요청은 수십 초가 걸릴 수 있지만, 재사용되는 웜 세션은 일반적으로 1초 미만으로 완료됩니다.
Single Request
POST /api/single/
실제 브라우저를 실행하지 않고 브라우저와 유사한 현실적인 네트워크 특성으로 HTTP 요청을 전송합니다. 가장 빠른 엔드포인트입니다.
Request Body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
method |
string | Yes | - | HTTP 메서드: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS |
url |
string | Yes | - | 대상 URL. 캐시 방지를 위해 현재 타임스탬프를 삽입하려면 URL 내 어디서든 {ts}를 사용하세요. |
headers |
[string, string][] | No | - | [name, value] 쌍 형태의 커스텀 헤더 |
unblocker |
boolean | No | true |
실제 브라우저 헤더(User-Agent, Sec-Ch-Ua, Sec-Fetch-*, Accept-Encoding) 전송 여부. 기본값은 활성화입니다. 일반 클라이언트 시그니처를 전송하려면 false로 설정하세요. |
timeout_ms |
number | No | 15000 | 전체 타임아웃(ms 단위, 최대: 120000) |
connect_timeout_ms |
number | No | 5000 | 연결 타임아웃(ms 단위) |
accept_timeout_ms |
number | No | 5000 | 수락 타임아웃(ms 단위, 연결 수락 대기 시간) |
server_response_timeout_ms |
number | No | 15000 | 서버 응답 타임아웃(ms 단위, 첫 바이트 대기 시간) |
dns_cache_timeout_sec |
number | No | 120 | DNS 캐시 TTL(초 단위, 최대: 240) |
followRedirects |
number | No | disabled | 따를 최대 리디렉션 수(0-20). 비활성화하려면 생략하세요. |
tryJsonData |
boolean | No | false | 가능한 경우 응답 본문을 JSON으로 파싱 |
returnBuffer |
boolean | No | false | 디코딩된 문자열 대신 원시 버퍼 반환 |
data |
any | No | - | 요청 본문(문자열 또는 객체, JSON으로 자동 직렬화됨) |
proxy |
string | No | - | 동일한 출구를 고정하기 위한 이전 응답의 프록시 ID. 불투명 문자열을 그대로 다시 전달하세요. 원시 프록시 주소는 400 Invalid proxy format 오류와 함께 거부됩니다. 일부 ID는 고정할 수 없습니다. Pinning an exit 항목을 참고하세요. |
browser |
string | No | Chrome | 표시할 브라우저: Chrome, Edge, Safari, Firefox 또는 Tor. Browser profiles 항목을 참고하세요. |
os |
string | No | - | 표시할 운영체제: Windows, macOS, Android 또는 iOS. 제품군 이름을 지정하면 해당 버전 전체를 허용합니다. |
version |
string | No | newest | 카탈로그에 나열된 표시할 브라우저 버전. 일치하는 항목이 여러 개이면 최신 버전이 우선합니다. |
profile |
string | No | - | 위 세 필드 대신 사용할 GET /api/profiles의 정확한 프로필 ID. |
validate |
object | No | - | 응답 검증 규칙(아래 참조) |
Browser profiles
기본적으로 요청은 최신 Google Chrome으로 표시됩니다. 대상에 따라 특정 브라우저만 허용하고 다른 브라우저는 거부할 수 있으므로, browser, os, version를 통해 측정된 프로필 카탈로그의 범위를 좁히고 profile로 ID를 직접 지정하여 선택합니다.
{
"method": "GET",
"url": "https://example.com",
"browser": "Firefox",
"os": "Windows"
}
규칙:
- 선택 기능을 사용하려면
unblocker설정이 필요합니다 (기본적으로 활성화됨).unblocker설정이 꺼져 있으면 브라우저 header가 전송되지 않으므로, 요청이 불완전하게 적용되는 대신 거부됩니다. - 여러 프로필이 일치하는 경우 최신 버전이 우선 적용됩니다.
- 카탈로그에서 제공할 수 없는 조합인 경우 사용 가능한 항목을 명시하는 오류를 반환합니다. 요청이 다른 브라우저로 전송되는 일은 절대 없습니다.
- 동일한 4개 필드를
POST /proxy/의request객체 내에서도 사용할 수 있습니다.
GET /api/profiles는 전체 카탈로그를 반환하며 API key가 필요하지 않습니다:
{
"profiles": [
{ "id": "...", "browser": "Chrome", "version": "...", "os": "...", "osFamily": "macOS" }
],
"default": "..."
}
osFamily은(는) 피커를 구성할 때 필터링할 값이며, os에는 표시용 릴리스 이름이 유지됩니다.
유효성 검사 규칙
validate 객체를 통해 성공 및 실패 조건을 정의할 수 있습니다. fail 조건이 일치하면 해당 request는 실패로 처리됩니다. accept 조건이 설정된 경우 일치하는 response만 성공으로 처리됩니다.
{
"validate": {
"status": { "accept": [200, 201], "fail": [403, 503] },
"headers": { "accept": {"content-type": "application/json"} },
"data": { "accept": ["product"], "fail": ["captcha", "blocked"] }
}
}
| 필드 | 타입 | 설명 |
|---|---|---|
validate.status.accept |
number[] | 허용할 HTTP 상태 코드 |
validate.status.fail |
number[] | 거부할 HTTP 상태 코드 |
validate.headers.accept |
object | 반드시 포함되어야 하는 헤더 키-값 쌍 |
validate.headers.fail |
object | 실패를 트리거하는 헤더 키-값 쌍 |
validate.data.accept |
string[] | 응답 본문에 반드시 포함되어야 하는 문자열 |
validate.data.fail |
string[] | 실패를 트리거하는 응답 본문 내 문자열 |
예시
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
}'
응답:
{
"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"
}
본문으로 이동하는 도중 대상이 봇 검사를 실행하면, 응답에 벤더 이름과 검사 통과 여부를 나타내는 defense 객체도 함께 포함됩니다.
{
"status": 200,
"data": "<!doctype html>...",
"total_time": 3.61,
"defense": {
"vendor": "sgcaptcha",
"solved": true,
"present": ["sgcaptcha"],
"ms": 3412,
"cookie": "_I_=<clearance>"
}
}
| 필드 | 타입 | 설명 |
|---|---|---|
status |
number | 타깃에서 반환된 HTTP 상태 코드 |
headers |
array | 리디렉션 홉당 하나의 객체. 각 객체에는 상태 라인과 모든 응답 헤더가 포함된 result 필드가 있습니다. 다중 값 헤더(Set-Cookie, Link, WWW-Authenticate)는 문자열 배열로 반환됩니다. |
data |
string/object | 응답 본문(tryJsonData가 true인 경우 JSON) |
total_time |
number | 총 요청 시간(초) |
proxy |
string | 요청이 통과한 프록시의 인코딩된 ID(요청에 proxy가 제공된 경우에만 해당). 동일한 출구를 고정하기 위해 후속 호출에서 재사용할 수 있습니다. |
defense |
object | 타깃이 이 요청에 대해 봇 검사를 실행했거나 사이트 자체 쿠키를 사용한 재시도로 본문을 가져온 경우 표시됩니다. defense.solved는 검사 통과 여부를 나타내며, defense.retry는 재시도로 콘텐츠를 가져왔는지 여부를 나타냅니다. 모든 필드 및 전체 시스템 목록은 Site checks를 참조하세요. |
error |
string | 요청 실패 시 오류 메시지 |
Proxy Request
POST /api/proxy/
실패 시 자동 재시도 기능과 함께 순환 프록시를 통해 요청을 라우팅합니다. 선택적으로 타깃에 표시되는 출구 국가 세트로 범위를 지정할 수 있습니다.
Request Body
| 매개변수 | 타입 | 필수 여부 | 기본값 | 설명 |
|---|---|---|---|---|
request |
object | 예 | - | 단일 요청 본문(위의 Single Request와 동일한 필드) |
timeout_ms |
number | 아니요 | 45000 | 모든 시도에 대한 전체 타임아웃(ms, 최대: 120000) |
maxTries |
number | 아니요 | 5 | 최대 프록시 순환 시도 횟수(최대: 90) |
ignoreProxies |
string[] | 아니요 | - | 순환에서 제외할 프록시 ID(이전 응답에서 반환된 ID 사용) |
exitCountries |
string[] | 아니요 | - | 타깃에 표시되는 두 자리 국가 코드의 엄격한 허용 목록(예: ["CZ", "GB"]). 값은 공백이 제거되고 대문자로 변환되며 중복이 제거됩니다. 출구를 알 수 없는 프록시는 제외되며 요청되지 않은 국가로 절대 폴백되지 않습니다. |
exitClass |
string | 아니요 | - | standard 또는 premium. premium는 보호된 타깃에서 표준 풀이 실패할 때 요청이 프리미엄 출구로 에스컬레이션되도록 허용합니다. 프리미엄 출구가 포함된 플랜이 필요합니다. |
exitCountries 범위 지정
선택 시 타깃에 표시되는 최신 국가 메타데이터가 사용되며, 일반적으로 약 10분 이내에 새로고침됩니다. 요청 중의 실시간 지리적 위치 조회가 아닙니다. 프록시 호스트 주소에서 서빙 국가를 유추하지 마세요.
현재 풀에 요청된 국가와 일치하는 항목이 없는 경우 응답은 오류 봉투와 함께 HTTP 200을 반환합니다.
{
"error": "No eligible proxy found for exit countries: CZ, GB",
"code": "no_eligible_proxy",
"details": { "exitCountries": ["CZ", "GB"] },
"total": 0.084
}
요청된 범위를 유지하고 나중에 다시 시도하십시오. 워크플로의 국가 요구사항이 명시적으로 변경될 때만 범위를 변경하거나 확장하십시오.
예시
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"
}
}'
응답:
{
"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
}
| 필드 | 타입 | 설명 |
|---|---|---|
proxy |
string | 사용된 proxy의 인코딩된 식별자입니다. Single 또는 Browser 요청에서 proxy 필드로 전달하여 재사용하거나, ignoreProxies를 통해 다음 Proxy 요청에서 건너뛸 수 있습니다. |
exitCountry |
string | 요청을 처리한 proxy의 대상 가시 2자리 국가 코드입니다. 요청 시 exitCountries를 설정한 경우에만 표시됩니다. 응답을 신뢰하기 전에 요청한 코드 중 하나인지 항상 확인하십시오. |
exitClass |
string | 요청을 처리한 exit 클래스이며, 요청에서 이를 지정했을 때 성공한 응답에 표시됩니다. premium는 premium exit가 본문을 반환했음을 의미하며, standard는 standard 풀이 반환했음을 의미합니다. 실패한 호출은 아무것도 처리하지 않으므로 exitClass를 포함하지 않습니다. 시도 중 발생한 상황은 attemptReport를 확인하십시오. |
total |
number | 초 단위의 외부 총 소요 시간(float)입니다. proxy 선택, 재시도 및 성공한 시도가 포함됩니다. total_time는 내부 요청 전용이며, total는 항상 total_time보다 크거나 같습니다. |
profile |
string | 로테이션이 선택한 브라우저 프로필이며, 요청한 프로필과 일치하지 않는 경우에만 표시됩니다. 표시되지 않는다면 요청이 작성된 그대로 전송되었음을 의미합니다. 정상 작동한 브라우저를 유지하려면 후속 호출 시 해당 id를 profile로 다시 전달하십시오. |
error |
string | 요청이 실패한 경우의 오류 메시지입니다. scope 누락 시 code는 no_eligible_proxy이며 details.exitCountries는 정규화된 scope를 반환합니다. |
attemptReport |
object | 실패한 모든 Proxy 호출에 표시됩니다. 차단된 풀, 비활성 풀, 일치하지 않는 validate 규칙이 모두 동일한 오류로 처리되지 않도록 시도 중 발생한 항목을 집계합니다. 아래를 참조하십시오. |
모든 Single Request 응답 필드도 포함되며, defense 역시 포함됩니다. 봇 감지에 걸린 proxy 시도는 Single과 동일한 방식으로 이를 보고합니다.
Proxy 호출이 실패한 이유
시도 결과와 관계없이 Download maxTry limit reached는 동일하게 표시되므로, 실패한 모든 Proxy 응답에는 오류와 함께 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
}
| Field | Type | Description |
|---|---|---|
total |
integer | 시도 횟수 |
noResponse |
integer | exit이 응답하지 않아 사이트에 도달하지 못함 |
defense |
integer | 사이트가 응답했으며 해당 응답에서 bot check가 감지됨 |
contentRejected |
integer | HTTP 200, bot check 없음, 사용자의 validate.data에 의해서만 거부됨 |
statusRejected |
integer | 사이트가 응답했고 bot check가 없었으나 사용자의 validate.status에 의해 거부됨 |
other |
integer | 응답을 받았으나 위의 어느 항목에도 해당하지 않음 |
vendors |
string[] | 작업 내에서 감지된 bot-check 벤더 목록 |
profilesTried |
string[] | 작업에서 전송한 브라우저 프로필 목록 (최초 사용 순서). default은 request가 수정 없이 전송되었음을 의미합니다. |
summary |
string | 개수를 기반으로 생성된 한 문장의 요약으로, 로그 기록에 안전함 |
error 문자열은 변경되지 않으므로 이를 매칭하는 클라이언트는 정상적으로 계속 동작합니다. 각 개수별 대처 방법: Proxy Request의 재시도 횟수가 소진된 이유.
exitClass
일부 대상 사이트는 시도 횟수와 관계없이 표준 풀의 exit을 거부합니다. exitClass: premium은 Proxy가 표준 풀 내에서만 순환하는 대신 해당 request를 표준 풀 외에 premium exit으로 승격할 수 있도록 지시합니다.
{
"exitClass": "premium",
"request": { "method": "GET", "url": "https://example.com/report" }
}
전송하기 전에 알아두어야 할 세 가지 사항이 있습니다.
이는 허용치일 뿐, 강제 명령이 아닙니다. 표준 풀이 여전히 응답을 먼저 시도하며 대개 더 빠릅니다. 프리미엄 exit는 풀이 request에 짧은 예산을 소진했거나 대상이 명시적으로 거부한 경우에만 참여합니다. 프리미엄 exit를 시도하기 전에 표준 풀이 응답한 request는 정상적인 성공으로 처리되며 프리미엄 트래픽 비용이 발생하지 않습니다. 프리미엄 exit가 시도되면 아래 설명과 같이 해당 트래픽이 계산됩니다.
response를 통해 실제로 응답한 대상을 확인할 수 있습니다. 클래스를 지정하면 response에 exitClass이 반환됩니다.
{
"status": 200,
"exitClass": "premium",
"proxy": "Y2QXVK",
"data": "..."
}
premium는 프리미엄 출구에서 본문을 반환했음을 의미합니다. standard는 표준 풀에서 반환했음을 의미하며, 프리미엄 출구를 확보하지 못했거나 플랜에 포함된 프리미엄 트래픽(및 추가 구매분)이 해당 결제 주기에 모두 소진되었을 때도 이 응답을 받습니다. 둘 다 오류가 아니며, 월별 수치 대신 요청별로 프리미엄 트래픽을 대조할 수 있습니다. 동일한 값이 X-FourA-Exit-Class 응답 헤더로 전달됩니다 (Response Headers 참조).
프리미엄 트래픽은 네트워크에서 측정됩니다. 프리미엄 시도는 페이지 반환 여부와 관계없이 네트워크를 통과할 때 압축 및 암호화된 송수신량을 측정합니다. 다른 출구가 응답하여 아직 실행 중이던 시도는 즉시 중단되며 계산에 포함되지 않습니다. 프리미엄 트래픽은 프리미엄 허용량과 총 대역폭 모두에 포함됩니다. 동일한 바이트가 두 번 보고되지만 합산되지는 않습니다. 프리미엄 출구가 페이지를 전달한 경우 해당 트래픽이 요청의 전체 트래픽이 되므로 해당 페이지가 표준 트래픽으로 중복 계산되지 않습니다. Usage & Limits 페이지에 총 트래픽, 프리미엄 점유율, 측정 기준이 되는 프리미엄 허용량이 표시됩니다.
필드를 생략하는 것은 standard를 전송하는 것과 다릅니다. 생략하면 결정을 명시하지 않는 상태로 유지됩니다. standard를 전송하면 이 요청을 절대 승격하지 않도록 명시적으로 지정하므로, 특정 작업을 프리미엄 트래픽에서 완전히 제외할 수 있습니다.
소진은 오류가 아닙니다. 허용량이 소진된 후 premium를 지정한 요청도 계속 작동합니다. 표준 풀에서 처리하며 응답에는 standard가 표시됩니다. 허용량 소진으로 인해 중단되는 작업은 없습니다.
exitClass: premium는 프리미엄 출구가 포함된 플랜이 필요합니다. 프리미엄 출구가 없는 플랜에서는 요청이 프리미엄 출구를 전혀 사용하지 않습니다. X-FourA-Limit: plan_limit_premium를 포함한 403으로 거부되거나 (Rate Limits 참조), 응답에 exitClass: standard가 포함되어 표준 풀에서 처리됩니다. 두 경우를 모두 처리하십시오.
Browser Profile Rotation
Proxy는 출구를 교체합니다. 사이트가 요청 출처 출구가 아닌 FourA가 제시한 브라우저를 거부하는 경우, Proxy는 카탈로그의 다른 브라우저 제품군으로도 전환합니다. 시도 횟수는 추가되지 않습니다. 교체는 재시도 시 전송되는 내용을 변경할 뿐 재시도 발생 여부를 변경하지 않습니다.
Proxy는 사이트가 최근에 수락한 제품군을 일정 시간 동안 기억하므로, 동일한 사이트에 대한 후속 호출 시 기본값 대신 해당 제품군으로 시작할 수 있습니다. 교체가 선택한 모든 제품군과 마찬가지로 응답의 profile에 해당 이름이 명시됩니다.
내부 request에 명시된 profile, browser, os 또는 version는 절대 재정의되지 않으며, 자체 User-Agent 또는 Cookie 헤더가 포함된 요청도 마찬가지입니다. 통과 권한은 이를 획득한 서명에 바인딩되기 때문입니다.
Browser Request
POST /api/browser/
Chrome 브라우저 인스턴스에서 URL을 엽니다. 페이지가 로드되고 JavaScript가 실행된 후 완전히 렌더링된 HTML과 cookie jar가 반환됩니다.
Request Body
| 매개변수 | 타입 | 필수 여부 | 기본값 | 설명 |
|---|---|---|---|---|
url |
string | 예 | - | 대상 URL |
headers |
object | 아니요 | - | 키-값 쌍 형태의 커스텀 header |
cookies |
array | 아니요 | - | 설정할 cookie 목록: [{name, value, domain?}] |
userAgent |
string | 아니요 | - | 커스텀 User-Agent 문자열 |
unblocker |
boolean | 아니요 | true |
페이지 로드 전에 요구되는 검사(챌린지 페이지 또는 유사한 게이트)를 완료합니다. 기본값으로 활성화되어 있습니다. 챌린지 페이지를 포함하여 페이지가 반환하는 내용을 그대로 렌더링하려면 false(으)로 설정하세요. |
proxy |
string | 아니요 | - | 동일한 출구 노드를 고정하기 위한 이전 응답의 proxy ID입니다. 불투명 문자열을 그대로 다시 전달하세요. 원시 proxy 주소는 400 Invalid proxy format 오류와 함께 거부됩니다. |
exitCountry |
string | 아니요 | - | 요청이 나가는 국가의 두 자리 국가 코드(ISO 3166-1 alpha-2)입니다. 브라우저의 시계를 일치하는 시간대로 설정합니다. 브라우저 시계를 출구 노드에 맞추기를 참조하세요. |
timeout_ms |
number | 아니요 | 30000 | 페이지 로드 제한 시간(ms 단위, 최대: 120000) |
checkStatus |
number | 아니요 | - | 예상 HTTP 상태 코드(다를 경우 요청 실패) |
checkText |
string | 아니요 | - | 렌더링된 페이지에 반드시 포함되어야 하는 텍스트 |
브라우저 시계를 출구 노드에 맞추기
페이지는 브라우저의 시간대를 읽어 감지된 IP의 국가와 비교할 수 있습니다. 불일치는 봇 탐지기가 사용하는 가장 간단한 신호 중 하나이며, 이를 제거하는 데 추가 비용은 들지 않습니다.
트래픽이 나가는 국가로 exitCountry를 설정하면 브라우저가 해당 국가에 속한 시간대를 보고합니다.
{
"url": "https://example.com",
"proxy": "A1B2C3",
"exitCountry": "BR"
}
규칙:
- 값은 프록시가 호스팅된 위치가 아니라 대상이 확인하는 국가인 출구(exit) 국가입니다. 두 위치는 실질적으로 다른 경우가 많습니다.
- 이 값을 생략하면 FourA는 출구 국가를 알고 있을 때 해당 국가를 사용하며, 그렇지 않은 경우 추측하는 대신 브라우저 시계를 그대로 둡니다.
- FourA가 인식하지 못하는 국가 코드는 필드를 생략한 것과 동일하게 처리됩니다. 오류로 처리되지 않습니다.
- 시계만 국가 설정을 따릅니다.
Accept-Language및 사이트에서 제공하는 콘텐츠는 변경되지 않으므로 페이지 언어가 갑자기 바뀌지 않습니다.
userAgent 매개변수
userAgent를 전송하면 페이지, 워커 및 대상 모두에 해당 문자열이 그대로 표시됩니다. FourA는 이 값에서 일치하는 client hints(sec-ch-ua, sec-ch-ua-platform, navigator.platform 및 탐지기가 이름으로 요청하는 고엔트로피 값)도 파생하므로, request가 header와 JavaScript에서 서로 다른 브라우저를 보고하지 않습니다.
response의 userAgent는 실제로 표시된 값입니다. 이는 clearance를 재생성할 때 중요합니다. cf_clearance cookie는 출구 및 이를 획득한 User-Agent에 바인딩되므로 사용되었다고 생각하는 문자열이 아니라 response가 보고한 문자열을 다시 보내야 합니다. Site checks를 참조하세요.
Chromium이 아닌 문자열(예: Firefox User-Agent)을 보내면 Chromium 브랜드 목록이 연결되지 않은 상태로 그대로 표시됩니다.
예제
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"
}'
응답:
{
"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"
}
| 필드 | 타입 | 설명 |
|---|---|---|
status |
number | 대상의 HTTP 상태 코드 |
headers |
object | 응답 헤더 |
body |
string or object | 완전히 렌더링된 페이지 콘텐츠. content-type이 HTML인 경우 문자열 HTML, 페이지가 JSON을 반환하여 자동 파싱된 경우 객체입니다. |
cookies |
array | 페이지의 전체 cookie 객체 목록. 각 cookie에는 name, value, domain, path, expires, httpOnly, secure, sameSite 및 기타 cookie 속성이 포함됩니다. |
userAgent |
string | 사용된 브라우저 User-Agent |
defenseSolved |
boolean | 이번 호출에서 봇 방어를 감지하고 성공적으로 우회한 경우 true입니다. 그렇지 않으면 생략됩니다. 호출 비용이 5크레딧인지 10크레딧인지 결정합니다. |
defenses |
object | present에는 페이지 로드 중에 인식된 모든 공급업체가 나열되고, cleared에는 최종 페이지가 우회 권한을 보유한 공급업체가 나열됩니다. 특정 공급업체가 present에 나타나고 cleared에는 전혀 나타나지 않을 수 있습니다. 사이트 검사를 참고하세요. |
proxy |
string | 요청이 통과한 프록시의 인코딩된 ID (요청 시 proxy가 제공된 경우에만 해당). 동일한 출구를 유지하기 위해 후속 호출에서 이를 재사용합니다. |
error |
string | 요청 실패 시 오류 메시지 |
출구 고정 (Pinning an Exit)
Single 또는 Browser 요청의 proxy 값은 이전 호출에서 사용된 출구를 고정합니다. 프록시 주소가 아닌, 전달받은 불투명 ID를 그대로 다시 전달해야 합니다.
다음 세 가지 값은 거부되며, 모두 400 오류를 반환합니다.
| 오류 | 의미 |
|---|---|
Invalid proxy format |
FourA가 발급한 ID가 아닙니다. 원시 프록시 주소를 입력하면 이 오류가 발생합니다. |
Proxy not found |
ID 디코딩에 성공했으나 더 이상 유효한 출구로 연결되지 않습니다. 새 호출을 통해 새로운 ID를 받으세요. |
Managed exit: this proxy id cannot be pinned to a request |
출구가 존재하지만 FourA가 지정된 요청을 위해 계속 열어둘 수 없는 상태입니다. 요금제에 남은 프리미엄 트래픽이 없을 때 프리미엄 출구 ID를 사용하면 이 오류가 발생합니다. 반환되었던 세션을 재사용하거나, POST /api/proxy/를 통해 호출을 실행하여 선택되는 출구를 사용하세요. |
고정된 프리미엄 출구는 프리미엄 트래픽으로 측정됩니다. 요청별로 확인할 수 있도록 응답에 X-FourA-Exit-Class: premium가 포함되며, 사이트에서 원하는 페이지를 반환했는지 여부와 관계없이 출구에서 처리된 트래픽은 총 대역폭뿐만 아니라 사용량 및 한도 페이지의 프리미엄 트래픽으로 집계됩니다. 고정 기능을 사용하려면 요금제에 프리미엄 출구가 포함되어 있고 잔여 허용량이 있어야 합니다. 그렇지 않으면 위의 managed-exit 400 오류와 함께 ID가 거부됩니다.
HTTP 상태 코드
| 코드 | 설명 |
|---|---|
| 200 | Request 완료 (대상 response는 내부 status 확인) |
| 400 | 유효하지 않은 request body, 파라미터, 사설/예약된 대역의 대상 IP, 또는 고정할 수 없는 proxy ID |
| 401 | 누락되었거나 유효하지 않은 API key |
| 403 | endpoint 또는 파라미터가 플랜에 포함되어 있지 않습니다. X-FourA-Limit에 명시됨: plan_limit_feature 또는 plan_limit_premium. |
| 404 | Not Found: 해당 경로에 endpoint가 없습니다. |
| 413 | JSON request body가 100 KB를 초과합니다. 응답은 JSON이 아니며 X-FourA-Request-Id를 포함하지 않습니다. |
| 429 | 플랜 제한(X-FourA-Limit 설정됨) 또는 플랫폼 공유 분당 허용량 초과(header 없음) |
| 500 | 내부 서버 오류 |
| 502 | Upstream unavailable. FourA가 엔진에 도달했으나 응답을 사용할 수 없습니다. 다시 시도하십시오. |
| 503 | 서비스가 일시적으로 비활성화되었거나 용량이 초과됨, 또는 엔진 재시작 중 Backend service unavailable 발생 |
| 504 | Upstream timeout. 엔진이 이 request의 제한 시간 내에 완료되지 않았습니다. timeout_ms 값을 늘리거나 다시 시도하십시오. |
다음 단계
- Smart Fetch (Auto): FourA가 자동으로 경로를 선택하도록 설정하는 시점
- 올바른 Endpoint 선택하기: Single, Proxy, Browser를 직접 선택하는 시점
- Authentication: API key 관리
- 오류 처리: 안정적인 오류 처리 방법
- 사이트 검사:
defense필드 확인 및 clearance 재현 - Proxy Request 시도 횟수가 초과된 이유:
attemptReport확인 및 조치 방법 - Rate Limits: request 제한 이해하기
- 빠른 시작: 30초 만에 첫 request 보내기