자주 발생하는 문제

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는 콘텐츠를 body 필드에 반환합니다(data 아님).

403 Forbidden 또는 CAPTCHA 페이지

증상: API가 CAPTCHA 챌린지 또는 액세스 거부 페이지가 포함된 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 로테이션 시도 횟수를 늘리십시오.

Timeout 오류

증상: timeout 오류와 함께 request가 실패합니다.

원인: 대상 페이지가 로드되는 데 설정된 timeout보다 오래 걸립니다.

해결책: timeout_ms 값을 늘리십시오(기본값: single 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
  }'

브라우저 요청의 경우 페이지에 checkText 값이 실제로 표시되는지 확인하십시오. 오타가 있으면 항상 시간 초과가 발생합니다.

429 Too Many Requests (RPM 제한)

증상: API가 "rate limit exceeded" 메시지와 함께 429 상태를 반환합니다.

원인: 분당 요청 수(RPM) 제한을 초과했습니다. 이는 동시성 제한(아래 503 참조)과는 다릅니다.

해결책: 재시도하기 전에 응답의 retryAfter 필드를 사용하여 적절한 시간 동안 대기하십시오:

import time
import requests

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:
            body = resp.json()
            wait = body.get("retryAfter", 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"}
)

Dashboard에서 현재 사용량을 확인하여 rate limit을 확인하십시오.

503 Service Unavailable

증상: API가 503 상태를 반환합니다.

원인: 두 가지 경우에 발생합니다.

  1. 동시성 한도 초과. 실행 중인 동시 request가 너무 많습니다. 이는 분당 request를 제한하는 429와 다릅니다. 503의 경우 RPM을 초과하지는 않았지만 동시에 실행할 수 있는 최대 request 수에 도달한 것입니다.
  2. 서비스 일시 중지. 유지보수 작업이 진행 중입니다.

두 경우 모두 response에 retryAfter 필드가 포함됩니다.

해결 방법: 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):
            body = resp.json()
            wait = body.get("retryAfter", 2 ** i)
            time.sleep(wait)
            continue
        return resp
    raise Exception("Request not resolved after retries")

503 동시성 제한에 자주 도달하는 경우 스크래핑 파이프라인에서 병렬 request 수를 줄이거나 대시보드에서 플랜의 동시성 제한을 확인하세요.

504 Upstream Timeout

증상: API가 504를 반환하며 {"error": "Upstream timeout"}.

원인: request에 대해 선언한 시간 예산 내에 작업이 완료되지 않았습니다. 느린 타겟, 콜드 챌린지 해결, 매우 큰 페이지 등이 원인일 수 있습니다. 키, 파라미터 또는 proxy의 문제가 아닙니다.

해결책: 호출에 더 많은 시간을 할당하거나 재시도하세요. FourA는 사용자의 timeout_ms에 약간의 여유 시간을 더해 대기하므로, 이 값을 늘리면 실제 대기 시간이 연장됩니다:

{
  "url": "https://slow-site.com/report",
  "timeout_ms": 90000
}

보호된 대상에 대한 /api/auto/의 경우 콜드 첫 호출(cold first call)에 수십 초가 걸릴 수 있습니다. 이 timeout_ms은(는) 전체 단계를 포괄하며 최대 180000까지 허용합니다.

502 Upstream Unavailable

증상: API가 {"error": "Upstream unavailable"}과 함께 502를 반환하거나 {"error": "Backend service unavailable"}과 함께 503을 반환합니다.

원인: FourA가 자체 엔진에 도달했지만 응답을 사용할 수 없습니다. 대개 인스턴스가 재시작 중이기 때문입니다.

해결 방법: 짧은 백오프(backoff) 후 재시도하십시오. 두 경우 모두 service_error로 분류되며 success만 청구되므로 재시도에 추가 비용이 발생하지 않습니다. 1~2분 이상 지속되는 경우 상태 페이지를 확인하십시오.

401 Authentication Errors

증상: 모든 request가 401 Unauthorized를 반환합니다.

체크리스트:

  1. header가 X-API-Key: YOUR_API_KEY인지 확인합니다(Authorization: Bearer 또는 Api-Key이 아님).
  2. API 키에 추가 공백이나 줄바꿈이 있는지 확인합니다.
  3. 현재 키가 유출되었을 가능성이 있는 경우 대시보드에서 새 키를 생성합니다.

400 Target Resolves to a Private/Reserved IP

