Skip to main content
The Wallet API is in Beta. Endpoints and response formats may change.

Overview

The Wallet Balances endpoint retrieves all token and NFT holdings for a Solana wallet — SOL, SPL tokens, Token-2022, and NFTs — with USD pricing, logos, and metadata. Results are sorted by USD value in descending order: tokens with pricing data appear first, followed by tokens without prices. The endpoint returns up to 100 tokens per request, so pagination is manual. Use the page parameter to fetch additional pages and read pagination.hasMore to know when more results are available. Each request is a single API call and costs 100 credits.
USD prices are sourced from DAS and update hourly, covering the top 10,000 tokens by market cap. pricePerToken and usdValue are null for unsupported tokens. Prices are estimates, not real-time market rates.

When to use this

Use the Wallet Balances API when you need to:
  • Display portfolio holdings: show users their complete token and NFT holdings.
  • Calculate USD values: get portfolio valuations with hourly-updated pricing.
  • Build wallet UIs: power wallet dashboards and asset lists.
  • Track token holdings: monitor specific token balances across wallets.
  • Portfolio analytics: analyze holdings distribution and concentration.
  • Tax reporting: generate holdings snapshots for tax purposes.

Quickstart

Basic balance query

Get all token balances for a wallet with USD values:
const getWalletBalances = async (address) => {
  const url = `https://api.helius.xyz/v1/wallet/${address}/balances?api-key=YOUR_API_KEY`;

  const response = await fetch(url);
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }

  const data = await response.json();

  const solBalance = data.balances[0]; // SOL is always first when showNative=true
  console.log(`SOL Balance: ${solBalance.balance} SOL ($${solBalance.usdValue})`);
  console.log(`Page ${data.pagination.page} Total Value: $${data.totalUsdValue}`);
  console.log(`Token Count (this page): ${data.balances.length}`);

  // Display top holdings
  data.balances.slice(0, 5).forEach(token => {
    console.log(`${token.symbol}: ${token.balance} ($${token.usdValue || 'N/A'})`);
  });

  return data;
};

getWalletBalances("86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY");

Include NFTs in results

Get both tokens and NFTs in a single request with showNfts=true:
const getWalletWithNfts = async (address) => {
  const url = `https://api.helius.xyz/v1/wallet/${address}/balances?api-key=YOUR_API_KEY&showNfts=true`;

  const response = await fetch(url);
  const data = await response.json();

  console.log(`Tokens: ${data.balances.length}`);
  console.log(`NFTs: ${data.nfts?.length || 0}`);

  // Display NFTs
  data.nfts?.forEach(nft => {
    console.log(`NFT: ${nft.name || 'Unnamed'} (${nft.collectionName || 'Unknown Collection'})`);
  });

  return data;
};

getWalletWithNfts("86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY");

Filter the results

Use query parameters to narrow what is returned:
// Only show tokens with non-zero balances
const url = `https://api.helius.xyz/v1/wallet/${address}/balances?api-key=YOUR_API_KEY&showZeroBalance=false`;

// Exclude native SOL from results
const url = `https://api.helius.xyz/v1/wallet/${address}/balances?api-key=YOUR_API_KEY&showNative=false`;

// Get only the top 50 tokens by value
const url = `https://api.helius.xyz/v1/wallet/${address}/balances?api-key=YOUR_API_KEY&limit=50`;

Query parameters

ParameterTypeDefaultDescription
pageinteger1Page number for pagination (1-indexed)
limitinteger100Maximum number of tokens per page (1-100)
showZeroBalancebooleanfalseInclude tokens with zero balance
showNativebooleantrueInclude native SOL in results
showNftsbooleanfalseInclude NFTs in results (max 100, first page only)

Response format

{
  "balances": [
    {
      "mint": "So11111111111111111111111111111111111111111",
      "symbol": "SOL",
      "name": "Solana",
      "balance": 1.5,
      "decimals": 9,
      "pricePerToken": 145.32,
      "usdValue": 217.98,
      "logoUri": "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png",
      "tokenProgram": "spl-token"
    },
    {
      "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
      "symbol": "USDC",
      "name": "USD Coin",
      "balance": 1000.5,
      "decimals": 6,
      "pricePerToken": 1.0,
      "usdValue": 1000.5,
      "logoUri": "https://example.com/usdc-logo.png",
      "tokenProgram": "spl-token"
    }
  ],
  "nfts": [
    {
      "mint": "7Xq8wXyXVqfBPPqVJjPDwG9zN5wCVxBYZ6z7vPYBzr6F",
      "name": "Degen Ape #1234",
      "imageUri": "https://example.com/nft.png",
      "collectionName": "Degen Ape Academy",
      "collectionAddress": "DegN1dXmU2uYa4n7U9qTh7YNYpK4u8L9qXx7XqYqJfGH",
      "compressed": false
    }
  ],
  "totalUsdValue": 1218.48,
  "pagination": {
    "page": 1,
    "limit": 100,
    "hasMore": true
  }
}

