Skip to content

muhammetakkurtt/dexscreener-realtime-client

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

13 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

DexScreener Realtime Client

Node.js/TypeScript SDK and CLI for consuming real-time WebSocket streams from the DexScreener Realtime Monitor Apify Actor. This client makes it easy to integrate real-time DexScreener data into your backends, bots, and data pipelines with flexible authentication and automatic reconnection.

Documentation

  • User Guide - Complete tutorials, examples, and best practices
  • API Reference - Technical reference for all classes and methods
  • Examples - Working code examples

Prerequisites

Quick Start

  1. Clone the repository:
git clone https://github.com/muhammetakkurtt/dexscreener-realtime-client.git
cd dexscreener-realtime-client
  1. Install dependencies:
npm install
  1. Build the project:
npm run build
  1. Configure environment variables:
cp .env.example .env
# Edit .env with your credentials
  1. Run an example:
npx tsx examples/basic-sdk.ts

Configuration

Create a .env file in the project root with the following variables:

Variable Description
APIFY_TOKEN Your Apify API token for authentication
DEX_ACTOR_BASE Base URL for your DexScreener Realtime Monitor Actor (supports http/https/ws/wss protocols)

Example:

APIFY_TOKEN=apify_api_xxxxxxxxxxxxx
DEX_ACTOR_BASE=https://muhammetakkurtt--dexscreener-realtime-monitor.apify.actor

Protocol Normalization: The SDK automatically converts HTTP/HTTPS URLs to WebSocket (WS/WSS) protocols:

  • http:// β†’ ws://
  • https:// β†’ wss://
  • ws:// and wss:// are used as-is

You can provide the base URL in any format - the SDK handles the conversion automatically.

SDK Usage

Quick Start - Minimal Configuration

The simplest way to get started with default settings:

import { DexScreenerStream } from './dist/index.js';

const stream = new DexScreenerStream({
  baseUrl: process.env.DEX_ACTOR_BASE!,
  apiToken: process.env.APIFY_TOKEN!,
  pageUrl: 'https://dexscreener.com/solana?rankBy=trendingScoreH6&order=desc',
  
  onPair: (pair) => {
    console.log(`${pair.baseToken?.symbol}: $${pair.priceUsd}`);
  },
});

stream.start();

Basic Stream with Authentication Modes

The SDK supports flexible authentication strategies:

import { DexScreenerStream } from './dist/index.js';

const stream = new DexScreenerStream({
  baseUrl: process.env.DEX_ACTOR_BASE!,
  apiToken: process.env.APIFY_TOKEN!,
  pageUrl: 'https://dexscreener.com/solana?rankBy=trendingScoreH6&order=desc',
  streamId: 'solana-trending',
  authMode: 'auto', // 'auto' | 'header' | 'query' | 'both' (default: 'auto')
  
  onBatch: (event, { streamId }) => {
    console.log(`[${streamId}] Received ${event.pairs?.length ?? 0} pairs`);
  },
  
  onPair: (pair, { streamId }) => {
    console.log(`[${streamId}] ${pair.baseToken?.symbol}/${pair.quoteToken?.symbol} ${pair.priceUsd}`);
  },
  
  onError: (error, { streamId }) => {
    console.error(`[${streamId}] Error:`, error);
  },
  
  onStateChange: (state, { streamId }) => {
    console.log(`[${streamId}] State: ${state}`);
  },
});

stream.start();

// Stop when done
// stream.stop();

Authentication Modes:

  • auto (default): Tries header authentication first, falls back to query parameter if needed
  • header: Sends token only in Authorization header (more secure)
  • query: Sends token only as URL query parameter
  • both: Sends token in both header and query parameter

Multi-Stream

Monitor multiple DexScreener pages simultaneously:

import { DexScreenerMultiStream } from './dist/index.js';

