> ## Documentation Index
> Fetch the complete documentation index at: https://www.helius.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# getTransfersByAddress Overview and Tutorial

> Query parsed, human-readable token and native SOL transfer objects for a Solana address with filters by mint, time, amount, and counterparty.

## Overview

[`getTransfersByAddress`](/api-reference/rpc/http/gettransfersbyaddress) is a Helius-exclusive RPC method that returns parsed, human-readable token and native SOL transfer objects for a wallet address. It is not part of standard Solana RPC.

It is focused on transfer activity, so it returns concise transfer records instead of full transaction payloads. Each record is normalized with parsed owner and token accounts, mints, raw amounts, decimals, UI amounts, instruction positions, and confirmation status, so you can reconcile balance movement without reimplementing Solana token parsing.

This method requires a [Developer plan](/billing/plans) or higher and costs 10 credits per request.

<CardGroup cols={2}>
  <Card title="Parsed transfer objects" icon="arrow-right-arrow-left">
    Return human-readable transfer records with parsed accounts, amounts, decimals, and transfer types.
  </Card>

  <Card title="Reconciliation ready" icon="scale-balanced">
    Model SOL, WSOL, Token-2022 fees, mints, burns, and account owner changes so balances can be reconciled accurately.
  </Card>

  <Card title="Mint, time, and amount filters" icon="filter">
    Narrow transfer history by mint address, block time range, or raw amount range.
  </Card>

  <Card title="Counterparty filters" icon="users">
    Filter transfers by sender or recipient with `with` and `direction`.
  </Card>
</CardGroup>

## When to use this

Use `getTransfersByAddress` when you need:

* Wallet transfer history for payments or transfer monitoring
* Portfolio activity and token movement analytics
* Balance reconciliation you can trust for ledgers and accounting
* Counterparty-specific transfer reports (who sent or received what)
* Normalized SOL/WSOL, Token-2022 fee, mint, and burn handling without writing a parser

