Schemas Get a free key
On-chain · Tokens

Token screener and token holders: free on-chain token API

A token screener and a token holders API for Ethereum, BNB Chain, Base and HyperEVM: find a token's contract, rank tokens by volume, inflow or smart-money inflow, see the top holders of a token by their real balance and share of the supply, and who bought or sold it today. Ask your AI, or call it from code on one free key.

Ask your AI · Claude, ChatGPT, CursorConnect in a minute →

“Who are the top holders of PEPE by balance, and what share of the supply do they hold?”

token_search token_holders

“Which tokens did smart money buy the most this week?”

token_screener
bash
curl -H "X-API-KEY: $VIKE_API_KEY" \
  "https://data.vike.io/v1/onchain/tokens/search?q=Wrapped+Ether&limit=5"
  • Match by symbol or name, any case: an exact symbol first, then symbols and names that start with what you typed. A contract address is not searched.
  • Every answer carries the token_address the other token routes take: 0x + 40 lower-case hex digits.
  • Pass chain for BNB Chain, Base or HyperEVM; the default is Ethereum.
Token screener

Token screener: rank tokens by on-chain activity

The tokens wallets moved, bought or accumulated most in a window.

bash
curl -H "X-API-KEY: $VIKE_API_KEY" \
  "https://data.vike.io/v1/onchain/tokens/screener?window=7d&sort=smart_inflow&limit=20"
sortranks tokens by
volumeUSD moved in the window, in and out
net_inflowUSD in minus USD out: who is accumulating
holdershow many wallets sent or received it
smart_inflownet inflow of the smart-money wallets alone (Ethereum)
  • Windows: 24h, 7d, 30d, 90d. Up to 100 tokens.
  • Filters: min_volume_usd, min_holders, and smart_money_only for the smart-money wallets alone.
  • Smart money = wallets with more than $100,000 of realized profit on Ethereum; Ethereum only.
On-chain · API · analytics

Token screener

Tokens ranked by window volume, net inflow, holder count or smart-money inflow.

Route
GET /v1/onchain/tokens/screener
MCP
token_screener
Windows
24h, 7d, 30d, 90d
Free APIArchiveStreamMCP

Fields

FieldTypeDescription
token_addressstringToken contract, 0x-prefixed
symbolstring|nullSymbol, when the token is known
namestring|nullName, when the token is known
volume_usdnumberUSD moved in the window, in and out
net_flow_usdnumberUSD in minus USD out; with sort=smart_inflow, the smart-money wallets' alone
in_usdnumberUSD received by wallets in the window
out_usdnumberUSD sent by wallets in the window
unique_holdersintegerWallets that sent or received it in the window
tx_countintegerTransfers counted

Real rows

Token screener · rows

GET
Open this side to see the captured response.

    

Load it

bash
curl -H "X-API-KEY: $VIKE_API_KEY" \
  "https://data.vike.io/v1/onchain/tokens/screener?limit=10"

Every parameter of /v1/onchain/tokens/screener → · back to the catalog

Token holders

Top token holders by real balance

Who holds a token now, how much it is worth and what share of the supply.

bash
curl -H "X-API-KEY: $VIKE_API_KEY" \
  "https://data.vike.io/v1/onchain/tokens/0x6982508145454ce325ddbe47a25d4ec3d2311933/holders?limit=20&sort=balance"
sortranks wallets byeach row adds
balancewhat they hold now, read from the chainbalance, value_usd, supply_pct
flow (default)all-time net inflow in USD: a flow, not a holding—
  • By balance, the candidates are the top 150 wallets by net inflow and the top 150 by volume; candidate_coverage says how much of the supply they hold, and balance_approximate is true below 20%.
  • Up to 50 holders, each with its label when known; exclude_exchanges=true leaves out exchange wallets.
  • CLI: vike-data token holders <token> ranks by inflow; by balance, run the MCP tab's vike-data call.
On-chain · API dataset · per token

Token holders

Holder leaderboard per token, ranked by cumulative net inflow in USD. With sort=balance, by the balance read from the chain.

Route
GET /v1/onchain/tokens/{token_address}/holders
MCP
token_holders
Cadence
Daily aggregates
Coverage
Top wallets by all-time net inflow of one token (USD at transfer time), with gross volume, transfer count, first and last active day and the wallet's label when known. limit up to 50. Find a token first with /tokens/search.
Rows
Free APIArchiveStreamMCP