const multi = new DexScreenerMultiStream({
  baseUrl: process.env.DEX_ACTOR_BASE!,
  apiToken: process.env.APIFY_TOKEN!,
  authMode: 'auto', // Applied to all streams
  
  streams: [
    { id: 'solana-trending', pageUrl: 'https://dexscreener.com/solana?rankBy=trendingScoreH6&order=desc' },
    { id: 'base-latest', pageUrl: 'https://dexscreener.com/base?rankBy=trendingScoreH6&order=desc&minLiq=30000' },
    { id: 'ethereum-volume', pageUrl: 'https://dexscreener.com/ethereum?rankBy=volume&order=desc' },
  ],
  
  onPair: (pair, { streamId }) => {
    console.log(`[${streamId}] ${pair.baseToken?.symbol} ${pair.priceUsd}`);
  },
});

multi.startAll();

// Stop all streams
// multi.stopAll();

See examples/ directory for complete working examples.

CLI Usage

After building the project, use the CLI to consume streams without writing code.

stdout Mode (default)

Print JSON events to stdout:

node dist/cli.cjs \
  --base-url https://muhammetakkurtt--dexscreener-realtime-monitor.apify.actor \
  --api-token apify_api_xxxxxxxxxxxxx \
  --page-url "https://dexscreener.com/solana?rankBy=trendingScoreH6&order=desc" \
  --auth-mode auto

Or using environment variable:

export APIFY_TOKEN=apify_api_xxxxxxxxxxxxx
node dist/cli.cjs \
  --base-url https://muhammetakkurtt--dexscreener-realtime-monitor.apify.actor \
  --page-url "https://dexscreener.com/solana?rankBy=trendingScoreH6&order=desc"

JSONL File Mode

Append events to a JSON Lines file:

node dist/cli.cjs \
  --base-url https://muhammetakkurtt--dexscreener-realtime-monitor.apify.actor \
  --page-url "https://dexscreener.com/solana?rankBy=trendingScoreH6&order=desc" \
  --mode jsonl \
  --jsonl-path ./events.jsonl

Webhook Mode

Forward events to an HTTP endpoint:

node dist/cli.cjs \
  --base-url https://muhammetakkurtt--dexscreener-realtime-monitor.apify.actor \
  --page-url "https://dexscreener.com/solana?rankBy=trendingScoreH6&order=desc" \
  --mode webhook \
  --webhook-url https://api.example.com/webhooks/dexscreener

Multiple Streams

node dist/cli.cjs \
  --base-url https://muhammetakkurtt--dexscreener-realtime-monitor.apify.actor \
  --page-url "https://dexscreener.com/solana?rankBy=trendingScoreH6&order=desc" \
  --page-url "https://dexscreener.com/base?rankBy=trendingScoreH6&order=desc" \
  --page-url "https://dexscreener.com/ethereum?rankBy=trendingScoreH6&order=desc"

CLI Options

Option Description Required
--base-url Apify Standby Actor base URL (http/https/ws/wss) Yes
--api-token Apify API token (or use APIFY_TOKEN env) Yes
--page-url DexScreener page URL(s) to monitor Yes
--auth-mode Authentication mode: auto, header, query, both No (default: auto)
--mode Output mode: stdout, jsonl, webhook No (default: stdout)
--jsonl-path File path for JSONL output Required for jsonl mode
--webhook-url Webhook URL for HTTP POST Required for webhook mode
--retry-ms Reconnection delay in ms No (default: 3000)
--keep-alive-ms Health check interval in ms No (default: 120000, set to 0 to disable)

API Reference

DexStreamOptions

type DexStreamOptions = {
  baseUrl: string;           // Apify Standby Actor base URL (http/https/ws/wss)
  apiToken: string;          // Apify API token
  pageUrl: string;           // DexScreener page URL
  streamId?: string;         // Optional stream identifier
  authMode?: 'auto' | 'header' | 'query' | 'both';  // Authentication mode (default: 'auto')
  retryMs?: number;          // Reconnection delay (default: 3000)
  keepAliveMs?: number;      // Health check interval (default: 120000, set to 0 to disable)
  onBatch?: (event: DexEvent, ctx: StreamContext) => void;
  onPair?: (pair: Pair, ctx: StreamContext) => void;
  onError?: (error: unknown, ctx: StreamContext) => void;
  onStateChange?: (state: ConnectionState, ctx: StreamContext) => void;
};

MultiStreamConfig

