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

# spot.holders

> One holder's row on a token, each time a trade or transfer changes it.

Subscribe on an open stream connection. See [Connecting to streams](/streams/overview) for the connection, frames and reconnecting.

## Filters

<ParamField body="chain" type="string" required>
  The [chain slug](/concepts/chains) the token is on.
</ParamField>

<ParamField body="token" type="string" required>
  One token address on `chain`. The subscription spends one unit of the [address budget](/streams/filters#the-address-budget).
</ParamField>

<ParamField body="flags" type="string[]">
  [Wallet classifications](/resources/glossary#wallet-classifications) to keep, with the values the [Token holders](/reference/rest/token-holders#filters) `flags` parameter takes. A holder is kept when it carries at least one of them, and `fomo` keeps wallets flagged `fomo`. Leave it out to keep every holder. A busy token's holders change on most of its trades, so `flags` cuts the updates you receive.
</ParamField>

The channel takes no `throttleMs` and sends no `exit` frame.

## Update

Each update's `data` is one holder's whole row on the token after a change, in the row shape [Token holders](/reference/rest/token-holders) returns, without `rank`. Its trading figures cover `lifetime`.

* Keep one row per `chain`, token and `address`. A later update replaces the earlier one.
* Rank the rows by `balance` yourself, largest first.
* A holder that sells out arrives with `balance` 0. Drop it.

A row carries no value and no unrealized PnL. Price it with the formulas on [Token holders](/reference/rest/token-holders#response).

## Snapshot, then stream

1. Subscribe.
2. Read [Token holders](/reference/rest/token-holders) with the same `flags` and `period=lifetime`.
3. Merge the read and the updates on `address`.

The read returns at most 150 holders, and the stream sends every holder that changes. A holder outside the read can arrive on the stream, so rank the merged rows by `balance`.

Read again after every reconnect.

## Errors

| Code | When |
| - | - |
| `VALIDATION_ERROR` | `chain` or `token` missing; a token address in the wrong format for the chain; an unknown flag; an unknown filter field; the [address budget](/streams/filters#the-address-budget) is spent |
| `UNSUPPORTED_CHAIN` | `chain` is not a supported slug |

<RequestExample>
  ```json Subscribe theme={null}
  {
    "action": "subscribe",
    "channel": "spot.holders",
    "filters": {
      "chain": "solana",
      "token": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
      "flags": ["bundler", "insider"]
    }
  }
  ```
</RequestExample>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.