Лимиты запросов

Каждый API request в FourA проходит три проверки перед тем, как попасть в движок: лимиты вашего тарифного плана, затем общий лимит платформы для вызванного endpoint, затем общий лимит платформы для всего трафика. Каждая проверка может отклонить request самостоятельно и возвращает собственное тело ответа.

Три проверки по порядку

  1. Лимиты тарифного плана. То, что разрешено вашим планом: доступные endpoint и параметры, количество одновременных request на endpoint, лимит request в минуту, количество browser request в день, а также доступные кредиты и трафик за расчетный период.
  2. Глобальный лимит платформы. Все запросы, которые хост API обрабатывает в данный момент, независимо от целевого endpoint. Отказ на этом этапе возвращает "service": "api".
  3. Лимит платформы на endpoint. Трафик сервисов single, proxy или browser, к которым вы обратились.

Сначала проверяется ваш тарифный план. Этот порядок зафиксирован в контракте и не является деталью реализации. Общие лимиты платформы разделяются всеми пользователями, поэтому request, который в любом случае был бы отклонен, не должен расходовать общие ресурсы. Если аккаунт отправляет больше положенного по плану, он отсекается до того, как затронет ресурсы других пользователей.

Проверки 2 и 3 учитывают общий трафик FourA, а не ваш. Отказ на любом из этих этапов означает "FourA перегружен", а не "вы отправили слишком много". Проверка 1 относится исключительно к вашему аккаунту и не зависит от других процессов на платформе.

Отказ на любой из общих проверок возвращает вашему аккаунту все задействованные лимиты, включая поминутный лимит и дневной слот browser request, так как request не достиг бэкенда. Это также не учитывается в паузе повторных попыток, описанной в разделе Requests per minute: отказ произошел из-за емкости FourA, а не из-за вашего плана.

POST /api/auto/ не занимает отдельного слота. Вложенные вызовы Single, Proxy и Browser, которые он выполняет для вас, проходят все три проверки как стандартные request. Поэтому параллельный пакет вызовов auto расходует лимиты вашего плана через свои подзапросы. (В статистике ваших request и проценте успешности сам вызов auto учитывается один раз, а вложенные вызовы отображаются как его попытки.)

Лимиты тарифного плана

При срабатывании лимита плана возвращается header X-FourA-Limit с указанием конкретного лимита. Тот же код содержится в теле ответа в поле reason, что позволяет строить ветвление логики без чтения headers. Тело ответа при превышении любого лимита плана содержит error, reason и documentation; остальные поля зависят от типа лимита.

X-FourA-Limit Статус Что исчерпано
plan_limit_feature 403 Вызванный endpoint или параметр exitCountries не входит в ваш тариф
plan_limit_premium 403 exitClass: premium не входит в ваш тариф
plan_limit_concurrency 429 Одновременные запросы к этому endpoint
plan_limit_rate 429 Запросы в минуту к этому endpoint
plan_limit_browser_daily 429 Запросы браузера за день
plan_limit_credits 429 Платные кредиты за расчетный период
plan_limit_bandwidth 429 Трафик за расчетный период

Значения лимитов определяются вашим тарифом. Во вкладке Limits & Features в Usage & Limits они указаны рядом с текущим использованием. Не хардкодьте их: каждый отказ содержит значение лимита, вызвавшего блокировку.

Отклоненный запрос ничего не расходует. Результат имеет статус rate_limit, а оплачивается только success.

Endpoint или параметр не входит в тариф

Код 403 с plan_limit_feature означает, что запрос требует функцию, не включенную в тариф. Проверка выполняется до подсчета, поэтому отклоненный вызов не влияет на счетчики rate limit или дневного расхода.

{
  "error": "The browser endpoint is not included in your plan (Free). Upgrade to use it.",
  "reason": "plan_limit_feature",
  "documentation": "https://foura.ai/prices"
}

Те же код и статус возвращаются в ответ на вызов POST /api/proxy/, устанавливающий exitCountries на тарифе без геотаргетинга. Строка error указывает имя параметра:

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

plan_limit_premium имеет тот же формат для exitClass: premium на тарифе без премиум-выходов. FourA может вместо этого обработать такой request из стандартного пула и вернуть exitClass: standard в response, поэтому обрабатывайте оба варианта. Ни один из них не расходует премиум-выход. См. exitClass.

Ни один 403 не устанавливает Retry-After. Ожидание не изменит результат.

Simultaneous requests

