getProgramAccounts — Solana JSON-RPC
Returns all accounts owned by a given Solana program, optionally narrowed by data-size and memcmp filters.
https://triport.io/sol- Network
- Solana
- Scope
- sol_read_rpc_heavy
- Auth
- x-token: $TRIPORT_API_KEY (or Authorization: Bearer)
- Rate limit
- free+ — 2 rps (free) / 5 rps (basic) / 20 rps (pro) / 80 rps (business), with burst
Endpoint and plans: Solana RPC endpoint.
getProgramAccounts returns every account whose owner is the supplied
programId. It is the canonical way to enumerate program state — for example,
all token accounts of a mint, all open orders on a market, or all PDAs created
by your own program.
This is a heavy method (sol_read_rpc_heavy category) and is rate-limited
far more strictly than standard read RPC: just 2 rps on the Free trial, up to
80 rps on business. A single unfiltered call can scan a very large account set,
so always narrow the result with filters (a memcmp byte match and/or a
dataSize match) and request only the bytes you need with dataSlice. Treat
this method as expensive and cache its results where you can.
By default the result is a plain array of ProgramAccount objects. Set
withContext: true to wrap the array in an RpcContext envelope ({ context, value }), which is useful when you need the slot the result was evaluated at.
Parameters
JSON-RPC params is a positional array: [programId, config?].
programIdstring (base-58 Pubkey)required^[1-9A-HJ-NP-Za-km-z]{32,44}$.configobjectoptionalconfig (GetProgramAccountsConfig)objectencodingstringoptionalbase58, base64, base64+zstd, or jsonParsed.commitmentstringoptionalprocessed, confirmed, or finalized.dataSliceobjectoptional{ "offset": <integer>, "length": <integer> }. Only valid with binary encodings.filtersarrayoptionaldataSize filter or a memcmp filter (see below).minContextSlotintegeroptionalwithContextbooleanoptionaltrue, wraps the result array in an RpcContext envelope ({ context, value }). Defaults to false.filters entries (AccountFilter)objectdataSizeintegermemcmpobjectResponse
With withContext: true, the array is wrapped in an envelope:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"context": { "slot": 348392041, "apiVersion": "2.0.18" },
"value": [
{ "pubkey": "Cx...", "account": { "lamports": 2039280, "owner": "Tok...", "executable": false, "rentEpoch": 18446744073709551615, "space": 165, "data": ["...", "base64"] } }
]
}
}pubkeystring (base-58)accountobjectAccountInfo).account.lamportsintegeraccount.ownerstring (base-58)programId.account.executablebooleanaccount.rentEpochintegeru64).account.spaceintegeraccount.dataarray | object[<data>, <encoding>]. For jsonParsed: a decoded object, or the binary tuple if no parser matched.Errors
Errors use the standard JSON-RPC envelope (error.code, error.message,
error.data).
| Code | HTTP | Meaning | When it happens |
|---|---|---|---|
-32602 | 400 | Invalid params | programId is not valid base-58, or config/filters contain an invalid value (e.g. base58 encoding on oversized data, malformed memcmp). |
| — | 403 | Tier insufficient | API key's tier/scope does not include sol_read_rpc_heavy. Rejected before the RPC layer: plain HTTP body {"error":"tier_insufficient", …} with an X-Required-Tier header — there is no JSON-RPC error object. |
| — | 429 | Rate limit exceeded | More than your tier's sustained RPS for sol_read_rpc_heavy (2 / 5 / 20 / 80, with burst) was sent. Plain HTTP body {"error":"rate_limited", …} with limit_rps, burst_capacity and retry_after_sec; honour Retry-After and X-RateLimit-Reset. |
-32601 | 404 | Method not found | Method name misspelled or not available on this chain. |
Example rate-limit response — HTTP 429 with a plain body, not a JSON-RPC envelope:
{
"error": "rate_limited",
"message": "Rate limit reached: your free plan allows 2 requests/s for sol_read_rpc_heavy. Retry in 1s (see the Retry-After header) or upgrade for a higher limit at https://triport.io/app/pricing",
"current_tier": "free",
"category": "sol_read_rpc_heavy",
"limit_rps": 2,
"burst_capacity": 4,
"retry_after_sec": 1,
"upgrade_url": "https://triport.io/app/pricing",
"docs_url": "https://triport.io/errors/http-429-rate-limit"
}See the shared errors reference for the full envelope and retry guidance.
Examples
JavaScript (fetch)
const res = await fetch("https://triport.io/sol", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.TRIPORT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "getProgramAccounts",
params: [
"TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
{
encoding: "base64",
commitment: "finalized",
filters: [{ dataSize: 165 }],
},
],
}),
});
const { result } = await res.json();
console.log(`${result.length} accounts owned by the program`);Notes
- Always filter. An unfiltered query can scan a huge account set and is the
fastest way to exhaust your tier's RPS. Combine a
dataSizefilter (match the exact account layout size) with one or morememcmpfilters (match a discriminator or owner field) to return only what you need. - Trim the payload with
dataSlice. If you only read a few fields, request a byte window instead of full account data.dataSliceis ignored byjsonParsed. - Heavy rate limits. This method sits in
sol_read_rpc_heavy(2 / 5 / 20 / 80 rps), an order of magnitude below standard read RPC. Cache results and back off on HTTP429rate_limitedusing theRetry-Afterheader. - Pagination. This method returns the full matching set in one response and
has no cursor. For large, paginated enumeration use
getProgramAccountsV2(see the method catalog) once its full schema is published. - Related methods:
getAccountInfo(a single account by key) andgetBalance(lamports only). - Empty result? See
why getProgramAccounts returns an empty array
for
dataSize,memcmpencoding and Token vs Token-2022 mismatches.