Ключевые выводыЕдиного лимита нет: маршруты стоят либо на 60, либо на 300 запросах в минуту.
- Единого лимита нет: маршруты стоят либо на 60, либо на 300 запросах в минуту.
- Кураторские списки получают 60, а всё, что ключуется уже известным адресом, — 300.
- Обнаружение идёт по дефицитному уровню, а обогащение по щедрому — обратно тому, что закладывают в большинство схем.
- Пачка до 30 адресов в
/tokens/v1/поднимает теоретический потолок до 9 000 адресов токенов в минуту вместо 300. - Публичный справочник бесплатен и без ключа, а самостоятельного апгрейда в нём нет, но условия использования упоминают платную версию с лимитами, определяемыми при оформлении.
- Документация не описывает ни код ошибки, ни заголовки, ни сброс окна, ни область действия счётчика: считайте у себя и по каждому эндпоинту.
- Условия разрешают коммерческое использование, но запрещают конкурирующие продукты и перепродажу API третьим лицам.
Краткое содержание подготовлено с помощью ИИ.
Два лимита, а не один
Документация по лимитам указывает число в описании каждого эндпоинта, а не на отдельной странице, — поэтому и упускают, что лимитов два. Лимит запросов в минуту целиком зависит от того, какой маршрут вы вызываете:
| Уровень | Маршруты |
|---|---|
| 60 запросов/мин | /token-profiles/latest/v1, /token-profiles/recent-updates/v1, /community-takeovers/latest/v1, /ads/latest/v1, /token-boosts/latest/v1, /token-boosts/top/v1, /orders/v1/{chainId}/{tokenAddress}, /metas/trending/v1, /metas/meta/v1/{slug} |
| 300 запросов/мин | /latest/dex/pairs/{chainId}/{pairId}, /latest/dex/search, /token-pairs/v1/{chainId}/{tokenAddress}, /tokens/v1/{chainId}/{tokenAddresses} |
Одна оговорка, прежде чем строить вокруг этой таблицы конфиг: справочник правят на месте, и маршруты добавлялись и исчезали без смены версии. Считайте список снимком и сверяйте его с живым справочником перед релизом. Сами два числа — 60 и 300 — держатся стабильно.
И заметьте, что документация утверждает, а что нет. В описании каждого эндпоинта указан его собственный лимит; нигде не сказано, черпают ли маршруты с одинаковым числом из общего ведра или считаются независимо. Деление 60/300 удобно для разговора об API, но это не документированное утверждение об устройстве ограничителя.
У этого разделения есть внутренняя логика, стоит её заметить. Уровень 60 в минуту — это всё, что возвращает кураторский список: профили, бусты, реклама, community takeovers, трендовые меты, — где данные меняются медленно, а все вызывающие получают один и тот же ответ. Уровень 300 в минуту — всё, что ключуется адресом, который у вас уже есть. DexScreener щедр там, где ваши запросы конкретны, и скуп там, где они широкие.
Это переворачивает экономику, которую обычно предполагают. Обнаружение — поиск нового — идёт по дефицитному бюджету, а обогащение, то есть оценка и измерение найденного, — по щедрому. Любая схема, которая агрессивно опрашивает ленту обнаружения и скупо запрашивает пары, устроена наоборот. Если ваша цель — новые пары через API, двухэтапная схема — опрос профилей на 60, обогащение на 300 — как раз то, что описывает эта таблица.
Одно число для перспективы: 60 запросов в минуту — это раз в секунду, и именно этот потолок вам позволено закладывать в план независимо от того, как часто на самом деле меняются данные. А вот на стороне запросов число в минуту значит куда больше — и здесь в дело вступает группировка.
Какие маршруты сидят на 60
Проще запомнить закономерность, чем список: если маршрут возвращает список, который вы не параметризовали, он на уровне 60. Профили latest и recent-updates, community takeovers, реклама, оба буст-маршрута, трендовые меты, мета по слагу — ни один не принимает фильтр по сети, возрасту или размеру, поэтому все получают по сути одну и ту же нагрузку, и 60 вызовов в минуту с запасом хватает, чтобы держать её свежей.
Единственный маршрут этого уровня, не являющийся кураторским списком, — /orders/v1/{chainId}/{tokenAddress}: он проверяет оплаченные заказы по конкретному токену и параметризован, но всё равно ограничен шестьюдесятью. Если ваш конвейер проверяет статус заказов по каждому токену, именно этот эндпоинт упрётся в лимит первым, а не запросы пар вокруг него.
Публичный лимит API действует без всякого ключа: каждый маршрут в справочнике — неаутентифицированный GET, и рядом с опубликованными числами 60 и 300 не описано никакого самостоятельного пути апгрейда. Но это не вся картина. Условия использования API от DexScreener прямо говорят, что пользователь может выбрать между бесплатной и платной версией API Services, причём спецификации — в том числе ограничение частоты и число запросов в секунду — определяются при оформлении. То есть «бесплатный тариф» разумно описывает то, что открывает публичный справочник, но не доказывает отсутствия более высокого уровня: если нужен запас, это разговор с DexScreener, а не параметр, который можно отправить.
Как уместить 30 адресов в один вызов
Вот рычаг, который меняет арифметику проекта. /tokens/v1/{chainId}/{tokenAddresses} принимает, дословно по справочнику, один или несколько адресов токенов через запятую — до 30 адресов — и возвращает пары по всем сразу одним ответом. И относится он к уровню 300 в минуту.
Перемножим: 30 адресов × 300 вызовов в минуту = 9 000 адресов токенов в минуту с одного вызывающего против 300, если запрашивать по одному адресу через /token-pairs/v1/{chainId}/{tokenAddress}. Тридцатикратная разница ценой одного join.
import requests
BASE = "https://api.dexscreener.com"
HEAD = {"Accept": "application/json"}
def chunks(items, size=30): # документированный потолок: 30 адресов на вызов
for i in range(0, len(items), size):
yield items[i:i + size]
def pairs_for_tokens(chain_id, addresses):
out = []
for batch in chunks(addresses):
r = requests.get(f"{BASE}/tokens/v1/{chain_id}/{','.join(batch)}",
headers=HEAD, timeout=15)
if r.status_code == 429: # не документировано, но обработать стоит
raise RuntimeError("упёрлись в лимит — отступить и повторить")
r.raise_for_status()
out.extend(r.json() or [])
return out
# 90 токенов → 3 вызова вместо 90
pairs = pairs_for_tokens("solana", token_list)
print(len(pairs), "пар из", len(token_list), "токенов")
На что смотреть: разбиение на части — это и есть весь смысл, а потолок пачки жёсткий, ровно 30; отправите 31 — полагаетесь на неопределённое поведение. Учтите и то, что один токен может вернуть несколько пар, поэтому длина ответа не совпадёт с длиной входа: ключуйте результаты по pairAddress, а не рассчитывайте на соответствие один к одному.
Чего пример намеренно не делает: нет отступления, нет ретраев, нет контроля параллелизма. Добавьте это до запуска на большом списке — при 300 вызовах в минуту наивный цикл с параллельными воркерами пересечёт черту быстро.
Арифметика планирования следует напрямую — с одной честной пометкой: это теоретические минимумы при опубликованном лимите, в предположении 300 равномерно доступных вызовов в минуту и отсутствия всплесковых или глобальных ограничителей, которых документация не описывает:
| Токенов под наблюдением | Вызовов за цикл | Теоретический минимум обновления |
|---|---|---|
| 300 | 10 | 2 секунды |
| 1 000 | 34 | 7 секунд |
| 5 000 | 167 | 34 секунды |
| 9 000 | 300 | 60 секунд |
Планируйте ниже этих цифр, а не по ним. За пределами примерно девяти тысяч адресов токенов при минутном цикле опубликованный бюджет одного вызывающего заканчивается — и с этого момента вопрос перестаёт быть про код.
Что происходит при упоре в лимит
Здесь честный ответ таков: документация об этом не говорит. Справочник задаёт числа и форму ответа 200 для каждого маршрута; он не определяет ни кода состояния при превышении, ни того, сообщают ли какие-либо заголовки об остатке бюджета, ни того, как сбрасывается окно, ни — что важнее всего — на что именно ключуется счётчик.
Проектируйте с учётом этой неопределённости, а не в обход неё:
Считайте на своей стороне. Раз ни одно поле ответа не документировано как индикатор остатка, единственный надёжный бюджет — собственный счётчик; и пока вы не измерили обратное, считайте по каждому эндпоинту отдельно, а не по уровню, потому что документация нигде не говорит, делят ли маршруты с одинаковым числом общее ведро. Счётчик считайте авторитетным, а любую ошибку — подтверждением того, что предел уже пройден.
Обрабатывайте 429, но не полагайтесь на него. Общепринятый ответ — HTTP 429, и сниппет выше его проверяет, — но поскольку он не документирован, не стройте логику в расчёте на то, что придёт заголовок Retry-After с полезным значением. Экспоненциальный откат с джиттером, ведомый вашим собственным счётчиком, переживёт любое фактическое поведение сервера.
Следите и за задержкой, а не только за кодами. Некоторые площадки сначала троттлят и лишь потом отклоняют, и клиент, который алертит только на коды ошибок, будет выглядеть здоровым, пока его данные устаревают. Снимайте p95 длительности запроса по каждому маршруту.
Не предполагайте область действия. Ключа нет, а значит, нет и аккаунта, к которому можно привязать расход, — то есть счётчик может ключеваться только на что-то сетевого уровня. Но справочник этого не утверждает, не обещает независимого бюджета каждому адресу и не описывает модель всплесков. Измерьте фактическое поведение, прежде чем проектировать парк вокруг предположения о нём.
Последний пункт — то место, где появляется инфраструктура, и только после того, как исчерпаны программные рычаги: группируйте по 30, кешируйте ленты профилей вместо повторного опроса, опрашивайте обнаружение не чаще, чем меняются данные, и обогащайте по адресам, а не широким обходом. За этими рычагами — если ваши замеры подтвердят, что отдельные вызывающие действительно получают отдельные бюджеты, — наши персональные прокси дают выделенные IPv4-адреса, статичные на весь срок плана, по одному на воркера, чтобы всплеск одной задачи не съедал квоту другой. И прочитайте условия использования API до масштабирования — они конкретны, а не расплывчаты: коммерческое использование разрешено, но нельзя строить и продвигать продукт, чья основная цель — прямая конкуренция с DexScreener, и нельзя перепродавать, сублицензировать или иначе предоставлять API Services третьим лицам.