type MultiStreamConfig = {
  baseUrl: string;
  apiToken: string;
  streams: Array<{ id: string; pageUrl: string }>;
  authMode?: 'auto' | 'header' | 'query' | 'both';  // Authentication mode for all streams (default: 'auto')
  retryMs?: number;
  keepAliveMs?: number;
  onBatch?: (event: DexEvent, ctx: StreamContext) => void;
  onPair?: (pair: Pair, ctx: StreamContext) => void;
  onError?: (error: unknown, ctx: StreamContext) => void;
  onStateChange?: (state: ConnectionState, ctx: StreamContext) => void;
};

DexEvent

type DexEvent = {
  stats?: DexEventStats;
  pairs?: Pair[];
  event_type?: string;
  timestamp?: string;
};

Pair

type Pair = {
  // Identity & Classification
  type?: PairType;               // Raw pair type discriminator (e.g. typeAMM)
  chainId?: string;              // Blockchain network (e.g., "solana", "ethereum")
  dexId?: string;                // DEX identifier (e.g., "raydium", "uniswap")
  pairAddress?: string;          // Unique pair contract address
  labels?: string[];             // Classification labels (e.g., ["CPMM"])
  
  // Token Information
  baseToken?: Token;             // Base token details
  quoteToken?: Token;            // Quote token details
  quoteTokenSymbol?: string;     // Quote token symbol (convenience field)
  
  // Pricing
  price?: string;                // Price in quote token
  priceUsd?: string;             // Normalized USD price
  priceUSD?: string;             // Raw USD price from DexScreener, when present
  priceChange?: PriceChange;     // Price changes over time periods

  // Trading Activity
  txns?: Txns;                   // Transaction counts (buys/sells)
  buyers?: UserCounts;           // Unique buyer counts over time periods (m5, h1, h6, h24)
  sellers?: UserCounts;          // Unique seller counts over time periods (m5, h1, h6, h24)
  makers?: UserCounts;           // Unique maker counts over time periods (m5, h1, h6, h24)
  
  // Volume Metrics
  volume?: Volume;               // Total trading volume over time periods
  volumeBuy?: Volume;            // Buy-side volume over time periods
  volumeSell?: Volume;           // Sell-side volume over time periods
  
  // Market Data
  liquidity?: Liquidity;         // Liquidity in USD, base, and quote tokens
  marketCap?: number;            // Market capitalization
  fdv?: number;                  // Fully diluted valuation
  
  // Metadata & Features
  pairCreatedAt?: number;        // Normalized Unix timestamp in milliseconds
  pairCreatedAtRaw?: PairCreatedAtRaw; // Raw { seconds, nanos } timestamp, when present
  profile?: Profile;             // Token profile information (eti, header, website, twitter, linkCount, imgKey)
  cmsProfile?: CmsProfile;       // CMS profile information (headerId, iconId, description, links, nsfw)
  isBoostable?: boolean;         // Whether pair can be boosted
  boosts?: Boosts;               // Active boost information
  launchpad?: Launchpad;         // Launchpad information (progress, creator, migrationDex, meta)
  
  // Additional Fields
  c?: string;                    // Additional metadata field
  a?: string;                    // Additional metadata field
  
  // Future Extensibility
  [key: string]: unknown;        // Allows access to new fields added by the API
};

The SDK normalizes current Actor payloads before invoking callbacks. Raw fields such as priceUSD, stats.*.volumeUSD, pairCreatedAt: { seconds, nanos }, and nested type.value.launchpad are preserved where useful, while camelCase aliases like priceUsd, stats.*.volumeUsd, pairCreatedAt, quoteTokenSymbol, and launchpad.migrationDex are guaranteed for SDK consumers.

type PairCreatedAtRaw = {
  seconds?: number | string;
  nanos?: number | string;
};

type PairType = {
  case?: string;
  value?: {
    a?: string;
    launchpad?: Launchpad;
    [key: string]: unknown;
  };
};

Example DexEvent Structure

The SDK automatically parses WebSocket messages and delivers clean DexEvent objects to your callbacks. Here's what you receive in the onBatch callback:

