# DEX Token Price & Liquidity Monitor (`praise-most-high/dex-token-price-monitor`) Actor

Live on-chain pool prices, liquidity and 24h volume for any token or pair across every chain Dexscreener indexes, with built-in change detection for scheduled monitoring.

- **URL**: https://apify.com/praise-most-high/dex-token-price-monitor.md
- **Developed by:** [angel nguyen](https://apify.com/praise-most-high) (community)
- **Categories:** Automation, Other, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.30 / 1,000 pool records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

> **Run it without installing anything:** [apify.com/praise-most-high/dex-token-price-monitor](https://apify.com/praise-most-high/dex-token-price-monitor)
> — this repository is the MIT-licensed source of that Actor. Clone it, `apify push` your own
> copy, or just run the hosted one. No API key is required by the upstream this Actor reads.

## DEX Token Price & Liquidity Monitor

> **Unofficial.** This Actor is **not affiliated with, endorsed by, or sponsored by Dexscreener.**
> "Dexscreener" is used here only to name the public API this Actor reads. It is an independent
> tool that calls Dexscreener's own documented public endpoints.

Look up the live on-chain price of any token or pool — across every chain Dexscreener indexes —
and diff this run against the last one, so you see what **moved**, not just what **is**.

Every row carries the numbers that actually change: `priceUsd`, `liquidityUsd`, `volume24h`,
`priceChange24hPct`, `fdv`, `marketCap`, and the 24h buy/sell split. Point it at a watchlist,
schedule it hourly, and in `changesOnly` mode it emits only the pools whose watched fields moved.

### What it is good for

- **Price & liquidity watch** — get a row the moment a pool's price moves more than *n*%, or its
  liquidity drains.
- **Cross-DEX comparison** — turn `allPoolsPerToken` on and one token returns every pool it
  trades in, on every DEX on that chain, priced side by side.
- **Treasury / portfolio marking** — mark a bag to a real, tradeable pool price rather than to a
  thin quote, using `minLiquidityUsd` to throw the thin pools away.
- **Listing and launch monitoring** — `pairCreatedAt` plus a scheduled run tells you when a new
  pool appears for a token you follow.

### What it is not

It does not scrape the Dexscreener **website**, it does not solve a CAPTCHA, and it does not use
a headless browser or a proxy pool. It calls `api.dexscreener.com`, the documented public API
host — which is why it is fast and stable. It returns **market data only**: no wallets, no
traders, no holders, no personal data of any kind.

**Data freshness.** Straight from the API on every run; nothing is cached between runs. Measured
2026-08-22: the WBNB/USDT pool on PancakeSwap moved `priceUsd` 693.79 → 694.57 and changed its
liquidity and 24h volume **inside 20 seconds**. These fields genuinely move — the change event is
not billing for a diff that never fires.

### Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `tokens` | string\[] | `[]` | `chain:address`, e.g. `bsc:0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c`. |
| `allPoolsPerToken` | boolean | `false` | Off → one row per token (its deepest pool). On → every pool that token trades in. |
| `pairs` | string\[] | `[]` | `chain:pairAddress`. The most precise and cheapest input if you already know the pool. |
| `searchTerms` | string\[] | `[]` | Free-text pool search, e.g. `WBNB USDT`. |
| `resultsPerSearchTerm` | integer | `20` | Cap per search term (1–100). Ignored for token/pair lookups. |
| `minLiquidityUsd` | integer | `0` | Drop pools thinner than this. A price off an empty pool is not a price. |
| `changesOnly` | boolean | `false` | Emit a row only when a watched field differs from the previous run. |
| `watchFields` | string\[] | `["priceUsd","liquidityUsd","volume24h"]` | Any output field is valid. |
| `minChangePct` | integer | `0` | Noise gate for numeric watched fields. `0` reports every movement. |
| `maxConcurrency` | integer | `5` | Deliberately conservative — see Responsible use. |

`changesOnly` keeps its previous snapshot in the Actor's own named key-value store, keyed by
`chainId + pairAddress`. **The first run has no baseline, so it emits everything and says so in
the log** — it is not silently pretending nothing changed.

At least one of `tokens`, `pairs`, `searchTerms` must be non-empty; the Actor exits with a clear
message rather than a silent empty dataset if all three are blank.

#### Chain IDs

Dexscreener's own, lower-case: `ethereum`, `bsc`, `solana`, `base`, `polygon`, `arbitrum`,
`avalanche`, `optimism`, and the rest of its coverage. A `chain:address` that Dexscreener does
not index simply returns no pools — the Actor logs it rather than inventing a row.

### Output

One dataset item per pool per run:

```
chainId, dexId, pairAddress, labels[], pair,
baseTokenAddress, baseTokenName, baseTokenSymbol,
quoteTokenAddress, quoteTokenName, quoteTokenSymbol,
priceUsd, priceNative,
liquidityUsd, liquidityBase, liquidityQuote,
fdv, marketCap,
volume24h, volume6h, volume1h,
priceChange24hPct, priceChange6hPct, priceChange1hPct,
txns24hBuys, txns24hSells,
pairCreatedAt, pairUrl, scrapedAt
```

Plus, when `changesOnly` is on: `changedFields[]`, `previous{}`, `changePct{}`, `previousSeenAt`.

One honest wrinkle in the upstream, passed through rather than hidden: for some pools
Dexscreener returns a raw factory **contract address** in `dexId` instead of a DEX name (e.g.
`0x97bCD9BB…` rather than `pancakeswap`). The Actor reports what the API returns; it does not
guess a name.

### Pricing, in plain words

Pay-per-event. `actor-start` is charged once per run at the platform minimum. `pair-record` is
charged per row emitted. `price-change` is charged **in addition to** `pair-record` for a row
that carries a diff — a change row is a strict superset of a pool record, and it is priced as
one extra event, not as a hidden multiplier. A run that finds nothing charges the start event
and nothing else.

Every price is published on the Actor's Store page. Free-plan pricing is the list price; Apify's
own subscription-tier discounts apply on top of it.

### Responsible use

**Public data only.** The Actor reads `api.dexscreener.com`, a documented public API. No account,
no API key, no session cookie, no CAPTCHA solving, no headless browser, no proxy rotation.

**Never the website.** `dexscreener.com` itself sits behind a Cloudflare managed challenge — even
its `robots.txt` is challenged. This Actor **never touches the website and never attempts to pass
a challenge.** Only the open API host is used. If that host starts refusing, the Actor backs off
and says so rather than routing around.

**No personal data.** Pools, tokens and prices. No wallet addresses of persons, no trader
rankings, no holder lists, no identities.

**Rate limits, as published.** `docs.dexscreener.com/api/reference` (read 2026-08-22) publishes
**300 requests/minute** for every endpoint this Actor uses — `/latest/dex/search`,
`/latest/dex/pairs/{chain}/{pair}`, `/tokens/v1/{chain}/{addresses}` and
`/token-pairs/v1/{chain}/{address}`. `maxConcurrency` defaults to **5**, token lookups are
batched up to 30 addresses per request to use fewer of them, and the Actor backs off 30s on a
429 rather than retrying hard.

**Your obligations as a user.** On-chain prices are facts, but Dexscreener's aggregation is
Dexscreener's work — attribute it if you republish. This is a research and monitoring tool, not
a redistribution pipeline, and nothing it returns is financial advice.

# Actor input Schema

## `tokens` (type: `array`):

Tokens to look up, as chain:address. By default you get the token's single deepest pool — one row per token. Chain IDs are Dexscreener's own: bsc, ethereum, solana, base, polygon, arbitrum, avalanche, …

## `allPoolsPerToken` (type: `boolean`):

Off: one row per token — its deepest pool (batched, up to 30 tokens per request). On: every pool the token trades in on that chain, which is where cross-DEX price differences show up. On costs more, because it returns many more rows.

## `pairs` (type: `array`):

Specific pools to look up, as chain:pairAddress. Use this when you already know the exact pool you care about — it is the cheapest and most precise input.

## `searchTerms` (type: `array`):

Free-text pool search, e.g. "WBNB USDT". Handy for discovery, but a search result set changes between runs — for monitoring, resolve once and then watch the pair addresses.

## `resultsPerSearchTerm` (type: `integer`):

Cap on pools kept per search term. Ignored for token and pair lookups.

## `minLiquidityUsd` (type: `integer`):

Drop pools thinner than this. A price quoted off a near-empty pool is not a price anyone can trade at; 0 keeps everything.

## `changesOnly` (type: `boolean`):

Compare each pool against the previous run's snapshot and emit a row ONLY when a watched field changed. The first run has no baseline, so it emits everything and says so in the log.

## `watchFields` (type: `array`):

Fields compared when 'Emit changes only' is on. Any output field is valid — priceUsd, liquidityUsd, volume24h, fdv, marketCap, txns24hBuys, …

## `minChangePct` (type: `integer`):

Noise gate for 'Emit changes only'. A numeric watched field must move at least this much before it counts as a change. 0 reports every movement — on a live pool that is almost every run.

## `maxConcurrency` (type: `integer`):

Concurrent requests to api.dexscreener.com. Dexscreener publishes a 300 requests/minute limit on these endpoints; the default sits far below it on purpose.

## Actor input object example

```json
{
  "tokens": [
    "bsc:0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
    "ethereum:0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
  ],
  "allPoolsPerToken": false,
  "pairs": [],
  "searchTerms": [],
  "resultsPerSearchTerm": 20,
  "minLiquidityUsd": 0,
  "changesOnly": false,
  "watchFields": [
    "priceUsd",
    "liquidityUsd",
    "volume24h"
  ],
  "minChangePct": 0,
  "maxConcurrency": 5
}
```

# Actor output Schema

## `records` (type: `string`):

No description

## `csv` (type: `string`):

No description

## `datasetView` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "tokens": [
        "bsc:0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
        "ethereum:0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
    ],
    "watchFields": [
        "priceUsd",
        "liquidityUsd",
        "volume24h"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("praise-most-high/dex-token-price-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "tokens": [
        "bsc:0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
        "ethereum:0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    ],
    "watchFields": [
        "priceUsd",
        "liquidityUsd",
        "volume24h",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("praise-most-high/dex-token-price-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "tokens": [
    "bsc:0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
    "ethereum:0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
  ],
  "watchFields": [
    "priceUsd",
    "liquidityUsd",
    "volume24h"
  ]
}' |
apify call praise-most-high/dex-token-price-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,praise-most-high/dex-token-price-monitor"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/NiotKXttym1SKtsup/builds/oOsEUAWLjTaNpzJeW/openapi.json
