Learning how to build a copy trading bot in Python is not hard in the way most tutorials imply. Streaming a wallet, reading a swap and firing your own swap is maybe 200 lines of code. The hard part is everything that happens after the demo works: the 900 milliseconds you did not budget for, the five different venues a Solana trade can route through, the sell you never mirrored, and the restart that forgets you are holding a bag.
This guide walks the full architecture of a Solana copy trading bot in Python — detection, decoding, sizing, filtering, execution, exits and production hardening — with code sketches you can actually build on. It also does the thing the GitHub repos and affiliate tutorials skip: it tells you where the design leaks money, what the infrastructure costs, and at what point building your own stops being the rational choice. If you want the non-developer version of this, start with how to copy trade on Solana instead.
What a copy trading bot in Python actually has to do
A copy trading bot is a loop with six responsibilities. Every tutorial covers the first two. Almost none cover the last four, which is exactly why so many self-built bots quietly underperform the wallet they are copying.
- Detect. Know that the target wallet did something, as close to instantly as the network allows.
- Decode. Turn a raw transaction into a normalised event: this wallet spent 4.2 SOL and received 1.9M of mint X.
- Decide. Apply your filters and size the position against your own balance, not theirs.
- Execute. Build, sign and land your own swap before the price moves away from you.
- Mirror the exit. Sell the same proportion they sell, when they sell it.
- Survive. Reconnect, deduplicate, reconcile state after a crash, and never double-buy.
Points five and six are where the real engineering lives. A bot that copies entries but not exits is not a copy trading bot — it is a random buyer of memecoins that a profitable trader happened to touch. Our breakdown of Solana copy trading statistics shows how much of a leader's edge lives in the exit timing rather than the entry.
The latency budget nobody shows you
Before writing a line of code, do the arithmetic. Solana produces a block roughly every 400 milliseconds. Your bot's total delay is the sum of four segments, and only one of them is under your control by writing better Python.
| Segment | What it is | How to shrink it |
|---|---|---|
| Detection | Leader's tx lands → your process sees it | Geyser gRPC at processed commitment instead of polling or public WebSockets |
| Decision | Decode, filter, size | Balance-diff decoding, cached filter data, zero blocking HTTP calls in the hot path |
| Build | Quote + transaction construction | Pre-warm blockhashes and token accounts; direct venue instructions beat a quote round-trip |
| Landing | Broadcast → included in a block | Priority fees, staked-connection RPC, retry on the same blockhash |
A naive stack — public RPC polling with getSignaturesForAddress, a synchronous requests call for a quote, default priority fees — routinely lands you several seconds behind the leader. On a token that just moved 40% in two blocks, several seconds is not a copy. It is a purchase at the top of the candle the leader created, and the leader is the one selling into it.
Set a target before you build: detection under 100 ms, decision under 20 ms, and a signed transaction broadcast inside the same or next slot. If your architecture cannot hit that, the honest move is to copy slower traders — swing positions rather than bonding-curve scalps — or to stop competing on speed entirely.
The Python stack a copy trading bot actually needs
Python is a perfectly reasonable language for this, with one caveat: keep the hot path free of anything that blocks. The libraries that matter in 2026:
solders— Rust-backed bindings for keypairs, pubkeys, instructions and transaction (de)serialisation. Substantially faster than pure-Python parsing, and the type you will pass around everywhere.solana-py— the RPC client (AsyncClient) for account reads, blockhashes and sending transactions.grpcioandgrpcio-tools— for the Yellowstone (Geyser) gRPC stream. You generate Python stubs fromgeyser.protowithgrpc_tools.protoc.base58— Solana addresses and signatures come off the wire as raw bytes, not base58 strings.httpxoraiohttp— async HTTP for the Jupiter quote and swap endpoints. Neverrequestsin the hot path.anchorpy— optional, for decoding Anchor program instructions and events against an IDL when balance diffs are not enough.asyncioplus SQLite or Postgres — the event loop and a durable position store. In-memory state is how bots lose track of open bags.
Everything else — pandas, ML frameworks, backtesting suites — belongs in your research repo, not in the process that has 400 milliseconds to make a decision.
Step 1: Stream the target wallet
Detection is the single biggest lever on your bot's performance, and you have three realistic options on Solana, ranked worst to best.
Polling getSignaturesForAddress. Simple, works on any endpoint, and hopelessly slow. You are adding your poll interval plus RPC round-trip to every trade, and public endpoints will rate-limit you long before you poll fast enough to matter. Fine for a paper-trading prototype, useless in production.
WebSocket logsSubscribe with a mentions filter. A real push stream and free on most providers. The catch: it delivers logs, not full transaction metadata, so you still need a follow-up getTransaction call to see what actually happened — which puts an RPC round-trip back in your hot path. Subscriptions also drop silently on shared endpoints, so you need a heartbeat and reconnect logic regardless.
Yellowstone gRPC (Geyser). The professional answer. A Geyser plugin streams transactions directly from a validator with full metadata attached, filtered server-side to the accounts you care about. Providers such as Helius, Triton, QuickNode and Chainstack all expose it. In Python you generate the stubs from the proto files, then subscribe:
import asyncio, grpc
from generated import geyser_pb2, geyser_pb2_grpc
TARGET = "2fg5QD1eD7rzNNCsvnhmXFm5hqNgwTTG8p7kQ6f3rx6f"
def credentials(token: str):
return grpc.composite_channel_credentials(
grpc.ssl_channel_credentials(),
grpc.metadata_call_credentials(
lambda _, cb: cb((("x-token", token),), None)
),
)
def request():
req = geyser_pb2.SubscribeRequest()
f = req.transactions["leader"]
f.account_include.append(TARGET)
f.vote = False
f.failed = False
req.commitment = geyser_pb2.CommitmentLevel.PROCESSED
yield req
async def stream(endpoint: str, token: str):
async with grpc.aio.secure_channel(endpoint, credentials(token)) as ch:
stub = geyser_pb2_grpc.GeyserStub(ch)
async for update in stub.Subscribe(request()):
if update.HasField("transaction"):
await handle(update.transaction)
Two details matter more than they look. Subscribe at processed commitment, not confirmed — waiting for confirmation is waiting for a supermajority of votes, and you do not need that certainty to decide whether to place your own order. And set failed = False: a failed leader transaction is not a signal, and copying one is how you pay fees for nothing.
Step 2: Decode the trade without parsing every DEX
This is where most self-built bots break within a week. A Solana trade can execute on the pump.fun bonding curve, on PumpSwap, on Raydium's AMM or CLMM or CPMM programs, on Meteora DLMM, on Orca Whirlpools, or through Jupiter, which wraps any of the above in its own instruction and hides the venue in inner CPIs. Write a parser per program and you will be rewriting it every time a new launchpad or AMM takes over volume.
The robust approach is to stop parsing instructions and start diffing balances. Every confirmed transaction carries preTokenBalances, postTokenBalances, preBalances and postBalances in its metadata. Filter those to the leader's accounts and you get the economic truth of the trade regardless of which program produced it:
WSOL = "So11111111111111111111111111111111111111112"
def decode_swap(meta, keys, owner: str):
"""Return (mint, delta) for the non-SOL token the owner's balance moved."""
before, after = {}, {}
for b in meta.pre_token_balances:
if b.owner == owner:
before[b.mint] = float(b.ui_token_amount.ui_amount_string or 0)
for b in meta.post_token_balances:
if b.owner == owner:
after[b.mint] = float(b.ui_token_amount.ui_amount_string or 0)
idx = keys.index(owner)
sol_delta = (meta.post_balances[idx] - meta.pre_balances[idx]) / 1e9
for mint in set(before) | set(after):
if mint == WSOL:
continue
delta = after.get(mint, 0) - before.get(mint, 0)
if delta != 0:
side = "buy" if delta > 0 else "sell"
return {"mint": mint, "side": side, "amount": abs(delta),
"sol_delta": sol_delta}
return None
Venue-agnostic, future-proof, and roughly forty lines. Three caveats to handle explicitly: the SOL delta includes fees, so never treat it as a clean price; a wrapped-SOL account can absorb part of the movement, so check both native and WSOL balances; and a plain token transfer to another wallet also shows up as a negative delta — check whether a known DEX program appears in the instruction list before you classify something as a sell. If you need the exact route, add Anchor IDL decoding on top, but keep the balance diff as your source of truth.
The same logic is what powers any serious Solana wallet tracker, and it is worth building even if you never place a trade with it — you can run it in observe-only mode for a week and see what copying a wallet would actually have returned.
Step 3: Size the position against your own book
You cannot copy a whale one-to-one, and you should not try. Three sizing models, each with a failure mode:
- Fixed notional. Always buy 0.5 SOL. Simple and predictable; ignores the leader's conviction entirely, so you size a throwaway scalp identically to their highest-conviction entry.
- Fixed fraction of your bankroll. Always 2% of your balance. Scales with your account and caps ruin; still ignores their conviction.
- Proportional mirroring. They spent 3% of their SOL balance, so you spend 3% of yours. Closest to a true copy, but it requires tracking their balance, and it inherits their risk appetite whether or not it suits you.
Whichever you pick, cap it. A max_position_sol ceiling, a daily loss limit that halts the bot, and a hard rule against re-entering a mint you already hold will save you more money than any latency optimisation. Our guide to position sizing covers the maths in detail, and copy trading risk management covers the controls that actually exist when someone else is making the decisions.
One effect worth internalising: if the leader's buy is a meaningful share of the pool and you pile in behind them, you push the price yourself. Your fill is worse than theirs by construction, and on thin liquidity the gap can exceed the move you were copying. That is not a bug in your code — it is the structural cost of being second, and it is why slippage deserves a line item in your PnL, not a footnote.
Step 4: Filter before you copy
A profitable wallet is not profitable on every trade. Blindly mirroring everything means you also mirror their experiments, their airdrop farming, their wallet-to-wallet transfers and the occasional honeypot they exited at a loss. A filter stack worth having:
- Token safety. Mint and freeze authority revoked, LP burned or locked, holder concentration under a threshold. The checks in our Solana rug check walkthrough translate directly into code.
- Liquidity floor. Skip pools below a minimum depth — your exit is only as good as the liquidity available when you need it.
- Trade size floor. If the leader spent 0.05 SOL, they are testing, not trading.
- Cooldown and dedupe. One position per mint, and a per-minute cap so a leader's rapid-fire session does not open fifteen positions at once.
- Time of day and drawdown guards. Halt after N consecutive losses and require manual restart.
Every filter that needs an external API call must be served from a cache that is warmed in the background. A 300 ms rug-check lookup inside the hot path costs you more in fill price than it saves in avoided rugs — pre-fetch token metadata the moment the mint appears, and let the trade decision read local state.
Step 5: Execute the swap
Two execution paths, and the choice is a real trade-off rather than a best practice.
Aggregator route. Jupiter's Swap API gives you a quote and a ready-to-sign transaction across every venue. The free tier lives at lite-api.jup.ag/swap/v1/quote and the keyed tier at api.jup.ag; check the current docs before you hardcode a version, since Jupiter has revised both the base URL and the route engine more than once. The flow is a GET for the quote, a POST to build the swap transaction, then sign and send:
import base64, httpx
from solders.transaction import VersionedTransaction
from solders.keypair import Keypair
BASE = "https://lite-api.jup.ag/swap/v1"
async def buy(client: httpx.AsyncClient, kp: Keypair, mint: str,
lamports: int, slippage_bps: int = 300):
quote = (await client.get(f"{BASE}/quote", params={
"inputMint": WSOL, "outputMint": mint,
"amount": lamports, "slippageBps": slippage_bps,
"restrictIntermediateTokens": True,
})).json()
swap = (await client.post(f"{BASE}/swap", json={
"quoteResponse": quote,
"userPublicKey": str(kp.pubkey()),
"wrapAndUnwrapSol": True,
"dynamicComputeUnitLimit": True,
"prioritizationFeeLamports": {"priorityLevelWithMaxLamports": {
"priorityLevel": "high", "maxLamports": 1_000_000}},
})).json()
raw = VersionedTransaction.from_bytes(base64.b64decode(swap["swapTransaction"]))
signed = VersionedTransaction(raw.message, [kp])
return signed
Direct venue route. You build the swap instruction for the specific program yourself — pump.fun's bonding curve, a Raydium pool, a Meteora bin. You skip two HTTP round-trips, which is the single largest chunk of controllable latency in the whole pipeline. The cost is that you now maintain venue-specific code and account-derivation logic forever, and you are on the hook every time a program upgrades.
Sensible answer for most builders: aggregator for correctness, direct route only for the one or two venues where you genuinely compete on speed. Whichever you choose, send with skip_preflight=True (preflight simulation costs you a round-trip to tell you what you already know), pay a real priority fee, and consider Jito bundles if you are being sandwiched — our Solana MEV explainer covers when that is worth the tip. Budget for the full cost stack too: priority fees, tips, the aggregator's platform fee where applicable, and the base transaction fees on every attempt, including the ones that fail.
Ready to copy trade on Solana?
Start copying the most profitable traders in under 2 minutes. No coding, no complex setup. Just connect and earn.
Step 6: Mirror the exit
Here is the section missing from nearly every "how to build a copy trading bot in Python" tutorial on the internet, and it is the one that decides whether your bot makes money.
Entries are easy because they are absolute: the leader spent 4 SOL, you spend your equivalent. Exits are relative. When the leader sells, they sell a fraction of a position whose size and cost basis you may not know — they might have been holding it since before you started streaming. Selling your whole bag because they trimmed 25% turns a winning copy into a fraction of the leader's return.
The fix is to track two position ledgers: theirs (inferred from the stream, starting at zero the moment you begin watching) and yours (known exactly). On every leader sell, compute the fraction of their tracked balance that left, and apply that same fraction to yours:
def exit_amount(leader_before, leader_sold, my_balance):
if leader_before <= 0 or my_balance <= 0:
return 0
fraction = min(leader_sold / leader_before, 1.0)
amount = my_balance * fraction
# Dust guard: finish the position instead of leaving unsellable crumbs.
if my_balance - amount < my_balance * 0.05:
return my_balance
return amount
Three edge cases to handle or you will bleed: a leader whose position predates your tracking (treat the first observed sell as unknown-basis and either skip or exit fully — decide deliberately); a leader who moves tokens to a second wallet, which looks identical to a sell in balance-diff terms; and the dust tail, where repeated fractional exits leave you holding a slice too small to sell for more than the fee.
You also need your own safety net independent of the leader. If they go offline holding a position that is down 60%, nothing in a pure mirroring design gets you out. A local stop loss and a maximum hold time are not optional extras — they are the difference between copying a trader and inheriting their worst day.
Step 7: Make it survive production
The demo works. Now make it run for a month unattended.
- Idempotency. Key every action on the leader's transaction signature and persist it. Streams replay on reconnect, and a duplicate buy at a worse price is the most expensive bug in this category.
- Durable state. Open positions, cost basis and the leader's inferred balances belong in SQLite or Postgres, written before you send the transaction, not after. On boot, reconcile against your actual token accounts via
getTokenAccountsByOwner— the chain is the truth, your database is a cache. - Reconnect with backoff. gRPC streams drop. Wrap the subscribe loop, reconnect with jitter, and alert if you have been disconnected for more than a few seconds, because a silent dead stream looks exactly like a quiet market.
- Latency telemetry. Log leader slot, detection timestamp, broadcast timestamp and landed slot for every copy. Then track the metric that matters: your fill price versus theirs, in basis points, per trade. If that number is consistently negative and larger than the leader's edge, no amount of feature work saves the bot.
- Kill switch. A file or environment flag that stops new entries while still allowing exits. You will want it at 3am.
- Key hygiene. The bot holds a hot key. Fund it with what you are willing to lose, keep it out of the repo and out of the container image, and never reuse your main wallet.
What it costs to run a Python copy trading bot
The code is free. The infrastructure is not, and this is the number people discover in month two.
| Line item | Reality |
|---|---|
| Public RPC | Free, rate-limited, and not viable for anything latency-sensitive |
| Geyser gRPC access | A paid plan on every major provider; dedicated nodes cost multiples of shared plans — check current pricing, it moves |
| Hosting | A VPS in the same region as your endpoint; cross-continent hops add tens of milliseconds for no reason |
| Priority fees and tips | Per transaction, paid on winners and losers alike, and they spike exactly when you most want to land |
| Your time | The largest cost by far — and it recurs every time a venue changes |
Run the bot in observe-only mode first and log the trades it would have taken. If the simulated edge, after fees and your measured slippage versus the leader, does not clearly beat zero, you have learned something valuable for the price of a VPS.
Binance, ccxt, and the CEX version of this question
A large share of people searching for a copy trading bot in Python are thinking about Binance rather than Solana, so it is worth being blunt about the difference: on a centralised exchange you cannot see another person's trades. There is no public API that streams an arbitrary Binance user's fills. The transparency that makes on-chain copy trading possible simply does not exist there.
What a "Binance copy trading bot" in Python actually means is one of three things:
- Mirroring your own accounts. Using
ccxtor the official SDK to replicate fills from a master account into sub-accounts or separate API keys. Genuinely useful, and entirely within your control. - Consuming a signal feed. A Telegram channel, webhook or private API you have been granted access to. Your bot is an execution layer, and the quality of the signal is someone else's problem.
- Using the exchange's own product. Platform-native copy trading, where the exchange handles the mirroring and you are a customer rather than a builder — see our breakdown of Binance copy trading and the wider copy trading platform comparison for how the fee models differ.
The architecture above still applies to the CEX case — detect, decode, size, filter, execute, mirror the exit — but the detection layer becomes a private feed instead of a public chain, and you inherit custody risk you do not have when you trade from your own wallet. That trade-off is the core of what crypto copy trading is and how the on-chain version differs.
Build or buy: the honest comparison
Building this is the best way to actually understand copy trading, and if you are a developer it is a genuinely good project. But be clear about what you are signing up for.
| Dimension | Build it in Python | Use a copy trading platform |
|---|---|---|
| Control | Total — every filter is yours | Whatever the settings expose |
| Time to first trade | Weeks to a prototype, longer to trust it with size | Minutes |
| Fixed cost | Infrastructure monthly, win or lose | Depends on the fee model — uwuu charges a performance fee, so you pay when you profit |
| Maintenance | Yours, forever, including venue migrations | Someone else's problem |
| Trader selection | You find and vet wallets yourself | A verified on-chain leaderboard does the filtering |
And note what the table hides: none of this engineering fixes trader selection. A bot with a 40 ms detection loop copying a mediocre wallet loses money faster than a slow bot copying a good one. Finding the wallet is the alpha; the code is logistics. That is why the leaderboard at uwuu.ai/leaderboard is verified on-chain — and why tools like KOL trackers and the DexScreener API are research inputs, not execution stacks.
uwuu is the same architecture described above, run as a service: non-custodial, so your keys stay in your wallet, sub-400ms execution, a verified on-chain leaderboard instead of a wallet you found on Twitter, and smart trade filtering rather than blind mirroring. If you would rather spend your evenings on strategy than on protobuf stubs, that is the shortcut. If you want the middle ground, compare the options in our best Solana trading bot roundup or read how a managed copy trading bot automates a crypto strategy.
Ready to copy trade on Solana?
Start copying the most profitable traders in under 2 minutes. No coding, no complex setup. Just connect and earn.
Frequently Asked Questions
Can I use Python to create a trading bot?
Yes. Python is a standard choice for crypto trading bots and has mature Solana tooling — solders for fast keypair and transaction handling, solana-py for RPC, and grpcio for Yellowstone Geyser streams. The language is rarely the bottleneck; your data feed and transaction landing strategy are.
How long does it take to build a copy trading bot in Python?
A working prototype that detects a wallet and fires a swap is a weekend for an experienced developer. A version you would trust with real size — with exit mirroring, durable state, reconnect logic, filters and telemetry — is considerably more work, and it needs ongoing maintenance as Solana venues change.
Is it legal to run a copy trading bot?
Running automated software against public blockchain data is legal in most jurisdictions, and reading on-chain activity requires no one's permission because the data is public by design. Rules differ by country and change, especially around managing other people's money — check your local regulations before you trade for anyone but yourself.
Do I need a paid RPC to run a Solana copy trading bot?
For anything latency-sensitive, yes. Public endpoints are rate-limited and shared, which shows up as dropped subscriptions and delayed detection. A paid plan with Geyser gRPC access is the practical floor for competitive copy trading, and it is a fixed monthly cost you pay whether or not the bot profits.
Why does my bot get worse fills than the wallet it copies?
Because you are structurally second. You detect after their transaction lands, you broadcast after that, and on thin liquidity your own buy moves the price further in the direction they already pushed it. Measure the gap in basis points per trade — if it exceeds the leader's average edge, the strategy is negative regardless of code quality.
Can I copy a Binance trader with a Python bot?
Not directly. There is no public API that streams another Binance user's fills, so "Binance copy trading bots" are really mirroring your own sub-accounts, executing a signal feed you have access to, or using the exchange's own copy trading product. On-chain wallets are public, which is why Solana copy trading is programmable and CEX copy trading is not.
Verdict: build it to learn, then decide
Building a copy trading bot in Python is the fastest way to understand why copy trading works and where it leaks. Stream the wallet with Geyser gRPC, decode with balance diffs instead of per-DEX parsers, size against your own book, filter before the hot path, execute with real priority fees, and mirror exits proportionally — that is the whole system, and it is achievable.
What the exercise usually teaches is that the code was never the constraint. Infrastructure costs are fixed and recurring, latency has a floor you cannot code past, and the single biggest variable in your returns is which wallet you chose to copy. Build it for the understanding. Then decide honestly whether maintaining it beats copying a verified trader in two minutes and spending your time on selection instead.
Related Articles
Solana Copy Trading in 2026: What 1,710 Real Trades Reveal
77% of copy trades happen on the pump.fun bonding curve, the median hold is 24 seconds, and 63% of tracked wallets have exactly one copier. Original data from 1,710 real copied positions.
Solana MEV Explained: Sandwich Bots, Jito & Who Wins (2026)
What Solana MEV is, how Jito bundles and sandwich bots extract value from your swaps, MEV protection strategies, and why copy trading beats building MEV bots for most traders in 2026.
Helius API: Solana RPC, DAS & Webhooks Explained (2026)
How the Helius API works on Solana: RPC, DAS indexing, webhooks, LaserStream gRPC, real pricing traps, vs QuickNode, and when copy trading beats building your own infrastructure.
DexScreener API: Endpoints, Rate Limits & Alternatives (2026)
A practical DexScreener API guide for 2026: key endpoints, rate limits, Solana new-pairs workflows, alert bot architecture, alternatives, and the copy-trading gap.
Best Solana Trading Bot in 2026: Automate & Copy Trade Like a Pro
Discover how to use a Solana trading bot to copy the most profitable traders on-chain. Fully automated, no coding required, and built for speed.
How to Copy Trade on Solana: Step-by-Step Tutorial (2026)
A complete step-by-step walkthrough on how to copy trade on Solana. From connecting your wallet to picking your first trader — everything you need to know.
Copy Trading Bot: How to Automate Your Crypto Strategy in 2026
A copy trading bot lets you automate your entire crypto strategy by mirroring top performers. Learn how to set one up and start earning passively.
