Key takeawaysThere is no trending endpoint: the site's ranking is computed and not published through the API.
- There is no trending endpoint: the site's ranking is computed and not published through the API.
- Boosts multiply an existing Trending Score rather than creating it, so boosted tokens and trending tokens overlap but aren't the same list.
- Boost objects carry only
amountandtotalAmounton top of profile fields — no price, liquidity or timestamp. - Boosts last 12–24 hours per pack, and 500 active boosts unlock the Golden Ticker, which is a computable threshold.
- Neither boost route filters by chain, so a Solana-only scanner costs the same discovery budget as a multi-chain one.
- The score's inputs are named but its weights aren't, and two of them — page visits and community reactions — aren't in any API, so the ranking can't be rebuilt.
- A separate docs page at
docs.dexscreener.com/api/websocketspublishes a WebSocket API for the same feeds, wrapping payloads as{limit, data}.
This summary was created with AI.
DexScreener's trending list is a ranking the site computes and doesn't publish. The API's nearest routes return boosted tokens — paid promotions — which correlate with trending but aren't the same list, and knowing the difference decides whether your scanner is measuring the market or measuring marketing budgets.
What the site shows and what the API returns
The site's trending list ranks tokens by a Trending Score computed from on-chain and off-chain metrics. The API exposes no route for it. There is no trending endpoint, no trending pairs feed, and no parameter on any documented route that sorts by rank.
What exists instead sits under /token-boosts/: latest/v1 for tokens that were just boosted and top/v1 for tokens with the most active boosts. Both are documented at 60 requests a minute — the scarce tier in our DexScreener rate-limit guide. The trending endpoint documentation people go looking for is, in practice, the boosts documentation — and the substitution is only sometimes valid.
Before the relationship between the two, it's worth seeing what the score is made of — because that explains why no amount of public-API work reconstructs it. DexScreener names the inputs but not the formula:
| Documented inputs to the Trending Score | Not published |
|---|---|
| Volume, liquidity, transactions | The weight of each input |
| Unique makers and holders | How inputs are normalised or decayed |
| Visits to the token page | How boost multipliers combine with the rest |
| Community reactions | How ties and cooldowns are handled |
| Verified / Enhanced Token Info | The refresh cadence of the ranking |
| Security and audit signals |
Two of those inputs — page visits and community reactions — aren't on-chain at all and aren't exposed through any API route, so even a perfect replica of the on-chain half would be missing terms of the equation. That's the structural reason the ranking can't be rebuilt from the public API rather than merely being absent from it.
Here's the relationship, stated as precisely as the docs allow. Boosts don't create the ranking; they multiply an existing Trending Score. DexScreener says so directly: boosts apply a multiplier to a token's existing score and don't replace the other on-chain and off-chain metrics in the ranking algorithm, so a token with weak fundamentals won't reach the top just by buying them. Two consequences follow, and they point in opposite directions. A heavily boosted token is likely to be visible on the trending list, so top/v1 is a decent proxy for "what's being promoted into view right now". But the trending list also contains tokens that bought nothing, and the boost feeds contain tokens whose fundamentals never lifted them anywhere. Treat boosts as a signal about promotion spend, not as the ranking.
One more distinction worth keeping straight, because search results conflate them. DexScreener also runs a Metas product — curated thematic narratives, each aggregating many tokens — and it is a different thing again from the trending list of pairs. Whether the public API reference currently exposes a Metas route has changed over time; the reference is edited in place and routes have appeared and disappeared without a version bump, so check the live page rather than any article, this one included.
Two small traps that show up in real query logs. Searching /latest/dex/search?q=trending returns tokens whose name or symbol literally contains the word "trending" — search matches text, not rank. And /orders/v1/{chainId}/{tokenAddress} lists order types that include trendingBarAd: that's a purchased advertising placement on the trending bar, not a Trending Score and not an organic position in the ranking. A token with a paid trendingBarAd order is a token that bought a banner slot, which is worth knowing before you treat it as a ranking signal.
How boosts actually work
Understanding the product explains the data. A boost is purchased in packs, lasts 12 to 24 hours depending on the pack, and the active count is displayed next to the token across the platform. At 500 or more active boosts a token earns the Golden Ticker, which turns its symbol gold sitewide. Not everything is eligible: tokens inactive for over 24 hours, or flagged for security risk by third-party audit partners, can't be boosted; purchases are non-refundable; and boosts can be removed if moderators or auditors flag the token as malicious.
The API objects mirror that model. Both boost routes return the same shape — the token-profile fields (url, chainId, tokenAddress, icon, header, description, links) plus two numbers:
| Field | Meaning |
|---|---|
amount |
Boosts in this purchase |
totalAmount |
Total active boosts on the token |
That pair is the whole analytical value of the boosted pairs endpoint, though the schema only names the fields without defining them. In the live feed the behaviour is legible: amount tracks the amount attached to that boost event, while totalAmount reflects the token's active total — the same token can appear several times with amount of 10 and 30 against a single totalAmount of 70, while another shows amount 500 against totalAmount 550. Read that as observed behaviour rather than a documented contract, and it still supports the useful inference: repeated small events mean visibility bought in increments, one large event means a single push. And totalAmount crossing 500 is the Golden Ticker threshold — a computable event, unlike the ranking itself.
What the boost objects don't carry is any timestamp, price, liquidity or volume. They identify a token and its promotion, nothing more. To learn whether a promoted token is worth anything you enrich it through the pair routes, which sit at 300 requests a minute:
import requests
BASE = "https://api.dexscreener.com"
HEAD = {"Accept": "application/json"}
def top_boosted(): # 60 req/min tier
r = requests.get(f"{BASE}/token-boosts/top/v1", headers=HEAD, timeout=15)
r.raise_for_status()
data = r.json()
return data if isinstance(data, list) else data.get("data", [])
def enrich(chain_id, addresses): # 300 req/min tier, 30 per call
out = []
for i in range(0, len(addresses), 30):
batch = ",".join(addresses[i:i + 30])
r = requests.get(f"{BASE}/tokens/v1/{chain_id}/{batch}", headers=HEAD, timeout=15)
r.raise_for_status()
out.extend(r.json() or [])
return out
boosts = {b["tokenAddress"]: b for b in top_boosted() if b["chainId"] == "solana"}
for pair in enrich("solana", list(boosts)):
b = boosts[pair["baseToken"]["address"]]
liq = (pair.get("liquidity") or {}).get("usd") or 0
print(f"{pair['baseToken']['symbol']:<12} boosts={b['totalAmount']:>5.0f} liq=${liq:>12,.0f}")
What to look at: boosts come from the scarce tier and enrichment from the generous one, batched 30 addresses per call. The liquidity object is nullable, hence the defensive or {}. And the join is on baseToken.address — a boosted token can appear in several pairs, so decide whether you want the deepest pool or all of them.
What this doesn't do: no deduplication across polls, no persistence, no rate-limit backoff, and no chain grouping — the filter above handles one chain at a time by design, which is the next section.
Filtering boosted tokens by chain
Neither boost route takes a chain parameter. Both return a mixed list across every chain DexScreener indexes, so trending tokens on Solana — or on Base, or anywhere else — means filtering chainId client-side, exactly as in the snippet above.
That has a budget implication worth planning for. Because you can't ask the API for one chain, you pay the same 60-per-minute cost regardless of how narrow your interest is, and a multi-chain scanner and a Solana-only scanner consume identical discovery budget. The savings appear on the enrichment side: /tokens/v1/{chainId}/{tokenAddresses} is chain-scoped, so group your filtered addresses by chain and batch each group separately — the same two-tier pattern our new-pairs guide describes for profile polling and pair lookup.
The practical shape, then, is one call per cycle to a boost route, a client-side split by chainId, and one batched enrichment call per chain per thirty addresses.
Streaming boosts instead of polling
Here's the part most write-ups miss: DexScreener publishes a WebSocket API on its own documentation page — docs.dexscreener.com/api/websockets, separate from the REST reference and easy to miss because nothing on the reference page links to it. Its OpenAPI title is "DEX Screener Websocket API", the base is wss://api.dexscreener.com, and the paths mirror the REST ones — /token-boosts/latest/v1, /token-boosts/top/v1, /token-profiles/latest/v1, /token-profiles/recent-updates/v1, /community-takeovers/latest/v1, /ads/latest/v1.
The message shape differs from REST in a way you need to handle. On connection the server responds with a handshake object rather than a bare array:
{ "limit": 90, "data": [ { "chainId": "solana", "tokenAddress": "...", "amount": 10, "totalAmount": 520, "url": "..." } ] }
So the payload is {limit, data}, with data holding the same Boost objects the REST route returns. Code written against the REST response will break on the extra wrapper — parse defensively, as the snippet above does.
For a boost monitor this is the better transport, and not because of rate limits. A stream removes the diffing problem: with polling you compare each response against your own store to find what changed, and anything that appears and disappears between two polls is invisible to you. With a subscription you receive updates as they happen, which for a feed whose whole point is "who just paid for visibility" is the difference between catching a spend and inferring one.
Two caveats before you rewrite your scanner. The trending list itself still isn't there — streaming boosts streams boosts, not the site's ranking. And the WebSocket documentation covers the connection and the payload but not reconnect semantics, so treat a dropped connection as a state gap: reconnect, take the handshake payload as your new baseline, and reconcile against your store rather than assuming continuity.
Where does infrastructure come in? Mostly it doesn't, for this workload. One WebSocket connection replaces a polling loop entirely, and the enrichment side batches thirty addresses per call. Scale becomes a question only when you run many independent monitors — separate chains, separate strategies, separate customers — and even then the first move is consolidating them behind one stream and one enrichment worker rather than multiplying pollers. If after that you still need parallel workers with separate budgets, our proxies for crypto projects provide dedicated IPv4 addresses, static for the full plan term, one per worker — measure the limiter's scope first, since the documentation doesn't define it, and read the API terms: commercial use is allowed, but building a product that competes directly with DexScreener, or reselling the API to third parties, is not.