Fields

FieldTypeDescription
walletstringHolder, 0x-prefixed
net_flow_usdnumberInflow − outflow, USD — the ranking
volume_usdnumberInflow + outflow, USD
tx_countintegerTransfers counted
first_seenstringFirst active day, YYYY-MM-DD
last_activestringLast active day, YYYY-MM-DD
entitystringResolved entity; empty when unlabelled
wallet_typestringLabel type; empty when unlabelled
balancenumbersort=balance: the balance read from the chain now, whole tokens
value_usdnumber|nullsort=balance: balance × the latest daily price; null when unpriced
supply_pctnumber|nullsort=balance: share of the total supply, in percent; null when the supply is unknown
balance_basisstringsort=balance: chain (read from the chain) or unsupported (a native coin: still ranked by inflow)
balance_approximatebooleansort=balance: true when a balance could not be read, the supply is unknown or the candidates explain little of the supply
candidate_coveragenumber|nullsort=balance: share of the supply the candidate wallets hold, 0 to 1

Real rows

Token holders · rows

GET
Open this side to see the captured response.

    

Load it

bash
curl -H "X-API-KEY: $VIKE_API_KEY" \
  "https://data.vike.io/v1/onchain/tokens/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48/holders?chain=ethereum&limit=10"

Every parameter of /v1/onchain/tokens/{token_address}/holders → · back to the catalog

Buyers and sellers

Who bought and who sold it

The top net buyers or net sellers of a token in the last hour, day, week or month.

bash
curl -H "X-API-KEY: $VIKE_API_KEY" \
  "https://data.vike.io/v1/onchain/tokens/0x6982508145454ce325ddbe47a25d4ec3d2311933/transfers?period=24h&tab=bought&hide_contracts=true"
  • tab=bought: the wallets that bought more than they sold; tab=sold (the default): the reverse. Largest first, by net USD.
  • period: 1h, 24h, 7d, 30d; chain=all adds up the four chains.
  • net_usd is USD received minus USD spent, so a buyer's is negative.
  • hide_contracts=true leaves out the pools, routers and other contracts we know of.
  • min_amount / max_amount: count only the transfers of at least / at most this many whole tokens, each one kept or dropped before a wallet's totals are added up. E.g. …/transfers?period=24h&tab=bought&min_amount=1000000000 ranks the buyers on PEPE transfers of 1,000,000,000 or more.
On-chain · API dataset · buyers · sellers

Token transfers

Who bought and who sold a token over a period, aggregated from raw transfers.

Route
GET /v1/onchain/tokens/{token_address}/transfers
MCP
token_transfers
Cadence
Synced block by block
Coverage
Per-token buyer and seller totals over a period (period, tab=bought|sold, chain) on Ethereum, BNB Chain, Base and HyperEVM — chain=ethereum|bsc|base|hyperevm is a filter, not a namespace. Per-wallet transfer lists at /wallets/{address}/transactions cover the same four chains. Amount and USD fields on this route are whole tokens and plain USD (they were integers scaled by 10^6 until 2026-10-13).
Rows
Free APIArchiveStreamMCP

Fields

FieldTypeDescription
addressstringWallet, 0x-prefixed
boughtnumberTokens received, whole tokens
soldnumberTokens sent, whole tokens
net_tokensnumberbought − sold, whole tokens
usd_spentnumberUSD value of tokens received, in USD
usd_receivednumberUSD value of tokens sent, in USD
net_usdnumberusd_received − usd_spent, in USD
net_usd_rawnumbernet_usd rounded to cents
chainsarrayChain tags the wallet traded on, e.g. eth
titlestring|nullKnown wallet title, when one exists
addr_shortstringDisplay form, 0xabcd...1234
bought_fmtstringDisplay string of bought
sold_fmtstringDisplay string of sold
net_tokens_fmtstringDisplay string of |net_tokens|
usd_spent_fmtstringDisplay string of usd_spent
usd_received_fmtstringDisplay string of usd_received
net_usd_fmtstringDisplay string of net_usd
net_bar_pctinteger|net_usd| as a percent of the page's largest

Real rows

Token transfers · rows