Use [`getTransactionsForAddress`](/rpc/gettransactionsforaddress) instead when you need full transaction data, signatures-only history, or non-transfer activity. A common pattern is to page through transfers here, then fetch the underlying full transactions with batched [`getTransaction`](/api-reference/rpc/http/gettransaction) calls (see [Fetch full transactions for transfer rows](#fetch-full-transactions-for-transfer-rows)).

## Accuracy and reconciliation

`getTransfersByAddress` is built for applications that need transfer history they can trust for ledgers, payment tracking, portfolio activity, and balance reconciliation. Instead of returning raw transaction payloads and leaving every edge case to your parser, the API returns normalized transfer objects.

The response explicitly models the transfer cases that commonly make Solana history difficult to reconcile:

* Standard SPL token and native SOL transfers.
* Token-2022 transfers with withheld fees, represented as ordinary `transfer` rows with separate fee fields.
* Mints and burns, represented as transfers with a `null` sender or recipient.
* SOL wrapping and unwrapping behavior, with a default mode designed to avoid noisy lifecycle rows.
* Token account owner changes via SetAuthority.
* Token-2022 withheld fee withdrawals.
* Intermediary account flows, returned as the underlying transfer records instead of being collapsed into a guessed net movement.

For supported visible transfer events, this lets you reconcile balance movement without reimplementing Solana token parsing logic. Known exclusions, such as hidden SOL movements inferred only from balance changes, are called out in [Limitations](#limitations).

## Quickstart

```javascript theme={"system"}
const response = await fetch("https://mainnet.helius-rpc.com/?api-key=YOUR_API_KEY", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    jsonrpc: "2.0",
    id: "1",
    method: "getTransfersByAddress",
    params: ["86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY"]
  })
});

const data = await response.json();
console.log(data.result.data);
```

## Request parameters

Pass the wallet owner address, not an associated token account (ATA). The API finds transfer activity for token accounts owned by that wallet.

<ParamField body="address" type="string" required>
  Base58-encoded owner wallet address to query transfers for. Pass the wallet owner address, not an associated token account (ATA).
</ParamField>

<ParamField body="config" type="object">
  Optional configuration object for filtering, pagination, commitment, ordering, and SOL/WSOL behavior.
</ParamField>

<ParamField body="with" type="string">
  Filter by counterparty address. Returns only transfers to or from this address.
</ParamField>

<ParamField body="direction" type="string" default="any">
  Filter by transfer direction relative to `address`.

  * `in`: transfers received by `address`
  * `out`: transfers sent by `address`
  * `any`: incoming and outgoing transfers
</ParamField>

<ParamField body="mint" type="string">
  Filter by token mint address. Use `So11111111111111111111111111111111111111111` for native SOL and `So11111111111111111111111111111111111111112` for WSOL.
</ParamField>

<ParamField body="solMode" type="string" default="merged">
  Controls how native SOL and WSOL are represented.

  * `merged`: WSOL is treated as native SOL. Wrap and unwrap lifecycle rows are excluded, and WSOL mint values are rewritten to the native SOL mint.
  * `separate`: WSOL is preserved as a distinct mint, and wrap and unwrap lifecycle rows are included.
</ParamField>

<ParamField body="filters" type="object">
  Additional filters for amount, block time, and slot.
</ParamField>

<ParamField body="limit" type="number" default="100">
  Maximum number of transfers to return. Range: 1 to 100.
</ParamField>

<ParamField body="paginationToken" type="string">
  Cursor from the previous response for pagination.
</ParamField>

<ParamField body="commitment" type="string" default="finalized">
  Data commitment level.

  * `finalized`
  * `confirmed`
</ParamField>

<ParamField body="minContextSlot" type="number">
  The minimum slot that the request can be evaluated at
</ParamField>

<ParamField body="sortOrder" type="string" default="desc">
  Result ordering.

  * `desc`: newest first
  * `asc`: oldest first
</ParamField>

## Response

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "id": "1",
  "result": {
    "data": [
      {
        "signature": "5GEX7Q3X5Q8yJGbKYoR7mtzQmG8tpoEwzjPgqVmn3y5xg3yKwqXcDdN5YVcc9V6vA4TuH5iM6FHRVhTxvz4AX2zG",
        "slot": 315073428,
        "blockTime": 1736159420,
        "type": "transfer",
        "fromUserAccount": "7hPhaUpydpvm8wtiS3k4LPZKUmivQRs7YQmpE1hFshHx",
        "toUserAccount": "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY",
        "fromTokenAccount": "HcvK3EJ74iM9g11cUgsaPvLSrhCvCwcrWxBNd87LsC1x",
        "toTokenAccount": "CBcYniR9G9CN3zGMnwNE4SWbqkYWvCFVreEob9xHnQCY",
        "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
        "amount": "2500000",
        "decimals": 6,
        "uiAmount": "2.5",
        "confirmationStatus": "finalized",
        "transactionIdx": 35,
        "instructionIdx": 1,
        "innerInstructionIdx": 0
      }
    ],
    "paginationToken": "315073428:35:1:0:splTransfer"
  }
}
```

### Response field details

* `fromUserAccount` and `toUserAccount` are always present. When a side does not exist, the value is `null`.
* `fromTokenAccount` and `toTokenAccount` are only included when token-account endpoints are meaningful for the row. They are omitted completely for native SOL transfers.
* Mint transfers are one-sided: `fromUserAccount` is `null`, and they can only be returned as inbound transfers for the recipient.
* Burn transfers are one-sided: `toUserAccount` is `null`, and they can only be returned as outbound transfers for the burning owner.

## Filters

Use comparison filters for numeric range queries. All comparison fields are optional and can be combined.

```json theme={"system"}
{
  "gt": 1000000,
  "gte": 1000000,
  "lt": 1000000000,
  "lte": 1000000000
}
```

| Filter      | Type               | Description                         |
| ----------- | ------------------ | ----------------------------------- |
| `amount`    | `ComparisonFilter` | Raw transfer amount, not UI amount. |
| `blockTime` | `ComparisonFilter` | Block timestamp in Unix seconds.    |
| `slot`      | `ComparisonFilter` | Slot number.                        |

## Transfer types

The `type` field identifies the transfer behavior represented by each row.

| Type                  | Description                                                                                                                    | `fromUserAccount` | `toUserAccount`               |
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ----------------- | ----------------------------- |
| `transfer`            | Standard token or SOL transfer between two wallets.                                                                            | Sender            | Recipient                     |
| `mint`                | New tokens minted to a wallet.                                                                                                 | `null`            | Recipient                     |
| `burn`                | Tokens permanently destroyed.                                                                                                  | Sender            | `null`                        |
| `wrap`                | SOL wrapped into WSOL. Excluded by default in `solMode: "merged"`.                                                             | `null`            | Owner                         |
| `unwrap`              | WSOL unwrapped back to native SOL, or rent recovered from closing a token account. Excluded by default in `solMode: "merged"`. | Owner             | `null` or lamport destination |
| `changeOwner`         | Token account ownership changed with SetAuthority.                                                                             | Old owner         | New owner                     |
| `withdrawWithheldFee` | Token-2022 withheld fees collected from a mint or accounts.                                                                    | `null`            | Fee recipient                 |

### Transfer types and instructions

| Transfer type         | Covered instructions                                                                                                                                                                                                    | Default visibility         |
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------- |
| `transfer`            | `SystemProgram::Transfer`, `SystemProgram::TransferWithSeed`, `SystemProgram::WithdrawNonceAccount`, `SystemProgram::CreateAccount`, `SystemProgram::CreateAccountWithSeed`, `SystemProgram::CreateAccountAllowPrefund` | Always                     |
| `transfer`            | `Token::Transfer`, `Token::TransferChecked`, `Token-2022::Transfer`, `Token-2022::TransferChecked`                                                                                                                      | Always                     |
| `transfer`            | `Token-2022::TransferCheckedWithFee`, with `feeAmount` and `feeUiAmount` fields                                                                                                                                         | Always                     |
| `mint`                | `Token::MintTo`, `Token::MintToChecked`                                                                                                                                                                                 | Always                     |
| `burn`                | `Token::Burn`, `Token::BurnChecked`                                                                                                                                                                                     | Always                     |
| `wrap`                | `Token::SyncNative`, `Token::InitializeAccount`, `Token::InitializeAccount2`, `Token::InitializeAccount3` when used for WSOL lifecycle handling                                                                         | `solMode: "separate"` only |
| `unwrap`              | `Token::CloseAccount` on WSOL with balance greater than zero                                                                                                                                                            | `solMode: "separate"` only |
| `unwrap`              | `Token::CloseAccount` rent recovery for non-WSOL token accounts, or WSOL accounts with zero token balance                                                                                                               | `solMode: "separate"` only |
| `changeOwner`         | `Token::SetAuthority(AccountOwner)`                                                                                                                                                                                     | Always                     |
| `withdrawWithheldFee` | `Token-2022::WithdrawWithheldTokensFromMint`, `Token-2022::WithdrawWithheldTokensFromAccounts`                                                                                                                          | Always                     |

## SOL and wSOL behavior

SOL exists on Solana in two forms that often appear together in real user activity:

* **Native SOL** is the chain's native asset. It lives directly in a wallet or account as lamports. One SOL is 1,000,000,000 lamports.
* **Wrapped SOL (WSOL, often written wSOL)** is an SPL token representation of SOL. It uses the WSOL mint `So11111111111111111111111111111111111111112` and lives in a token account, like USDC or any other SPL token.

Users and applications wrap SOL when they need SOL to behave like an SPL token, usually for DeFi, swaps, token-account-based accounting, or program interfaces that only accept SPL tokens. Wrapping typically funds a token account with native SOL and syncs it into WSOL. Unwrapping closes the WSOL token account and returns the SOL to a lamport destination.

That lifecycle can create confusing history if you are trying to answer a simple question like "how much SOL moved between this wallet and someone else?" A wrap or unwrap often moves SOL between accounts controlled by the same owner. If those lifecycle rows are shown as ordinary transfers by default, apps can double count activity or show internal bookkeeping as external payments.

By default, `getTransfersByAddress` uses `solMode: "merged"`. In this mode:

* Native SOL and WSOL are treated as one SOL asset when querying by `So11111111111111111111111111111111111111111`.
* WSOL transfer rows are normalized to the native SOL mint so SOL-denominated history is easier to reconcile.
* Wrap and unwrap lifecycle rows are excluded because they usually represent movement between accounts controlled by the same owner, not a payment to another user.
* SOL and WSOL transfers between different owners are still represented as transfers.
* Rent recovered from `CloseAccount` is represented as a native SOL `unwrap` row when close-account lifecycle rows are returned.

Use `solMode: "separate"` when you need WSOL as a distinct SPL token mint or want to inspect wrap and unwrap lifecycle records. In this mode, WSOL keeps the mint `So11111111111111111111111111111111111111112`, and wrap/unwrap records are returned with `type: "wrap"` or `type: "unwrap"`.

For WSOL account closures in `solMode: "separate"`, `unwrap` records for the WSOL mint represent the remaining WSOL token balance returned as SOL. Rent refunded from the closed token account is returned as a separate native SOL `unwrap` row.

## Token-2022 transfer fees

Token-2022 `TransferCheckedWithFee` instructions are represented as one transfer record with `type: "transfer"`. The destination amount is returned in `amount`; withheld fee details are returned in `feeAmount` and `feeUiAmount`.

For transfers with fees, the source is debited `amount + feeAmount`, while the destination is credited `amount`.

```json theme={"system"}
{
  "signature": "WcvF2eFxArpqRJySzDuiP6Xw8BMprWytMpYCxk2ExBt5C1WyxWzDWcCWXW8iKQVYR9AtdQxPE1uu1SMEZvbbhdr",
  "slot": 409259683,
  "blockTime": 1774635210,
  "type": "transfer",
  "fromUserAccount": "5aZZ4duJUKiMsJN9vRsoAn4SDX7agvKu7Q3QdFWRfWze",
  "toUserAccount": "FESSvM1cVUchc13XQY8e41oeYxMnyqQNYVZwoznfJsTo",
  "fromTokenAccount": "3VUYGjYktCzNhDVymNb3Z1iHewtfPFRvdA53qSWuxdXy",
  "toTokenAccount": "51cEFBA1virMuPqHXvNGs8FKKTMqeEVKzugv1hqPU2Zc",
  "mint": "CKfatsPMUf8SkiURsDXs7eK6GWb4Jsd6UDbs7twMCWxo",
  "amount": "48650000",
  "decimals": 5,
  "uiAmount": "486.5",
  "feeAmount": "13450000",
  "feeUiAmount": "134.5",
  "confirmationStatus": "finalized",
  "transactionIdx": 1315,
  "instructionIdx": 4,
  "innerInstructionIdx": 0
}
```

## Examples

### Filter by USDC

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "getTransfersByAddress",
  "params": [
    "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY",
    {
      "mint": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"
    }
  ]
}
```

### Incoming transfers from a sender

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "getTransfersByAddress",
  "params": [
    "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY",
    {
      "with": "7hPhaUpydpvm8wtiS3k4LPZKUmivQRs7YQmpE1hFshHx",
      "direction": "in"
    }
  ]
}
```

### Amount and time range

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "getTransfersByAddress",
  "params": [
    "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY",
    {
      "mint": "So11111111111111111111111111111111111111112",
      "filters": {
        "amount": {
          "gte": 1000000000,
          "lt": 10000000000
        },
        "blockTime": {
          "gte": 1735718400,
          "lt": 1738396800
        }
      }
    }
  ]
}
```

### Paginated request

```json theme={"system"}
{
  "jsonrpc": "2.0",
  "id": "1",
  "method": "getTransfersByAddress",
  "params": [
    "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY",
    {
      "limit": 50,
      "paginationToken": "315069220:308:2:1:splTransfer"
    }
  ]
}
```

### Fetch full transactions for transfer rows

`getTransfersByAddress` returns parsed transfer rows, not full transaction payloads. If you need the full transaction for every transfer, page through transfers first, dedupe by `signature`, then fetch the full transactions with batched [`getTransaction`](/api-reference/rpc/http/gettransaction) calls.

`getTransfersByAddress` is not batchable across multiple owner addresses. Query one owner address at a time, then batch the resulting `getTransaction` requests by signature. A single transaction can emit multiple transfer rows, so always dedupe signatures before fetching transactions.

```javascript theme={"system"}
const API_KEY = "YOUR_API_KEY";
const RPC_URL = `https://mainnet.helius-rpc.com/?api-key=${API_KEY}`;
const OWNER_ADDRESS = "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY";

async function rpc(method, params) {
  const response = await fetch(RPC_URL, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      jsonrpc: "2.0",
      id: "1",
      method,
      params
    })
  });

  const body = await response.json();
  if (body.error) {
    throw new Error(body.error.message);
  }
  return body.result;
}

