# Откуда в DexScreener API берутся новые пары

> У DexScreener API нет эндпоинта новых пар. Его документированные маршруты отдают профили, бусты, мета-тренды и точечные запросы пар, а нужная вам отметка времени создания приходит внутри ответа — как поле, по которому вы фильтруете сами.

- Источник: https://papaproxy.net/ru/blog/dexscreener-new-pairs.php
- Опубликовано: 2026-08-09
- Автор: Alex Young
- Рубрика: API и данные · Блог PapaProxy.net

---

## Ключевые выводы

- Эндпоинта новых пар нет, и ни один маршрут не принимает фильтр «создано после».
- Схема профиля не обещает отметки времени: «новое» — это то, чего ваш клиент ещё не видел.
- `pairCreatedAt` — поле объекта Pair, допускающее null: по нему фильтруют локально, а не запрашивают.
- Лимиты двухуровневые: 60 запросов в минуту у лент обнаружения и 300 у запросов пар и токенов.
- Ключуйте состояние по `chainId:pairAddress` — у токена позже могут появиться новые пулы.
- DexScreener — индексатор без опубликованной задержки обнаружения: быть первым на запуске можно только с ончейн-источником.

## Эндпоинт, который все ищут

Начнём с полной документированной поверхности — именно она закрывает вопрос. Публичный справочник на `api.dexscreener.com` перечисляет эти маршруты и никаких других:

| Маршрут | Лимит |
| --- | --- |
| `/token-profiles/latest/v1` | 60 запросов/мин |
| `/token-profiles/recent-updates/v1` | 60 запросов/мин |
| `/community-takeovers/latest/v1` | 60 запросов/мин |
| `/ads/latest/v1` | 60 запросов/мин |
| `/token-boosts/latest/v1`, `/token-boosts/top/v1` | 60 запросов/мин |
| `/orders/v1/{chainId}/{tokenAddress}` | 60 запросов/мин |
| `/metas/trending/v1`, `/metas/meta/v1/{slug}` | 60 запросов/мин |
| `/latest/dex/pairs/{chainId}/{pairId}` | 300 запросов/мин |
| `/latest/dex/search` | 300 запросов/мин |
| `/token-pairs/v1/{chainId}/{tokenAddress}` | 300 запросов/мин |
| `/tokens/v1/{chainId}/{tokenAddresses}` | 300 запросов/мин |

Маршрута «новые пары» в этом списке нет, как нет и маршрута, принимающего фильтр «создано после». Документация эндпоинта пар описывает точечный запрос: `/latest/dex/pairs/{chainId}/{pairId}` возвращает одну конкретную пару, адрес которой вы уже знаете. Того «эндпоинта последних пар», который ищут, — чтобы отдал всё созданное за последние десять минут, — в публичном API не существует. То, что сайт показывает на вкладке новых пар, документированным маршрутом не открыто.

Отсюда же растёт и сам поисковый спрос. Скринер новых пар на сайте заметно богаче документированного API: он фильтрует всю проиндексированную вселенную пар по возрасту, сети, ликвидности, объёму, лаунчпаду и наличию профиля и сортирует прямо по возрасту. Ни один документированный REST-запрос эту вселенную не открывает. Публичный API позволяет получить пары только после того, как у вас уже есть кандидат — токен или пара, — а это совсем другая точка старта.

Большую часть путаницы вокруг темы снимает разделение трёх задач:

| Задача | Откуда это берётся на самом деле |
| --- | --- |
| Каждый созданный пул в момент появления | Ончейн-RPC, подписка на логи или собственная лента лаунчпада |
| Новые или недавно обновлённые профили токенов | `/token-profiles/latest/v1` и `/token-profiles/recent-updates/v1` |
| Возраст уже найденной пары | Поле `pairCreatedAt` в объекте Pair |

Ещё две вещи стоит заметить, глядя на эту таблицу. Каждый вызов — обычный GET без ключа и аутентификации. И лимиты делятся на два уровня: 60 в минуту у «поисковых» маршрутов и 300 у запросов пар и токенов. Это различие определяет все дальнейшие решения: эндпоинты, которыми токены *находят*, — дефицитные, а те, которыми их *обогащают*, в пять раз щедрее.

## Что на самом деле возвращают token-profiles и token-boosts

Маршрут последних профилей токенов — ближайшее к ленте обнаружения, и его схема меньше, чем ожидают: `url`, `chainId`, `tokenAddress`, `icon`, `header`, `description` и массив `links`. И всё.

Перечитайте список и заметьте, чего схема **не обещает**: отметки времени. В документированном контракте нет ничего, что позволяло бы сортировать или фильтровать профили по возрасту, а слово «latest» описывает порядок, который применяет эндпоинт, а не поле, с которым можно работать.

