How to build a pump.fun and fomo copy trading bot on a social trading API
Pick traders worth copying from pump.fun and fomo.family data, watch them live, filter their trades and size your own. A working blueprint with TypeScript code.
6 min read
A copy trading bot looks simple: when a good trader buys, you buy; when they sell, you sell. Most pump.fun copy trading bots lose money anyway, and rarely because of code. They copy the wrong people, they copy trades they can't get the same price on, and they keep holding after the trader they copied has left.
This guide builds a pump.fun and fomo.family copy trading bot around those three problems. It uses social trading data (leaderboards, PnL, callouts and how followers did) to choose whom to follow. It watches those traders live and filters which of their trades are worth copying. It does not place trades for you: pumpfomo is a read-only data API, and execution stays with your own wallet and keys. The code is TypeScript.
The pipeline
- Find candidates on pump.fun's and fomo.family's leaderboards.
- Vet them with PnL breakdowns, trading stats and callout records.
- Watch them live over one WebSocket.
- Decide which of their trades to copy, with filters you can explain.
- Execute with your own wallet, outside this API.
- Review: compare your fills with theirs and drop who isn't working.
1. Find candidates
Both platforms rank traders by PnL, and both rankings are a starting list, not an answer.
const BASE = "https://api.pumpfomo.com"
const headers = { Authorization: `Bearer ${process.env.PUMPFOMO_KEY}` }
const get = async (path: string) => {
const r = await fetch(BASE + path, { headers })
if (!r.ok) throw new Error(`${path}: ${r.status}`)
return (await r.json()).data
}
// pump.fun: top 100 by realized PnL this month
const pump = await get("/v1/pump/leaderboard?period=monthly&sort=realized")
// fomo.family: top traders over 30 days
const fomo = await get("/v1/fomo/leaderboard/30d")
const candidates = [
...pump.entries.map((e) => ({ platform: "pump", id: e.userId, wallet: e.walletAddress, name: e.username,
realized: e.realizedPnlUsd, unrealized: e.unrealizedPnlUsd })),
...fomo.leaderboard.map((t) => ({ platform: "fomo", id: t.id, handle: t.userHandle, name: t.displayName,
pnl: t.pnl30d, trades: t.numTrades })),
]Two leaderboard calls cost 2 credits. Notice sort=realized: pump.fun's leaderboard can also sort by combined or unrealized PnL. On a weekly board, the top spot is often one open bag that has run, which is luck you can no longer copy.
Other places to look:
- Leaderboard positions: the single best positions behind the pump.fun board.
- Streak leaderboard: wallets that have traded every day for the longest. They're active, but not necessarily good.
- Clan leaderboard: fomo.family groups ranked by combined PnL, with their members.
- Callouts: pump.fun traders who publish calls, which you can score directly (next section).
2. Vet them
Here is what separates a trader worth copying from a lucky week, and where to read each signal:
| Question | Signal | Endpoint |
|---|---|---|
| Is the profit real or on paper? | Realized vs. unrealized PnL | /v1/pump/users/{wallet}/pnl, /v1/fomo/users/{handle}/trades |
| Is it one trade or many? | Trade count, biggest trade, volume over 1, 7 and 30 days | /v1/pump/users/{wallet}/trader-stats |
| Is it consistent? | The equity curve over 30 days | /pnl/chart, /pnl-chart |
| Can you keep up? | Average hold time | /v1/fomo/users/{handle} (averageHoldTimeSeconds) |
| Did following them pay? | Callout hit rates and followers' PnL | /v1/pump/users/{wallet}/callout-stats |
Hold time decides whether copying is even possible. Your copy lands seconds after their trade. A trader who holds for two days gives you room. A trader who flips in 40 seconds is gone by the time you're in, and your buy is part of what they sell into.
Callout stats are the closest thing to a track record. pump.fun measures each trader's callouts: how many reached 1.2x, 1.5x and 2x, the median multiple, and how long the peak took. It also measures the PnL of the people who bought after the call (pump.fun calls them "tail") at 1 hour, 4 hours and 24 hours. That last number answers your question directly: did following this person make money?
async function vetPump(wallet: string) {
const [pnl, stats, calls] = await Promise.all([
get(`/v1/pump/users/${wallet}/pnl?period=1m`),
get(`/v1/pump/users/${wallet}/trader-stats`),
get(`/v1/pump/users/${wallet}/callout-stats`),
])
const m = calls.monthly
return {
realizedShare: pnl.realizedPnl.usd / Math.max(1, Math.abs(pnl.pnl.usd)),
trades30d: stats.window30d.trades,
biggestTradeShare: stats.biggestTradeUsd / Math.max(1, stats.allTimeVolumeUsd),
callouts: m.totalCallouts,
hit2x: m.twoXPercent,
medianMultiple: m.medianMultiple,
followersPnl4h: m.tailPnl4hUsd, // what people who bought after their calls made in 4h
}
}That's 5 + 1 + 2 = 8 credits per trader. Vetting 200 candidates once a week costs 1,600 credits.
A simple rule set that removes most bad picks:
- At least 30 trades in 30 days, so there's a sample to judge.
- Realized PnL is most of total PnL.
- No single trade above about a fifth of their volume.
- For callers: at least 10 calls a month and a positive
tailPnl4hUsd. - Average hold time of an hour or more, unless you're running very fast infrastructure.
3. Watch them live
Follow your shortlist on one connection. pump.fun traders go in by user id, which follows every wallet we know for them. fomo.family traders go in by handle (on fomo, the profile address isn't the trading wallet, so addresses wouldn't work anyway).
import WebSocket from "ws"
type Signal = { platform: "pump" | "fomo"; who: string; side: "buy" | "sell"; token: string;
chain: string; usd: number; mcap?: number; ts: number }
function watch(pumpIds: string[], fomoHandles: string[], onSignal: (s: Signal) => void) {
const ws = new WebSocket("wss://api.pumpfomo.com/v1/stream", { headers })
ws.on("open", () => ws.send(JSON.stringify({
op: "subscribe", channel: "traders", pump: pumpIds, fomo: fomoHandles, replay: false,
})))
ws.on("message", (raw) => {
const m = JSON.parse(raw.toString())
if (m.type === "trade") onSignal({ platform: "pump", who: m.trader?.userId ?? m.wallet, side: m.side,
token: m.mint, chain: m.chain, usd: m.amountUsd, mcap: m.marketCapUsd, ts: m.ts })
if (m.type === "fomo_trade" && m.kind !== "thesis") onSignal({ platform: "fomo", who: m.trader.handle,
side: m.kind, token: m.token.address, chain: m.token.chain, usd: m.amountUsd, mcap: m.marketCapUsd, ts: m.ts })
})
ws.on("close", () => setTimeout(() => watch(pumpIds, fomoHandles, onSignal), 2000))
}A connection takes up to 1,000 pump.fun traders and 100 fomo handles. Streams come with the plan from Builder up. The WebSocket guide covers reconnects and replay in depth.
4. Decide what to copy
Most of a copy trading bot's edge lives in the trades it skips. Filters worth having, all cheap to check:
const MAX_LAG_MS = 8_000
const held = new Map<string, number>() // token -> our size in USD
async function shouldCopy(s: Signal): Promise<number> {
if (Date.now() - s.ts > MAX_LAG_MS) return 0 // too late: the price has moved
if (s.side === "sell") return held.get(s.token) ?? 0 // mirror exits, always
if (s.usd < 200) return 0 // a small buy is a test, not a conviction
if (held.has(s.token)) return 0 // one entry per token
if (s.mcap && (s.mcap < 30_000 || s.mcap > 50_000_000)) return 0
if (s.platform === "fomo") {
const w = await get(`/v1/fomo/tokens/${s.chain}/${s.token}/warnings`)
if (w.disableSelling || w.disableBuying) return 0 // can't get out: don't get in
} else {
const a = await get(`/v1/pump/coins/${s.token}/market-activity`)
if (a["1h"].numBuyers < 15) return 0 // too thin to exit
}
return Math.min(100, s.usd * 0.05) // size: a fraction of theirs, capped
}Token warnings also lists each warning fomo.family shows before a trade, with its severity, if you want to be stricter. The ideas behind the filters:
- Lag kills. If the signal is more than a few seconds old, the price you'd pay isn't the price they paid.
- Size relative to conviction. A trader's $50 buy is often a probe. Copy the trades they put money behind.
- Liquidity before entry. If a coin has a handful of buyers in the last hour, you'll be selling into nobody.
- Mirror the exit, always. The most expensive copy-trading bug is copying the buy and missing the sell.
- Cap everything: per trade, per token, per day.
5. Execute (outside this API)
pumpfomo doesn't trade, by design: it never holds keys or signs anything. Your bot sends its own transactions:
- Solana: pump.fun coins still on the bonding curve trade through pump.fun's program; graduated ones trade on PumpSwap and other pools. An aggregator like Jupiter routes across them for you.
- EVM chains: a DEX router or an aggregator on the coin's chain.
Keep the signing key in its own process, set slippage limits, and pay a priority fee on Solana when blocks are busy. Log the price you got next to the price the trader got.
6. Review, and drop who isn't working
Once a week, compare:
- Your realized PnL per copied trader (your own wallet's PnL works for this on pump.fun).
- Their PnL over the same window.
- Your average entry against theirs. That gap is your real cost of copying.
Drop traders whose copies lose even when they win. It means they're too fast, or their wins come from trades you can't reproduce.
What it costs
| Piece | Credits | Per month |
|---|---|---|
| Leaderboards, daily | 2 a day | ~60 |
| Vetting 200 traders, weekly | 1,600 a week | ~6,900 |
| One stream, always on | included | 0 |
| Pre-trade checks, 300 a day | 1 to 2 each | ~18,000 |
| Total | ~25,000 |
That fits in the Builder plan ($149 a month, 500,000 credits), the first with a stream, many times over. See pricing.
Frequently asked questions
What is a pump.fun copy trading bot?
It's a program that watches chosen pump.fun traders and places similar trades from your own wallet when they trade. The hard parts are choosing whom to copy, skipping trades you can't reproduce, and always mirroring exits.
Can I copy fomo.family traders?
Yes. Follow their fomo handles on the stream's traders channel and you'll get each buy and sell as it happens, with token, size, price and market cap. Execute on the same chain with your own wallet.
Does pumpfomo execute trades?
No. pumpfomo is a read-only data API. It supplies the signals (leaderboards, PnL, callouts, live trades), and your bot executes with its own keys.
Which traders should I copy?
Traders with a sample of trades, mostly realized profit, no single trade carrying the record, and hold times long enough for you to follow. For pump.fun callers, check that the people who bought after their calls made money (tailPnl4hUsd and tailPnl24hUsd in callout stats).
How fast will my bot be?
Trades reach the stream within seconds of the trader's own. Add your filtering and your transaction's time to land. Plan for a few seconds of lag, and copy traders whose positions last much longer than that.
Is copy trading on pump.fun profitable?
Sometimes, and less often than leaderboards suggest. The leader buys first and you buy after, often from the same thin pool. Test on paper, keep sizes small and measure your fills against theirs.
Where to go next
- pump.fun API guide for the REST basics.
- fomo.family API guide for fomo traders, swaps and leaderboards.
- WebSocket guide for every stream channel.
- Get a free key and start with the leaderboards.
Try it on real data, free.
10,000 credits a month, wallet or Telegram sign-in, no card. Every endpoint in these guides works on the Free plan; streams start at Builder.
More guides

9 min read
The pump.fun API in 2026: what exists, what doesn't, and how to use it
Does pump.fun have a public API? What its apps call, which pump.fun data you can get (profiles, trades, PnL, callouts) and how to start with curl and Python.
Read the guide
7 min read
The fomo.family API: trader profiles, swaps, PnL and leaderboards from the fomo app
fomo.family has no public API. Here is what fomo data exists (traders, swaps, PnL, leaderboards, clans, theses) and how to read it with one key, with code.
Read the guide
7 min read
The pump.fun WebSocket API: stream every trade, new coin and callout as it happens
Stream pump.fun trades on Solana and 11 EVM chains, new coins, callouts and fomo.family traders over one WebSocket. Channels, filters and Node and Python code.
Read the guide
7 min read
Building a fomo wallet tracker: who is behind a wallet, and every trade a fomo trader makes
Why a fomo.family profile address won't show a trader's trades, how to follow fomo and pump.fun traders live, and how to find the person behind a wallet.
Read the guide