GET
Open this side to see the captured response.

    

Load it

bash
curl -H "X-API-KEY: $VIKE_API_KEY" \
  "https://data.vike.io/v1/onchain/tokens/0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48/transfers?period=24h&chain=ethereum"

Every parameter of /v1/onchain/tokens/{token_address}/transfers → · back to the catalog

Live

Every big transfer of a token, live

Subscribe once; filter by token, size, wallet or the label of either side.

python
import json, os
from websockets.sync.client import connect

with connect("wss://stream.vike.io/v1/stream/onchain",
             additional_headers={"X-API-KEY": os.environ["VIKE_API_KEY"]}) as ws:
    ws.send(json.dumps({"action": "subscribe", "id": "pepe", "channel": "chain.transfers",
                        "filter": {"token": "0x6982508145454ce325ddbe47a25d4ec3d2311933", "min_usd": 100000}}))
    for message in ws:
        frame = json.loads(message)
        if frame["type"] == "ping":
            ws.send(json.dumps({"action": "pong"}))
        elif frame["type"] == "event":
            e = frame["event"]
            print(e["subject"]["token_symbol"], e["data"]["amount"], e["data"]["value_usd"],
                  e["subject"]["from"], "->", e["subject"]["to"])
  • Channel chain.transfers at wss://stream.vike.io/v1/stream/onchain.
  • Filters: wallet, token, chain, min_usd, min_amount, entity, wallet_type, contract. min_amount counts whole tokens and needs token.
  • Both sides of every transfer come with their label when we know it.
  • Every filter, a real event and e-mail or webhook alerts with no code: Whale alerts.
Studies

7 token questions, answered with code

Each a question, the sentence to ask your AI agent, and the Python that answers it.

On-chain · API

Find a token's contract address by name or ticker

Search a ticker or a token name and get the matching tokens on one chain, each with its 0x-prefixed contract address, from /tokens/search.

Uses
/tokens/search, /tokens/{…}/holders
Verified
live API, 2026-11-03: 5 calls, all 200
Free APIArchiveStreamMCP
Ask your AI agent: “What is the contract address of PEPE on Ethereum?”

The code

python
import os
import requests

API_KEY = os.environ["VIKE_API_KEY"]  # your key, read from the environment

# the contract address of PEPE on Ethereum
r = requests.get(
    "https://data.vike.io/v1/onchain/tokens/search?q=PEPE&limit=3",
    headers={"X-API-Key": API_KEY},
)
On-chain · API

Top holders of token X

Rank a token's top wallets by net inflow in USD, with labels: an approximation of the largest holders, not a balance.

Uses
/tokens/{…}/holders, /wallets/{…}/balances
Verified
live API, 2026-11-03: 5 calls, all 200
Free APIArchiveStreamMCP
Ask your AI agent: “Who are the top holders of LINK on Ethereum?”

The code

python
import os
import requests

API_KEY = os.environ["VIKE_API_KEY"]  # your key, read from the environment

# the five wallets with the largest accumulated net inflow of LINK
r = requests.get(
    "https://data.vike.io/v1/onchain/tokens/0x514910771af9ca656af840dff83e8264ecf986ca/holders?limit=5",
    headers={"X-API-Key": API_KEY},
)
On-chain · API

Who bought and who sold token X in the last 24h / 7d?

Screen Ethereum tokens for smart-money inflow, take the top token's biggest buyers and label them in one batch call, flagging the ones that are not exchanges, protocols or bots.

Uses
/labels/batch, /tokens/screener, /tokens/{…}/transfers
Verified
live API, 2026-11-03: 3 calls, all 200
Free APIArchiveStreamMCP

The code

python
"""Who is buying the token smart money is moving into? Screen, take the top token, label its biggest buyers.

Run:  VIKE_API_KEY=... python oc-early-buyers.py    (--dry-run lists the requests and makes none)
"""
import os
import sys
from urllib.parse import urlencode

NAME = "oc-early-buyers"
BASE = "https://data.vike.io"
DRY = "--dry-run" in sys.argv
# Wallet types that are intermediaries, not an owner deciding to buy; everything else is worth a look.
PLUMBING = {"cex", "defi", "mev"}


def fail(why):
    sys.exit(f"{NAME}: {why}")