Конкурентность считается отдельно для каждого endpoint: ваш тариф задает один лимит для Single, один для Proxy и один для Browser. Request, превышающий лимит, возвращается с кодом 429 и Retry-After: 1:

{
  "error": "Concurrency limit reached: your plan allows 50 simultaneous proxy request(s). Retry when an in-flight request finishes.",
  "reason": "plan_limit_concurrency",
  "documentation": "https://foura.ai/prices",
  "limit": 50,
  "in_flight": 51,
  "retry_after_seconds": 1
}

in_flight учитывает и отклоненный request, поэтому его значение как минимум на единицу больше, чем у limit.

Решение заключается в ограничении собственного параллелизма, а не в увеличении числа повторных попыток. Повторная немедленная отправка того же пакета в ответ на 429 вызовет еще один 429 для каждого вызова внутри него. См. готовый шаблон в Параллельное выполнение запросов.

Requests per minute

Для Single и Proxy действует лимит запросов в минуту, который рассчитывается по скользящему окну в одну минуту. Учитываются только принятые requests: отклоненный request исключается из подсчета, поэтому аккаунт, стабильно запрашивающий чуть больше установленного лимита, получает объем в рамках своей квоты, а не блокировку почти всех запросов.

{
  "error": "Rate limit reached: your plan allows 600 single requests per minute. Cool down and retry.",
  "reason": "plan_limit_rate",
  "documentation": "https://foura.ai/prices",
  "limit_per_minute": 600,
  "current_rate": 613,
  "retry_after_seconds": 17
}

retry_after_seconds показывает, через сколько времени будет разрешен еще один request, если между ними ничего не отправлять: минимум 1 секунда и максимум 120. Header Retry-After содержит то же самое значение.

Для повторной отправки отклоненных requests с меньшим интервалом действует отдельное правило. Когда количество отклоненных этим лимитом requests за скользящую минуту превышает лимит в два раза, вызов отклоняется с паузой в 30 секунд:

{
  "error": "Rate limit cooldown: 1250 requests over your plan's 600 single requests per minute were refused in the last minute and kept arriving. Pause for 30 seconds.",
  "reason": "plan_limit_rate",
  "documentation": "https://foura.ai/prices",
  "limit_per_minute": 600,
  "current_rate": 540,
  "refused_last_minute": 1250,
  "cooldown": true,
  "retry_after_seconds": 30
}

Отказы во время паузы не учитываются, поэтому пауза завершается сама по себе по истечении минуты, даже если клиент продолжает повторять запросы. Чтобы отличить паузу от обычного лимита, используйте cooldown, а не текст error.

Запросы браузера в день

Для Browser нет поминутного лимита. Лимит тарифного плана представляет собой количество запросов браузера в день, подсчитываемое с полуночи UTC, и счетчик учитывает каждый принятый запрос браузера, а не только успешные.

{
  "error": "Daily browser limit reached: your plan allows 300 browser requests per day (resets at midnight UTC).",
  "reason": "plan_limit_browser_daily",
  "documentation": "https://foura.ai/prices",
  "limit_per_day": 300,
  "used_today": 301
}

Этот отказ не содержит retry_after_seconds и header Retry-After, так как ожидание составляет часы, а не секунды. Воспринимайте это как остановку и запланируйте следующий запуск на полночь UTC.

Кредиты за расчетный период

Учитываются только оплаченные кредиты, то есть только успешные request. Когда общая сумма списаний достигает лимита кредитов, доступных вам в этом периоде, последующие request отклоняются до сброса периода или покупки дополнительных кредитов.

{
  "error": "Credit limit reached: 75,000 of 75,000 credits used this billing period. Upgrade your plan or wait for the reset.",
  "reason": "plan_limit_credits",
  "documentation": "https://foura.ai/prices",
  "used": 75000,
  "hard_stop": 75000,
  "retry_after_seconds": 86400,
  "resets_at": "2026-10-01T00:00:00.000Z"
}

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

Трафик за расчетный период

Тарифные планы с лимитом трафика отклоняют запросы, как только стандартный трафик за текущий период достигает этого ограничения. Для премиум-трафика предусмотрен отдельный лимит, и он не учитывается в этом ограничении. Купленный трафик учитывается так же, как и включенный в тариф, а строка error указывает общий доступный объем, а не только то, что входит в базовый тарифный план.