{
  "stats": {
    "m5": { "txns": 54923, "volumeUsd": 9045447.56, "volumeUSD": 9045447.56 },
    "h1": { "txns": 756730, "volumeUsd": 134179114.12, "volumeUSD": 134179114.12 },
    "h6": { "txns": 4880021, "volumeUsd": 1151490222.86, "volumeUSD": 1151490222.86 },
    "h24": { "txns": 19323940, "volumeUsd": 4377335189.87, "volumeUSD": 4377335189.87 }
  },
  "pairs": [
    {
      "chainId": "solana",
      "dexId": "raydium",
      "labels": ["CPMM"],
      "pairAddress": "EAf2Qn1kNix6gdiaEviWqzKwKtJUJTXTRT3nZLYcV9QY",
      "baseToken": {
        "address": "FT6ZnLbmaQbUmxbpe69qwRgPi9tU8QGY8S7gqt4Wbonk",
        "name": "BIG",
        "symbol": "BIG",
        "decimals": 6
      },
      "quoteToken": {
        "address": "USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB",
        "name": "World Liberty Financial USD",
        "symbol": "USD1",
        "decimals": 6
      },
      "quoteTokenSymbol": "USD1",
      "price": "0.001820",
      "priceUsd": "0.001820",
      "priceUSD": "0.001820",
      "txns": {
        "m5": { "buys": 68, "sells": 28 },
        "h1": { "buys": 1333, "sells": 1064 },
        "h6": { "buys": 32404, "sells": 29022 },
        "h24": { "buys": 35242, "sells": 32222 }
      },
      "buyers": { "m5": 51, "h1": 622, "h6": 7600, "h24": 8290 },
      "sellers": { "m5": 27, "h1": 565, "h6": 6549, "h24": 6859 },
      "makers": { "m5": 76, "h1": 996, "h6": 8906, "h24": 9249 },
      "volume": { "m5": 9933.02, "h1": 296433.65, "h6": 9458621.98, "h24": 9981693.42 },
      "volumeBuy": { "m5": 4850, "h1": 144929.23, "h6": 4722534.19, "h24": 4996787.53 },
      "volumeSell": { "m5": 5083.01, "h1": 151504.42, "h6": 4736087.78, "h24": 4984905.89 },
      "priceChange": { "m5": -0.65, "h1": -8.89, "h6": 239, "h24": 2582 },
      "liquidity": { "usd": 151707.33, "base": 41663892, "quote": 75853 },
      "marketCap": 1820609,
      "fdv": 1820609,
      "pairCreatedAt": 1765041438000,
      "pairCreatedAtRaw": { "seconds": 1765041438, "nanos": 0 },
      "profile": {
        "eti": true,
        "header": true,
        "website": true,
        "twitter": true,
        "linkCount": 2,
        "imgKey": "2da648"
      },
      "cmsProfile": {
        "headerId": "4a2b4e6e0640ededdd9b3dab20d9f6900bddcc6878fe732d38c9f9cc80d98efc",
        "iconId": "82678f55db554c1d61b069daf596aeef6f1d665ee3a12f261b144c0326c9c17f",
        "description": "This is going to be $BIG",
        "links": [
          { "label": "Website", "url": "https://truthsocial.com/@unknown/posts/115673738803217830" },
          { "type": "twitter", "url": "https://x.com/i/communities/1997366922938126733" }
        ],
        "nsfw": false
      },
      "isBoostable": true,
      "c": "a",
      "a": "solamm"
    },
    {
      "chainId": "solana",
      "dexId": "pumpswap",
      "pairAddress": "8wXzwpLjk6QJMYYC1VHueNnxRVW2nFGvQjgEnV4Mv8sY",
      "baseToken": {
        "address": "CSrwNk6B1DwWCHRMsaoDVUfD5bBMQCJPY72ZG3Nnpump",
        "name": "Franklin The Turtle",
        "symbol": "Franklin",
        "decimals": 6
      },
      "quoteToken": {
        "address": "So11111111111111111111111111111111111111112",
        "name": "Wrapped SOL",
        "symbol": "SOL",
        "decimals": 9
      },
      "quoteTokenSymbol": "SOL",
      "price": "0.00007098",
      "priceUsd": "0.009336",
      "priceUSD": "0.009336",
      "txns": {
        "m5": { "buys": 57, "sells": 54 },
        "h1": { "buys": 7924, "sells": 799 },
        "h6": { "buys": 13090, "sells": 5776 },
        "h24": { "buys": 37491, "sells": 28148 }
      },
      "buyers": { "m5": 49, "h1": 7196, "h6": 8713, "h24": 13450 },
      "sellers": { "m5": 46, "h1": 465, "h6": 2077, "h24": 6558 },
      "makers": { "m5": 94, "h1": 7543, "h6": 9818, "h24": 15675 },
      "volume": { "m5": 17675.25, "h1": 334508.48, "h6": 2505119.75, "h24": 12825807.97 },
      "volumeBuy": { "m5": 8714.96, "h1": 156717.8, "h6": 1242301.69, "h24": 6470078.63 },
      "volumeSell": { "m5": 8960.28, "h1": 177790.68, "h6": 1262818.06, "h24": 6355729.34 },
      "priceChange": { "m5": -0.34, "h1": -19.48, "h6": -22.12, "h24": 223 },
      "liquidity": { "usd": 403605.74, "base": 21566984, "quote": 1537.8354 },
      "marketCap": 9335780,
      "fdv": 9335780,
      "pairCreatedAt": 1764588851000,
      "pairCreatedAtRaw": { "seconds": 1764588851, "nanos": 0 },
      "profile": {
        "eti": true,
        "header": true,
        "website": true,
        "twitter": true,
        "linkCount": 2,
        "imgKey": "731b40"
      },
      "isBoostable": true,
      "c": "a",
      "a": "pumpfundex",
      "launchpad": {
        "progress": 100,
        "creator": "6EF8rrecthR5Dkzon8Nwu78hRvfCKubJ14M5uBEwF6P",
        "migrationDex": "pumpswap",
        "meta": { "id": "pumpfun" }
      }
    }
  ],
  "event_type": "pairs",
  "timestamp": "2026-01-21T08:28:36.113Z"
}

