# Proxy Request 재시도 횟수가 초과된 이유

> URL: https://foura.ai/ko/docs/troubleshooting/proxy-attempt-report
> Updated: 2026-09-30
> Index: https://foura.ai/llms.txt

## 문제

`POST /api/proxy/` 호출 시 데이터 없이 오류가 반환됩니다. 메시지는 짧으며 항상 동일한 형식입니다.

```json
{
  "error": "Download maxTry limit reached",
  "total": 34.812,
  "request": { "...": "..." }
}
```

이 문장은 모든 출구가 차단되었든, 모든 출구가 다운되었든, 또는 FourA가 거의 모든 시도에서 실제 페이지를 가져왔으나 사용자 정의 `validate` 규칙에 의해 폐기되었든 상관없이 동일하게 표시됩니다. 이 세 가지 상황에는 각기 다른 해결책이 필요합니다.

## 해결 방법: `attemptReport`

시도를 실행했으나 실패한 모든 Proxy 호출은 오류 외에도 `attemptReport` 객체를 포함하며, 여기에는 `"error": "Timeout"`(으)로 종료된 호출도 포함됩니다. 확인되지 않는 호스트 이름은 시도 전에 `status: 0`(으)로 실패하며 리포트가 생성되지 않습니다. 이 객체는 각 시도에서 실제로 발생한 상황을 집계합니다:

```json
{
  "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
}
```

`error` 문자열은 의도적으로 변경되지 않으므로 이를 매칭하는 클라이언트는 계속 정상 작동합니다. 한 줄 요약은 `attemptReport.summary`에서 확인하거나, 조건부 분기를 처리할 때는 카운트 값을 확인하십시오.

### 필드

| 필드 | 타입 | 집계 대상 |
|-------|------|----------------|
| `total` | integer | 시도 횟수 |
| `noResponse` | integer | exit 노드에서 응답이 없었거나 사이트가 제시간에 응답하지 않음 |
| `defense` | integer | 사이트가 응답했으며 해당 응답에서 bot-check 벤더가 감지됨 |
| `contentRejected` | integer | HTTP 200, 봇 체크 없음, 사용자의 `validate.data` 설정에 의해서만 거부됨 |
| `statusRejected` | integer | 사이트가 응답함, 봇 체크 없음, 사용자의 `validate.status` 설정에 의해 거부됨 |
| `other` | integer | 응답을 받았으나 위의 어느 항목에도 해당하지 않음 |
| `vendors` | string[] | 작업 전체에서 감지된 모든 bot-check 벤더 |
| `profilesTried` | string[] | 작업에서 전송한 브라우저 프로필 목록(최초 사용 순서). `default`는 작성된 그대로 요청이 전송되었음을 의미합니다. |
| `summary` | string | 카운트 값으로 생성된 한 문장 요약. 로그에 기록하거나 사용자에게 표시하기에 안전합니다. |

## 데이터 해석하기

### `contentRejected` 값이 높은 경우

페이지는 수신되었습니다. 사용자의 `validate.data` 규칙이 해당 페이지와 일치하지 않았습니다.

이 문제는 직접 해결할 수 있는 영역이며, 다른 모든 지표가 가리고 있는 부분이기도 합니다. 즉, 모든 메트릭에서는 요청 실패로 표시되지만 FourA는 실제로 정상 콘텐츠를 계속 전달하고 있었습니다. `validate` 없이 `POST /api/single/`를 통해 페이지를 한 번 가져와 실제 응답 내용을 확인한 후, 그에 맞게 규칙을 다시 작성하십시오.

흔한 원인 중 하나는 서로 구성이 다른 페이지 세트에 단일 규칙을 적용한 경우입니다. 기사 페이지에는 존재하지만 동영상 페이지에는 없는 선택자는 동영상 페이지에 도달할 때마다 매번 실패하며 비용이 계속 발생합니다.

### `statusRejected` 값이 높은 경우

사이트가 응답했으나 사용자의 `validate.status` 규칙에 의해 거부되었습니다. 해당 상태 코드가 401, 403, 429 또는 503인 경우 사이트에 페이지가 없는 것이 아니라 클라이언트를 거부하고 있는 것입니다. 다음을 시도하십시오:

- 다른 브라우저 프로필 사용(내부 `request` 객체의 `browser`, `os`, `version`)
- 콘텐츠가 특정 지역으로 제한된 경우 `exitCountries` 적용
- 거부 해제를 위해 JavaScript 실행이 필요한 경우 `POST /api/browser/` 적용

### `defense` 값이 높은 경우

응답에서 봇 체크가 감지되었으며, `vendors` 항목에 감지된 벤더가 명시됩니다. FourA가 현재 해결 가능한 항목과 단순 보고만 제공하는 항목은 [Site checks](https://foura.ai/docs/api/site-checks)에서 확인하십시오. 해당 벤더가 이 endpoint에서 자동 해결되지 않는 대상이라면 호출을 `POST /api/browser/` 또는 `POST /api/auto/`(으)로 전환하십시오.

### `noResponse` 값이 높은 경우

exit 노드가 전혀 응답하지 않아 타깃에 대한 정보를 파악하지 못했습니다. `maxTries` 값을 늘리고, `timeout_ms` 값을 늘린 후, 해당 URL이 공용 인터넷에서 정상 확인되는지 점검하십시오.

### `other` 값이 높은 경우

사이트가 상태 코드로 응답했고 봇 체크는 감지되지 않았으며, `validate.headers` 규칙 등 다른 원인으로 시도가 실패했습니다. 설정한 `timeout_ms`보다 느린 대상은 `noResponse`(으)로 집계됩니다.

## 브라우저 프로필 로테이션

사이트가 FourA가 보낸 브라우저를 거부하면 Proxy는 해당 브라우저를 고집하지 않고 [공개 프로필 카탈로그](https://foura.ai/docs/api/endpoints)의 다른 패밀리를 시도합니다. 추가 시도 횟수가 소모되지 않습니다. 로테이션은 재시도 시 전송되는 내용을 변경할 뿐, 재시도 발생 여부 자체를 바꾸지 않습니다.

또한 Proxy는 사이트가 기본 브라우저를 거부한 후 해당 사이트에서 마지막으로 작동했던 패밀리를 사이트별로 기억합니다. 이후 해당 사이트로 전송되는 request는 첫 번째 시도부터 해당 패밀리로 시작할 수 있으며, 사이트가 이 패밀리마저 거부하기 시작하면 FourA는 다음 패밀리로 넘어갑니다. 모바일 브라우저는 JSON으로 응답하는 사이트에 대해서만 기억됩니다.

`profilesTried` 항목을 통해 이 동작 과정을 확인할 수 있습니다. 항목이 하나라면 모든 시도에서 동일한 브라우저를 전송했음을 의미합니다. `default`는 작성된 그대로의 request이며, 카탈로그 ID는 FourA가 해당 사이트에 대해 이미 학습한 패밀리입니다. 항목이 여러 개라면 로테이션이 실행되었으나 사이트가 각각을 모두 거부했음을 의미하며, 이는 로테이션을 전혀 실행하지 않은 상태와는 다른 상황입니다.

**성공적인** Proxy response에서는 로테이션이 요청하지 않은 브라우저를 선택한 경우에만 `profile` 필드가 나타납니다.

```json
{
  "status": 200,
  "data": "<!doctype html>...",
  "proxy": "A1B2C3",
  "profile": "...",
  "total": 4.108
}
```

이 값은 `GET /api/profiles`의 카탈로그 ID입니다. 값이 없으면 request가 작성된 그대로 전송되었음을 의미합니다. 값이 있으면 작동한 브라우저가 직접 입력한 것과 다르다는 의미이므로, 실패한 브라우저를 재시도하는 대신 후속 호출에서 해당 ID를 `profile`로 다시 전달하십시오. 대시보드 [Playground](https://foura.ai/docs/dashboard/playground)에서는 **Carry**를 통해 이 작업을 자동으로 처리합니다.

request에 명시된 `profile`, `browser`, `os` 또는 `version`은 절대 재정의되지 않습니다. 클리어런스는 이를 획득한 시그니처에 바인딩되므로, 자체 `User-Agent` 또는 `Cookie` header가 포함된 request 역시 재정의되지 않습니다.

## 코드에서 읽기

```python
import requests

API = "https://eu.api.foura.ai"
H = {"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"}

r = requests.post(f"{API}/api/proxy/", headers=H, json={
    "maxTries": 5,
    "request": {
        "method": "GET",
        "url": "https://example.com/product/42",
        "validate": {"data": {"accept": ["Add to cart"]}},
    },
}).json()

if "error" in r:
    rep = r.get("attemptReport", {})
    print(rep.get("summary", r["error"]))

    if rep.get("contentRejected", 0) > rep.get("total", 0) / 2:
        # The pages arrived. The validate rule is what threw them away.
        raise SystemExit("validate.data did not match the real page")
    if rep.get("defense", 0):
        print("bot check met:", ", ".join(rep.get("vendors", [])))
```

## 관련 문서

- [API Endpoints](https://foura.ai/docs/api/endpoints): Proxy 요청 및 응답 전체 레퍼런스
- [Site checks](https://foura.ai/docs/api/site-checks): 벤더, `defense` 및 통과 세션 재사용
- [Request Outcomes](https://foura.ai/docs/api/outcomes): 거부된 응답의 분류 및 과금 방식
- [Common Issues](https://foura.ai/docs/troubleshooting/common-issues): 기타 문제 및 해결 방법
- [Choosing the Right Endpoint](https://foura.ai/docs/guides/choosing-task-type): Proxy 사용이 적절하지 않은 경우