증상: request가 FourA를 떠나기 전에 API가 Target <ip> resolves to a private/reserved IP와 함께 400을 반환합니다.

원인: 귀하의 url이(가) 사설, 루프백 또는 예약된 IP 대역(RFC 5735, RFC 6598 또는 IPv6 예약 블록)으로 확인됩니다. FourA는 내부 호스트에 접근하는 데 네트워크가 사용되는 것을 막기 위해 이러한 대상을 거부합니다.

해결 방법: 공개 URL을 가져오십시오. 테스트 중인 경우 https://example.com 또는 https://httpbin.org/get과 같은 공개 대상을 사용하십시오. 대상이 직접 운영하는 서비스인 경우 먼저 공개 호스트 이름으로 노출하십시오.

{ "error": "Target <ip> resolves to a private/reserved IP" }

exitCountries 사용 시 no_eligible_proxy 발생

증상: exitCountries 옵션을 포함한 /api/proxy/ 호출 시 HTTP 200 및 JSON 에러 엔벨로프가 반환됩니다:

{
  "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")

워크플로우의 국가 요구사항이 실제로 변경된 경우에만 국가 목록을 확장하십시오. 다른 국가로 자동 폴백(fallback)되면 다운스트림의 지역 종속 로직이 손상될 수 있습니다.

Response Body가 깨진 텍스트로 반환됨

증상: 대상이 UTF-8이 아닌 문자셋을 사용할 때 응답 data(또는 body)에 글자 깨짐(mojibake) 또는 읽을 수 없는 문자가 포함됩니다.

원인: 기본적으로 FourA는 대상의 Content-Type 헤더나 HTML <meta charset> 태그를 기반으로 response body를 UTF-8로 자동 디코딩합니다. 대상이 문자셋을 잘못 명시하면 텍스트가 깨지게 됩니다.

해결책: 바이너리 페이로드(이미지, protobuf, raw 오디오)의 경우 request에 returnBuffer: true를 설정하십시오. body는 문자셋 트랜스코딩이 적용되지 않은 base64 버퍼로 반환됩니다.

{
  "method": "GET",
  "url": "https://example.com/image.png",
  "returnBuffer": true
}

charset을 잘못 선언한 텍스트 대상의 경우 원시 바이트를 직접 디코딩하십시오. returnBuffer: true(으)로 가져오고, base64-decode한 다음 올바른 charset을 적용하십시오.

JSON 대신 예기치 않은 HTML 반환

증상: 대상 사이트에서 JSON을 예상했지만 HTML을 수신했습니다.

원인: 대상 페이지가 header에 따라 다른 콘텐츠를 제공할 수 있습니다.

해결 방법: Accept header를 추가하고 현실적인 브라우저 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
  }'

FourA가 JSON response를 자동으로 파싱하도록 tryJsonData을(를) true(으)로 설정할 수 있습니다.

본문이 콘텐츠가 아닌 Challenge 페이지인 경우

증상: 호출이 성공하고 status이(가) 200이지만 data(또는 body)이(가) 원하는 페이지가 아니라 봇 검사 페이지입니다.

원인: 대상이 봇 검사를 실행했고 FourA가 이에 직면했지만 통과하지 못했습니다. response에 표시됩니다: Single 및 Proxy는 solved: false와(과) 함께 defense을(를) 반환하고, Browser는 defenses.present에 벤더 정보가 포함된 defenseSolved: false을(를) 반환합니다.

해결책: 먼저 defense.vendor을(를) 확인한 후 단계를 올리세요. Single에서 다른 브라우저 프로필을 시도하거나, 다른 출구를 위해 Proxy로 이동하거나, JavaScript가 실행되도록 Browser를 사용하세요. 전체 필드 참조 및 벤더 목록: 안티 봇 방어.

실제 페이지만 포함하는 validate.data.accept 하위 문자열을 추가하세요. 추가하지 않으면 HTTP 200과 함께 반환된 challenge 페이지가 성공으로 간주되어 호출 시점이 아닌 다운스트림에서 문제를 발견하게 됩니다.

여전히 문제가 발생하나요?

위의 해결책 중 어느 것도 효과가 없는 경우:

  1. 상태 페이지에서 진행 중인 장애가 있는지 확인합니다.
  2. Dashboard에서 request 지표를 검토합니다.
  3. 실패한 response의 X-FourA-Request-Id을(를) 포함하여 request 세부 정보와 함께 support@foura.ai로 지원팀에 문의합니다.

다음 단계

최근 업데이트: 2026년 8월 12일