The getTokenAccountsByOwner RPC method is used to retrieve all SPL Token accounts owned by a specific public key. This is a fundamental method for wallets and applications that need to display a user’s token holdings or interact with their various token accounts. You must filter the query by either a specific token mint or a programId (e.g., the SPL Token Program or Token-2022 Program). For wallets with extensive token portfolios, consider using getTokenAccountsByOwnerV2 which provides cursor-based pagination support with configurable page sizes up to 10,000 accounts per request.

Common Use Cases

  • Displaying User Portfolio: Fetching all token accounts (and thus balances) for a given user’s wallet address to show their complete token portfolio.
  • Application Logic: Identifying a user’s specific token account for a particular mint before initiating a transfer or other interaction.
  • Verification: Checking which token accounts an owner possesses for a certain type of token.
  • Indexing Token Holders: While less efficient for global indexing than other methods, it can be used to find accounts for a known set of owners.

Request Parameters

  1. ownerPubkey (string, required): The base-58 encoded public key of the account owner whose token accounts you want to retrieve.
  2. filter (object, required): A JSON object that must specify either mint or programId:
    • mint (string): The base-58 encoded public key of a specific token mint. If provided, only token accounts for this mint owned by ownerPubkey will be returned.
    • programId (string): The base-58 encoded public key of the Token Program that governs the accounts. Common values are:
      • SPL Token Program: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
      • Token-2022 Program: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
  3. options (object, optional): An optional configuration object that can include:
    • commitment (string, optional): Specifies the commitment level.
    • encoding (string, optional): The encoding for account data. "jsonParsed" is highly recommended. Other options: "base64", "base64+zstd". Defaults to "base64".
    • dataSlice (object, optional): To retrieve a specific slice of the account data (offset: usize, length: usize). Only for base58, base64, or base64+zstd encodings.
    • minContextSlot (u64, optional): The minimum slot for the query.

Response Structure

The result.value field in the JSON-RPC response is an array of objects. Each object corresponds to an SPL Token account owned by ownerPubkey and matching the filter. Each object in the value array contains:
  • pubkey (string): The base-58 encoded public key of the token account itself.
  • account (object): Detailed information about the token account:
    • lamports (u64): Lamport balance for rent exemption.
    • owner (string): The owning program (e.g., the Token Program public key).
    • data: Account data. If "jsonParsed" encoding is used, this contains:
      • program (string): e.g., "spl-token".
      • parsed: An object with structured information:
        • info: Details such as:
          • mint (string): The mint address of the token.
          • owner (string): The owner of the token account (this should match ownerPubkey from the request).
          • tokenAmount (object): The balance of tokens (amount, decimals, uiAmount, uiAmountString).
          • state (string): State of the token account (e.g., "initialized").
          • isNative (boolean): If the account holds wrapped SOL.
          • delegate (string, optional): The delegate address if one is set.
          • delegatedAmount (object, optional): The delegated amount if a delegate is set.
        • type (string): e.g., "account".
    • executable (boolean): Whether the account is executable.
    • rentEpoch (u64): Next epoch rent is due.
    • space (u64, if not jsonParsed): Length of raw account data in bytes.
Example Response (with jsonParsed encoding, filtered by programId):
{
  "jsonrpc": "2.0",
  "result": {
    "context": {
      "slot": 183459000
    },
    "value": [
      {
        "pubkey": "AssociatedTokenAccountPubkey1...",
        "account": {
          "data": {
            "program": "spl-token",
            "parsed": {
              "info": {
                "isNative": false,
                "mint": "SomeTokenMintPubkey...",
                "owner": "OwnerPubkeyProvidedInRequest...",
                "state": "initialized",
                "tokenAmount": {
                  "amount": "1000000000", // 1 token if decimals is 9
                  "decimals": 9,
                  "uiAmount": 1.0,
                  "uiAmountString": "1.0"
                }
              },
              "type": "account"
            },
            "space": 165
          },
          "executable": false,
          "lamports": 2039280,
          "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
          "rentEpoch": 380
        }
      },
      {
        "pubkey": "AnotherAssociatedTokenAccountPubkey...",
        "account": {
          // ... similar structure for another token owned by the same owner
        }
      }
    ]
  },
  "id": 1
}

Code Examples

# Replace <OWNER_PUBKEY> and <TOKEN_MINT_PUBKEY> or <TOKEN_PROGRAM_ID>

# Example filtering by programId (SPL Token Program)
curl -X POST -H "Content-Type: application/json" -d \
  '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getTokenAccountsByOwner",
    "params": [
      "<OWNER_PUBKEY>",
      { "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" },
      { "encoding": "jsonParsed" }
    ]
  }' \
  <YOUR_RPC_URL>

# Example filtering by a specific mint
curl -X POST -H "Content-Type: application/json" -d \
  '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getTokenAccountsByOwner",
    "params": [
      "<OWNER_PUBKEY>",
      { "mint": "<SPECIFIC_TOKEN_MINT_PUBKEY>" },
      { "encoding": "jsonParsed", "commitment": "confirmed" }
    ]
  }' \
  <YOUR_RPC_URL>

Developer Tips

  • Filter Requirement: You must supply either a mint or a programId in the filter. It’s not possible to query all token accounts for an owner across all token types without one of these primary filters.
  • Associated Token Accounts: This method will return all token accounts owned by the public key, including standard Associated Token Accounts (ATAs) and any other SPL token accounts they might own (e.g., from older wallet implementations or custom setups).
  • Encoding: Using "jsonParsed" for the encoding option is highly recommended. It decodes the binary account data into a more usable JSON structure.
  • Performance: If an owner has a very large number of token accounts (especially when filtering only by programId), the response can be large. For such cases, use getTokenAccountsByOwnerV2 which provides built-in pagination support.
  • Token-2022 (Token Extensions): If you are working with tokens created using the Token-2022 program (which supports extensions like transfer fees, interest, etc.), ensure you use the correct programId: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb.
This guide provides a thorough understanding of the getTokenAccountsByOwner RPC method, enabling you to efficiently retrieve token account information for any Solana address.

Pagination for Large Token Portfolios

For wallets with extensive token holdings, use getTokenAccountsByOwnerV2 which provides:
  • Cursor-based pagination: Set limit (1-10,000) and use paginationKey to navigate through results
  • Incremental updates: Use changedSinceSlot to fetch only token accounts modified since a specific slot
  • Better performance: Prevents timeouts and enables real-time portfolio tracking
  • Pagination behavior: End of pagination is only indicated when no token accounts are returned. Fewer accounts than the limit may be returned due to filtering - continue pagination until paginationKey is null
// Example: Paginated query for all token accounts
const response = await fetch("https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: "1",
    method: "getTokenAccountsByOwnerV2",
    params: [
      "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
      { "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" },
      {
        encoding: "jsonParsed",
        limit: 1000
      }
    ]
  })
});

const data = await response.json();
console.log(`Found ${data.result.value.length} token accounts`);
if (data.result.paginationKey) {
  console.log("More results available, use paginationKey for next page");
  // Continue pagination even if fewer than limit accounts were returned
} else {
  console.log("End of pagination - no more token accounts available");
}