> ## 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.

# getTokenAccountsByOwnerV2

> Enhanced version of getTokenAccountsByOwner with additional features including cursor-based pagination and changedSinceSlot support for efficiently retrieving SPL token accounts owned by a specific wallet address.

## 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.

<Info>
  **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
  * **Optional `withContext`**: `true` adds `slot` and `apiVersion` under `result.context`; omit or `false` and they are not included
</Info>

<Warning>
  **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.
</Warning>

## Key Benefits

<CardGroup cols={2}>
  <Card title="Large Portfolios" icon="wallet">
    Handle wallets with thousands of token accounts without timeouts or memory issues
  </Card>

  <Card title="Real-time Tracking" icon="chart-line">
    Monitor portfolio changes in real-time using `changedSinceSlot` for incremental updates
  </Card>
</CardGroup>

## `withContext` (optional)

Boolean on the config object (`params[2]`). Only the shape of `result` changes, not filters, limits, or pagination. Omitted or `false`: `result.value` is the token account **array**. `true`: `result.context` plus `result.value` as an **object** (`accounts`, `paginationKey`). If you handle both, branch on `Array.isArray(result.value)`.

```json theme={"system"}
// Omitted or false
{ "jsonrpc": "2.0", "id": "1", "result": { "value": [], "paginationKey": null } }

// true
{ "jsonrpc": "2.0", "id": "1", "result": {
  "context": { "slot": 411895550, "apiVersion": "3.1.9" },
  "value": { "accounts": [], "paginationKey": null }
}}
```

## Pagination Best Practices

