getAccountInfo Solana Developer Guide

Learn how to read a single Solana account with getAccountInfo — response fields, encoding trade-offs, parsing program-specific data, and how to keep bandwidth costs down.

Reference documentation: getAccountInfo

Before We Begin

If you are new to Solana development, this is a good place to start your journey. You will need a FluxRPC API key to complete all the steps in this guide — our free keys are sufficient.

There is no need to copy-paste it — just navigate back to this page while logged in, and we will automatically use the key you select.

In this guide, we will accomplish the following:

  1. Fetch the data from a single account on the Solana blockchain
  2. Explain how to interpret the main response fields
  3. Weigh the advantages of different data encoding options
  4. Deal with program-specific data stored in accounts
  5. Optimize the request so it costs you less

We will provide examples in Python, TypeScript, Go, and cURL.

Reading Account Data on Solana

Solana accounts are identified by a 32-byte public key. With this public key, you can fetch the data stored in the account by using the getAccountInfo RPC call.

This is the right method to use when you only need information about a single account. If you need information about several accounts, it's faster and more efficient to use getMultipleAccounts — which is covered in the getMultipleAccounts guide.

This RPC call is very straightforward to use:

import requests
import json

APIKey = "<Your-API-Key>"
RPCRegion = "eu"
AccountPubKey = "MfDuWeqSHEqTFVYZ7LoexgAK9dxk7cy4DFJWjWMGVWa"

def fetchAccount(pubKey):
    print("getAccount for public key " + pubKey)
    headers = {'content-type': 'application/json'}
    url = "https://" + RPCRegion + ".fluxrpc.com?key=" + APIKey

    data = {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "getAccountInfo",
        "params": [
            pubKey,
            {
                "encoding": "base64"
            }
        ]
    }
    response = requests.post(url, data=json.dumps(data), headers=headers)
    return response

response = fetchAccount(AccountPubKey)
if response.status_code != 200:
    raise Exception("RPC returned HTTP error code " + str(response.status_code))
responseJSON = json.loads(response.text)
print(responseJSON)

It's not necessary to specify the commitment parameter on FluxRPC. We only support processed commitment.

You will get a response that looks something like the following:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "context": {
      "apiVersion": "1.33.7",
      "slot": 434450667
    },
    "value": {
      "owner": "11111111111111111111111111111111",
      "lamports": 94275198182,
      "executable": false,
      "rentEpoch": 18446744073709551615,
      "space": 0,
      "data": [
        "",
        "base64"
      ]
    }
  }
}

We've selected a pretty active account — if you re-run this request in a minute, the lamports will likely be different! Starting from the top, the significance of each field in the response is as follows:

Reference

The canonical field-by-field description of an account lives in the Solana account model documentation. We recommend keeping it open in a second tab while you work through this guide.

What Happens when the Public Key Doesn't Exist?

In the case where you make a getAccountInfo RPC call for a public key that doesn't exist, it will respond with:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "context": {
      "apiVersion": "1.33.7",
      "slot": 434654544
    },
    "value": null
  }
}

In other words, it will not return an error, but a null result in the value field. Be sure to handle this case in any code you write! There are many cases where this can come up:

  1. The account was closed and contains zero lamports
  2. There's an error in the public key caused by a user input error
  3. A Program Derived Address (PDA) was given the wrong inputs
  4. You have an error in your program and have passed something that's not a valid public key to getAccountInfo

Encoding

You may have noticed in our request, we selected base64 encoding. Data on Solana is stored as raw bytes, so it's necessary to choose an encoding scheme to transmit the information as text characters. There are 3 choices here:

Program-Specific Data

Solana accounts can store arbitrary data. Usually this is used by the program that owns them to store information needed for its operation.

For example, in Associated Token Accounts (ATA) the Token program stores the mint and amount of tokens held in the data field. We can fetch the token balance using the getTokenAccountBalance RPC method as follows:

curl "https://eu.fluxrpc.com?key=<Your-API-Key>" -s -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getTokenAccountBalance",
    "params": [
      "5Dui9R5UUFJuXm911BmijxZcsm5hmx5gBBdvTwzo9zfE"
    ]
  }'

This will return something like the following:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "context": {
      "apiVersion": "1.33.7",
      "slot": 434464244
    },
    "value": {
      "amount": "410000971248",
      "decimals": 6,
      "uiAmount": 410000.971248,
      "uiAmountString": "410000.971248"
    }
  }
}

From this response, we can see that the account holds 410000971248 base units of the token, and the mint has 6 decimals. This means it holds 410000.971248 tokens.

However, getTokenAccountBalance is really just parsing applied on top of a getAccountInfo request. Let's look at how we would get the mint and number of tokens by parsing getAccountInfo ourselves:

  1. Look at the Solana Token Account Structure
  2. Fetch the account data
  3. Convert the base64 data field to an array of bytes
  4. Slice the bytes according to the ATA layout to extract the data
  5. Convert the data to base58 (in the case of public keys) or an integer (in the case of a token amount)
