Skip to main content
POST
getTokenAccountsByOwnerV2
curl --request POST \
  --url 'https://mainnet.helius-rpc.com/?api-key=' \
  --header 'Content-Type: application/json' \
  --data '
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "getTokenAccountsByOwnerV2",
  "params": [
    "A1TMhSGzQxMr1TboBKtgixKz1sS6REASMxPo1qsyTSJd",
    {
      "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
    },
    {
      "encoding": "jsonParsed",
      "limit": 1000
    }
  ]
}
'
{
  "jsonrpc": "2.0",
  "id": "1",
  "result": {
    "context": {
      "apiVersion": "2.0.15",
      "slot": 341197933
    },
    "value": [
      {
        "pubkey": "BGocb4GEpbTFm8UFV2VsDSaBXHELPfAXrvd4vtt8QWrA",
        "account": {
          "lamports": 2039280,
          "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
          "data": {
            "program": "spl-token",
            "parsed": {
              "info": {
                "isNative": false,
                "mint": "2cHr7QS3xfuSV8wdxo3ztuF4xbiarF6Nrgx3qpx3HzXR",
                "owner": "A1TMhSGzQxMr1TboBKtgixKz1sS6REASMxPo1qsyTSJd",
                "state": "initialized",
                "tokenAmount": {
                  "amount": "420000000000000",
                  "decimals": 6,
                  "uiAmount": 420000000,
                  "uiAmountString": "420000000"
                }
              }
            },
            "space": 165
          },
          "executable": false,
          "rentEpoch": 18446744073709552000,
          "space": 165
        }
      }
    ],
    "paginationKey": "8WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
    "totalResults": 5000
  }
}

Overview

getTokenAccountsByOwnerV2 is an enhanced version of the standard getTokenAccountsByOwner method, specifically designed for efficiently querying token portfolios and handling wallets with extensive token holdings. This method introduces cursor-based pagination and incremental update capabilities.
New Features in V2:
  • Cursor-based pagination: Configure limits from 1 to 10,000 token accounts per request
  • Incremental updates: Use changedSinceSlot to fetch only recently modified token accounts
  • Portfolio scalability: Handle wallets with thousands of token accounts efficiently
  • Backward compatibility: Supports all existing getTokenAccountsByOwner parameters and filters
Filter Requirement: You must provide either a mint (specific token) or programId (SPL Token or Token-2022 program) in your query. Querying all token types for an owner without a filter is not supported.

Key Benefits

Large Portfolios

Handle wallets with thousands of token accounts without timeouts or memory issues

Real-time Tracking

Monitor portfolio changes in real-time using changedSinceSlot for incremental updates

Pagination Best Practices

Important Pagination Behavior: End of pagination is only indicated when no token accounts are returned. The API may return fewer accounts than your limit due to filtering - always continue pagination until paginationKey is null.

Basic Portfolio Query

// Get all SPL Token accounts for a wallet
let allTokenAccounts = [];
let paginationKey = null;

do {
  const response = await fetch(`https://mainnet.helius-rpc.com/?api-key=${API_KEY}`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      jsonrpc: '2.0',
      id: '1',
      method: 'getTokenAccountsByOwnerV2',
      params: [
        "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM", // wallet address
        { "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" },
        {
          encoding: 'jsonParsed',
          limit: 1000,
          ...(paginationKey && { paginationKey })
        }
      ]
    })
  });
  
  const data = await response.json();
  allTokenAccounts.push(...data.result.value);
  paginationKey = data.result.paginationKey;
} while (paginationKey);

console.log(`Total token accounts: ${allTokenAccounts.length}`);

Incremental Portfolio Updates

// Get only token accounts modified since a specific slot
const portfolioUpdates = await fetch(`https://mainnet.helius-rpc.com/?api-key=${API_KEY}`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    jsonrpc: '2.0',
    id: '1',
    method: 'getTokenAccountsByOwnerV2',
    params: [
      walletAddress,
      { "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" },
      {
        encoding: 'jsonParsed',
        limit: 1000,
        changedSinceSlot: lastUpdateSlot // Only get recent changes
      }
    ]
  })
});

Token Program Support

Token-2022 Support: Use TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb as the programId to query Token-2022 accounts with extensions like transfer fees, interest-bearing tokens, and more.
// Query Token-2022 accounts (supports token extensions)
const token2022Response = await fetch(`https://mainnet.helius-rpc.com/?api-key=${API_KEY}`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    jsonrpc: '2.0',
    id: '1',
    method: 'getTokenAccountsByOwnerV2',
    params: [
      walletAddress,
      { "programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb" }, // Token-2022
      { encoding: 'jsonParsed', limit: 1000 }
    ]
  })
});

Migration from getTokenAccountsByOwner

Migration is simple - just add pagination parameters to your existing queries:
{
  "jsonrpc": "2.0",
  "id": "1",
- "method": "getTokenAccountsByOwner",
+ "method": "getTokenAccountsByOwnerV2",
  "params": [
    "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
    { "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" },
    {
      "encoding": "jsonParsed",
+     "limit": 1000
    }
  ]
}

Request Parameters

address
string
required
Solana wallet address (pubkey) of the account owner to query token holdings for, as a base-58 encoded string.
mint
string
Specific Solana token mint address to retrieve only accounts for a particular token or NFT.
programId
string
Specific Solana token program ID (typically SPL Token program) that created the token accounts.
commitment
string
The commitment level for the request.
  • confirmed
  • finalized
  • processed
minContextSlot
number
The minimum slot that the request can be evaluated at.
dataSlice
object
Request a slice of the account’s data.
dataSlice.length
number
Number of bytes to return.
dataSlice.offset
number
Byte offset from which to start reading.
encoding
string
Encoding format for Account data.
  • base58
  • base64
  • base64+zstd
  • jsonParsed
limit
number
Maximum number of token accounts to return per request (1-10,000).
paginationKey
string
Base-58 encoded pagination cursor for fetching subsequent pages. Use the paginationKey from previous response.
changedSinceSlot
number
Only return token accounts that were modified at or after this slot number. Useful for incremental portfolio updates.

Authorizations

api-key
string
query
required

Your Helius API key. You can get one for free in the dashboard.

Body

application/json
jsonrpc
enum<string>

The JSON-RPC protocol version.

Available options:
2.0
Example:

"2.0"

id
string

A unique identifier for the request.

Example:

"1"

method
enum<string>
default:getTokenAccountsByOwnerV2

The name of the RPC method to invoke.

Available options:
getTokenAccountsByOwnerV2
Example:

"getTokenAccountsByOwnerV2"

params
string · object · object[]

Parameters for querying paginated token accounts owned by a specific public key.

Solana wallet address (pubkey) of the account owner to query token holdings for, as a base-58 encoded string.

Example:

"A1TMhSGzQxMr1TboBKtgixKz1sS6REASMxPo1qsyTSJd"

Response

Successfully retrieved paginated token accounts by owner.

jsonrpc
enum<string>

The JSON-RPC protocol version.

Available options:
2.0
Example:

"2.0"

id
string

Identifier matching the request.

Example:

"1"

result
object

Paginated token accounts with navigation metadata.