{
  "error": "Bandwidth limit reached: 50 GB is available to you this billing period.",
  "reason": "plan_limit_bandwidth",
  "documentation": "https://foura.ai/prices",
  "used_bytes": 53687091200,
  "limit_bytes": 53687091200,
  "retry_after_seconds": 86400,
  "resets_at": "2026-10-01T00:00:00.000Z"
}

Для обоих периодических лимитов retry_after_seconds ограничен 24 часами; resets_at указывает точный момент смены периода.

Plan limit fields

Field Type Present on Description
error string all Понятное для человека сообщение, включая лимитирующее число
reason string all plan_limit_ и название лимита. То же значение, что и в заголовке X-FourA-Limit.
documentation string all Ссылка на страницу тарифных планов
retry_after_seconds number concurrency, rate, credits, bandwidth Время ожидания. То же значение, что и в заголовке Retry-After.
limit number concurrency Разрешенное тарифным планом число одновременных requests к этому endpoint
in_flight number concurrency Число requests, выполняемых на этом endpoint для вашего аккаунта, включая отклоненный
limit_per_minute number rate Разрешенное тарифным планом число requests в минуту к этому endpoint
current_rate number rate Число requests за скользящую минуту, включая отклоненный
refused_last_minute number rate pause Число requests, отклоненных минутным лимитом за скользящую минуту. Только при 30-секундной паузе.
cooldown boolean rate pause true при 30-секундной паузе из-за слишком частых повторных попыток. Отсутствует при обычном отказе по минутному лимиту.
limit_per_day number browser daily Разрешенное тарифным планом число browser requests в день
used_today number browser daily Число browser requests, учтенных за сегодня, включая отклоненный
used number credits Израсходованные credits за текущий период
hard_stop number credits Лимит credits, при достижении которого requests в текущем периоде блокируются
used_bytes number bandwidth Стандартный трафик за текущий период, в байтах. Трафик Premium не включен.
limit_bytes number bandwidth Доступный объем трафика в байтах на текущий период
resets_at string credits, bandwidth Метка времени окончания периода в формате ISO 8601

Лимиты тарифного плана используют retry_after_seconds. Описанные ниже лимиты платформы используют retryAfter. Модуль повторных попыток должен считывать оба параметра или проверять заголовок Retry-After, который задается только лимитами тарифа.

Platform Limits

Проверки платформы отслеживают два параметра для каждого сервиса и еще один общий для всех:

  • Concurrency: сколько requests FourA выполняет одновременно.
  • RPM: сколько requests FourA принял за последние 60 секунд.

Оба счетчика являются общими для всех пользователей сервиса. Поля current и limits в приведенных ниже ответах описывают платформу, а не ваш аккаунт. Чтобы узнать собственные значения, используйте in_flight из ответа о лимитах тарифа или откройте раздел Usage & Limits в панели управления.

429: RPM Exceeded

{
  "error": "Rate limit exceeded",
  "status": 429,
  "service": "single",
  "retryAfter": 5,
  "current": {
    "concurrency": 12,
    "rpm": 3000
  },
  "limits": {
    "maxConcurrency": 500,
    "maxRpm": 3000
  }
}

Сервис исчерпал лимит запросов за последнюю минуту. Подождите retryAfter секунд.

503: Concurrency Exceeded

{
  "error": "Service at capacity",
  "status": 503,
  "service": "proxy",
  "retryAfter": 2,
  "current": {
    "concurrency": 500,
    "rpm": 1200
  },
  "limits": {
    "maxConcurrency": 500,
    "maxRpm": 3000
  }
}

Сервис выполняет максимально допустимое количество одновременных запросов. Это проходит за несколько секунд.

Сервис отключен

Когда сервис временно недоступен из-за технического обслуживания, API возвращает 503 с другим сообщением об ошибке:

{
  "error": "Service disabled",
  "status": 503,
  "service": "single",
  "retryAfter": 60,
  "current": { "concurrency": 0, "rpm": 0 },
  "limits": { "maxConcurrency": 500, "maxRpm": 3000 }
}

Это не rate limit. Сервис временно недоступен. Проверьте значение retryAfter и повторите попытку через указанное количество секунд. Обычно это решается в течение нескольких минут.

Оба формата 503 содержат одинаковые ключи, поэтому делайте ветвление по строке error, а не по наличию определенных полей. Service disabled означает техническое обслуживание, Service at capacity означает параллелизм.

Для формата технического обслуживания current.concurrency и current.rpm всегда равны 0: request был отклонен до проведения каких-либо измерений.