ConnectionState

type ConnectionState = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';

Configuration Files

The CLI supports configuration files for easier management of settings across environments.

Creating a Configuration File

Generate a default configuration file:

node dist/cli.cjs --init

This creates .dexrtrc.json or .dexrtrc.yaml in your current directory.

Configuration File Format

JSON Format (.dexrtrc.json):

{
  "baseUrl": "https://muhammetakkurtt--dexscreener-realtime-monitor.apify.actor",
  "apiToken": "apify_api_xxxxxxxxxxxxx",
  "pageUrls": [
    "https://dexscreener.com/solana?rankBy=trendingScoreH6&order=desc"
  ],
  "mode": "jsonl",
  "output": {
    "jsonlPath": "./events.jsonl",
    "compression": {
      "enabled": true,
      "level": 6
    },
    "rotation": {
      "maxSizeMB": 100,
      "interval": "daily"
    }
  }
}

YAML Format (.dexrtrc.yaml):

# DexScreener Client Configuration
baseUrl: https://muhammetakkurtt--dexscreener-realtime-monitor.apify.actor
apiToken: apify_api_xxxxxxxxxxxxx

pageUrls:
  - https://dexscreener.com/solana?rankBy=trendingScoreH6&order=desc

mode: jsonl

output:
  jsonlPath: ./events.jsonl
  compression:
    enabled: true
    level: 6
  rotation:
    maxSizeMB: 100
    interval: daily

Configuration Profiles

Use profiles for different environments:

{
  "profiles": {
    "dev": {
      "baseUrl": "https://dev-actor.apify.actor",
      "pageUrls": ["https://dexscreener.com/solana"],
      "mode": "stdout"
    },
    "prod": {
      "baseUrl": "https://prod-actor.apify.actor",
      "pageUrls": [
        "https://dexscreener.com/solana",
        "https://dexscreener.com/ethereum"
      ],
      "mode": "webhook",
      "output": {
        "webhookUrl": "https://api.example.com/events"
      }
    }
  },
  "default": "dev"
}

Use a specific profile:

node dist/cli.cjs --profile prod

Validate Configuration

Check your configuration without starting streams:

node dist/cli.cjs --validate

