Skip to main content

Blockchain Address Lookup API: Balance, Transfers and Activity for Any Address

A blockchain address lookup answers four questions about a wallet: what it holds now, what it sent and received lately, when it was first and last active, and which tokens it owns. This page answers each question with one GraphQL query on Ethereum (an EVM chain) and on Tron. The same queries work on every EVM network Bitquery supports by changing network, and the per-chain pages cover the rest. To ask the same questions in plain English, use the Bitquery MCP.

The examples use two well-known addresses:

  • Ethereum: 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 (vitalik.eth).
  • Tron: TLaGjwhvA8XQYSxFAcAXy7Dvuue9eGYitv (an OKX hot wallet).

Replace them with the address you want to look up. Every query runs on the v2 endpoint https://streaming.bitquery.io/graphql. Balances and activity times come from the Balances cube, which stores the current state per address and currency, so the lookup is fast even for addresses with years of history. dataset: combined merges the realtime and archive data, so an address that has been quiet for years is found too.

Current balance of an address​

The native coin balance (ETH on Ethereum, TRX on Tron) is the Balances row with Currency: { Native: true }. AmountInUSD gives its value in USD.

Ethereum​

Run this query in the IDE

query {
EVM(network: eth, dataset: combined) {
Balances(
where: {
Balance: { Address: { is: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" } }
Currency: { Native: true }
}
) {
Currency {
Name
Symbol
Native
}
Balance {
Address
Amount
AmountInUSD
}
}
}
}

Tron​

Run this query in the IDE

query {
Tron(dataset: combined) {
Balances(
where: {
Balance: { Address: { is: "TLaGjwhvA8XQYSxFAcAXy7Dvuue9eGYitv" } }
Currency: { Native: true }
}
) {
Currency {
Name
Symbol
Native
}
Balance {
Address
Amount
AmountInUSD
}
}
}
}

For the balance of one token, replace Native: true with SmartContract: { is: "<token contract>" }. For the balance on a past date, see Balance on a Specific Date.

Latest transfers in and out​

Two aliases on the Transfers cube return the latest outgoing (sent) and incoming (received) transfers of the address in one request, native coin and tokens together. Each row has the time, the transaction hash, the counterparty, the amount, its USD value and the currency. The queries read the last 3 days of the realtime dataset; for older transfers add dataset: combined and set the time window you need.

Ethereum​

Run this query in the IDE

query {
EVM(network: eth) {
sent: Transfers(
limit: { count: 10 }
orderBy: { descending: Block_Time }
where: {
Transfer: { Sender: { is: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" } }
Block: { Time: { since_relative: { days_ago: 3 } } }
TransactionStatus: { Success: true }
}
) {
Block {
Time
}
Transaction {
Hash
}
Transfer {
Receiver
Amount
AmountInUSD
Currency {
Symbol
SmartContract
}
}
}
received: Transfers(
limit: { count: 10 }
orderBy: { descending: Block_Time }
where: {
Transfer: { Receiver: { is: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" } }
Block: { Time: { since_relative: { days_ago: 3 } } }
TransactionStatus: { Success: true }
}
) {
Block {
Time
}
Transaction {
Hash
}
Transfer {
Sender
Amount
AmountInUSD
Currency {
Symbol
SmartContract
}
}
}
}
}

Tron​

Run this query in the IDE

query {
Tron {
sent: Transfers(
limit: { count: 10 }
orderBy: { descending: Block_Time }
where: {
Transfer: { Sender: { is: "TLaGjwhvA8XQYSxFAcAXy7Dvuue9eGYitv" } }
Block: { Time: { since_relative: { days_ago: 3 } } }
TransactionStatus: { Success: true }
}
) {
Block {
Time
}
Transaction {
Hash
}
Transfer {
Receiver
Amount
AmountInUSD
Currency {
Symbol
SmartContract
}
}
}
received: Transfers(
limit: { count: 10 }
orderBy: { descending: Block_Time }
where: {
Transfer: { Receiver: { is: "TLaGjwhvA8XQYSxFAcAXy7Dvuue9eGYitv" } }
Block: { Time: { since_relative: { days_ago: 3 } } }
TransactionStatus: { Success: true }
}
) {
Block {
Time
}
Transaction {
Hash
}
Transfer {
Sender
Amount
AmountInUSD
Currency {
Symbol
SmartContract
}
}
}
}
}

To follow new transfers live, turn the query into a subscription and drop limit, orderBy and the time filter. More filters (one token, minimum amount, counterparty) are on the ERC20 Token Transfers API and Tron Transfers API pages.

First and last activity​

Every Balances row carries FirstChangeTime and LastChangeTime: the first and the latest time that currency's balance changed at the address. Sorting the rows by them gives the address's first activity (first_activity, usually the first deposit) and its latest activity (last_activity) in one request, with the currency that moved.

Ethereum​

Run this query in the IDE

query {
EVM(network: eth, dataset: combined) {
first_activity: Balances(
limit: { count: 1 }
orderBy: { ascending: Balance_FirstChangeTime }
where: {
Balance: { Address: { is: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" } }
}
) {
Currency {
Symbol
SmartContract
}
Balance {
FirstChangeTime
}
}
last_activity: Balances(
limit: { count: 1 }
orderBy: { descending: Balance_LastChangeTime }
where: {
Balance: { Address: { is: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" } }
}
) {
Currency {
Symbol
SmartContract
}
Balance {
LastChangeTime
}
}
}
}

Tron​

Run this query in the IDE

query {
Tron(dataset: combined) {
first_activity: Balances(
limit: { count: 1 }
orderBy: { ascending: Balance_FirstChangeTime }
where: {
Balance: { Address: { is: "TLaGjwhvA8XQYSxFAcAXy7Dvuue9eGYitv" } }
}
) {
Currency {
Symbol
SmartContract
}
Balance {
FirstChangeTime
}
}
last_activity: Balances(
limit: { count: 1 }
orderBy: { descending: Balance_LastChangeTime }
where: {
Balance: { Address: { is: "TLaGjwhvA8XQYSxFAcAXy7Dvuue9eGYitv" } }
}
) {
Currency {
Symbol
SmartContract
}
Balance {
LastChangeTime
}
}
}
}

Add UpdateCount to Balance to see how many times each currency's balance changed at the address.

Token holdings of an address​

Without a Currency filter, Balances returns one row per token the address holds. Amount(selectWhere: { gt: "0" }) drops tokens it no longer holds, and ordering by Balance_AmountInUSD puts the largest positions first.

Ethereum​

Run this query in the IDE

query {
EVM(network: eth, dataset: combined) {
Balances(
limit: { count: 20 }
orderBy: { descending: Balance_AmountInUSD }
where: {
Balance: { Address: { is: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" } }
}
) {
Currency {
Name
Symbol
SmartContract
Native
}
Balance {
Amount(selectWhere: { gt: "0" })
AmountInUSD
}
}
}
}

Tron​

Run this query in the IDE

query {
Tron(dataset: combined) {
Balances(
limit: { count: 20 }
orderBy: { descending: Balance_AmountInUSD }
where: {
Balance: { Address: { is: "TLaGjwhvA8XQYSxFAcAXy7Dvuue9eGYitv" } }
}
) {
Currency {
Name
Symbol
SmartContract
Native
}
Balance {
Amount(selectWhere: { gt: "0" })
AmountInUSD
}
}
}
}

Anyone can send a token to any address, so a wallet's holdings often include airdropped spam tokens with a USD value. Check the SmartContract of a token before you trust its symbol. For NFT holdings, add Currency: { Fungible: false } (see NFTs Tracking Across Chains).

Look up one address on several EVM chains​

An EVM address is the same on every EVM chain, so one request with GraphQL aliases looks it up on Ethereum, BSC, Base and Arbitrum at once. This query returns the native coin balance and the time it last changed on each chain.

Run this query in the IDE

query {
ethereum: EVM(network: eth, dataset: combined) {
Balances(
where: {
Balance: { Address: { is: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" } }
Currency: { Native: true }
}
) {
Currency {
Symbol
}
Balance {
Amount
AmountInUSD
LastChangeTime
}
}
}
bsc: EVM(network: bsc, dataset: combined) {
Balances(
where: {
Balance: { Address: { is: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" } }
Currency: { Native: true }
}
) {
Currency {
Symbol
}
Balance {
Amount
AmountInUSD
LastChangeTime
}
}
}
base: EVM(network: base, dataset: combined) {
Balances(
where: {
Balance: { Address: { is: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" } }
Currency: { Native: true }
}
) {
Currency {
Symbol
}
Balance {
Amount
AmountInUSD
LastChangeTime
}
}
}
arbitrum: EVM(network: arbitrum, dataset: combined) {
Balances(
where: {
Balance: { Address: { is: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" } }
Currency: { Native: true }
}
) {
Currency {
Symbol
}
Balance {
Amount
AmountInUSD
LastChangeTime
}
}
}
}

Address pages for other chains​

Each chain has its own page with more address queries (balance history, balance on a date, balance updates, transfers):

ChainBalance and holdingsTransfers
EthereumEthereum Balance APIERC20 Token Transfers API
BSCBSC Balance APIBSC Transfers API
BaseBase Address Balance APIBase Transfers API
SolanaSolana Balances and Balance Updates APISolana Transfers API
TronTron Address Balance APITron Transfers API
BitcoinBitcoin Address APIBitcoin Address API

Solana has no Balances cube: its balances come from Solana.BalanceUpdates, shown on the Solana page.

Look up an address in plain English with the MCP​

The Bitquery MCP server lets an AI client such as Claude, ChatGPT or Cursor answer "who is this address and what has it done" without writing a query. Three groups of tools do the address lookup:

ToolWhat it answersInputs
labels_for_addressesWho owns a list of addresses: exchange deposit or hot wallet, mixer, scam, sanctioned entity and other labelsaddresses (required; separated by commas, pipes, spaces or new lines), chain (leave empty to search every chain), label_type, limit (default 200, up to 10000)
address_labelsEvery label of one address, wallet or token contractaddress (required), chain (leave empty to search every chain)
address_risk_reportAn AML risk score from 0 to 100 for a Tron, Bitcoin or Ethereum address, with the labelled entities it received from and sent to and its exposure by entity typechain and address (required), asset, after_time, before_time, direction (both, received, sent), view (all or direct), max_hops (1 to 6, default 2), min_amount_usd (default 100), weights, format (markdown or json)
<chain>_address_profileTransfer counts in and out, distinct senders and receivers, and first and last activity of one addressSee the table below

labels_for_addresses returns one row per labelled address with Labels (each written as chain/label_type:label_value), Label_Types, Sources, Source_Count and Status. An address that is missing from the answer has no label; when none of the addresses has one, the answer is a single row with Status NO_LABELS_FOUND. address_risk_report adds a band to the score (none at 0, low below 25, medium 25 to 49, elevated 50 to 74, high 75 and up). Its view: all traces funds up to max_hops hops on Tron; on Bitcoin and Ethereum the report is the direct view.

The address profile tools by chain​

The address profile tools share the address and format (rows or columnar) inputs and differ in the period they cover and the filters they take:

ToolsChainsPeriodFiltersReturns
eth_address_profile, bsc_address_profile, base_address_profile, arbitrum_address_profile, optimism_address_profile, matic_address_profile, robinhood_address_profileEthereum, BSC, Base, Arbitrum, Optimism, Polygon, Robinhood ChainWhole history, or after_time / before_timecontract or currency (one token), include_internal (0 by default; 1 also counts native coin moved by contract code inside a transaction)Sent_Transfers, Received_Transfers, Distinct_Receivers, Distinct_Senders, First_Sent, Last_Sent, First_Received, Last_Received; Sent_Amount and Received_Amount when one token is set
arc_address_profileArcWhole history, or after_time / before_timecontract, currency, asset_type (all, native, token, usdc), include_internal (1 by default)Same as the EVM tools, plus Sent_Assets and Received_Assets
tron_address_profileTronWhole history, or after_time / before_timecontract or currencySame as the EVM tools
solana_address_profileSolanaLast days days (default 90, up to 20000)NoneWindow_Days, Window_From, Sent_Transfers, Received_Transfers, Distinct_Receivers, Distinct_Senders
xrp_address_profileXRP LedgerLast days days (default 90, up to 20000)NonePayments sent and received, distinct receivers and senders, destination tags, other value records, filled offers, transactions signed, fees paid in XRP, first and last activity
xlm_address_profileStellarLast days days (default 90, up to 20000)NonePayments sent and received, distinct receivers and senders, accounts created, claimable balances, filled offers, transactions signed, fees paid in XLM, first and last activity, Created_By
btc_address_profile, bch_address_profile, ltc_address_profile, doge_address_profile, dash_address_profile, zec_address_profileBitcoin, Bitcoin Cash, Litecoin, Dogecoin, Dash, Zcash (transparent addresses)Whole historyNoneTotal received and sent in the chain's coin (received minus sent is the balance), distinct senders and receivers, receiving and spending counts, first and last activity
ada_address_profileCardanoWhole historycurrency (ADA by default; empty lists every asset), limit (default 20, up to 500)One row per asset: received, sent and current balance, output and transaction counts, first and last activity, address type, Is_Script, Stake_Key, distinct senders and receivers

Example prompts:

  • "Look up 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045: first and last activity on Ethereum, and who it sends to."
  • "Who owns these Tron addresses? TLaGjwhvA8XQYSxFAcAXy7Dvuue9eGYitv, TU4vEruvZwLLkSfV9bNw12EJTPvNr7Pvaa"
  • "Give me a risk report for this Tron address."

More on these tools: Counterparties, Holders and balances, Tracing MCP and Solana MCP.

Frequently Asked Questions

What is a blockchain address lookup?

A blockchain address lookup reads the public on-chain record of one wallet or contract address: its current balance, the tokens it holds, the transfers it sent and received, and when it was first and last active. With Bitquery you get all of it from one GraphQL API, for one address or many, on many chains, without running a node.

Can you look up an address without knowing the chain?

Mostly, yes. The address format narrows it down: 0x followed by 40 hex characters is an EVM address, T followed by 33 characters is Tron, 1, 3 or bc1 is Bitcoin, and a 32 to 44 character base58 string is usually Solana. An EVM address is the same on every EVM chain, so one GraphQL request with aliases can check Ethereum, BSC, Base and Arbitrum at once, as in the multi-chain query on this page. On the MCP, labels_for_addresses and address_labels search every chain when chain is left empty.

Is the address lookup API free?

Yes, with a free trial on real-time data. The archive and combined datasets, which the balance, activity and holdings queries on this page use, are part of the paid plans. Queries are billed in points, and the points per call depend on how much data the query reads. See How Billing Works for the current plans, trial limits and points.

Build with Bitquery

Ready to run this in production?

Get an API key and run these queries in minutes, or talk to us about plans and enterprise delivery.