Crypto wallet lookup & checker: who is behind an address
Paste any address and see who is behind it: its label on each chain and where each label comes from, its ENS name, whether it is a contract or a token, the chains it is active on, who funded it first, the exchanges it uses and its Hyperliquid and Polymarket identity. Ethereum, BNB Chain, Base and HyperEVM, one call, plain facts.
“Whose wallet is 0x28c6c06298d514db089934071355e5743bf21d60, and where does that label come from?”
wallet_check“Label these 100 addresses and tell me which are exchanges and whether any is flagged.”
wallet_batch_labelsEverything about one address, in one call
Labels and their sources, ENS, contract or token, active chains, first funder, exchanges, Hyperliquid and Polymarket identity. Plain facts, never a verdict.
Check an address: who is behind it, in one call
- Route
GET /v1/onchain/wallets/{address}/check- CLI
- —
- MCP
wallet_check· 5 credits- Cost
- 1 request of the hourly limit
Everything we know about one address in one call: its ENS name, labels per chain, which source claimed what (Ethereum) and where each other chain's label came from (label_origins: third_party, model, cross_chain or unknown), transfer counts per chain, the code found at the address, token details when it is a token contract, the earliest inbound transfers and the centralised exchanges it used on each chain it is active on, and its Hyperliquid and Polymarket identity. summary lists plain facts read off those blocks, never a verdict such as "safe". A block missing from the answer could not be read; an empty block means we looked and found nothing. first_funder is not proof of who funded the wallet, and exchange figures are a lower bound (the coverage of each says why).
Parameters
| Parameter | In | Description |
|---|---|---|
addressrequired | path | Wallet or contract address, 0x-prefixed hex, 42 characters |
chain | query | ethereum | bsc | base | hyperevm. Reads first_funder and exchanges on this chain only. Default: every chain the address has transfers on |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/onchain/wallets/0x28c6c06298d514db089934071355e5743bf21d60/check?chain=ethereum"
import os, requests
address = "0x28c6c06298d514db089934071355e5743bf21d60" # Binance 14
r = requests.get(
f"https://data.vike.io/v1/onchain/wallets/{address}/check",
params={"chain": "ethereum"},
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
).json()
for fact in r["summary"]:
print("-", fact)
for label in r["labels"]:
print(label["chain"], label["entity"], label["type"])
# any MCP client; or from the terminal:
vike-data call wallet_check --args '{"address": "0x28c6c06298d514db089934071355e5743bf21d60", "chain": "ethereum"}'
What comes back
| Block | What it says |
|---|---|
address | The address you asked about. |
ens | Its ENS name, or null. |
tags | Names attached to the address, such as a token's name. |
labels | Per chain: the entity and the wallet type. |
onchain | Per chain where it is active: how many transfers it has. |
token | Name, symbol and chain when the address is a token contract. |
hl_trader | Its Hyperliquid trader profile, when it has one. |
hl_vault | The Hyperliquid vault at this address, when there is one. |
hl_builder | The Hyperliquid builder at this address, when there is one. |
polymarket | The Polymarket account at this address, its owner, and the accounts it owns. |
code | Per chain: the code found at the address — contract, delegated wallet, safe multisig or proxy. |
label_sources | Ethereum: which source said what about the address (providers are named provider_a to provider_e). |
label_origins | BNB Chain, Base and HyperEVM: where each chain's label came from — third_party, model, cross_chain or unknown — and what it said. |
first_funder | Per chain: the earliest coin and token transfers in, with the sender and its label. |
exchanges | Per chain: the exchanges it sent to and received from over 365 days, with USD and shares. |
summary | Plain facts read off the blocks above. Never a verdict such as “safe”. |
A block missing from the answer could not be read; an empty one means we looked and found nothing.
A real answer: Binance 14
GET /v1/onchain/wallets/0x28c6c06298d514db089934071355e5743bf21d60/check?chain=ethereum · captured 2026-11-03
- labelled binance (cex) on ethereum, bsc, base
- active on 4 of 4 chains (ethereum, bsc, base, hyperevm)
- earliest inbound transfer on ethereum: from binance, 2021-04-22
- transfers with binance, bitmex, unnamed_cex, coinbase, abraxas capital mgmt (heka funds) and 97 more on ethereum (365d)
{
"address": "0x28c6c06298d514db089934071355e5743bf21d60",
"ens": null,
"tags": [],
"labels": [
{
"chain": "ethereum",
"entity": "binance",
"type": "cex"
},
{
"chain": "bsc",
"entity": "binance",
"type": "cex"
},
{
"chain": "base",
"entity": "binance",
"type": "cex"
}
],
"onchain": [
{
"chain": "ethereum",
"transfers": 57402273
},
{
"chain": "bsc",
"transfers": 18810
},
{
"chain": "base",
"transfers": 18231
},
{
"chain": "hyperevm",
"transfers": 2
}
],
"token": [],
"hl_trader": null,
"hl_vault": null,
"hl_builder": null,
"polymarket": {
"account": null,
"owned": []
},
"code": [],
"label_sources": [
{
"source": "provider_a",
"label": "Binance: Hot Wallet (0x28C)",
"entity": "Binance",
"category": "Hot Wallet"
},
{
"source": "provider_b",
"label": "Binance 14",
"entity": "binance",
"category": null
},
{
"source": "provider_c",
"label": "Binance: Hot Wallet",
"entity": "binance",
"category": "exchange"
},
{
"source": "provider_d",
"label": "binance",
"entity": "binance",
"category": null
}
],
"label_origins": [
{
"chain": "bsc",
"origin": "third_party",
"source": "provider_a",
"label": "Binance: Hot Wallet (0x28C)",
"entity": "Binance",
"category": "Hot Wallet"
},
{
"chain": "base",
"origin": "unknown"
}
],
"first_funder": [
{
"address": "0x28c6c06298d514db089934071355e5743bf21d60",
"chain": "ethereum",
"found": true,
"first_native_in": {
"from": "0x00799bbc833d5b168f0410312d2a8fd9e0e3079c",
"label": "binance",
"wallet_type": "cex",
"label_confidence": "medium",
"time": "2021-04-22T06:34:00Z",
"tx_hash": "0x7671e86accfb3cd75a9000e2d7eabced7fedab72aadeb93a4232cf1729b4e219",
"block": 12288433,
"amount": 1.0,
"amount_symbol": "ETH",
"amount_wei": "1000000000000000000",
"amount_usd": 2475.73
},
"first_token_in": {
"from": "0x0681d8db095565fe8a346fa0277bffde9c0edbbf",
"label": "binance",
"wallet_type": "cex",
"label_confidence": "medium",
"time": "2021-04-26T03:07:54Z",
"tx_hash": "0x3b1a92de6d98d50986659806f7bd0365f07bc1b869f1205cbb2a5c7ab7201a8d",
"block": 12313419,
"token_address": "0x5732046a883704404f284ce41ffadd5b007fd668",
"symbol": "BLZ",
"amount": 3920.999999,
"amount_usd": 1219.430999
}
}
],
"exchanges": [
{
"address": "0x28c6c06298d514db089934071355e5743bf21d60",
"chain": "ethereum",
"window": "365d",
"found": true,
"activity": {
"sent_usd": 395530378582.00854,
"recv_usd": 393397324977.6417,
"transfers": 11861793,
"counterparties": 4691377
},
"pattern": null,
"pattern_basis": null,
"exchanges": [
{
"entity": "binance",
"sent_usd": 302268933172.84656,
"recv_usd": 238011740196.01758,
"sent_share": 0.7642,
"transfers": 2410435,
"first_seen": "2025-11-03T11:40:47Z",
"last_seen": "2026-11-02T23:30:11Z"
},
{
"entity": "bitmex",
"sent_usd": 18455034505.216312,
"recv_usd": 0.0,
"sent_share": 0.0467,
"transfers": 83,
"first_seen": "2025-11-14T12:59:35Z",
"last_seen": "2026-10-29T16:35:47Z"
},
{
"entity": "unnamed_cex",
"sent_usd": 4285565612.875266,
"recv_usd": 302499866.863271,
"sent_share": 0.0108,
"transfers": 30231,
"first_seen": "2025-11-03T11:42:59Z",
"last_seen": "2026-10-29T21:31:47Z"
}
]
}
],
"summary": [
"labelled binance (cex) on ethereum, bsc, base",
"active on 4 of 4 chains (ethereum, bsc, base, hyperevm)",
"earliest inbound transfer on ethereum: from binance, 2021-04-22",
"transfers with binance, bitmex, unnamed_cex, coinbase, abraxas capital mgmt (heka funds) and 97 more on ethereum (365d)"
]
}
Trimmed: the first 3 of the 102 exchanges, each with fewer fields, and the coverage notes left out.
Who is behind an address, and who says so
Every source's own claim beside the consensus label; up to 100 addresses in one call.
Wallet labels
Entity, wallet type and risk flag per address — plus which source claimed what.
- Route
/v1/onchain/labels/{address}/provenance- Cadence
- Rebuilt by the label pipeline
- Coverage
- Ethereum addresses for
/labels/{address}/provenance, which returns the consensus label and every source's own claim, among themprovider_e(Polymarket wallets, the addresses that control or funded them, and mass payers), which answers for an address on any EVM chain and never feeds the consensus; POST /labels/batch labels a comma-separated list of addresses in one call, from the label set of thechainyou pass (ethereum, bsc, base or hyperevm);/wallets/{address}summarises flows over 24h, 7d, 30d, 90d and all time. - Rows
- MCP
wallet_label_provenance
Fields
| Field | Type | Description |
|---|---|---|
address | string | The address asked about |
found | boolean | At least one source knows this address (consensus is all null when only provider_e does) |
consensus.entity | string|null | Resolved entity name |
consensus.wallet_type | string|null | e.g. cex, market_maker, treasury, dex, mev |
consensus.cex_product | string|null | For exchange wallets, e.g. retail |
consensus.user_subtype | string|null | e.g. active |
consensus.risk_flag | string|null | Null when none |
consensus.confidence | string|null | Classification confidence, e.g. medium |
sources | array | One object per source: source, label, and entity / category when the source has them. A `provider_e` entry also carries basis, evidence, n_wallets, volume_usd, realized_pnl_usd, top_wallet and top_wallet_name |
source_count | integer | How many sources made a claim |
A real answer
Wallet labels · /labels/{address}/provenance
Load it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/onchain/labels/0x28c6c06298d514db089934071355e5743bf21d60/provenance"
import os, requests
rows = requests.get(
"https://data.vike.io/v1/onchain/labels/0x28c6c06298d514db089934071355e5743bf21d60/provenance",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
timeout=60,
).json()["sources"]
for row in rows[:5]:
print(row)
import os, requests
import polars as pl
df = pl.DataFrame(requests.get(
"https://data.vike.io/v1/onchain/labels/0x28c6c06298d514db089934071355e5743bf21d60/provenance",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
timeout=60,
).json()["sources"])
print(df.head())
GET /v1/onchain/labels/{address}/provenance · Where a label comes from: every source and the consensus
- CLI
vike-data labels- MCP
wallet_label_provenance· 1 credit- Cost
- 1 request of the hourly limit
Which source claimed what about this wallet. Degrades to fewer rows rather than erroring while one of its label sources is being refreshed. Source provider_e covers Polymarket wallets, the addresses that control or funded them, and the addresses that paid many of them (bridges, exchanges, reward payers), with basis (onchain_fact, or behaviour_inferred / behaviour_corroborated for a guess from behaviour), evidence, and for a wallet, controller or funder the wallets' count, volume and realized PnL. It never feeds consensus. found is true when any source knows the address, so an address only provider_e knows answers found: true with an all-null consensus.
Parameters
| Parameter | In | Description |
|---|---|---|
addressrequired | path | Wallet address, 0x-prefixed hex |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/onchain/labels/0x28c6c06298d514db089934071355e5743bf21d60/provenance"
import os, requests
r = requests.get(
"https://data.vike.io/v1/onchain/labels/0x28c6c06298d514db089934071355e5743bf21d60/provenance",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data labels 0x28c6c06298d514db089934071355e5743bf21d60
# any MCP client; or from the terminal:
vike-data call wallet_label_provenance --args '{"address": "0x28c6c06298d514db089934071355e5743bf21d60"}'
Label up to 100 addresses in one call
- Route
POST /v1/onchain/labels/batch- CLI
vike-data wallet batch- MCP
wallet_batch_labels· 2 credits- Cost
- 1 request of the hourly limit
Enrich a list of addresses in one call: entity, wallet type, risk flag, 30-day net flow, 30-day volume and 30-day transaction count, one row per input address in input order. The 30-day figures are live (the last 30 calendar days, the same window as the wallet summary) and are null only for an address with no label (found: false); a labelled wallet with no transfer in the window reads 0. An address flagged exploit is never typed cex. A row whose address source provider_e knows also carries provider_e: a list of that source's labels (class, entity, basis, evidence, the Polymarket wallets it is, controls or funded, their volume and realized PnL), on every chain, since an address is the same on every EVM chain. It is one more source beside the label: it never changes entity, wallet_type or found.
Parameters
| Parameter | In | Description |
|---|---|---|
addressesrequired | query | Comma-separated addresses. Capped at 100 |
chain | query | ethereum | bsc | base | hyperevm. Default ethereum. Labels and the 30-day flows are read from that chain's own tables. Any other name is a 400 |
Call it
curl -X POST -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/onchain/labels/batch?addresses=0x28c6c06298d514db089934071355e5743bf21d60,0xd8da6bf26964af9d7eed9e03e53415d37aa96045&chain=ethereum"
import os, requests
r = requests.post(
"https://data.vike.io/v1/onchain/labels/batch?addresses=0x28c6c06298d514db089934071355e5743bf21d60,0xd8da6bf26964af9d7eed9e03e53415d37aa96045&chain=ethereum",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data wallet batch 0x28c6c06298d514db089934071355e5743bf21d60 0xd8da6bf26964af9d7eed9e03e53415d37aa96045
# any MCP client; or from the terminal:
vike-data call wallet_batch_labels --args '{"addresses": ["0x28c6c06298d514db089934071355e5743bf21d60", "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"], "chain": "ethereum"}'
Who funded it first, and the exchanges it uses
The earliest transfers in, with each sender's label, and the exchanges it sent to and received from.
First funder, exchange usage & transactions
A wallet's earliest inbound native and token transfers with each sender's label, the centralised exchanges it sent to and received from, and its raw transfer list.
- Routes
/v1/onchain/wallets/{address}/first-funder,/v1/onchain/wallets/{address}/exchange-usage,/v1/onchain/wallets/{address}/transactions- Built on
- Token transfers, Wallet labels
- MCP
wallet_first_funder
GET /v1/onchain/wallets/{address}/first-funder · Who funded it first
- CLI
vike-data wallet first-funder- MCP
wallet_first_funder· 2 credits- Cost
- 1 request of the hourly limit
The earliest inbound transfers of a wallet, as two separate answers: first_native_in (the first plain send of the chain's coin) and first_token_in (the first priced token transfer), each with the sender, its label, time, transaction hash, block and amounts. Not proof of who funded the wallet: native rows hold top-level sends only, and history starts on a different date per chain (coverage).
Parameters
| Parameter | In | Description |
|---|---|---|
addressrequired | path | Wallet address, 0x-prefixed hex |
chain | query | ethereum | bsc | base | hyperevm. Default ethereum. Read from that chain's own transfer and label tables |
min_native | query | Dust floor for the native coin, in whole coins (ETH, BNB or HYPE; 0.01 is 0.01 coin, not wei). Inbound native transfers below it are skipped. Omitted resolves to 0.0001; an explicit 0 means no floor and returns the very first inbound, probing dust included |
min_usd | query | Floor for the token side, in USD. Token transfers priced below it, or with no USD price, are skipped. Omitted resolves to 1; an explicit 0 means no floor and includes unpriced tokens (mostly spam) |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/first-funder"
import os, requests
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/first-funder",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data wallet first-funder 0x556e9d5d9e64638edde632bbd4810c9fd0d88397
# any MCP client; or from the terminal:
vike-data call wallet_first_funder --args '{"address": "0x556e9d5d9e64638edde632bbd4810c9fd0d88397"}'
GET /v1/onchain/wallets/{address}/exchange-usage · Which exchanges it sends to and receives from
- CLI
vike-data wallet exchange-usage- MCP
wallet_exchange_usage· 3 credits- Cost
- 1 request of the hourly limit
Which centralised exchanges a wallet sent to and received from over a window: USD sent and received, transfer counts and first and last contact per exchange, plus pattern: "sweeps_to_single_cex" when at least 90% of the wallet's outgoing USD went to one exchange across at least 3 transfers. The pattern is observed, not a claim that the address is a deposit address, and exchange figures are a lower bound.
Parameters
| Parameter | In | Description |
|---|---|---|
addressrequired | path | Wallet address, 0x-prefixed hex |
chain | query | ethereum | bsc | base | hyperevm. Default ethereum. hyperevm has few labels, so a miss there says little |
window | query | 30d | 90d | 180d | 365d | all. Default 365d. A very active wallet over a long window is a 400 naming this parameter: narrow it |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/onchain/wallets/0x84b38bc60f3bd82640ecefa320dab2be62e2da15/exchange-usage?window=90d"
import os, requests
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x84b38bc60f3bd82640ecefa320dab2be62e2da15/exchange-usage?window=90d",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data wallet exchange-usage 0x84b38bc60f3bd82640ecefa320dab2be62e2da15 --window 90d
# any MCP client; or from the terminal:
vike-data call wallet_exchange_usage --args '{"address": "0x84b38bc60f3bd82640ecefa320dab2be62e2da15", "window": "90d"}'
Its transfer list: Wallet tracker →
Its ENS name
The name an address set for itself, such as vitalik.eth.
Reverse ENS lookup: from address to name
- Route
GET /v1/onchain/wallets/{address}/ens- CLI
vike-data wallet ens- MCP
wallet_ens· 1 credit- Cost
- 1 request of the hourly limit
Reverse ENS lookup — turn an address into vitalik.eth. Returns null where the address has no ENS name set.
Parameters
| Parameter | In | Description |
|---|---|---|
addressrequired | path | Wallet address, 0x-prefixed, exactly 42 characters |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/onchain/wallets/0xd8da6bf26964af9d7eed9e03e53415d37aa96045/ens"
import os, requests
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0xd8da6bf26964af9d7eed9e03e53415d37aa96045/ens",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data wallet ens 0xd8da6bf26964af9d7eed9e03e53415d37aa96045
# any MCP client; or from the terminal:
vike-data call wallet_ens --args '{"address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045"}'
Who it deals with most
Its top counterparties by volume in a window, each labelled where we know it.
Top counterparties by volume
- Route
GET /v1/onchain/wallets/{address}/counterparties- CLI
vike-data wallet counterparties- MCP
wallet_counterparties· 2 credits- Cost
- 1 request of the hourly limit
A real answer
Top counterparties · /wallets/{address}/counterparties
The addresses this wallet transacted with most, by combined transfer volume over a window.
Parameters
| Parameter | In | Description |
|---|---|---|
addressrequired | path | Wallet address |
chain | query | ethereum | bsc | base | hyperevm. Default ethereum |
window | query | 24h | 7d | 30d | 90d | 180d | all. Default 30d |
limit | query | Route default 100; applied cap 50 |
Call it
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/onchain/wallets/0xd8da6bf26964af9d7eed9e03e53415d37aa96045/counterparties?window=30d&limit=10"
import os, requests
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0xd8da6bf26964af9d7eed9e03e53415d37aa96045/counterparties?window=30d&limit=10",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
)
print(r.json())
vike-data wallet counterparties 0xd8da6bf26964af9d7eed9e03e53415d37aa96045 --window 30d --limit 10
# any MCP client; or from the terminal:
vike-data call wallet_counterparties --args '{"address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045", "window": "30d", "limit": 10}'
The money trail hop by hop, and a transaction by its hash: Transactions →
Questions about an address, answered with code
Each with the sentence to ask your AI instead. Every block was run against the live API on 2026-11-03.
Whose wallet is this? Labels and entity for any address
Put a name to an Ethereum address: its label, the sources behind it and its ENS name, in three calls.
- Uses
/labels/batch,/labels/{…}/provenance,/wallets/{…}/ens- Verified
- live API, 2026-11-03: 3 calls, all 200
The code
"""Put a name to an Ethereum address: label, who said so, and its ENS name.
Run: VIKE_API_KEY=... python oc-whose-wallet.py [0xADDRESS] (--dry-run lists the requests and makes none)
"""
import os
import sys
from urllib.parse import urlencode
NAME = "oc-whose-wallet"
BASE = "https://data.vike.io"
DRY = "--dry-run" in sys.argv
ARGS = [a for a in sys.argv[1:] if not a.startswith("--")]
WALLET = ARGS[0] if ARGS else "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"
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():
# A POST with no body; one address is a one-element list. An address that is not valid comes back as [].
batch = call("/v1/onchain/labels/batch", method="POST", addresses=WALLET)
# Who said it: the consensus plus every source's own claim. A thin list can mean a source is rebuilding.
prov = call(f"/v1/onchain/labels/{WALLET}/provenance")
# Reverse ENS. source says which path answered: local (our store) or rpc (a fresh lookup).
ens = call(f"/v1/onchain/wallets/{WALLET}/ens")
if DRY:
return
if not batch:
fail(f"{WALLET} is not a valid address")
row = batch[0]
print(f"{WALLET}")
if row["found"]:
print(f" label {row['entity']} ({row['wallet_type']}), confidence {row['confidence']}")
print(f" 30 days ${row['volume_30d_usd']:,.0f} volume, {row['tx_30d']} txs, risk flag {row['risk_flag'] or 'none'}")
else:
print(" label none on record")
claims = "; ".join(s["label"] for s in prov.get("sources", []))
print(f" sources {prov.get('source_count', 0)}: {claims or 'none name it'}")
name = ens["ens"]
if name:
print(f" ens {name}")
elif ens["source"] == "rpc":
print(" ens none found, but an rpc miss may only mean the resolvers were unreachable: retry before concluding")
else:
print(" ens no name set")
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}")
Label 100 addresses in one call: who are they, and are any flagged or sanctioned?
One call labels up to 100 addresses and screens them for sanctioned, exploit and phishing addresses: POST them to /labels/batch and each row comes back with its entity, wallet type and risk flag.
- Uses
/labels/batch,/labels/{…}/provenance,/wallets/{…}/transactions- Verified
- live API, 2026-11-03: 6 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# entity, type and risk flag for five addresses in one call
r = requests.post(
"https://data.vike.io/v1/onchain/labels/batch?addresses=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045,0xeae7380dd4cef6fbd1144f49e4d1e6964258a4f4,0xbbbbbbbbbb9cc5e90e3b3af64bdaf62c37eeffcb,0x47666Fab8bd0Ac7003bce3f5C3585383F09486E2,0xA160cdAB225685dA1d56aa342Ad8841c3b53f291",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the flagged addresses of a list, with their flag
r = requests.post(
"https://data.vike.io/v1/onchain/labels/batch?addresses=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045,0x47666Fab8bd0Ac7003bce3f5C3585383F09486E2,0xA160cdAB225685dA1d56aa342Ad8841c3b53f291",
headers={"X-API-Key": API_KEY},
)
# then: jq '[.[] | select((.risk_flag // "") != "") | {wallet, entity, risk_flag}]'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# every source's claim about one flagged address, plus the consensus
r = requests.get(
"https://data.vike.io/v1/onchain/labels/0xd90e2f925da726b50c4ed8d0fb90ad053324f31b/provenance",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the same lookup against Base's labels
r = requests.post(
"https://data.vike.io/v1/onchain/labels/batch?chain=base&addresses=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045,0xeae7380dd4cef6fbd1144f49e4d1e6964258a4f4",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# addresses 101 to 200, in a second call
# the list here: every address in the newest 500 transfers of a Coinbase hot wallet, in order of appearance
transfers = requests.get(
"https://data.vike.io/v1/onchain/wallets/0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43/transactions?limit=500",
headers={"X-API-Key": API_KEY},
).json()
ADDRESSES = list(dict.fromkeys(a for t in transfers for a in (t["from_address"], t["to_address"])))
BATCH_2 = ",".join(ADDRESSES[100:200])
r = requests.post(
f"https://data.vike.io/v1/onchain/labels/batch?addresses={BATCH_2}",
headers={"X-API-Key": API_KEY},
)
Who first funded this wallet?
One call returns the first coin and the first priced token a wallet received, each with the sender, the sender's label, the time and the amount.
- Uses
/wallets/{…}/first-funder- Verified
- live API, 2026-11-03: 4 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the first coin and the first priced token the wallet received, each with its sender's label
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/first-funder",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the same question on Base
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x2b1e8e051d85a65306910aef136d2aebf2eaccc5/first-funder?chain=base",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the very first inbound coin, whatever its size
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/first-funder?min_native=0",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# only a first coin of at least 0.5 ETH and a first token worth at least $1000
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/first-funder?min_native=0.5&min_usd=1000",
headers={"X-API-Key": API_KEY},
)
Which centralized exchanges does this wallet deposit to and withdraw from?
Call /wallets/{address}/exchange-usage; it lists each labelled exchange with the USD the wallet sent to it, the USD it received from it, transfer counts and first and last contact.
- Uses
/wallets/{…}/exchange-usage- Verified
- live API, 2026-11-03: 4 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# which exchanges a market-maker wallet used over 90 days, and how much went each way
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x84b38bc60f3bd82640ecefa320dab2be62e2da15/exchange-usage?window=90d",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# one line per exchange: deposits and withdrawals in USD
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x84b38bc60f3bd82640ecefa320dab2be62e2da15/exchange-usage?window=90d",
headers={"X-API-Key": API_KEY},
)
# then: jq '.exchanges[] | {entity, sent_usd, recv_usd, sent_transfers, recv_transfers}'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# a small wallet's exchanges over the last year
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/exchange-usage",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# exchanges a wallet used on BSC over all recorded history
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x40c9b7d91762f9c715478876310c554f4dc10435/exchange-usage?chain=bsc&window=all",
headers={"X-API-Key": API_KEY},
)
Is this address an exchange deposit address?
Call /wallets/{address}/exchange-usage and read pattern; sweeps_to_single_cex means at least 90% of its outgoing USD went to one exchange over at least 3 transfers, the shape of a deposit address.
- Uses
/wallets/{…}/exchange-usage,/wallets/{…}/transactions- Verified
- live API, 2026-11-03: 4 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# does this address forward its money to one exchange?
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/exchange-usage",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the address's inbound transfers over the last year, newest first
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/transactions?direction=in&days=365&limit=50",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the pattern and the exchange it points to, or null
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/exchange-usage",
headers={"X-API-Key": API_KEY},
)
# then: jq '{pattern, pattern_basis}'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the same check over the last 90 days
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/exchange-usage?window=90d",
headers={"X-API-Key": API_KEY},
)
Which of Ethereum, BNB Chain, Base and HyperEVM has this address been active on?
Call /wallets/{address} once per chain with chain=ethereum, bsc, base and hyperevm; each answers with that chain's transfer counts and first and last activity, and a chain with no transfers answers chain null.
- Uses
/wallets/{…},/wallets/{…}/balances- Verified
- live API, 2026-11-03: 5 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# has vitalik.eth been active on HyperEVM?
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045?chain=hyperevm",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the Ethereum figures
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045?chain=ethereum",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the BNB Chain figures
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045?chain=bsc",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the Base figures
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045?chain=base",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# chain and value of every holding worth at least 1 USD
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045/balances",
headers={"X-API-Key": API_KEY},
)
# then: jq '.holdings | map({chain, symbol, usd_value})'
Is this a burner wallet funded by exchanges? (age + first funder + exchange sweeps)
Combine /exchange-usage for a sweep pattern, /first-funder for who sent the first coins, and /wallets/{address} for the wallet's age and activity.
- Uses
/wallets/{…},/wallets/{…}/exchange-usage,/wallets/{…}/first-funder- Verified
- live API, 2026-11-03: 4 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# which exchanges the wallet used over the last year, and whether it sweeps to one of them
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/exchange-usage",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the first inbound ETH and the first priced inbound token
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/first-funder",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# first_seen, last_active and lifetime transfer count
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397",
headers={"X-API-Key": API_KEY},
)
# then: jq '{chain, all}'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# the same check over 90 days
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/exchange-usage?window=90d",
headers={"X-API-Key": API_KEY},
)
Sybil check: wallets funded by the same source
Call /wallets/{address}/first-funder for each wallet in your list and group the wallets by first_native_in.from; there is no reverse index, so it takes one call per wallet.
- Uses
/wallets/compare,/wallets/{…}/counterparties,/wallets/{…}/first-funder- Verified
- live API, 2026-11-03: 10 calls, all 200
The code
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# who sent this wallet its first ETH and its first priced token
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/first-funder",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# both senders and their labels, nothing else
r = requests.get(
"https://data.vike.io/v1/onchain/wallets/0x556e9d5d9e64638edde632bbd4810c9fd0d88397/first-funder",
headers={"X-API-Key": API_KEY},
)
# then: jq '{address, coin_from: .first_native_in.from, coin_label: .first_native_in.wallet_type, token_from: .first_token_in.from, token_label: .first_token_in.wallet_type}'
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# WALLET_A and WALLET_B are two wallets of one group: what they share over all history
WALLETS = [ # your list; one first-funder call per wallet, grouped by first_native_in.from
"0x556e9d5d9e64638edde632bbd4810c9fd0d88397",
"0x690c3eebf6ee237f00fc96f9766282f096c191cc",
"0x20bdd9bc103293f20a142f5118c00434e94cae4c",
]
groups = {}
for w in WALLETS:
first = requests.get(
f"https://data.vike.io/v1/onchain/wallets/{w}/first-funder",
headers={"X-API-Key": API_KEY},
).json().get("first_native_in")
if first and first["wallet_type"] != "cex": # an exchange hot wallet links nobody
groups.setdefault(first["from"], []).append(w)
WALLET_A, WALLET_B = next(g for g in groups.values() if len(g) > 1)[:2]
r = requests.get(
f"https://data.vike.io/v1/onchain/wallets/compare?address_a={WALLET_A}&address_b={WALLET_B}&window=all",
headers={"X-API-Key": API_KEY},
)
import os
import requests
API_KEY = os.environ["VIKE_API_KEY"] # your key, read from the environment
# FUNDER is the shared sender from the grouping; sent_usd > 0 marks the wallets it paid
WALLETS = [ # your list; one first-funder call per wallet, grouped by first_native_in.from
"0x556e9d5d9e64638edde632bbd4810c9fd0d88397",
"0x690c3eebf6ee237f00fc96f9766282f096c191cc",
"0x20bdd9bc103293f20a142f5118c00434e94cae4c",
]
groups = {}
for w in WALLETS:
first = requests.get(
f"https://data.vike.io/v1/onchain/wallets/{w}/first-funder",
headers={"X-API-Key": API_KEY},
).json().get("first_native_in")
if first and first["wallet_type"] != "cex": # an exchange hot wallet links nobody
groups.setdefault(first["from"], []).append(w)
FUNDER = next(f for f, g in groups.items() if len(g) > 1)
r = requests.get(
f"https://data.vike.io/v1/onchain/wallets/{FUNDER}/counterparties?window=all&limit=50",
headers={"X-API-Key": API_KEY},
)
Crypto wallet lookup FAQ
How do I look up who owns a crypto wallet address?
/v1/onchain/wallets/{address}/check, or ask your AI “whose wallet is 0x…?”. One call returns its label on each chain and where the label came from, its ENS name, whether it is a contract or a token, who funded it first, the exchanges it uses and its Hyperliquid and Polymarket identity.Can a wallet checker tell me if an address is safe?
Where does a wallet label come from?
label_sources lists which source said what about the address. On BNB Chain, Base and HyperEVM, label_origins says where each chain's label came from: third_party, model, cross_chain or unknown. /labels/{address}/provenance puts every source beside the consensus label, so you see where sources disagree.How do I label many addresses at once?
POST /v1/onchain/labels/batch with up to 100 comma-separated addresses in addresses. Rows come back in input order; an unknown address is found: false.Can I check an address on BNB Chain, Base or HyperEVM?
Does it tell a contract or a token from a wallet?
code says per chain what code sits at the address — a contract, a delegated wallet, a safe multisig or a proxy — and token gives the name and symbol when the address is a token.