cURL
curl --request POST \
--url 'https://devnet.helius-rpc.com/getCompressedAccountsByOwner?api-key=%3Capi_key%3E/getCompressedAccountsByOwner' \
--header 'Content-Type: application/json' \
--data '
{
"id": "test-account",
"jsonrpc": "2.0",
"method": "getCompressedAccountsByOwner",
"params": {
"owner": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"cursor": "11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP",
"dataSlice": {
"length": 1,
"offset": 1
},
"filters": [
{}
],
"limit": 1
}
}
'import requests
url = "https://devnet.helius-rpc.com/getCompressedAccountsByOwner?api-key=%3Capi_key%3E/getCompressedAccountsByOwner"
payload = {
"id": "test-account",
"jsonrpc": "2.0",
"method": "getCompressedAccountsByOwner",
"params": {
"owner": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"cursor": "11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP",
"dataSlice": {
"length": 1,
"offset": 1
},
"filters": [{}],
"limit": 1
}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
id: 'test-account',
jsonrpc: '2.0',
method: 'getCompressedAccountsByOwner',
params: {
owner: '111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj',
cursor: '11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP',
dataSlice: {length: 1, offset: 1},
filters: [{}],
limit: 1
}
})
};
fetch('https://devnet.helius-rpc.com/getCompressedAccountsByOwner?api-key=%3Capi_key%3E/getCompressedAccountsByOwner', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://devnet.helius-rpc.com/getCompressedAccountsByOwner?api-key=%3Capi_key%3E/getCompressedAccountsByOwner",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'id' => 'test-account',
'jsonrpc' => '2.0',
'method' => 'getCompressedAccountsByOwner',
'params' => [
'owner' => '111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj',
'cursor' => '11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP',
'dataSlice' => [
'length' => 1,
'offset' => 1
],
'filters' => [
[
]
],
'limit' => 1
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://devnet.helius-rpc.com/getCompressedAccountsByOwner?api-key=%3Capi_key%3E/getCompressedAccountsByOwner"
payload := strings.NewReader("{\n \"id\": \"test-account\",\n \"jsonrpc\": \"2.0\",\n \"method\": \"getCompressedAccountsByOwner\",\n \"params\": {\n \"owner\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\",\n \"cursor\": \"11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP\",\n \"dataSlice\": {\n \"length\": 1,\n \"offset\": 1\n },\n \"filters\": [\n {}\n ],\n \"limit\": 1\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://devnet.helius-rpc.com/getCompressedAccountsByOwner?api-key=%3Capi_key%3E/getCompressedAccountsByOwner")
.header("Content-Type", "application/json")
.body("{\n \"id\": \"test-account\",\n \"jsonrpc\": \"2.0\",\n \"method\": \"getCompressedAccountsByOwner\",\n \"params\": {\n \"owner\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\",\n \"cursor\": \"11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP\",\n \"dataSlice\": {\n \"length\": 1,\n \"offset\": 1\n },\n \"filters\": [\n {}\n ],\n \"limit\": 1\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://devnet.helius-rpc.com/getCompressedAccountsByOwner?api-key=%3Capi_key%3E/getCompressedAccountsByOwner")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"id\": \"test-account\",\n \"jsonrpc\": \"2.0\",\n \"method\": \"getCompressedAccountsByOwner\",\n \"params\": {\n \"owner\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\",\n \"cursor\": \"11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP\",\n \"dataSlice\": {\n \"length\": 1,\n \"offset\": 1\n },\n \"filters\": [\n {}\n ],\n \"limit\": 1\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "test-account",
"jsonrpc": "2.0",
"error": {
"code": 123,
"message": "<string>"
},
"result": {
"context": {
"slot": 100
},
"value": {
"items": [
{
"hash": "11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP",
"lamports": 100,
"leafIndex": 100,
"owner": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"slotCreated": 100,
"tree": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"address": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"data": {
"data": "SGVsbG8sIFdvcmxkIQ==",
"dataHash": "11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP",
"discriminator": 100
},
"seq": 100
}
],
"cursor": "11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP"
}
}
}{
"error": {
"code": 123,
"message": "<string>"
},
"id": "<string>",
"jsonrpc": "<string>"
}{
"error": {
"code": 123,
"message": "<string>"
},
"id": "<string>",
"jsonrpc": "<string>"
}JSON RPC Methods
Getcompressedaccountsbyowner
Retrieve all compressed accounts owned by a specific address. RPC method guide with use cases, tips and examples.
POST
/
getCompressedAccountsByOwner
cURL
curl --request POST \
--url 'https://devnet.helius-rpc.com/getCompressedAccountsByOwner?api-key=%3Capi_key%3E/getCompressedAccountsByOwner' \
--header 'Content-Type: application/json' \
--data '
{
"id": "test-account",
"jsonrpc": "2.0",
"method": "getCompressedAccountsByOwner",
"params": {
"owner": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"cursor": "11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP",
"dataSlice": {
"length": 1,
"offset": 1
},
"filters": [
{}
],
"limit": 1
}
}
'import requests
url = "https://devnet.helius-rpc.com/getCompressedAccountsByOwner?api-key=%3Capi_key%3E/getCompressedAccountsByOwner"
payload = {
"id": "test-account",
"jsonrpc": "2.0",
"method": "getCompressedAccountsByOwner",
"params": {
"owner": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"cursor": "11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP",
"dataSlice": {
"length": 1,
"offset": 1
},
"filters": [{}],
"limit": 1
}
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
id: 'test-account',
jsonrpc: '2.0',
method: 'getCompressedAccountsByOwner',
params: {
owner: '111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj',
cursor: '11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP',
dataSlice: {length: 1, offset: 1},
filters: [{}],
limit: 1
}
})
};
fetch('https://devnet.helius-rpc.com/getCompressedAccountsByOwner?api-key=%3Capi_key%3E/getCompressedAccountsByOwner', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://devnet.helius-rpc.com/getCompressedAccountsByOwner?api-key=%3Capi_key%3E/getCompressedAccountsByOwner",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'id' => 'test-account',
'jsonrpc' => '2.0',
'method' => 'getCompressedAccountsByOwner',
'params' => [
'owner' => '111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj',
'cursor' => '11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP',
'dataSlice' => [
'length' => 1,
'offset' => 1
],
'filters' => [
[
]
],
'limit' => 1
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://devnet.helius-rpc.com/getCompressedAccountsByOwner?api-key=%3Capi_key%3E/getCompressedAccountsByOwner"
payload := strings.NewReader("{\n \"id\": \"test-account\",\n \"jsonrpc\": \"2.0\",\n \"method\": \"getCompressedAccountsByOwner\",\n \"params\": {\n \"owner\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\",\n \"cursor\": \"11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP\",\n \"dataSlice\": {\n \"length\": 1,\n \"offset\": 1\n },\n \"filters\": [\n {}\n ],\n \"limit\": 1\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://devnet.helius-rpc.com/getCompressedAccountsByOwner?api-key=%3Capi_key%3E/getCompressedAccountsByOwner")
.header("Content-Type", "application/json")
.body("{\n \"id\": \"test-account\",\n \"jsonrpc\": \"2.0\",\n \"method\": \"getCompressedAccountsByOwner\",\n \"params\": {\n \"owner\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\",\n \"cursor\": \"11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP\",\n \"dataSlice\": {\n \"length\": 1,\n \"offset\": 1\n },\n \"filters\": [\n {}\n ],\n \"limit\": 1\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://devnet.helius-rpc.com/getCompressedAccountsByOwner?api-key=%3Capi_key%3E/getCompressedAccountsByOwner")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"id\": \"test-account\",\n \"jsonrpc\": \"2.0\",\n \"method\": \"getCompressedAccountsByOwner\",\n \"params\": {\n \"owner\": \"111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj\",\n \"cursor\": \"11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP\",\n \"dataSlice\": {\n \"length\": 1,\n \"offset\": 1\n },\n \"filters\": [\n {}\n ],\n \"limit\": 1\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "test-account",
"jsonrpc": "2.0",
"error": {
"code": 123,
"message": "<string>"
},
"result": {
"context": {
"slot": 100
},
"value": {
"items": [
{
"hash": "11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP",
"lamports": 100,
"leafIndex": 100,
"owner": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"slotCreated": 100,
"tree": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"address": "111111131h1vYVSYuKP6AhS86fbRdMw9XHiZAvAaj",
"data": {
"data": "SGVsbG8sIFdvcmxkIQ==",
"dataHash": "11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP",
"discriminator": 100
},
"seq": 100
}
],
"cursor": "11111112cMQwSC9qirWGjZM6gLGwW69X22mqwLLGP"
}
}
}{
"error": {
"code": 123,
"message": "<string>"
},
"id": "<string>",
"jsonrpc": "<string>"
}{
"error": {
"code": 123,
"message": "<string>"
},
"id": "<string>",
"jsonrpc": "<string>"
}The
Common Use Cases
Examples
The below examples work - just make sure you installed the dependencies.
For Rust examples: Requires
Example: Get All Compressed Accounts
Example: Paginated Account Discovery with Balance Aggregation
Example: Filter by Data Slice
getCompressedAccountsByOwner RPC method returns all compressed accounts owned by a specific address, with support for filtering, pagination, and data slicing.
You can test this method via the OpenAPI example or custom examples below.
- Portfolio Discovery: Find all compressed accounts for a wallet
- Token Account Enumeration: Discover user’s compressed token holdings
- Account Migration: Identify accounts to migrate from regular to compressed
- Balance Aggregation: Calculate total holdings across all accounts
owner(PublicKey, required): Base58-encoded public key of the account owner to query compressed accounts for.options(object, optional): Configuration object for filtering and pagination:filters(array, optional): Array of filter objects to narrow results by specific criteriadataSlice(object, optional): Slice of account data to return withoffsetandlengthfieldscursor(string, optional): Cursor for pagination from previous response to fetch next pagelimit(BN, optional): Maximum number of accounts to return (usebn()helper)
items(array): Array of compressed account objects with merkle contexthash(string): Unique hash identifying the account for merkle proof generationaddress(string, optional): Account address if availablelamports(number): Account balance in lamportsowner(string): Public key of the account ownerdata(object): Account data information including discriminator and data hashtree(string): Public key of the merkle tree storing this accountleafIndex(number): Position of account in the merkle treeseq(number): Sequence number for account orderingslotCreated(number): Slot when account was created
cursor(string | null): Pagination cursor for next batch, null if no more results
- Pagination Strategy: Use cursor-based pagination for owners with many accounts to avoid timeouts and ensure consistent results
- Data Slicing Optimization: Implement data slicing when you only need account metadata to reduce response size and improve performance
- Empty Response Handling: Handle cases gracefully where new addresses have no compressed accounts - this is normal behavior
- Caching Considerations: Cache results appropriately as compressed account states can change with each transaction
- Batch Size: Start with smaller batch sizes (50-100) and adjust based on response times and data needs
No accounts found
No accounts found
Owner has no compressed accountsThis is normal for new addresses or those that haven’t used compression:
const accounts = await rpc.getCompressedAccountsByOwner(owner);
if (accounts.items.length === 0) {
console.log("No compressed accounts found for this owner");
console.log("Create compressed accounts first using createAccountWithLamports or token operations");
}
Request timeout with large responses
Request timeout with large responses
Too many accounts returned at onceUse pagination and data slicing to reduce response size:
const accounts = await rpc.getCompressedAccountsByOwner(owner, {
limit: bn(50), // Smaller batch size
dataSlice: { // Reduce data per account
offset: 0,
length: 10
}
});
Dependencies & Setup
Dependencies & Setup
npm install @lightprotocol/stateless.js @solana/web3.js
light-client, solana-sdk, anyhow, and tokio crates. See Rust example comments for setup details.- TypeScript
- cURL
- Rust
import { createRpc, Rpc } from '@lightprotocol/stateless.js';
import { PublicKey } from '@solana/web3.js';
const rpc: Rpc = createRpc(
'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY',
'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY'
);
async function getAllCompressedAccounts() {
const owner = new PublicKey('OWNER_ADDRESS_HERE');
const result = await rpc.getCompressedAccountsByOwner(owner);
console.log(\`Found ${result.items.length} compressed accounts\`);
result.items.forEach((account, index) => {
console.log(\`Account ${index + 1}:\`);
console.log(\` Hash: ${account.hash.toString()}\`);
console.log(\` Lamports: ${account.lamports.toString()}\`);
console.log(\` Owner: ${account.owner.toBase58()}\`);
});
return result;
}
getAllCompressedAccounts();
curl -X POST https://devnet.helius-rpc.com?api-key=YOUR_API_KEY \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "getCompressedAccountsByOwner",
"params": {
"owner": "OWNER_PUBKEY_HERE"
}
}'
Rust Client:
light-client v0.14.0 is available on crates.io. Use LightClient for the current stable API.// Current API: light-client 0.14.0
use light_client::rpc::LightClient;
use solana_sdk::pubkey::Pubkey;
use std::str::FromStr;
use anyhow::Result;
#[tokio::main]
async fn main() -> Result<()> {
let client = LightClient::new("https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY".to_string()).await?;
// Query compressed accounts by owner
let owner = Pubkey::from_str("OWNER_PUBKEY_HERE")?;
match client.get_compressed_accounts_by_owner(&owner, None).await? {
response => {
println!("Found {} compressed accounts", response.value.items.len());
for (index, account) in response.value.items.iter().enumerate() {
println!("Account {}:", index + 1);
println!(" Hash: {}", account.hash);
println!(" Lamports: {}", account.lamports);
println!(" Owner: {}", account.owner);
println!(" Tree: {}", account.tree);
println!(" Leaf Index: {}", account.leaf_index);
}
}
}
Ok(())
}
TypeScript
import { createRpc, bn, Rpc } from '@lightprotocol/stateless.js';
import { PublicKey } from '@solana/web3.js';
const rpc: Rpc = createRpc(
'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY',
'https://devnet.helius-rpc.com/?api-key=YOUR_API_KEY'
);
async function getAllAccountsPaginated(owner: PublicKey) {
let allAccounts = [];
let cursor = undefined;
let totalBalance = bn(0);
const batchSize = 100;
do {
const batch = await rpc.getCompressedAccountsByOwner(owner, {
cursor,
limit: bn(batchSize)
});
allAccounts.push(...batch.items);
cursor = batch.cursor;
// Calculate running balance
batch.items.forEach(account => {
totalBalance = totalBalance.add(account.lamports);
});
console.log(\`Fetched ${batch.items.length} accounts, total: ${allAccounts.length}\`);
// Rate limiting
await new Promise(resolve => setTimeout(resolve, 100));
} while (cursor);
console.log(\`Total compressed accounts: ${allAccounts.length}\`);
console.log(\`Total balance: ${totalBalance.toString()} lamports\`);
return { accounts: allAccounts, totalBalance };
}
// Usage
const owner = new PublicKey('OWNER_ADDRESS_HERE');
getAllAccountsPaginated(owner);
import { createRpc } from '@lightprotocol/stateless.js';
import { PublicKey } from '@solana/web3.js';
const rpc = createRpc("https://devnet.helius-rpc.com?api-key=<your-api-key>");
const owner = new PublicKey("OWNER_PUBKEY_HERE");
async function getAccountsWithDataSlice() {
const accounts = await rpc.getCompressedAccountsByOwner(owner, {
dataSlice: {
offset: 0,
length: 32 // First 32 bytes only
}
});
console.log(\`Found ${accounts.items.length} accounts with data slice\`);
accounts.items.forEach((account, index) => {
console.log(\`Account ${index + 1}:\`);
console.log(\` Hash: ${account.hash.toString()}\`);
console.log(\` Data length: ${account.data?.data?.length || 0} bytes\`);
});
return accounts;
}
getAccountsWithDataSlice();
Body
application/json
An ID to identify the request.
Available options:
test-account The version of the JSON-RPC protocol.
Available options:
2.0 The name of the method to invoke.
Available options:
getCompressedAccountsByOwner Show child attributes
Show child attributes