Field notes

  • balance: human-readable amount, already adjusted for decimals — 1.5 means 1.5 SOL and 1000.5 means 1000.5 USDC. No lamport conversion is needed. This endpoint does not expose a raw amountRaw field; if you need the exact integer value, derive it as Math.round(balance * 10 ** decimals).
  • decimals: provided for reference only.
  • pricePerToken / usdValue: null for tokens without DAS pricing data (see the pricing note above).
  • totalUsdValue: total USD value for the current response page only. For full-portfolio value, paginate through all pages and sum each balance’s usdValue.
  • tokenProgram: which token standard each token uses — spl-token (legacy SPL Token) or token-2022 (Token Extensions). Both are fully supported.

Use cases

Build a portfolio dashboard

Display user holdings with USD values:
const renderPortfolio = async (address) => {
  const { balances, totalUsdValue } = await getWalletBalances(address);

  console.log(`Current Page Value: $${totalUsdValue.toLocaleString()}`);
  console.log(`\nTop Holdings:`);

  // totalUsdValue is page-scoped; paginate before computing full portfolio value.
  balances.slice(0, 10).forEach((token, i) => {
    if (token.usdValue) {
      console.log(`${i + 1}. ${token.symbol}: ${token.balance.toFixed(4)} ($${token.usdValue.toFixed(2)})`);
    }
  });
};

Calculate token concentration

Analyze portfolio diversification:
const analyzeConcentration = async (address) => {
  const { balances, totalUsdValue } = await getWalletBalances(address);

  const tokensWithValue = balances.filter(t => t.usdValue);

  if (tokensWithValue.length === 0) {
    console.log('No tokens with USD pricing data available');
    return null;
  }

  const topToken = tokensWithValue[0];
  const pageConcentration = (topToken.usdValue / totalUsdValue) * 100;

  console.log(`Largest Position on Current Page: ${topToken.symbol} (${pageConcentration.toFixed(1)}%)`);

  if (pageConcentration > 50) {
    console.log(`Warning: Current page is highly concentrated in ${topToken.symbol}`);
  }

  return { topToken, pageConcentration };
};

Track a specific token balance

Monitor a specific token across multiple wallets:
const getTokenBalance = async (address, tokenMint) => {
  const { balances } = await getWalletBalances(address);

  const token = balances.find(t => t.mint === tokenMint);

  if (!token) {
    console.log(`Token not found in wallet`);
    return null;
  }

  console.log(`${token.symbol} Balance: ${token.balance}`);
  console.log(`USD Value: $${token.usdValue || 'N/A'}`);

  return token;
};

// Example: Check USDC balance
getTokenBalance(
  "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY",
  "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v" // USDC mint
);

Export holdings for tax reporting

Generate a holdings snapshot:
const exportHoldingsSnapshot = async (address) => {
  const { balances, totalUsdValue } = await getWalletBalances(address);

  const snapshot = {
    date: new Date().toISOString(),
    address,
    pageValueUSD: totalUsdValue,
    holdings: balances
      .filter(t => t.usdValue)
      .map(t => ({
        symbol: t.symbol,
        mint: t.mint,
        balance: t.balance,
        pricePerToken: t.pricePerToken,
        usdValue: t.usdValue
      }))
  };

  console.log(JSON.stringify(snapshot, null, 2));
  return snapshot;
};

Pagination

For wallets with more than 100 tokens, page through results with the page parameter and pagination.hasMore:
const getAllBalances = async (address) => {
  let allBalances = [];
  let page = 1;
  let hasMore = true;

  while (hasMore) {
    const url = `https://api.helius.xyz/v1/wallet/${address}/balances?api-key=YOUR_API_KEY&page=${page}&limit=100`;

    const response = await fetch(url);
    const data = await response.json();

    allBalances = allBalances.concat(data.balances);
    hasMore = data.pagination.hasMore;
    page++;

    console.log(`Fetched page ${data.pagination.page}, total tokens so far: ${allBalances.length}`);
  }

  console.log(`Total tokens: ${allBalances.length}`);
  return allBalances;
};
NFTs are returned on the first page only (up to 100), regardless of token pagination.

Best practices

  • Filter zero balances for a cleaner UI. Use showZeroBalance=false to hide tokens the wallet no longer holds.
  • Include NFTs only when needed. NFTs are excluded by default for performance; set showNfts=true only when displaying them.
  • Handle missing price data. Always check whether pricePerToken and usdValue are null before displaying. These are hourly estimates from DAS, not real-time market rates.
  • Cache responses. Balance data can be cached for several seconds to reduce API calls.
  • Paginate large wallets. Some wallets hold thousands of tokens; implement pagination to handle them efficiently.

Common errors

Error CodeDescriptionSolution
400Invalid wallet address formatVerify the address is a valid base58 Solana address
401Missing or invalid API keyCheck your API key is included in the request
429Rate limit exceededReduce request frequency or upgrade your plan

Next steps

Historical Balance

Get a token or SOL balance at a past timestamp, datetime, or slot.

Wallet API Overview

All Wallet API endpoints and shared conventions.

API Reference

Request and response schemas for wallet balances.