<Warning>
  **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`.
</Warning>

### Basic Portfolio Query

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

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

<Tip>
  **Token-2022 Support**: Use `TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb` as the `programId` to query Token-2022 accounts with extensions like transfer fees, interest-bearing tokens, and more.
</Tip>

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

```diff theme={"system"}
{
  "jsonrpc": "2.0",
  "id": "1",
- "method": "getTokenAccountsByOwner",
+ "method": "getTokenAccountsByOwnerV2",
  "params": [
    "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
    { "programId": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" },
    {
      "encoding": "jsonParsed",
+     "limit": 1000
    }
  ]
}
```

## Related Methods

<CardGroup cols={2}>
  <Card title="getTokenAccountsByOwner" icon="wallet" href="/api-reference/rpc/http/gettokenaccountsbyowner">
    Original method without pagination
  </Card>

  <Card title="getProgramAccountsV2" icon="code" href="/api-reference/rpc/http/getprogramaccountsv2">
    V2 method for program account queries
  </Card>
</CardGroup>

## Request Parameters

<ParamField body="address" type="string" required>
  Solana wallet address (pubkey) of the account owner to query token holdings for, as a base-58 encoded string.
</ParamField>

<ParamField body="mint" type="string">
  Specific Solana token mint address to retrieve only accounts for a particular token or NFT.
</ParamField>

<ParamField body="programId" type="string">
  Specific Solana token program ID (typically SPL Token program) that created the token accounts.
</ParamField>

<ParamField body="commitment" type="string">
  The commitment level for the request.

  * `confirmed`
  * `finalized`
  * `processed`
</ParamField>

<ParamField body="minContextSlot" type="number">
  The minimum slot that the request can be evaluated at.
</ParamField>

<ParamField body="withContext" type="boolean">
  When `true`, returns `result.context` (snapshot metadata: `slot`, `apiVersion`) and nests
  `accounts` and `paginationKey` under `result.value` as an object. When `false`
  or omitted, `result.value` is the token account array for this page, with `paginationKey`
  on `result`. Same filters and limits apply.
</ParamField>

<ParamField body="dataSlice" type="object">
  Request a slice of the account's data.
</ParamField>

<ParamField body="dataSlice.length" type="number">
  Number of bytes to return.
</ParamField>

<ParamField body="dataSlice.offset" type="number">
  Byte offset from which to start reading.
</ParamField>

<ParamField body="encoding" type="string">
  Encoding format for Account data.

  * `base58`
  * `base64`
  * `base64+zstd`
  * `jsonParsed`
</ParamField>

<ParamField body="limit" type="number">
  Maximum number of token accounts to return per request (1-10,000).
</ParamField>

<ParamField body="paginationKey" type="string">
  Base-58 encoded pagination cursor for fetching subsequent pages. Use the paginationKey from previous response.
</ParamField>

<ParamField body="changedSinceSlot" type="number">
  Only return token accounts that were modified at or after this slot number. Useful for incremental portfolio updates.
</ParamField>


## OpenAPI

````yaml openapi/rpc-http/getTokenAccountsByOwnerV2.yaml POST /
openapi: 3.1.0
info:
  title: Solana RPC API
  version: 1.0.0
  description: >-
    Enhanced Solana token account discovery API with additional features
    including cursor-based pagination and changedSinceSlot support for
    efficiently retrieving SPL token balances, NFTs, and other token holdings
    associated with any wallet address. Supports incremental updates via
    slot-based filtering.
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0.html
servers:
  - url: https://mainnet.helius-rpc.com
    description: Mainnet RPC endpoint
  - url: https://devnet.helius-rpc.com
    description: Devnet RPC endpoint
security: []
paths:
  /:
    post:
      tags:
        - RPC
      summary: getTokenAccountsByOwnerV2
      description: >
        Enhanced version of getTokenAccountsByOwner with additional features
        including cursor-based pagination 

        and changedSinceSlot support for efficiently retrieving large sets of
        SPL token accounts owned by a 

        specific wallet address. Enables scalable portfolio queries with
        configurable page sizes up to 10,000 

        accounts per request. The changedSinceSlot parameter allows retrieving
        only token accounts modified 

        since a specific blockchain slot, perfect for real-time portfolio
        tracking and wallet balance 

        synchronization. Essential for wallets, portfolio trackers, DeFi
        applications, and any service 

        requiring comprehensive token holdings data for users with extensive
        token portfolios.


        Note: End of pagination is only indicated when no token accounts are
        returned. The API may return fewer 

        accounts than the limit due to filtering - continue pagination until
        paginationKey is null.


        **withContext**: Optional boolean on the configuration object (alongside
        encoding, limit, and so on). When 

        `withContext` is `true`, the RPC returns the standard Solana wrapped
        shape: `result.context` (snapshot 

        metadata, including `slot` and usually `apiVersion`) and `result.value`
        as an object containing `accounts`, 

        and `paginationKey`. When `withContext` is `false` or omitted, the
        account list is

        `result.value` as an array (same as classic `getTokenAccountsByOwner`),
        with `paginationKey`

        on `result`. Filters, limits, and pagination behavior are unchanged;
        only the JSON shape

        of `result` differs.
      operationId: getTokenAccountsByOwnerV2
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                jsonrpc:
                  type: string
                  description: The JSON-RPC protocol version.
                  enum:
                    - '2.0'
                  example: '2.0'
                id:
                  type: string
                  description: A unique identifier for the request.
                  example: '1'
                method:
                  type: string
                  enum:
                    - getTokenAccountsByOwnerV2
                  description: The name of the RPC method to invoke.
                  example: getTokenAccountsByOwnerV2
                  default: getTokenAccountsByOwnerV2
                params:
                  type: array
                  description: >-
                    Parameters for querying paginated token accounts owned by a
                    specific public key.
                  default:
                    - A1TMhSGzQxMr1TboBKtgixKz1sS6REASMxPo1qsyTSJd
                    - programId: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
                    - encoding: jsonParsed
                      limit: 1000
                  items:
                    oneOf:
                      - type: string
                        description: >-
                          Solana wallet address (pubkey) of the account owner to
                          query token holdings for, as a base-58 encoded string.
                        example: A1TMhSGzQxMr1TboBKtgixKz1sS6REASMxPo1qsyTSJd
                      - type: object
                        description: >-
                          Filter configuration to narrow down token accounts by
                          mint address or program ID.
                        properties:
                          mint:
                            type: string
                            description: >-
                              Specific Solana token mint address to retrieve
                              only accounts for a particular token or NFT.
                            example: 2cHr7QS3xfuSV8wdxo3ztuF4xbiarF6Nrgx3qpx3HzXR
                          programId:
                            type: string
                            description: >-
                              Specific Solana token program ID (typically SPL
                              Token program) that created the token accounts.
                            example: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
                      - type: object
                        description: >-
                          Enhanced configuration object with pagination support
                          and optional fields.
                        properties:
                          commitment:
                            type: string
                            description: The commitment level for the request.
                            enum:
                              - confirmed
                              - finalized
                              - processed
                            example: finalized
                          minContextSlot:
                            type: integer
                            description: >-
                              The minimum slot that the request can be evaluated
                              at.
                            example: 1000
                          withContext:
                            type: boolean
                            description: >
                              When `true`, returns `result.context` (snapshot
                              metadata: `slot`, `apiVersion`) and nests

                              `accounts` and `paginationKey` under
                              `result.value` as an object. When `false`

                              or omitted, `result.value` is the token account
                              array for this page, with `paginationKey`

                              on `result`. Same filters and limits apply.
                            example: true
                          dataSlice:
                            type: object
                            description: Request a slice of the account's data.
                            properties:
                              length:
                                type: integer
                                description: Number of bytes to return.
                                example: 10
                              offset:
                                type: integer
                                description: Byte offset from which to start reading.
                                example: 0
                          encoding:
                            type: string
                            description: Encoding format for Account data.
                            enum:
                              - base58
                              - base64
                              - base64+zstd
                              - jsonParsed
                            example: jsonParsed
                          limit:
                            type: integer
                            description: >-
                              Maximum number of token accounts to return per
                              request (1-10,000).
                            minimum: 1
                            maximum: 10000
                            example: 1000
                          paginationKey:
                            type: string
                            description: >-
                              Base-58 encoded pagination cursor for fetching
                              subsequent pages. Use the paginationKey from
                              previous response.
                            example: 9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM
                          changedSinceSlot:
                            type: integer
                            description: >-
                              Only return token accounts that were modified at
                              or after this slot number. Useful for incremental
                              portfolio updates.
                            example: 12345678
            example:
              jsonrpc: '2.0'
              id: '1'
              method: getTokenAccountsByOwnerV2
              params:
                - A1TMhSGzQxMr1TboBKtgixKz1sS6REASMxPo1qsyTSJd
                - programId: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
                - encoding: jsonParsed
                  limit: 1000
      responses:
        '200':
          description: Successfully retrieved paginated token accounts by owner.
          content:
            application/json:
              schema:
                type: object
                properties:
                  jsonrpc:
                    type: string
                    description: The JSON-RPC protocol version.
                    enum:
                      - '2.0'
                    example: '2.0'
                  id:
                    type: string
                    description: Identifier matching the request.
                    example: '1'
                  result:
                    oneOf:
                      - $ref: >-
                          #/components/schemas/TokenAccountsByOwnerV2ResultDirect
                        title: without withContext
                      - type: object
                        title: with withContext
                        description: >-
                          Wrapped result when `withContext` is `true` in the
                          request options.
                        required:
                          - context
                          - value
                        properties:
                          context:
                            type: object
                            description: >-
                              Snapshot metadata for the node response (slot
                              consistency, debugging).
                            properties:
                              slot:
                                type: integer
                                description: Slot at which the node built this response.
                                example: 341197933
                              apiVersion:
                                type: string
                                description: RPC API version when available.
                                example: 2.0.15
                          value:
                            $ref: '#/components/schemas/TokenAccountsByOwnerV2Page'
              example:
                jsonrpc: '2.0'
                id: '1'
                result:
                  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
        '400':
          description: Bad Request - Invalid request parameters or malformed request.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                jsonrpc: '2.0'
                error:
                  code: -32602
                  message: Invalid params
                id: '1'
        '401':
          description: Unauthorized - Invalid or missing API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                jsonrpc: '2.0'
                error:
                  code: -32001
                  message: Unauthorized
                id: '1'
        '429':
          description: Too Many Requests - Rate limit exceeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                jsonrpc: '2.0'
                error:
                  code: -32005
                  message: Too many requests
                id: '1'
        '500':
          description: Internal Server Error - An error occurred on the server.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                jsonrpc: '2.0'
                error:
                  code: -32603
                  message: Internal error
                id: '1'
        '503':
          description: Service Unavailable - The service is temporarily unavailable.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                jsonrpc: '2.0'
                error:
                  code: -32002
                  message: Service unavailable
                id: '1'
        '504':
          description: Gateway Timeout - The request timed out.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                jsonrpc: '2.0'
                error:
                  code: -32003
                  message: Gateway timeout
                id: '1'
      security:
        - ApiKeyQuery: []
components:
  schemas:
    TokenAccountsByOwnerV2ResultDirect:
      type: object
      description: >-
        Paginated token accounts when `withContext` is false or omitted. Matches
        the familiar shape where the account list is `result.value` as an array
        (not nested under `accounts`).
      properties:
        value:
          type: array
          description: Token accounts for the current page.
          items:
            $ref: '#/components/schemas/TokenAccountByOwnerV2Entry'
        paginationKey:
          type: string
          description: >-
            Pagination cursor for the next page. Null only when no token
            accounts are returned (end of pagination). Note that fewer accounts
            than the limit may be returned due to filtering, but this does not
            indicate end of pagination.
          example: 8WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM
          nullable: true
    TokenAccountsByOwnerV2Page:
      type: object
      description: >-
        Paginated token accounts when `withContext` is true. Contains `accounts`
        and `paginationKey` under `result.value` alongside `result.context`.
      properties:
        accounts:
          type: array
          description: Token accounts for the current page.
          items:
            $ref: '#/components/schemas/TokenAccountByOwnerV2Entry'
        paginationKey:
          type: string
          description: >-
            Pagination cursor for the next page. Null only when no token
            accounts are returned (end of pagination). Note that fewer accounts
            than the limit may be returned due to filtering, but this does not
            indicate end of pagination.
          example: 8WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM
          nullable: true
    ErrorResponse:
      type: object
      properties:
        jsonrpc:
          type: string
          description: The JSON-RPC protocol version.
          enum:
            - '2.0'
          example: '2.0'
        error:
          type: object
          properties:
            code:
              type: integer
              description: The error code.
              example: -32602
            message:
              type: string
              description: The error message.
            data:
              type: object
              description: Additional data about the error.
        id:
          type: string
          description: Identifier matching the request.
          example: '1'
    TokenAccountByOwnerV2Entry:
      type: object
      properties:
        pubkey:
          type: string
          description: Account Pubkey as a base-58 encoded string.
          example: BGocb4GEpbTFm8UFV2VsDSaBXHELPfAXrvd4vtt8QWrA
        account:
          type: object
          description: Token account details.
          properties:
            lamports:
              type: integer
              description: Number of lamports assigned to the account.
              example: 2039280
            owner:
              type: string
              description: Pubkey of the program this account has been assigned to.
              example: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
            data:
              type: object
              description: Token state data associated with the account.
              properties:
                program:
                  type: string
                  description: Program name.
                  example: spl-token
                parsed:
                  type: object
                  description: Parsed token data.
                  properties:
                    info:
                      type: object
                      description: Token account information.
                      properties:
                        isNative:
                          type: boolean
                          description: Indicates if the account holds native SOL.
                          example: false
                        mint:
                          type: string
                          description: Pubkey of the token mint.
                          example: 2cHr7QS3xfuSV8wdxo3ztuF4xbiarF6Nrgx3qpx3HzXR
                        owner:
                          type: string
                          description: Pubkey of the account owner.
                          example: A1TMhSGzQxMr1TboBKtgixKz1sS6REASMxPo1qsyTSJd
                        state:
                          type: string
                          description: Token account state.
                          example: initialized
                        tokenAmount:
                          type: object
                          description: Token amount details.
                          properties:
                            amount:
                              type: string
                              description: Raw balance without decimals.
                              example: '420000000000000'
                            decimals:
                              type: integer
                              description: Number of decimals.
                              example: 6
                            uiAmount:
                              type: number
                              description: Balance in user-friendly format.
                              example: 420000000
                            uiAmountString:
                              type: string
                              description: Balance as a string.
                              example: '420000000'
                space:
                  type: integer
                  description: Space allocated for the account.
                  example: 165
            executable:
              type: boolean
              description: Indicates if the account contains a program.
              example: false
            rentEpoch:
              type: integer
              description: Epoch at which the account will next owe rent.
              example: 18446744073709552000
            space:
              type: integer
              description: Data size of the account.
              example: 165
  securitySchemes:
    ApiKeyQuery:
      type: apiKey
      in: query
      name: api-key
      description: >-
        Your Helius API key. You can get one for free in the
        [dashboard](https://dashboard.helius.dev/api-keys).

````