getProgramAccounts — Solana RPC Method
getProgramAccounts returns all accounts owned by a specified program. Filters narrow results by data size or byte content at a specific offset, making this the primary method for discovering accounts with a particular structure.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
programId | string | Yes | Base-58 encoded program public key. |
commitment | string | No | processed, confirmed, or finalized. Default: finalized. |
encoding | string | No | base58, base64, base64+zstd, jsonParsed. Default: base64. |
dataSlice | object | No | {offset: usize, length: usize}. Not available with jsonParsed. |
filters | array | No | Array of {dataSize: usize} and/or {memcmp: {offset: usize, bytes: string, encoding?: string}}. |
withContext | bool | No | If true, wraps the result in a context object with slot info. |
minContextSlot | number | No | Minimum slot at which the request can be evaluated. |
Request
curl -X POST https://api.mainnet-beta.solana.com \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getProgramAccounts",
"params": [
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
{
"encoding": "jsonParsed",
"filters": [
{"dataSize": 165},
{"memcmp": {"offset": 32, "bytes": "vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg"}}
]
}
]
}'
TypeScript (@solana/kit)
import { createSolanaRpc, address } from "@solana/kit";
const rpc = createSolanaRpc("https://api.mainnet-beta.solana.com");
const accounts = await rpc
.getProgramAccounts(
address("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
{
encoding: "jsonParsed",
filters: [
{ dataSize: 165n },
{ memcmp: { offset: 32n, bytes: "vines1vzrYbzLMRdu58ou5XTby4qAqVRLmqo36NKPTg" } },
],
}
)
.send();
console.log(`Found ${accounts.length} token accounts`);
Response
{
"jsonrpc": "2.0",
"result": [
{
"pubkey": "C2gJg6tKpQs41PRS1nC8aw3ZKNZK3HQQZGVrDFDup5nx",
"account": {
"data": { "program": "spl-token", "parsed": { "...": "..." }, "space": 165 },
"executable": false,
"lamports": 2039280,
"owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"rentEpoch": 18446744073709551615,
"space": 165
}
}
],
"id": 1
}
| Field | Type | Description |
|---|---|---|
pubkey | string | Base-58 public key of the account. |
account | object | Account data, same structure as getAccountInfo response. |
Filter types
dataSize
Filters accounts by exact data size in bytes. For example, SPL Token accounts are always 165 bytes:
{"dataSize": 165}
memcmp
Compares bytes at a specific offset in the account data. The bytes field is a base-58 encoded value to match:
{"memcmp": {"offset": 32, "bytes": "owner-pubkey-base58"}}
Combine multiple filters — all must match (AND logic).
Common errors
- Response too large — unfiltered queries against programs with millions of accounts (like the Token program) may time out or be rejected by the provider.
- Invalid filters — mismatched offset or encoding in
memcmpreturns an error. - Rate limited — many RPC providers apply stricter rate limits to
getProgramAccountsbecause it is a heavy operation.
Performance
getProgramAccounts is one of the heaviest RPC methods. Without filters, it scans every account owned by the program. On mainnet, the Token program alone owns hundreds of millions of accounts. Always use filters to narrow results. Use dataSlice to reduce response size when you do not need the full account data.
For large-scale account scanning, consider using Geyser plugins or dedicated indexing services, which are more efficient than polling getProgramAccounts.
FAQ
Why is getProgramAccounts slow or timing out?
Without filters, the method scans every account for the given program. Popular programs have millions of accounts. Always use dataSize and memcmp filters to narrow results.
How do I find all token accounts for a wallet?
Filter by dataSize: 165 (SPL Token account size) and memcmp at offset 32 with the wallet’s public key (the owner field in the Token account layout). Or use the dedicated getTokenAccountsByOwner method.
Can I use multiple filters?
Yes. Pass multiple objects in the filters array. All filters must match for an account to be included (AND logic). Combining dataSize with memcmp is the standard pattern.
What is the memcmp offset for common fields? For SPL Token accounts (165 bytes): mint is at offset 0 (32 bytes), owner is at offset 32 (32 bytes). For other programs, refer to the program’s account layout documentation.
Is there a limit on results? There is no protocol limit, but RPC providers may enforce their own limits on response size or query time. If your query returns too many results, add more specific filters.
Parameters
| Parameter | Type | Required | Description | Default |
|---|---|---|---|---|
programId | string | Yes | Base-58 encoded public key of the program to query. | — |
commitment | string | No | Commitment level: processed, confirmed, or finalized. | finalized |
encoding | string | No | Data encoding: base58, base64, base64+zstd, jsonParsed. | base64 |
dataSlice | object | No | Limit returned data: {offset: usize, length: usize}. Not available with jsonParsed. | — |
filters | array | No | Array of filter objects: {dataSize: usize} or {memcmp: {offset: usize, bytes: string}}. | — |
withContext | bool | No | Wrap the result in a context object with slot info. | — |
minContextSlot | number | No | Minimum slot at which the request can be evaluated. | — |
Updated: