Skip to main content
Beta: The Wallet API is currently in beta. APIs and response formats may change.

Overview

The Wallet Balances endpoint retrieves all token and NFT holdings for a Solana wallet. Get SOL, SPL tokens, Token-2022, and NFTs with USD pricing, logos, and metadata—all sorted by value. Pagination is manual - the API returns up to 100 tokens per request. Results are sorted by USD value in descending order. Tokens with pricing data appear first, followed by tokens without prices. Pagination: Use the page parameter to fetch additional pages. The response includes pagination.hasMore to indicate if more results are available. Each request makes a single API call and costs 100 credits.
USD Pricing: Token prices are sourced from DAS (Digital Asset Standard) and update hourly. Pricing covers the top 10,000 tokens by market cap. Not all tokens will have pricing data—pricePerToken and usdValue will be null for unsupported tokens. Prices are estimates and should not be relied upon as real-time market rates; support for real-time prices will be added in the future.

API Reference

View detailed API documentation for wallet balances

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:
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 Options

Customize the results with query parameters:

Hide Zero Balances

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

Hide Native SOL

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

Limit Results

// Get only 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": "So11111111111111111111111111111111111111112",
      "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
  }
}

Use Cases

Build a Portfolio Dashboard

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

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

  // Display top 10 holdings (SOL is first, then other tokens sorted by 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 concentration = (topToken.usdValue / totalUsdValue) * 100;

  console.log(`Largest Position: ${topToken.symbol} (${concentration.toFixed(1)}%)`);

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

  return { topToken, concentration };
};

Track 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,
    totalValueUSD: 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;
};

Token Program Support

The Wallet API supports both token standards:
Token ProgramDescriptionSupport
spl-tokenLegacy SPL Token standardFull support
token-2022New Token Extensions standardFull support
The tokenProgram field in the response indicates which standard each token uses.

Pagination

For wallets with many tokens (>100), use manual pagination with the page parameter:
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;
};

Best Practices

Use showZeroBalance=false to hide tokens the wallet no longer holds. This prevents cluttered portfolio views.
NFTs are excluded by default for performance. Only set showNfts=true when you need to display them.
USD prices are sourced from DAS and only cover the top 10,000 tokens with hourly updates. Always check if pricePerToken and usdValue are null before displaying. These are estimates, not real-time market rates.
Balance data can be cached for several seconds without issue. Reduce API calls by caching responses.
Some wallets hold thousands of tokens. Implement pagination to handle large datasets 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

Need Help?