Rate Limits

Всяка FourA API заявка преминава през три проверки, преди да достигне до даден engine: лимитите на вашия собствен план, след това споделения лимит на платформата за извикания endpoint, и накрая споделения лимит на платформата за целия трафик. Всяка проверка може самостоятелно да отхвърли заявка, като всяка от тях връща различно тяло на отговора.

Трите проверки по ред

  1. Лимити на плана. Какво позволява вашият собствен план: кои endpoint-и и параметри включва, колко заявки могат да се изпълняват едновременно за endpoint, колко в минута, колко заявки с браузър на ден, както и наличните кредити и трафик за отчетния период.
  2. Глобален лимит на платформата. Всичко, което API хостът, който сте извикали, обработва в този момент, независимо към кой endpoint е насочен трафикът. Отказ тук връща "service": "api".
  3. Лимит на платформата за endpoint. Трафикът към single, proxy или browser услугата, която сте извикали.

Вашият собствен план се оценява първи, като този ред е договорено условие, а не детайл от имплементацията. Споделените лимити са общ ресурс, така че заявка, която платформата така или иначе щеше да откаже, не трябва да ги изразходва по пътя към отхвърлянето си. Акаунт, който изпраща много повече от позволеното по неговия план, бива спрян, преди да засегне ресурси, от които черпят другите.

Проверки 2 и 3 отчитат общия трафик на FourA, а не вашия. Тълкувайте отказ от която и да е от тях като "FourA е зает", а не като "изпратихте твърде много". Проверка 1 се отнася само за вашия акаунт и нищо друго на платформата не ѝ влияе.

Отказ от която и да е от споделените проверки връща на вашия акаунт всичко, което допускането ѝ е отчело: както капацитета за минута, така и дневния слот за браузър, тъй като заявката никога не е достигнала backend. Това не се зачита и към паузата за повторен опит, описана в Заявки в минута: капацитетът на FourA я е отхвърлил, а не вашият план.

POST /api/auto/ няма собствен слот. Под-заявките за Single, Proxy и Browser, които тя извършва вместо вас, преминават и трите проверки като всяка друга заявка, така че паралелна група от автоматични повиквания се отчита към вашия план чрез своите под-заявки. (Вашият брой заявки и процент на успеваемост отчитат самото автоматично повикване еднократно; под-заявките се показват като негови опити.)

Лимити на плана

Лимит на плана отговаря с 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 Едновременни requests към този endpoint
plan_limit_rate 429 Requests в минута към този endpoint
plan_limit_browser_daily 429 Browser requests за деня
plan_limit_credits 429 Таксувани кредити за периода на фактуриране
plan_limit_bandwidth 429 Bandwidth за периода на фактуриране

Стойностите за всеки лимит зависят от вашия план, а разделът Limits & Features в Usage & Limits ги показва до текущото ви потребление в реално време. Не ги задавайте твърдо в кода: всеки отказ връща лимита, който го е предизвикал.

Отказаният request не изразходва нищо. Резултатът е rate_limit, като се таксува само success.

Endpoint или параметър извън плана

Грешка 403 с plan_limit_feature означава, че заявката изисква функционалност, която не е включена в плана. Проверката се извършва преди каквото и да е отчитане, така че отказаната заявка не засяга вашите rate limits или дневни броячи.