import requests
import json
import base64
import base58

APIKey = "<Your-API-Key>"
RPCRegion = "eu"
AccountPubKey = "5Dui9R5UUFJuXm911BmijxZcsm5hmx5gBBdvTwzo9zfE"

def fetchAccount(pubKey):
    print("getAccount for public key " + pubKey)
    headers = {'content-type': 'application/json'}
    url = "https://" + RPCRegion + ".fluxrpc.com?key=" + APIKey

    data = {
        "jsonrpc": "2.0",
        "id": 1,
        "method": "getAccountInfo",
        "params": [
            pubKey,
            {
                "encoding": "base64"
            }
        ]
    }
    response = requests.post(url, data=json.dumps(data), headers=headers)
    return response

response = fetchAccount(AccountPubKey)
if response.status_code != 200:
    raise Exception("RPC returned HTTP error code " + str(response.status_code))
responseJSON = json.loads(response.text)
print(responseJSON)  # Print the raw data from getAccountInfo

result = responseJSON["result"]["value"]
if result == None: # Handle NULL result
    raise Exception("Public Key not found")

dataBytes = base64.b64decode(result["data"][0])

if len(dataBytes) == 0: # Handle empty data field, probably this is an account owned by the System program, not a token account!
    raise Exception("Public Key found, but could not parse the data. Is it a token account?")

# The first 32 bytes in an ATA are the token mint
mint = base58.b58encode(dataBytes[0:32]).decode("utf-8")
# The next 32 bytes are the owner of this token account
owner = base58.b58encode(dataBytes[32:64]).decode("utf-8")
# The next 8 bytes (uint64) are the amount of tokens they own, in base units
amount = int.from_bytes(dataBytes[64:72], byteorder='little')

print("Mint: " + mint)
print("Owner: " + owner)
print("Amount owned (base units): " + str(amount))

Note that we only have the token amount in base units! If we wanted to get the user-facing amount of tokens, we'd have to additionally run getAccountInfo on the token mint (USDC at public key EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v in this case), and extract the mint decimals.

There are many RPC methods that work similarly — they could be accomplished with multiple getAccountInfo calls, but it would be a bit of a pain, so we define specialized RPC methods for convenience. As a result, a good understanding of getAccountInfo is a solid first step to understanding many of the other methods in the RPC reference!

A Final Note on Encoding

If we had instead selected jsonParsed encoding for our last getAccountInfo call like so:

curl "https://eu.fluxrpc.com?key=<Your-API-Key>" -s -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "getAccountInfo",
    "params": [
      "5Dui9R5UUFJuXm911BmijxZcsm5hmx5gBBdvTwzo9zfE",
      {
        "encoding": "jsonParsed"
      }
    ]
  }'

You'll get something like the following:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "context": {
      "apiVersion": "1.33.7",
      "slot": 434468103
    },
    "value": {
      "lamports": 2039280,
      "data": {
        "program": "spl-token",
        "parsed": {
          "info": {
            "isNative": false,
            "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
            "owner": "4ePFLN3dkHoaJNXYeScr5ZDp823tSt2ZJPbcZgccbASv",
            "state": "initialized",
            "tokenAmount": {
              "amount": "410000971248",
              "decimals": 6,
              "uiAmount": 410000.971248,
              "uiAmountString": "410000.971248"
            }
          },
          "type": "account"
        },
        "space": 165
      },
      "owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
      "executable": false,
      "rentEpoch": 18446744073709551615,
      "space": 165
    }
  }
}

We'd like to point out that some of this data is not actually stored in the account 5Dui9R5UUFJuXm911BmijxZcsm5hmx5gBBdvTwzo9zfE.

For example, you might notice the decimals (6) in there! That data is actually stored in the token mint (EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v).

When you specify jsonParsed encoding on an Associated Token Address (ATA), the RPC will assume you need this extra data and include it in the response. It will not include it for the other encoding types.

Watch out

This inconsistency catches new developers by surprise regularly. If a field appears under jsonParsed but vanishes when you switch to base64 in production, this is usually why.

Optimization

An engineer's task is to do for a dime what anyone can do for a dollar! Here are some tips that will help you scale:

  1. If you have to call more than one account, use getMultipleAccounts instead of getAccountInfo. It has less overhead.
  2. Use base64 encoding, and convert to other formats in your application.
  3. Use more specialized RPC methods instead of multiple getAccountInfo calls.
  4. Consider using Lantern! It will save you a lot of bandwidth, because you'll be answering your own RPC requests. There's also no rate limit, and serving 1,000 requests per second is quite easy to achieve — all on our affordable Developer plan. At other RPCs, you'd be looking at $1500 per month for that kind of rate limit.

Next Steps

A good method to learn next is getMultipleAccounts — it is the first optimization most Solana developers reach for, and it builds directly on everything you just read.

← All developer guides