Platform Limit Fields

Field Type Description
error string Читаемое сообщение об ошибке
status number HTTP status code (429 или 503)
service string Какой сервис отклонил вызов: single, proxy, browser или api
retryAfter number Рекомендуемое время ожидания в секундах перед повторной попыткой
current.concurrency number Requests, которые сервис выполнял на всей платформе в момент отказа
current.rpm number Requests, принятые сервисом на всей платформе за последние 60 секунд
limits.maxConcurrency number Лимит параллелизма сервиса на всей платформе
limits.maxRpm number Лимит сервиса в минуту на всей платформе

Handling Every Refusal With One Helper

Retry-After задан для лимитов тарифа, которых имеет смысл подождать, retry_after_seconds находится в их телах, а retryAfter находится в телах платформы. Считывайте все три в указанном порядке и останавливайтесь на тех лимитах тарифа, которые ожидание не сбросит:

import time
import requests

# Plan limits that a short wait never clears.
STOP_ON = {
    "plan_limit_feature",
    "plan_limit_premium",
    "plan_limit_browser_daily",
    "plan_limit_credits",
    "plan_limit_bandwidth",
}

def wait_seconds(resp, attempt):
    header = resp.headers.get("Retry-After")
    if header and header.isdigit():
        return int(header)
    try:
        body = resp.json()
    except ValueError:
        return 2 ** attempt
    return body.get("retry_after_seconds") or body.get("retryAfter") or 2 ** attempt

def fetch(url, api_key, max_retries=5):
    for attempt in range(max_retries):
        resp = requests.post(
            "https://eu.api.foura.ai/api/single/",
            headers={"X-API-Key": api_key, "Content-Type": "application/json"},
            json={"method": "GET", "url": url},
        )

        limit = resp.headers.get("X-FourA-Limit")
        if limit in STOP_ON:
            raise RuntimeError(f"stopped by plan limit {limit}: {resp.json().get('error')}")

        if resp.status_code in (429, 503):
            time.sleep(wait_seconds(resp, attempt))
            continue

        return resp

    raise RuntimeError("Max retries exceeded")

Дневной лимит не восстанавливается часами, а лимит периода не восстанавливается днями, поэтому воспринимайте их как полную остановку, а не как ожидание. Прочтите resets_at из тела ответа, если хотите запланировать следующий запуск.

Советы

  • Ограничивайте количество одновременных запросов in flight вместо повторной отправки отклоненной пачки. Шквал повторных попыток превращает одну ошибку 429 во множество.
  • Сначала проверяйте X-FourA-Limit. Этот параметр сразу показывает, относится ли лимит к вашему тарифу или к платформе, и ни один отказ платформы его не устанавливает.
  • Не прописывайте числа жестко в коде. Каждый ответ с ограничением тарифа содержит вызвавший отказ лимит, а раздел Usage & Limits отображает их все.
  • Значение retryAfter для ограничений платформы фиксировано по типу: 2 секунды для concurrency, 5 для RPM, 60 для технического обслуживания.
  • Сопоставляйте по error, чтобы различать два типа ошибок 503. Обе структуры содержат current и limits, поэтому простая проверка на наличие этих полей примет техническое обслуживание за проблему с concurrency.
  • Ошибка 403 с X-FourA-Limit относится к вашему тарифу, а не к целевому сайту. Целевой сайт вообще не отвечал.

Порт proxy имеет собственные лимиты

Все вышеперечисленное относится к JSON API. Трафик, отправляемый через proxy.foura.ai, регулируется отдельным набором лимитов тарифа в других единицах: одновременно открытые туннели, открытия туннелей в минуту и стандартный трафик за расчетный период. Эти отказы приходят в виде HTTP-статуса с заголовком X-Foura-Error, а не в виде JSON-тела, так как у CONNECT нет тела для передачи данных. Ознакомьтесь с Proxy Port для таблицы статусов и How Your Plan Is Metered, чтобы узнать, из какого пула списываются гигабайты порта.

Связанные разделы

  • Run Requests in Parallel: Готовый шаблон с ограничением concurrency
  • Usage & Limits: Все лимиты тарифа рядом с текущим расходом
  • API Endpoints: Полный справочник параметров
  • Error Handling: Все типы ошибок и ответов
  • Response Headers: X-FourA-Limit, Retry-After и остальные
  • Troubleshooting: Распространенные проблемы и их решения
Обновлено: 30 сентября 2026 г.