На практике живой эндпоинт сейчас возвращает больше, чем перечислено в схеме, — отметку `updatedAt` вместе с полями вроде `cto` и `openGraph`. Это полезно знать, но с двумя оговорками, которые важнее самого удобства. Это **не** время создания пары: поле отражает активность по профилю, а не момент появления пула. И оно не входит в документированный контракт, то есть может измениться или исчезнуть без смены версии. Читайте его, если оно помогает вашему диффу, но не стройте на нём конвейер и никогда не подменяйте им `pairCreatedAt`.

Та же форма у community takeovers и у бустов: бусты добавляют данные о продвижении, а не о создании.

Отсюда прямое следствие для архитектуры: **состояние живёт в вашем клиенте, а не в API.** Вы опрашиваете, сравниваете полученный набор с уже сохранённым, и всё невиданное считается «новым». Пропустите опрос — и записи можно потерять совсем: курсора, с которого можно продолжить, здесь нет.

И эти ленты избирательны, но не совсем так, как это обычно описывают. Токены листятся на DexScreener автоматически, а метаданные профиля могут подтягиваться из внешних списков токенов; платный продукт расширенной информации — это способ предоставить или обновить эти данные быстрее и на своих условиях. Бусты же — прямо покупаемый продукт продвижения. Поэтому точная формулировка такая: перед вами лента **активности профилей и метаданных**, а не поток всех пулов, коснувшихся DEX за последнюю минуту. Для сканера это иногда ровно то, что нужно, а иногда — ровно то, что не нужно.

Эндпоинт последних токенов, на который ссылаются старые туториалы, — `/latest/dex/tokens/{tokenAddresses}` — относится к прежнему поколению этого API. Актуальный справочник документирует вместо него `/tokens/v1/{chainId}/{tokenAddresses}`, а «документация latest dex tokens», которую вы найдёте в постах годичной давности, указывает на устаревший путь. Используйте версионированный маршрут.

## Как фильтровать по pairCreatedAt постфактум

Вот здесь и находится настоящий ответ. Поле pairCreatedAt входит в объект **Pair** — ту форму, которую возвращают маршруты запроса пар и токенов, — и в схеме это целое число, допускающее null. Это Unix-время в миллисекундах, и допустимость null важна: часть пар приходит без него, поэтому код, считающий поле обязательным, упадёт на первой же такой.

Главное — это поле ответа, а не параметр запроса. Никакого `pairCreatedAt_gt` отправить нельзя. Поэтому рабочая схема двухэтапная: находим адреса токенов-кандидатов на лентах с лимитом 60 в минуту, затем запрашиваем их пары на маршрутах с лимитом 300 и фильтруем по возрасту локально.

PythonКопировать код

```python
import time, requests

BASE = "https://api.dexscreener.com"
HEAD = {"Accept": "application/json"}
seen_pairs: set[str] = set()      # keyed by pair, not by token — see note below

def latest_profiles():
    r = requests.get(f"{BASE}/token-profiles/latest/v1", headers=HEAD, timeout=15)
    r.raise_for_status()
    data = r.json()
    return data if isinstance(data, list) else [data]      # допускаем обе формы

def pairs_for_token(chain_id, token_address):              # уровень 300 запросов/мин
    r = requests.get(f"{BASE}/token-pairs/v1/{chain_id}/{token_address}",
                     headers=HEAD, timeout=15)
    r.raise_for_status()
    return r.json() or []

def fresh_pairs(max_age_minutes=60):
    cutoff_ms = (time.time() - max_age_minutes * 60) * 1000
    out = []
    for profile in latest_profiles():                      # кандидаты, перепроверяются каждый цикл
        for pair in pairs_for_token(profile["chainId"], profile["tokenAddress"]):
            key = f"{pair['chainId']}:{pair['pairAddress']}"
            if key in seen_pairs:                          # ваше хранилище — единственный курсор
                continue
            created = pair.get("pairCreatedAt")            # может быть null — не предполагайте
            if created and created >= cutoff_ms:
                seen_pairs.add(key)
                out.append(pair)
    return out

for p in fresh_pairs():
    age_min = (time.time() * 1000 - p["pairCreatedAt"]) / 60000
    print(f"{p['chainId']:<10} {p['baseToken']['symbol']:<12} {age_min:6.1f} мин  {p['url']}")
```

На что смотреть — и это та деталь, которую чаще всего реализуют неверно: **состояние ключуется по паре, а не по токену**. У одного токена может быть много пулов — именно поэтому `/token-pairs/v1/{chainId}/{tokenAddress}` возвращает список, — и если пометить как виденный токен, то новый пул, созданный для него завтра, не будет обнаружен никогда. Ключ `chainId:pairAddress` и перепроверка кандидатов каждый цикл это исправляют. `pairCreatedAt` читается через `.get` и проверяется на истинность, потому что в схеме допускает null. А два уровня лимитов соблюдены самой конструкцией: один вызов за цикл к ленте с лимитом 60 и более дешёвый маршрут с лимитом 300 для обогащения.