def call(path, method="GET", **params):
    url = BASE + path + ("?" + urlencode(params) if params else "")
    if DRY:
        print(method, url)
        return None
    key = os.environ.get("VIKE_API_KEY") or fail("set VIKE_API_KEY")
    import requests

    r = requests.request(method, url, headers={"X-API-Key": key}, timeout=60)
    if r.status_code != 200:
        fail(f"{method} {path} answered HTTP {r.status_code}: {r.text[:200]}")
    return r.json()


def main():
    # Ethereum by default. A token is keyed by address: the screener's symbol is null for a token outside our registry.
    screen = call("/v1/onchain/tokens/screener", sort="smart_inflow", window="7d", limit=5)
    # --dry-run has no response to read
    rows = [{"token_address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "volume_usd": 0}] if DRY else screen
    # The zero address is the chain's native coin (ETH), which often tops the screen; /transfers lists no buyers for it.
    rows = [r for r in rows or [] if int(r["token_address"], 16)]
    if not rows:
        fail("the screener returned no token contracts")

    # Ten rows, one side per call, and no limit parameter. usd_spent and net_usd are plain USD.
    for row in rows:
        token = row["token_address"]
        buyers = call(f"/v1/onchain/tokens/{token}/transfers", period="7d", tab="bought")
        if DRY or buyers:
            break
        print(f"{token} has no buyers in the window, trying the next token")
    else:
        fail(f"none of the top {len(rows)} screened tokens has buyers in the window")
    wallets = ["0xbbbbbbbbbb9cc5e90e3b3af64bdaf62c37eeffcb", "0x06cff7088619c7178f5e14f0b119458d08d2f5ef"]
    if not DRY:
        print(f"top smart-money inflow over 7d: {token}  (${row['volume_usd']:,.0f} volume)")
        wallets = [b["address"] for b in buyers]

    # A POST with no body: the addresses ride in the query string, at most 100 per call.
    labels = call("/v1/onchain/labels/batch", method="POST", addresses=",".join(wallets))
    if DRY:
        return
    if len(labels) != len(wallets):
        fail(f"/labels/batch returned {len(labels)} rows for {len(wallets)} wallets")
    by_wallet = {row["wallet"]: row for row in labels}
    for b in buyers:
        row = by_wallet.get(b["address"].lower(), {})
        kind = (row.get("wallet_type") or "") if row.get("found") else ""
        who = f"{row['entity']} ({kind})" if kind else "unlabelled"
        # bought counts every transfer in, so a flash-loan loop or a router "buys" billions and keeps nothing
        passed_on = b["net_tokens"] < 0.01 * b["bought"]
        flag = "   (passed it on)" if passed_on else "" if kind in PLUMBING else "   <- look here"
        print(f"  {b['address']}  bought ${b['usd_spent']:,.0f}  kept {b['net_tokens']:,.0f}  {who}{flag}")


if __name__ == "__main__":
    try:
        main()
    except Exception as e:  # a shape the example does not expect fails by name, not by traceback
        fail(f"{type(e).__name__}: {e}")
On-chain · API

Is smart money exiting token X?

Screen Ethereum tokens with smart_money_only=true, find token X in the list and read net_flow_usd; negative over 7 and 30 days means the cohort sent out more of it than it received.

Uses
/tokens/screener
Verified
live API, 2026-11-03: 4 calls, all 200
Free APIArchiveStreamMCP
Ask your AI agent: “Is smart money selling PEPE on Ethereum? Compare the last 7 and 30 days.”

The code

python
import os
import requests

API_KEY = os.environ["VIKE_API_KEY"]  # your key, read from the environment

# smart-money flow in PEPE over 7 days, picked out of the top 100 tokens by cohort volume
r = requests.get(
    "https://data.vike.io/v1/onchain/tokens/screener?smart_money_only=true&sort=volume&window=7d&limit=100",
    headers={"X-API-Key": API_KEY},
)
# then: jq '.[] | select(.token_address == "0x6982508145454ce325ddbe47a25d4ec3d2311933") | {token_address, symbol, net_flow_usd, volume_usd, in_usd, out_usd, unique_holders}'
On-chain · API

Which holders of a token have not moved in months? (diamond hands)

Rank a token's top 50 wallets by net inflow with /tokens/{token_address}/holders and keep the unlabelled ones whose last_active date is months old, then confirm the balance.

Uses
/labels/batch, /tokens/{…}/holders, /wallets/{…}/balances
Verified
live API, 2026-11-03: 4 calls, all 200
Free APIArchiveStreamMCP
Ask your AI agent: “Which of PEPE's top holders have not moved their PEPE since December 2025?”

The code

python
import os
import requests

API_KEY = os.environ["VIKE_API_KEY"]  # your key, read from the environment

# PEPE's top 50 accumulators, keeping the unlabelled ones that have not moved PEPE since 1 December 2025
r = requests.get(
    "https://data.vike.io/v1/onchain/tokens/0x6982508145454ce325ddbe47a25d4ec3d2311933/holders?limit=50",
    headers={"X-API-Key": API_KEY},
)
# then: jq '[.[] | select(.entity == "" and .last_active < "2025-12-01")]'
On-chain · API

PEPE on-chain analytics: top holders, whales, buyers and sellers

Resolve the token with /tokens/search, rank its biggest accumulators with /tokens/{token_address}/holders, and read the period's top buyers and sellers with /tokens/{token_address}/transfers.

Uses
/tokens/search, /tokens/{…}/holders, /tokens/{…}/transfers
Verified
live API, 2026-11-03: 5 calls, all 200
Free APIArchiveStreamMCP
Ask your AI agent: “Who are the top holders of PEPE, and who bought the most in the last 24 hours?”

The code

python
import os
import requests

API_KEY = os.environ["VIKE_API_KEY"]  # your key, read from the environment

# PEPE's 50 biggest accumulators on Ethereum, with labels
r = requests.get(
    "https://data.vike.io/v1/onchain/tokens/0x6982508145454ce325ddbe47a25d4ec3d2311933/holders?limit=50",
    headers={"X-API-Key": API_KEY},
)
On-chain · API

Which tokens are flowing into Base but out of Ethereum? (cross-chain flows)

Rank Base tokens by net inflow with /tokens/screener, then read the same tokens' signed net flow on Ethereum; a token's net flow on a chain is the supply minted there minus the supply burned, in USD.

Uses
/tokens/screener, /tokens/search
Verified
live API, 2026-11-03: 5 calls, all 200
Free APIArchiveStreamMCP
Ask your AI agent: “Which Base tokens had the largest net inflow over the last 7 days, and what was their net flow on Ethereum?”

The code

python
import os
import requests

API_KEY = os.environ["VIKE_API_KEY"]  # your key, read from the environment

# the Base tokens that gained the most supply, in USD, over the 7-day window
r = requests.get(
    "https://data.vike.io/v1/onchain/tokens/screener?chain=base&sort=net_inflow&window=7d&limit=5",
    headers={"X-API-Key": API_KEY},
)
FAQ

Token holders and token screener FAQ

How do I check the top holders of a token?
Find its contract with /tokens/search, then call /tokens/{token_address}/holders?sort=balance: the wallets that hold the most of it now, each with its balance read from the chain, its USD value and its share of the supply, up to 50 rows. In Claude or ChatGPT, ask for the top holders and the agent calls token_search and token_holders.
Are token holders ranked by balance or by inflow?
Both, by choice. The default, sort=flow, ranks wallets by their all-time net inflow of the token in USD: a flow, not a holding. sort=balance ranks by the balance read from the chain among candidate wallets: the top 150 by net inflow and the top 150 by volume. candidate_coverage says how much of the supply those candidates hold, and balance_approximate is true below 20%.
What is the token screener?
GET /tokens/screener ranks the tokens of one chain by volume, net_inflow, holders, smart_inflow over 24h, 7d, 30d, 90d, filtered by a minimum volume or number of wallets, up to 100 tokens. The MCP tool is token_screener; the CLI command vike-data token screener.
What counts as smart money in the screener?
Wallets with more than $100,000 of realized profit on Ethereum. sort=smart_inflow ranks tokens by their net inflow alone, and smart_money_only=true limits every figure to them; both are Ethereum only, any other chain is a 400.
Which chains are covered?
Ethereum, BNB Chain, Base and HyperEVM: pass chain=ethereum, bsc, base or hyperevm (default ethereum). Ranking holders by balance is not available on every chain: the answer is then a 400 that names it.