async function getAllTransfers(address) {
  const transfers = [];
  let paginationToken;

  do {
    const result = await rpc("getTransfersByAddress", [
      address,
      {
        limit: 100,
        ...(paginationToken ? { paginationToken } : {})
      }
    ]);

    transfers.push(...result.data);
    paginationToken = result.paginationToken;
  } while (paginationToken);

  return transfers;
}

async function getTransactionsInBatches(signatures, batchSize = 100) {
  const transactions = [];

  for (let i = 0; i < signatures.length; i += batchSize) {
    const batch = signatures.slice(i, i + batchSize).map((signature, index) => ({
      jsonrpc: "2.0",
      id: `${i + index}`,
      method: "getTransaction",
      params: [
        signature,
        {
          encoding: "jsonParsed",
          maxSupportedTransactionVersion: 0
        }
      ]
    }));

    const response = await fetch(RPC_URL, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(batch)
    });

    const results = await response.json();
    for (const item of results) {
      if (item.error) {
        throw new Error(item.error.message);
      }
      transactions.push(item.result);
    }
  }

  return transactions;
}

const transfers = await getAllTransfers(OWNER_ADDRESS);
const signatures = [...new Set(transfers.map((transfer) => transfer.signature))];
const transactions = await getTransactionsInBatches(signatures);

console.log(`Fetched ${transfers.length} transfer rows`);
console.log(`Fetched ${transactions.length} unique transactions`);
```

## Limitations

* Failed transactions are not included in V1.
* Hidden SOL movements inferred only from balance changes are not supported in V1.
* `harvestWithheldTokensToMint` is not supported in V1 because it does not indicate the collected amount.
* Intermediary account flows are not reduced. If a transaction moves funds through intermediary accounts, the underlying transfer records are returned.
* Not batchable across multiple owner addresses. Query one owner at a time.

## Next steps

<CardGroup cols={2}>
  <Card title="getTransactionsForAddress" icon="clock-rotate-left" href="/rpc/gettransactionsforaddress">
    Full transaction history with filtering, sorting, and token-account support.
  </Card>

  <Card title="API reference" icon="code" href="/api-reference/rpc/http/gettransfersbyaddress">
    Full request and response schema for getTransfersByAddress.
  </Card>

  <Card title="Indexing guide" icon="layer-group" href="/rpc/how-to-index-solana-data">
    Backfill and sync transfer data into your own index.
  </Card>

  <Card title="Historical data overview" icon="arrow-right-arrow-left" href="/rpc/historical-data">
    Compare all Solana historical data methods.
  </Card>
</CardGroup>