{
  "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 в план без geo targeting. Низът 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 при план без premium exits. FourA може вместо това да обслужи такава заявка от стандартния пул и да върне exitClass: standard в отговора, така че обработвайте и двата варианта. Нито един от тях не изразходва premium exit. Вижте exitClass.

Нито една грешка 403 не задава Retry-After. Изчакването няма да промени резултата.

Едновременни заявки

Concurrency се отчита за всеки endpoint: вашият план включва отделен лимит за Single, за Proxy и за Browser. Заявката, която надвишава лимита, се връща като 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 брои и отказаната заявка, така че отчита поне с едно повече от limit.

Решението е да ограничите собствения си паралелизъм, вместо да опитвате отново по-агресивно. Отговорът на 429 чрез незабавно повторно изпращане на същия batch генерира нов 429 за всяко повикване в него. Вижте Run Requests in Parallel за готов примерен модел.

Requests per minute

Single и Proxy имат лимит на минута, измерван през плъзгащ се едноминутен прозорец. Само приетите заявки се броят към него: отказаната заявка се премахва от сметката, така че акаунт, който постоянно изисква малко над лимита си, получава пълния си разрешен обем, вместо да му бъде отказано почти всичко.

{
  "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 показва след колко време би била допусната още една заявка, ако междувременно не изпращате нищо друго: най-малко 1 секунда и най-много 120. Retry-After header съдържа същата стойност.

Повторният опит за отказани заявки по-бързо от това има собствено правило. Когато броят на отказаните от този лимит заявки в рамките на плъзгащата се минута надвиши два пъти лимита, повикването се отказва с 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 requests на ден

Browser няма лимит за минута. Лимитът на плана му е брой browser requests на ден, броени от полунощ UTC, като броячът отчита всяка допусната browser request, а не само успешните.

{
  "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 и Retry-After header, тъй като изчакването е с часове, а не със секунди. Приемете го като спиране и насрочете следващото изпълнение за полунощ UTC.

Кредити за периода на фактуриране

Зачитат се само таксуваните кредити, което означава само успешни requests. Когато таксуваната обща сума достигне наличните за вас кредити за този период, по-нататъшните requests се отказват, докато периодът не се нулира или не закупите още.

{
  "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 е броят фактурирани кредити, при който заявките спират за този период. Четете го директно от body, вместо да го изчислявате: той вече включва всички допълнително закупени кредити към плана.

Трафик за периода на фактуриране

Плановете с лимит на трафика отказват заявки, след като стандартният трафик за този период го достигне. Премиум трафикът има отделен лимит и не се зачита към този таван. Закупеният трафик се отчита по същия начин като включения в плана, а низът 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 е точният момент, в който периодът се подновява.

Полета за лимити на плана

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

Лимитите на плана използват retry_after_seconds. Лимитите на платформата по-долу използват retryAfter. Помощната логика за повторни опити трябва да чете и двете или да чете хедъра Retry-After, който се задава само от лимитите на плана.

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

Проверките на платформата проследяват две стойности за всяка услуга и още една обща за всички тях:

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

Двата брояча се споделят от всички, които използват тази услуга. current и limits в отговорите по-долу описват платформата, а не вашия акаунт. Ако ви е необходима вашата стойност, прочетете in_flight от отговора за лимит на плана или отворете Usage & Limits в dashboard.

429: Превишен RPM

{
  "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: заявката е била отхвърлена, преди да бъде измерено каквото и да било.

Platform Limit Fields

Field Type Description
error string Четливо за хора съобщение за грешка
status number HTTP статус код (429 или 503)
service string Коя услуга е отказала повикването: single, proxy, browser или api
retryAfter number Препоръчително време за изчакване в секунди преди нов опит
current.concurrency number Заявки, които услугата е изпълнявала на ниво платформа при отказа
current.rpm number Заявки, които услугата е приела на ниво платформа през последните 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 секунди за конкурентност, 5 за RPM, 60 за поддръжка.
  • Съпоставете по error, за да различите двата вида 503. И двете структури съдържат current и limits, така че проверка за "налични ли са тези полета?" разчита поддръжката като проблем с конкурентността.
  • Грешка 403 с X-FourA-Limit е свързана с вашия план, а не с целевия сайт. Целевият сайт изобщо не е отговорил.

Портът за прокси има собствени стойности

Всичко по-горе се отнася за JSON API. Трафикът, който изпращате през proxy.foura.ai, се подчинява на отделен набор от стойности за плана в различна мерна единица: отворени тунели едновременно, отваряния на тунели в минута и стандартен трафик за отчетния период. Тези откази пристигат като HTTP статус с X-Foura-Error заглавка (header), а не като JSON тяло, тъй като CONNECT няма тяло, в което да се постави такова. Вижте Proxy Port за таблицата със статуси и How Your Plan Is Metered за това от кой пул се черпят гигабайтите на порта.

Свързани

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