> ## Documentation Index
> Fetch the complete documentation index at: https://www.helius.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# How to Use getTokenAccountsByOwner

> Learn getTokenAccountsByOwner use cases, code examples, request parameters, response structure, and tips.

The [`getTokenAccountsByOwner`](https://www.helius.dev/docs/api-reference/rpc/http/gettokenaccountsbyowner) RPC method is used to retrieve all SPL [Token accounts](https://www.helius.dev/blog/how-to-get-token-holders-on-solana) 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`](/api-reference/rpc/http/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](https://www.helius.dev/blog/solana-commitment-levels).
   * **`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`):**

```json theme={"system"}
{
  "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

<CodeGroup>
  ```bash cURL theme={"system"}
  # 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>
  ```

  ```javascript JavaScript (using @solana/web3.js) theme={"system"}
  const { Connection, PublicKey } = require('@solana/web3.js');

  async function findOwnerTokenAccounts(ownerAddress, filter, encoding = 'jsonParsed') {
    // Replace with your RPC endpoint
    const connection = new Connection('https://mainnet.helius-rpc.com/?api-key=<api-key>');
    const ownerPubKey = new PublicKey(ownerAddress);

    try {
      let actualFilter;
      if (filter.mint) {
        actualFilter = { mint: new PublicKey(filter.mint) };
      } else if (filter.programId) {
        actualFilter = { programId: new PublicKey(filter.programId) };
      } else {
        console.error("Filter must contain either 'mint' or 'programId'");
        return;
      }

      const accounts = await connection.getTokenAccountsByOwner(
        ownerPubKey,
        actualFilter,
        { encoding }
      );

      console.log(`Found ${accounts.value.length} token accounts for owner ${ownerAddress}:`);
      accounts.value.forEach(accInfo => {
        console.log(`  Token Account: ${accInfo.pubkey.toBase58()}`);
        if (encoding === 'jsonParsed' && accInfo.account.data.parsed) {
          console.log(`    Mint: ${accInfo.account.data.parsed.info.mint}`);
          console.log(`    Balance: ${accInfo.account.data.parsed.info.tokenAmount.uiAmountString}`);
        }
        // console.log(JSON.stringify(accInfo, null, 2)); // For full details
      });

    } catch (error) {
      console.error(`Error fetching token accounts for owner ${ownerAddress}:`, error);
    }
  }

  // Replace with an actual owner's public key
  const exampleOwner = 'HXtBm8XZbxaTt41uqaKhwUAa6Z1aPyvJdsZVENiWsetg'; // Example wallet address

  // Example 1: Find all SPL Token Program accounts owned by `exampleOwner`
  findOwnerTokenAccounts(exampleOwner, { programId: 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA' });

  // Example 2: Find USDC token accounts owned by `exampleOwner`
  // const usdcMint = 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v';
  // findOwnerTokenAccounts(exampleOwner, { mint: usdcMint });

  // Example 3: Find Token-2022 Program accounts owned by `exampleOwner`
  // findOwnerTokenAccounts(exampleOwner, { programId: 'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb' });
  ```
</CodeGroup>

## 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`](/api-reference/rpc/http/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`](/api-reference/rpc/http/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

```typescript theme={"system"}
// 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");
}
```

## Related Methods

<CardGroup cols={2}>
  <Card title="getTokenAccountsByOwnerV2" href="/api-reference/rpc/http/gettokenaccountsbyownerv2">
    Paginated version with cursor-based navigation for large portfolios
  </Card>

  <Card title="getTokenAccountBalance" href="/api-reference/rpc/http/gettokenaccountbalance">
    Get the balance of a specific token account
  </Card>
</CardGroup>