Features

  • πŸ”„ Real-time Streaming - WebSocket connection with automatic reconnection
  • πŸ” Flexible Authentication - Multiple auth modes (header, query, both, auto-fallback)
  • πŸ”§ Protocol Normalization - Automatic HTTP/HTTPS to WS/WSS conversion
  • 🌐 Multi-Stream Support - Monitor multiple pages/chains simultaneously
  • πŸ” Advanced Filtering - Filter pairs by chain, liquidity, volume, price change
  • πŸ”§ Data Transformation - Select and reshape fields with aliases
  • πŸ“Š Monitoring - Prometheus metrics, health checks, structured logging
  • πŸ“¦ Output Management - Compression, rotation, batching, throttling, sampling
  • ⚑ Production Ready - Error handling, graceful shutdown, keep-alive management

For detailed guides and examples, see the User Guide.


Filtering and Transformation

Filtering Pairs

import { FilterBuilder } from './dist/index.js';

const filter = FilterBuilder.combineFilters([
  FilterBuilder.chainFilter(['solana', 'ethereum']),
  FilterBuilder.liquidityFilter(50000),
  FilterBuilder.volumeFilter('h24', 100000)
], 'AND');

Transforming Data

import { Transformer } from './dist/index.js';

const transformer = new Transformer({
  fields: ['baseToken.symbol', 'priceUsd', 'volume.h24'],
  aliases: { 'baseToken.symbol': 'symbol', 'priceUsd': 'price' }
});

See User Guide for complete filtering and transformation examples.


Monitoring

The SDK provides production-ready monitoring capabilities:

  • Health Checks - HTTP endpoint for health status
  • Prometheus Metrics - Export metrics for monitoring
  • Structured Logging - JSON/text logging with levels
  • Performance Monitoring - Track processing duration and memory
  • Alerts - Threshold-based alerting

Quick Example:

import { HealthChecker, MetricsCollector, StructuredLogger } from './dist/index.js';

const health = new HealthChecker(3000);
const metrics = new MetricsCollector();
const logger = new StructuredLogger('info', 'json');

health.start();  // http://localhost:3000/health

CLI Usage:

node dist/cli.cjs \
  --page-url "https://dexscreener.com/solana" \
  --health-port 3000 \
  --metrics-port 9090 \
  --log-level info \
  --log-format json

See User Guide for detailed monitoring setup and API Reference for complete API documentation.


CLI Flags Reference

Core Options

Flag Description Default
--base-url Apify Actor base URL Required
--api-token Apify API token (or use APIFY_TOKEN env) Required
--page-url DexScreener page URL(s) to monitor Required
--mode Output mode: stdout, jsonl, webhook stdout
--retry-ms Reconnection delay in milliseconds 3000
--keep-alive-ms Health check interval in milliseconds 120000

Configuration Options

Flag Description
--init Generate default configuration file
--profile <name> Use specific configuration profile
--validate Validate configuration and exit
--interactive Launch interactive configuration wizard

Output Options

Flag Description
--jsonl-path <path> File path for JSONL output
--webhook-url <url> Webhook URL for HTTP POST
--compress Enable gzip compression
--rotate-size <mb> Rotate file when size exceeds MB
--rotate-interval <interval> Rotate file by time: hourly, daily
--batch-size <n> Batch size for webhook mode
--batch-interval <ms> Batch interval in milliseconds
--sample-rate <percent> Sample rate percentage (0-100)

Monitoring Options

Flag Description
--health-port <port> HTTP health check endpoint port
--metrics-port <port> Prometheus metrics endpoint port
--log-level <level> Log level: error, warn, info, debug
--log-format <format> Log format: text, json
--perf Enable performance monitoring
--verbose Verbose output mode
--quiet Quiet mode (errors only)
--debug Debug mode with detailed diagnostics

Documentation


Development

# Run tests
npm test

# Type check
npm run typecheck

# Watch mode for development
npm run dev

About

Node.js/TypeScript SDK + CLI that connects to the DexScreener Realtime Monitor (Apify Actor) and streams live on-chain trending market data via SSE. Use it in bots, trading systems, analytics pipelines, or any backend that needs low-latency DexScreener feed ingestion.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors