Почему для proxy request исчерпаны попытки

Проблема

Вызов POST /api/proxy/ возвращает ошибку без данных. Сообщение короткое и всегда имеет одинаковый формат:

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

Эта фраза звучит одинаково, был ли заблокирован каждый выходной узел, был ли он недоступен, или FourA получал реальную страницу почти при каждой попытке, а ваши собственные правила validate отбрасывали ее. Для каждого из этих трех случаев требуются противоположные решения.

Решение: attemptReport

Каждый вызов Proxy, который исчерпал попытки и завершился ошибкой, содержит объект attemptReport рядом с ошибкой, включая случаи с завершением по "error": "Timeout". Если имя хоста не разрешается, сбой происходит до любых попыток с ошибкой status: 0 и без отчета. Он фиксирует то, с чем фактически столкнулись попытки:

{
  "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 для получения краткого ответа в одну строку или используйте счетчики для ветвления логики.

Поля

Field Type Что подсчитывает
total integer Количество выполненных попыток
noResponse integer Выходной узел не ответил или сайт не ответил вовремя
defense integer Сайт ответил, и в ответе обнаружена защита от ботов
contentRejected integer HTTP 200, нет защиты от ботов, отклонено только вашим правилом validate.data
statusRejected integer Сайт ответил, нет защиты от ботов, отклонено вашим правилом validate.status
other integer Ответ получен, но ни один из указанных выше случаев не подошел
vendors string[] Все поставщики защиты от ботов, обнаруженные в рамках задачи
profilesTried string[] Профили браузера, отправленные задачей, в порядке первого использования. default означает, что запрос ушел ровно в том виде, как вы его написали.
summary string Одно предложение на основе счетчиков. Подходит для логирования или показа пользователю.

Как читать данные

Высокое значение contentRejected

Страницы были получены. Ваше правило validate.data с ними не совпало.

Эту проблему вы можете исправить самостоятельно, и именно ее скрывают все остальные метрики: запросы выглядят как неудачные во всех отчетах, хотя FourA все это время доставлял реальный контент. Запросите страницу один раз через POST /api/single/ вообще без validate, посмотрите на реальный ответ и перепишите правило под него.

Частая причина: одно правило применяется к набору страниц с разной структурой. Селектор, присутствующий на страницах статей и отсутствующий на страницах с видео, будет падать при каждом попадании на видео, постоянно расходуя бюджет.

Высокое значение statusRejected

Сайт ответил, но ваше правило validate.status отклонило ответ. Если статусы 401, 403, 429 или 503, сайт блокирует клиента, а не сообщает об отсутствии страницы. Попробуйте:

  • Другой профиль браузера (browser, os, version во внутреннем объекте request)
  • exitCountries, если контент заблокирован по региону
  • POST /api/browser/, если для прохождения проверки требуется JavaScript

Высокое значение defense

В ответах обнаружена защита от ботов, а vendors указывает конкретную систему. Ознакомьтесь с разделом Проверки сайтов, чтобы узнать, какие проверки FourA проходит автоматически, а о каких только сообщает. Если защита не обходится на этом endpoint, переключите вызов на POST /api/browser/ или POST /api/auto/.

Высокое значение noResponse

Выходные узлы вообще не ответили, поэтому о цели ничего не удалось узнать. Увеличьте maxTries, увеличьте timeout_ms и проверьте, что URL резолвится из публичного интернета.

Высокое значение other

Сайт вернул статус, защита от ботов не обнаружена, но попытка завершилась неудачей по другой причине, например из-за правила validate.headers. Ответ цели дольше, чем timeout_ms, учитывается в noResponse.

Ротация профилей браузера

Когда сайт отклоняет браузер, отправленный FourA, Proxy прекращает его использовать и пробует другое семейство из public profile catalogue. Это не расходует дополнительных попыток: ротация меняет параметры повторного запроса, но не влияет на сам факт его выполнения.

Proxy также запоминает для каждого сайта семейство, которое сработало последним после того, как сайт отклонил вариант по умолчанию. Следующий request к этому сайту может сразу начаться с этого семейства с первой попытки, и FourA перейдет к следующему семейству, если сайт начнет отклонять и его. Мобильный браузер запоминается только для сайтов, возвращающих JSON.

Через profilesTried можно отследить этот процесс. Одна запись означает, что каждая попытка отправляла один и тот же браузер: default соответствует исходному запросу, а идентификатор каталога указывает на семейство, которое FourA уже запомнил для этого сайта. Несколько записей означают, что ротация сработала и сайт отклонил каждую из них, что отличается от ситуации, когда ротация не выполнялась вовсе.

В успешном response от Proxy поле profile появляется только тогда, когда ротация выбрала браузер, который вы не запрашивали:

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

Значение представляет собой идентификатор каталога из GET /api/profiles. Отсутствие означает, что request был отправлен в точности как указано. Наличие означает, что сработавший браузер отличается от указанного вами, поэтому передавайте этот id как profile в последующих вызовах вместо повторной отправки завершившегося ошибкой. В Playground Playground панели управления это выполняется автоматически с помощью опции Carry.

Явно заданные в вашем request параметры profile, browser, os или version никогда не переопределяются. Это также касается request с вашим собственным header User-Agent или Cookie, так как clearance привязан к сигнатуре, с помощью которой он был получен.

Чтение значения в коде

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: Полный справочник по Proxy request и response
  • Site checks: Вендоры, defense и повторное использование clearance
  • Request Outcomes: Классификация и тарификация отклоненных response
  • Common Issues: Другие проблемы и способы их решения
  • Choosing the Right Endpoint: Когда Proxy не подходит для задачи
Обновлено: 30 сентября 2026 г.