자주 발생하는 문제
FourA API 사용 시 가장 자주 발생하는 문제에 대한 해결 방법입니다.
비어 있거나 불완전한 콘텐츠
증상: API가 200 상태 코드를 반환하지만 data 필드가 비어 있거나 예상된 콘텐츠가 누락되어 있습니다.
원인: 대상 페이지가 초기 페이지 로드 후 JavaScript를 사용하여 콘텐츠를 렌더링합니다.
해결 방법: 단일 endpoint에서 브라우저 endpoint로 전환하십시오. checkText를 사용하여 콘텐츠가 로드되었는지 확인합니다.
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/products",
"timeout_ms": 15000,
"checkText": "product-list"
}'
참고: 브라우저 endpoint는 콘텐츠를 data가 아닌 body 필드로 반환합니다.
403 Forbidden 또는 검증 페이지
증상: API가 검증 페이지 또는 접근 거부 페이지가 포함된 HTML을 반환합니다.
원인: 대상 사이트에서 request를 자동화된 것으로 감지하여 차단했습니다.
해결 방법: 자동 IP 순환을 위해 proxy endpoint를 사용하세요:
curl -X POST https://eu.api.foura.ai/api/proxy/ \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"maxTries": 5,
"request": {
"method": "GET",
"url": "https://example.com/prices",
"unblocker": true
}
}'
문제가 지속되면 maxTries 값을 늘려 proxy 순환 재시도 횟수를 늘리십시오.
대상 서버가 반환한 403은 body 내에 status: 403이 포함된 HTTP 200으로 수신됩니다. X-FourA-Limit header를 포함하여 호출 자체에서 발생하는 403은 다른 문제입니다. 자세한 내용은 플랜에 포함되지 않은 403 오류를 참고하십시오.
Timeout 오류
증상: timeout 오류와 함께 request가 실패합니다.
원인: 대상 페이지를 로드하는 데 설정된 timeout보다 오랜 시간이 걸립니다.
해결 방법: timeout_ms 값을 늘리십시오(기본값: 단일 15초, browser 30초, proxy 45초).
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://slow-site.com",
"timeout_ms": 60000
}'
브라우저 request의 경우 checkText 값이 페이지에 실제로 표시되는지 확인하십시오. 오타가 있으면 checkText:<your text> not found 오류와 함께 호출이 실패합니다.
403 Not in Your Plan
증상: API가 X-FourA-Limit header 및 plan_limit_feature 또는 plan_limit_premium의 reason와 함께 403을 반환합니다.
{
"error": "Geo targeting (the exitCountries parameter) is not included in your plan (Free). Remove the parameter or upgrade.",
"reason": "plan_limit_feature",
"documentation": "https://foura.ai/prices"
}
원인: 현재 플랜에 호출한 endpoint 또는 전송한 parameter가 포함되어 있지 않습니다. plan_limit_feature에는 제외된 endpoint 및 geo targeting이 없는 exitCountries가 해당되며, plan_limit_premium에는 프리미엄 출구가 없는 exitClass: premium가 해당됩니다. 대상 서버에는 연결되지 않았으며, 크레딧도 차감되지 않았습니다.
해결 방법: parameter를 제거하거나, 플랜에 포함된 endpoint를 호출하거나, 플랜을 업그레이드하세요. 플랜에 포함된 항목은 Usage & Limits의 Limits & Features 탭에서 확인할 수 있습니다. 변경 없이 재시도하지 마세요. 대기해도 결과가 달라지지 않으므로 Retry-After 헤더가 설정되지 않습니다.
429 Too Many Requests
증상: API가 429를 반환합니다.
원인: 두 가지 검사 중 하나에서 호출을 거부했으며, response를 통해 원인을 확인할 수 있습니다. X-FourA-Limit 헤더가 포함되어 있다면 플랜의 제한(해당 endpoint의 동시 request 수 또는 분당 request 수, 일일 Browser request 수, 또는 청구 주기의 크레딧/대역폭) 중 하나에 도달한 것입니다. 해당 헤더가 없다면 해당 서비스에 대한 플랫폼의 공유 분당 허용량이 초과된 것이며, 이는 사용자의 트래픽이 아닌 FourA의 전체 트래픽과 관련된 문제입니다.
해결 방법: 먼저 X-FourA-Limit를 확인하세요. 제한 해제까지 몇 초 남지 않았다면 대기하고, 그렇지 않다면 중단하세요. 대기로 해결되는 플랜 제한의 경우 대기 시간(초)이 Retry-After 헤더 및 retry_after_seconds에 표시되며, 공유 제한의 경우 retryAfter에 표시됩니다.
import time
import requests
# Plan limits that come back in hours or days, not seconds.
STOP_ON = {"plan_limit_browser_daily", "plan_limit_credits", "plan_limit_bandwidth"}
def make_request(endpoint_url, payload, retries=3):
for i in range(retries):
resp = requests.post(
endpoint_url,
headers={"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"},
json=payload
)
if resp.status_code == 429:
limit = resp.headers.get("X-FourA-Limit")
if limit in STOP_ON:
raise Exception(f"stopped by {limit}: {resp.json().get('error')}")
header = resp.headers.get("Retry-After")
body = resp.json()
wait = (
int(header) if header and header.isdigit()
else body.get("retry_after_seconds") or body.get("retryAfter") or 2 ** i
)
time.sleep(wait)
continue
return resp
raise Exception("Rate limit not resolved after retries")
# Example: single request
make_request(
"https://eu.api.foura.ai/api/single/",
{"method": "GET", "url": "https://example.com"}
)
header에 plan_limit_concurrency 또는 plan_limit_rate가 표시된 경우, 재시도를 반복하기보다 동시 호출 수와 분당 시작 호출 수를 제한하는 것이 해결책입니다. 거부된 배치를 즉시 다시 보내면 전체 배치가 다시 거부됩니다. 거부된 호출은 분당 한도에 포함되지 않지만, 해당 한도의 2배를 초과하여 계속 유입되면 거부가 쿨다운으로 전환됩니다. 429 body에 cooldown: true가 포함되고 30초 동안 일시 중지(retry_after_seconds: 30)하도록 요청합니다. 병렬로 요청 실행에 해당 패턴이 안내되어 있으며, 대시보드의 사용량 및 한도에서 제한 한도와 함께 실시간 카운터를 확인할 수 있습니다.
503 Service Unavailable
증상: API가 503 상태를 반환합니다.
원인: 다음 두 가지 경우에 발생합니다.
- 서비스 용량 초과. FourA가 해당 엔진에서 동시에 실행 가능한 최대 request 수를 이미 처리하고 있습니다. 이는 사용자의 트래픽뿐만 아니라 전체 트래픽을 기준으로 집계됩니다.
error필드에Service at capacity가 표시됩니다. 일반적으로 몇 초 내에 해제됩니다. - 서비스 일시 비활성화. 유지 관리 작업이 진행 중입니다.
error필드에Service disabled가 표시됩니다.
두 경우 모두 response에 retryAfter 필드가 포함됩니다. 둘 다 플랜 한도 문제는 아닙니다. 플랜 자체 한도는 503이 아닌 403 또는 429의 X-FourA-Limit header로 항상 응답합니다.
해결 방법: retryAfter초 동안 대기한 후 다시 시도하십시오.
import time
import requests
def make_request_with_retry(endpoint_url, payload, retries=3):
for i in range(retries):
resp = requests.post(
endpoint_url,
headers={"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"},
json=payload
)
if resp.status_code in (429, 503):
header = resp.headers.get("Retry-After")
body = resp.json()
wait = (
int(header) if header and header.isdigit()
else body.get("retry_after_seconds") or body.get("retryAfter") or 2 ** i
)
time.sleep(wait)
continue
return resp
raise Exception("Request not resolved after retries")
용량 초과로 인한 503은 FourA 서버가 혼잡한 상태임을 의미하므로, 백오프 후 재시도하는 것이 해결책입니다. 429 및 X-FourA-Limit 오류로 요청이 거부되는 경우라면 클라이언트 측 문제입니다. 파이프라인의 병렬 request 수를 줄이십시오.
504 Upstream Timeout
증상: API가 {"error": "Upstream timeout"}와 함께 504를 반환합니다.
원인: request에 지정한 시간 예산 내에 작업이 완료되지 않았습니다. 대상 서버 지연, 콜드 챌린지 해결, 매우 큰 페이지 등이 원인일 수 있습니다. 키, 파라미터 또는 proxy 문제는 아닙니다.
해결 방법: 호출 시간을 더 늘리거나 재시도하십시오. FourA는 timeout_ms 값에 약간의 여유 시간을 더해 대기하므로, 이 값을 늘리면 대기 시간이 실제로 연장됩니다.
{
"url": "https://slow-site.com/report",
"timeout_ms": 90000
}
보호된 대상에 대한 /api/auto/의 경우, 초기 콜드 호출은 수십 초가 소요될 수 있습니다. timeout_ms은 전체 사다리 단계를 포함하며 최대 180000까지 허용합니다.
/api/auto/ 자체에서 해당 예산이 모두 소진되어도 호출은 HTTP 200으로 응답합니다. 본문에는 time budget exhausted로 시작하는 error이 포함되며, status은 일반적으로 504입니다 (이전에 실패한 시도가 대신 해당 상태를 남길 수 있습니다). timeout_ms을 늘리거나 다시 시도하세요.
502 Upstream Unavailable
증상: API가 {"error": "Upstream unavailable"}와 함께 502를 반환하거나, {"error": "Backend service unavailable"}과 함께 503을 반환합니다.
원인: FourA가 자체 엔진에 도달했으나 인스턴스 재시작 등의 이유로 응답을 사용할 수 없습니다.
해결 방법: 짧은 백오프와 함께 다시 시도하세요. 둘 다 service_error로 분류되며 success만 청구되므로 재시도 시 추가 비용이 발생하지 않습니다. 1~2분 이상 지속되면 상태 페이지를 확인하세요.
401 인증 오류
증상: 모든 요청이 401 Unauthorized를 반환합니다.
체크리스트:
- 헤더가
X-API-Key: YOUR_API_KEY인지 확인합니다 (Authorization: Bearer또는Api-Key아님) - API 키에 불필요한 공백이나 줄바꿈이 있는지 확인합니다
- 현재 키가 노출되었을 가능성이 있다면 대시보드에서 새 키를 생성합니다
400 Target Resolves to a Private or Reserved IP
증상: 요청이 FourA를 벗어나기 전에 API가 Refusing to fetch <target>: target resolves to a private or reserved IP range와 함께 400을 반환합니다.
원인: url이 사설, 루프백 또는 예약된 IP 범위(RFC 5735, RFC 6598 또는 IPv6 예약 블록)로 확인됩니다. FourA는 내부 호스트 접근에 네트워크가 사용되지 않도록 이러한 대상을 거부합니다.
해결 방법: 공개 URL을 가져오세요. 테스트 중인 경우 https://example.com 또는 https://httpbin.org/get와 같은 공개 대상을 사용하세요. 대상이 직접 운영하는 서비스라면 먼저 공개 호스트 이름으로 노출하세요.
{ "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." }
조회할 수 없는 호스트 이름은 거부되지 않습니다. FourA가 도달할 수 없는 다른 대상과 마찬가지로 호출은 status: 0 및 사유(could not resolve <host>: <reason>)와 함께 HTTP 200으로 반환되며 요금이 청구되지 않습니다.
exitCountries 사용 시 no_eligible_proxy
증상: exitCountries를 사용한 /api/proxy/ 호출이 JSON 오류 envelope와 함께 HTTP 200을 반환합니다.
{
"error": "No eligible proxy found for exit countries: CZ, GB",
"code": "no_eligible_proxy",
"details": { "exitCountries": ["CZ", "GB"] },
"total": 0.084
}
원인: 현재 proxy 풀에 허용 목록과 일치하는 대상 가시 국가의 작동 가능한 exit 노드가 없습니다. FourA는 exitCountries을(를) 설정했을 때 요청되지 않은 국가로 절대 대체하지 않습니다.
해결 방법: 요청된 범위를 유지하고 나중에 다시 시도하십시오. 풀은 약 10분마다 갱신되므로, 현재 일치하는 항목이 없는 국가도 보통 1시간 이내에 다시 사용 가능해집니다.
import time, requests
def fetch_scoped(url, countries, max_attempts=6, wait_sec=600):
for _ in range(max_attempts):
r = requests.post("https://eu.api.foura.ai/api/proxy/",
headers={"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"},
json={"maxTries": 5, "exitCountries": countries,
"request": {"method": "GET", "url": url}}).json()
if r.get("code") == "no_eligible_proxy":
time.sleep(wait_sec)
continue
return r
raise RuntimeError(f"no eligible exit in {countries} after {max_attempts} attempts")
워크플로의 국가 요구사항이 실제로 변경된 경우에만 국가 목록을 확장하십시오. 다른 국가로 자동 폴백되면 다운스트림의 지리적 종속 로직이 손상될 수 있습니다.
Response Body가 깨진 텍스트로 반환됨
증상: 대상이 UTF-8이 아닌 문자 집합을 사용할 때 response data(또는 body)에 모지바케 또는 읽을 수 없는 문자가 포함됩니다.
원인: 기본적으로 FourA는 대상의 Content-Type header 또는 HTML <meta charset> 태그를 기반으로 response body를 UTF-8로 자동 디코딩합니다. 대상이 문자 집합 정보를 잘못 제공하면 텍스트가 깨집니다.
해결 방법: 바이너리 페이로드(이미지, protobuf, 원시 오디오)의 경우 request에 returnBuffer: true를 설정하십시오. 그러면 Single 및 Proxy가 문자 집합 트랜스코딩 없이 원시 바이트인 {"type": "Buffer", "data": [<byte values>]}를 포함하는 객체로 data를 반환합니다.
{
"method": "GET",
"url": "https://example.com/image.png",
"returnBuffer": true
}
문자 집합(charset)을 잘못 선언한 텍스트 대상의 경우 원시 바이트를 직접 디코딩하십시오. returnBuffer: true(으)로 가져오고 data.data의 바이트 값을 읽은 다음 올바른 문자 집합으로 디코딩합니다.
JSON 대신 예기치 않은 HTML이 반환됨
증상: 대상 사이트에서 JSON을 예상했으나 HTML을 수신했습니다.
원인: 대상 페이지가 header에 따라 다른 콘텐츠를 제공할 수 있습니다.
해결 방법: 실제 브라우저 header 구성을 위해 Accept header를 추가하고 unblocker을(를) 활성화하십시오.
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://api.example.com/data",
"headers": [["Accept", "application/json"]],
"unblocker": true
}'
또한 tryJsonData 값을 true 설정하여 FourA가 JSON 응답을 자동으로 파싱하도록 할 수 있습니다.
본문이 콘텐츠가 아닌 챌린지 페이지인 경우
증상: 호출이 성공하여 status 코드가 200이지만, data(또는 body)에 원하는 페이지 대신 봇 검사 페이지가 표시됩니다.
원인: 대상 사이트에서 봇 검사를 실행했으며, FourA가 이를 감지했으나 통과하지 못했습니다. 응답에 해당 내용이 표시됩니다. Single 및 Proxy는 solved: false와 함께 defense를 반환하고, Browser는 defenses.present에 벤더 정보를 포함한 defenseSolved: false을 반환합니다.
해결 방법: 먼저 defense.vendor 필드를 확인한 후 단계를 조정하십시오. Single에서 다른 브라우저 프로필을 시도하거나, 다른 출구 노드를 위해 Proxy로 전환하거나, JavaScript가 실행되도록 Browser를 사용하십시오. 전체 필드 참조 및 벤더 목록: Site checks.
실제 페이지에만 존재하는 validate.data.accept 부분 문자열을 추가하십시오. FourA가 인식한 검사 페이지는 성공으로 처리되지 않습니다. X-FourA-Check-Page 헤더와 함께 반환되며 비용이 청구되지 않습니다. validate 설정이 없으면, FourA가 인식하지 못하고 HTTP 200으로 반환된 검사 페이지는 성공으로 간주되어 호출 시점이 아닌 다운스트림 단계에서 문제를 발견하게 됩니다.
문제가 여전히 해결되지 않나요?
위 방법으로 해결되지 않는 경우:
- 진행 중인 장애가 있는지 상태 페이지에서 확인하십시오.
- Dashboard에서 요청 지표를 검토하십시오.
- 요청 세부 정보(실패한 응답의
X-FourA-Request-Id포함)를 작성하여 support@foura.ai로 지원 팀에 문의하십시오.
다음 단계
- Error Handling: API 오류 코드 참조
- Rate Limits: 모든 플랜 한도 및 플랫폼 한도와 관련 필드
- Request Outcomes: 결과 분류 방식
- Site checks:
defense필드가 제공하는 정보 - Choosing the Right Endpoint: 대상에 적합한 최적의 방식 선택
- Dashboard Overview: 요청 모니터링