state_getKeys - JSON-RPC Method
Description​
Returns storage keys that match a given prefix. This JSON-RPC method is useful for discovering all storage entries under a specific module or querying multiple related storage items. Be cautious with broad prefixes as they may return large result sets.
Parameters​
Parameter | Type | Required | Description |
---|---|---|---|
prefix | string | Yes | Hex-encoded storage key prefix to match |
blockHash | string | No | Block hash to query at. If omitted, uses the latest block |
Returns​
Field | Type | Description |
---|---|---|
result | array | Array of hex-encoded storage keys matching the prefix |
Request Example​
{
"jsonrpc": "2.0",
"method": "state_getKeys",
"params": [
"0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9"
],
"id": 1
}
Response Example​
{
"jsonrpc": "2.0",
"result": [
"0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9de1e86a9a8c739864cf3cc5ec2bea59fd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d",
"0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da94f9aea1afa791265fae359272badc1cf8eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48"
],
"id": 1
}
Code Examples​
JavaScript​
const getStorageKeys = async (prefix, blockHash = null) => {
const params = blockHash ? [prefix, blockHash] : [prefix];
const response = await fetch('https://api-polkadot.n.dwellir.com', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
jsonrpc: '2.0',
method: 'state_getKeys',
params: params,
id: 1
})
});
const data = await response.json();
return data.result;
};
// Get all account keys (System.Account storage)
const accountPrefix = '0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9';
const accountKeys = await getStorageKeys(accountPrefix);
console.log(`Found ${accountKeys.length} accounts`);
// Extract account addresses from keys
accountKeys.forEach(key => {
// The account address is the last 32 bytes of the key
const addressHex = key.slice(-64);
console.log('Account key:', key);
console.log('Address portion:', addressHex);
});
Python​
import requests
import json
from substrateinterface import SubstrateInterface
def get_storage_keys(prefix, block_hash=None):
url = "https://api-polkadot.n.dwellir.com"
headers = {
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json"
}
params = [prefix, block_hash] if block_hash else [prefix]
payload = {
"jsonrpc": "2.0",
"method": "state_getKeys",
"params": params,
"id": 1
}
response = requests.post(url, headers=headers, data=json.dumps(payload))
return response.json()["result"]
# Example: Get all validator preferences keys
def get_validator_keys():
# Staking.Validators storage prefix
prefix = "0x5f3e4907f716ac89b6347d15ececedca9320c2dc4f5d7af5b320b04e2d1a3ff3"
keys = get_storage_keys(prefix)
print(f"Found {len(keys)} validator preference entries")
for key in keys:
# Extract validator account from key
validator_account = key[-64:]
print(f"Validator: 0x{validator_account}")
return keys
# Example: Query all keys under a module
def get_module_keys(module_prefix):
keys = get_storage_keys(module_prefix)
# Group keys by storage item
storage_items = {}
for key in keys:
# Storage keys typically have a fixed prefix per item
item_prefix = key[:66] # First 33 bytes (66 hex chars)
if item_prefix not in storage_items:
storage_items[item_prefix] = []
storage_items[item_prefix].append(key)
return storage_items
TypeScript (@polkadot/api)​
import { ApiPromise, WsProvider } from '@polkadot/api';
async function queryStorageKeys() {
const provider = new WsProvider('wss://api-polkadot.n.dwellir.com');
const api = await ApiPromise.create({ provider });
// Method 1: Using high-level API to get keys
const accountKeys = await api.query.system.account.keys();
console.log('Account addresses:', accountKeys.map(k => k.toHuman()));
// Method 2: Using low-level RPC for custom prefixes
const prefix = api.query.system.account.keyPrefix();
const keys = await api.rpc.state.getKeys(prefix);
console.log(`Found ${keys.length} account storage keys`);
// Method 3: Get keys for a specific map entry
const validatorKeys = await api.query.staking.validators.keys();
console.log('Active validators:', validatorKeys.length);
// Process keys to extract data
for (const key of keys) {
// Decode the storage key
const keyHex = key.toHex();
console.log('Storage key:', keyHex);
// Get the value for this key
const value = await api.rpc.state.getStorage(key);
console.log('Storage value:', value.toHex());
}
await api.disconnect();
}
// Advanced: Query keys with pagination
async function getKeysPagedExample() {
const api = await ApiPromise.create({
provider: new WsProvider('wss://api-polkadot.n.dwellir.com')
});
const prefix = api.query.system.account.keyPrefix();
const pageSize = 100;
let startKey = prefix;
let allKeys = [];
while (true) {
// Note: state_getKeysPaged is used for pagination
const keys = await api.rpc.state.getKeysPaged(prefix, pageSize, startKey);
if (keys.length === 0) break;
allKeys = allKeys.concat(keys);
startKey = keys[keys.length - 1];
console.log(`Fetched ${keys.length} keys, total: ${allKeys.length}`);
if (keys.length < pageSize) break;
}
console.log(`Total keys found: ${allKeys.length}`);
await api.disconnect();
}
Common Storage Prefixes​
Module | Storage Item | Prefix (example) |
---|---|---|
System | Account | 0x26aa394eea5630e07c48ae0c9558cef7b99d880ec681799c0cf30e8886371da9 |
Balances | TotalIssuance | 0xc2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80 |
Staking | Validators | 0x5f3e4907f716ac89b6347d15ececedca9320c2dc4f5d7af5b320b04e2d1a3ff3 |
Session | NextKeys | 0xcec5070d609dd3497f72bde07fc96ba0e0cdd062e6eaf24295ad4ccfc41d4609 |
Batch Query Example​
// Efficiently query multiple storage values
async function batchQueryStorage(api, keys) {
// Get all values in a single call
const values = await api.rpc.state.queryStorageAt(keys);
const results = {};
keys.forEach((key, index) => {
results[key.toString()] = values[index];
});
return results;
}
// Example usage
const keys = await getStorageKeys(accountPrefix);
const values = await batchQueryStorage(api, keys.slice(0, 10));
console.log('Batch query results:', values);
Use Cases​
- Account Discovery: Find all accounts with balances
- Validator Enumeration: List all validators in the network
- Storage Analysis: Analyze storage usage by module
- Migration Scripts: Iterate over storage for upgrades
- Indexing: Build indexes of on-chain data
Notes​
- Large prefixes may return many keys - use pagination when available
- Keys are returned in lexicographical order
- The prefix must be hex-encoded
- Consider using
state_getKeysPaged
for large datasets - Storage keys include both the storage prefix and the key data
Related Methods​
state_getKeysPaged
- Get keys with paginationstate_getStorage
- Get storage valuestate_getMetadata
- Get metadata to decode keys