Copy fomo.family traders in real time: the on-chain trades WebSocket
Follow chosen fomo.family traders or a whole leaderboard over one WebSocket and get each buy and sell as it lands on-chain. With a Python copy-trading listener.
fomo.family (referral link) shows you what its best traders bought, after they bought it. If you want to copy a trade, or just react to one, the app is the wrong place to learn about it: by the time a trade is on a screen, a person has to read it and act. A program should hear about it first.
That is what the trade stream is for. You open one WebSocket, say which fomo.family traders you want to follow, and receive each buy and sell they make as it is read off the chain: the trader, the wallet that traded, the token, the size and the transaction. This post shows how to use it and how to build a small copy-trading listener on top.
Why not poll, or watch the wallets yourself?
There are two ways to do this without a stream, and both have a cost.
- Polling the leaderboard tells you who is winning, not what they just did. A leaderboard is a summary of trades that already happened.
- Running your own on-chain listener works, once you know which wallets to listen to. fomo.family does not publish them. A trader has a handle and a PnL in the app; the addresses behind the handle are the part you have to prove, one transaction at a time, on Solana and on every EVM chain the app trades on. Then you need a node or an indexer per chain, and code that tells a swap from a transfer and a routed swap from three separate trades.
The stream is both halves done: the map from fomo.family handle to wallet that the rest of this API serves, joined to a feed of every swap on each chain. You name a handle and get that trader’s trades.
Try it in a terminal
With wscat installed (npm install -g wscat), follow the ten traders at the top of the 24-hour fomo.family leaderboard:
wscat -c "wss://provadata.com/ws/trades?key=$API_KEY&board=24h&top=10"
The first message confirms what you are following. After it, trades arrive as they happen:
{ "type": "subscribed", "filter": { "board": "24h", "top": 10 } }
{
"type": "trade",
"chain": "solana",
"side": "buy",
"trader": { "handle": "halvard", "wallet": "7xKq…9fQe", "walletStatus": "verified" },
"token": { "address": "2R52…wcCQ", "priceUsd": 0.0000329 },
"usdValue": 3871.2,
"amountToken": 117665653.5,
"txHash": "39Pv…foTi",
"block": 52795900,
"exchange": "pumpswap",
"tradedAt": "2026-10-09T09:00:00Z",
"seenAt": "2026-10-09T09:00:01.1Z",
"latencyMs": 1100,
"source": "onchain"
}
Addresses are shortened here; the stream sends them in full. Times are UTC. latencyMs is the gap between the trade and the moment we read it, so you can measure the delay yourself instead of taking our word for it.
Choosing who to follow
Every connection has its own subscription, and it must say who to follow. There are two ways, and you can combine them.
traders=halvard,newtrader: named traders, by fomo.family handle or by wallet address.board=24h(or7d,30d), optionally withtop=20: everyone on that leaderboard right now. The subscription follows the board as it changes, so a trader who climbs into the top 20 is followed from then on without you reconnecting.
Four filters narrow what you receive from those traders: chain, token, minUsd and side. To change the subscription on an open connection, send a message; it replaces the previous one.
{ "action": "subscribe", "traders": ["halvard"], "side": "buy", "minUsd": 500 }
A copy-trading listener in Python
This follows the top ten of the 24-hour board, keeps only buys of at least $200 made from a proven wallet, and hands each one to a function of yours. It reconnects when the connection drops and stops when the server says the request itself is wrong.
import asyncio, json, os
import websockets # pip install websockets
URL = ("wss://provadata.com/ws/trades?key=" + os.environ["API_KEY"]
+ "&board=24h&top=10&side=buy&minUsd=200")
def on_trade(t):
# Your logic goes here: size the position, check the token, place the order.
print(t["trader"]["handle"], "bought", t["token"]["address"],
"for $%.0f" % t["usdValue"], "on", t["chain"], "tx", t["txHash"])
async def follow():
while True:
try:
async with websockets.connect(URL) as ws:
async for raw in ws:
m = json.loads(raw)
if m["type"] != "trade" or m.get("replay"):
continue # never copy a replayed trade: it is old
if m["trader"]["walletStatus"] != "verified":
continue # only wallets proven to be this trader's
on_trade(m)
except websockets.ConnectionClosed as e:
print("closed:", e.code, e.reason)
if e.code == 1008:
return # plan or subscription problem: fix it, do not retry
except OSError as e:
print("connection failed:", e)
await asyncio.sleep(3)
asyncio.run(follow())
Four things to get right before you copy a trade
- Check
walletStatus.verifiedmeans an on-chain transaction proves the wallet is this fomo.family trader’s.likelymeans there is evidence but not proof. For anything that spends money, use verified only. How verification works explains the difference. - Use
latencyMs. If a trade reaches you late, the price has moved. Decide how old a trade may be and skip the ones past it. - Do not copy sells you never bought. A sell is only a signal to you if you hold the token. Track your own positions by token address, and treat a sell as an exit only for those.
- One trade, one message. A swap routed through several pools is sent once, for the token actually bought or sold, not once per hop. Adding or removing liquidity is not sent at all. You should still record each
txHashyou acted on, so a reconnect can never make you act twice.
The stream does not send a token’s name, symbol or market cap: it reports what the chain says, and those come from elsewhere. Look the token address up in your own source before buying. A token you cannot identify is a good reason not to copy.
Plans and limits
The stream is included in every paid plan. A connection counts as one request and the trades use no credits; what a plan sets is how many connections you may hold open and how many traders each one follows.
| Plan | Connections | Traders per connection |
|---|---|---|
| Starter | 1 | 10 |
| Growth | 5 | 100 |
| Scale | 20 | 500 |
If a plan follows fewer traders than a leaderboard has, board= follows the board from rank 1 down as far as the plan goes, and the subscribed message tells you the cut-off in top.
When the connection closes
A missing or wrong key is refused with a 401 before the connection opens. After that, the server explains itself in the close frame, and the code tells you whether to retry.
1008: the request is wrong. The plan has no stream, the subscription is invalid or names nobody, or the plan’s connections are all in use. Read the reason and fix it.1013and1001: try again. Your client was reading too slowly to keep up, or we restarted. Reconnect after a short pause.
The full reference, with every field and filter, is in the documentation. If you have not used the API before, the fomo.family API guide covers keys, leaderboards and wallet lookups first.