Чего пример намеренно не делает: нет персистентности, поэтому после перезапуска он сообщит обо всём заново (кладите `seen_pairs` в Redis или файл); нет отступления при упоре в лимит; нет устаревания списка кандидатов, поэтому набор токенов только растёт; нет обработки случая, когда у токена много пулов, а нужен самый ликвидный. И постоянная оговорка: токен попадает в этот цикл, только если у него есть профиль, — то есть даже корректный детектор по парам видит подмножество новых пар, а не все.

## Как сузить до одной сети

Большая часть поискового спроса вокруг темы касается одной сети, обычно Solana, и ответ API на «новые пары в Solana» снова непрямой. Ленты обнаружения не принимают параметр сети вовсе, поэтому фильтровать нужно по полю `chainId` уже после получения ответа — одной строкой в цикле выше.

Сеть как параметр пути есть у маршрутов запроса: `/token-pairs/v1/{chainId}/{tokenAddress}` и `/tokens/v1/{chainId}/{tokenAddresses}` для токенов, которые у вас уже есть, и `/latest/dex/pairs/{chainId}/{pairId}` для конкретной пары. Этим и исчерпывается «последние пары по сети» в документированном API: привязка к сети существует для запросов, но не для обнаружения.

Ещё два угла, о которых стоит знать. `/latest/dex/search` относится к уровню 300 в минуту и принимает свободный текстовый запрос — это удобно для обогащения и поиска пар по тикеру или адресу, хотя лентой новых пар по сети он тоже не является. И маршрут, который легко пропустить: `/metas/meta/v1/{slug}` возвращает полные объекты **Pair** пачкой по слагу тренда, — то есть если вас интересует тематика, а не полнота, это документированный способ получить много пар вместе с их `pairCreatedAt` одним вызовом уровня 60 в минуту.

Честное ограничение здесь архитектурное, а не числовое. DexScreener — индексатор, а не источник событий самой сети: токены листятся автоматически, как только появился пул и прошла хотя бы одна сделка, а логи блокчейна обрабатываются по собственному расписанию. Гарантии задержки обнаружения не публикуются, поэтому не предполагайте детерминированную цифру ни в одну сторону — и не берите её из чужого блог-поста. Если вашей стратегии важны секунды, обнаруживайте создание пула ончейн, а DexScreener используйте для обогащения того, что ваш стек уже нашёл.

## Поток вместо опроса

Естественный следующий вопрос — нельзя ли подписаться вместо опроса, и ответ утвердительный, только на странице, отдельной от REST-справочника. DexScreener документирует **WebSocket API** на `wss://api.dexscreener.com`, и его пути зеркалят REST-ленты: `/token-profiles/latest/v1`, `/token-profiles/recent-updates/v1`, `/token-boosts/latest/v1`, `/token-boosts/top/v1`, `/community-takeovers/latest/v1`, `/ads/latest/v1`.

Две вещи нужно знать до перехода. Нагрузка обёрнута: сервер присылает `{"limit": 90, "data": [ ... ]}`, а не голый массив, как REST, — и клиент, написанный под REST, сломается на лишнем слое. И потоки покрывают ровно ленты профилей и бустов, а не создание пар: подписка даёт активность профилей по факту и снимает задачу диффа из цикла выше, но всех новых пулов по-прежнему не выдаёт.

Поток помогает там, где опрос слабее всего: запись, появившаяся и исчезнувшая между двумя опросами, для поллера невидима, а для подписчика — нет. Чего он не меняет, так это стороны обогащения: вы всё так же тратите уровень 300 запросов в минуту, превращая кандидатов в пары с ликвидностью, объёмом и временем создания. И постоянное хранилище остаётся нужным: документация вебсокета описывает подключение и нагрузку, но не семантику переподключения, — считайте обрыв разрывом в состоянии, принимайте нагрузку рукопожатия за новую точку отсчёта и сверяйтесь с тем, что уже накоплено.

Инфраструктурным вопрос становится на масштабе: несколько сетей, несколько стратегий, растущий список наблюдения. Но с одним допущением здесь стоит быть осторожным. Справочник задаёт 60 и 300 запросов в минуту на эндпоинт, однако область действия ограничителя он не определяет: там не сказано, что бюджет считается по IP-адресу, не обещан независимый лимит каждому адресу и не описана модель всплесков. Поэтому правильный порядок такой: сначала измерьте область действия на живом поведении и только затем решайте, действительно ли отдельные воркеры получают независимые бюджеты. Что означают эти два уровня на практике, — в нашем [руководстве по лимитам DexScreener](/ru/blog/dexscreener-rate-limits.php). Если измерения это подтверждают, наши [персональные прокси](/ru/individual.php) дают выделенные IPv4-адреса, статичные на весь срок плана, по одному на воркера, — а перед масштабированием парка опроса сверьтесь с условиями использования DexScreener.
