A Pump.fun sniper bot is an automated Solana client that watches the Pump.fun program for new token creation, decodes the launch accounts, and submits a buy transaction before or alongside competing wallets. The hard parts are not the buy instruction itself but detection latency, transaction landing probability, and honest measurement of fill quality. This article explains the mechanism end to end, gives runnable detection and transaction-building code, and describes a measurement procedure you run yourself rather than trusting vendor speed claims. Concrete endpoint and provider selection is left to RPC Assistant so the methodology stays portable.
Scope and the direct answer
A Pump.fun sniper bot is a program that subscribes to Solana activity around the Pump.fun launch program, identifies newly created token mints, and fires a buy transaction with a configured priority fee and slippage before other buyers fill the bonding curve. It is not a single API call: it is a pipeline of detection, decoding, transaction construction, fee selection, submission, and confirmation tracking.
This article covers the engineering of that pipeline for people who already have a Solana keypair and basic familiarity with transactions. It does not recommend a specific bot product, and it does not claim any measured speed. Every number you care about — detection delay, landing rate, fill price — must be measured on your own infrastructure, because those values depend on your region, RPC path, fee settings, and the launch itself.
If you only need a concrete RPC endpoint or provider recommendation for Solana trading workloads, use the RPC Assistant guidance on the best Solana RPC provider rather than treating this page as a provider list.
- Assumed: a funded Solana keypair, Node.js or Python, and access to a Solana RPC endpoint you control or rent.
- Out of scope: legal, tax, or market advice; guaranteed-profit strategies; any claim about win rates.
- Deliverable: a detection loop, a transaction builder, and a measurement harness you can run repeatedly.
Prerequisites and assumptions before you write code
You need a Solana RPC endpoint that supports the subscription and lookup methods your bot uses. Public endpoints are rate-limited and unsuitable for sniping, so plan on a dedicated or high-throughput endpoint; see the node hosting overview and the RPC pricing page for capacity planning. You also need the Pump.fun program ID and its Anchor IDL, because decoding launch accounts depends on the program's account layout rather than a public REST API.
Assume the launch program can change. Anchor discriminators and account ordering are part of the program interface, so pin the IDL version you build against and re-verify after any program upgrade. Assume also that your transaction will compete with many others in the same slot; the design must tolerate failure and retry rather than assume a single submission lands.
- A keypair stored outside source control, loaded from an environment variable such as PRIVATE_KEY.
- An RPC_URL placeholder you replace with your own endpoint.
- The Pump.fun program ID and a pinned IDL file for decoding.
- A logging sink so every detection and submission is timestamped for later analysis.
How launch detection actually works
There are three practical detection paths, and they differ in latency and operational cost. The first is log subscription: subscribe to logs mentioning the Pump.fun program and filter for the create instruction. The second is account subscription: watch the program's associated accounts or the bonding-curve accounts derived per mint. The third is block or shred-level streaming, where you receive transaction data earlier in the propagation path, at the cost of more infrastructure and parsing work.
Log subscription is the simplest to operate and is enough to build a correct bot. It is also the path most sensitive to how quickly your RPC node sees the transaction and how quickly it forwards the notification. Shred-level or Geyser-style streams can reduce that delay, but they require a provider that exposes them and a parser that handles unfinalized data. Start with logs, measure, then decide whether earlier data is worth the complexity.
- logsSubscribe with a mention filter on the launch program: lowest operational overhead.
- Account or program subscription: useful when you need account state, not just the event.
- Block or shred streaming: earliest data, highest parsing and infrastructure burden.
Runnable detection loop in JavaScript
The following script subscribes to logs for the Pump.fun program and prints any signature whose log lines contain the create discriminator. It is deliberately minimal: it proves your endpoint delivers notifications and gives you a timestamp to compare against block time. Replace RPC_URL and the program ID with your own values, and confirm the discriminator against your pinned IDL before relying on it.
Run it for several minutes during active launch periods. If you see no notifications at all, the problem is connectivity or the filter, not your trading logic. If you see notifications but they arrive after the token already has trades, your detection path is too slow and you should test a different subscription or endpoint.
import { Connection, PublicKey } from '@solana/web3.js';
const RPC_URL = process.env.RPC_URL;
const PUMP_PROGRAM_ID = new PublicKey(process.env.PUMP_PROGRAM_ID);
const CREATE_DISCRIMINATOR = process.env.CREATE_DISCRIMINATOR; // from pinned IDL
const connection = new Connection(RPC_URL, { wsEndpoint: process.env.WS_URL });
connection.onLogs(PUMP_PROGRAM_ID, (logInfo) => {
const hit = logInfo.logs.some((line) => line.includes(CREATE_DISCRIMINATOR));
if (!hit) return;
console.log(JSON.stringify({
detectedAt: Date.now(),
signature: logInfo.signature,
err: logInfo.err
}));
}, 'confirmed');
console.log('listening for Pump.fun create events');Decoding the launch and building the buy transaction
Once you have a signature, fetch the transaction with getTransaction using jsonParsed or base64 encoding, then decode the instruction data with the Pump.fun IDL. You need the mint address, the bonding-curve account, and the associated token accounts the buy instruction expects. Do not guess account order: derive it from the IDL and the fetched transaction's account keys.
The buy transaction itself is a normal Solana transaction with a compute budget instruction, a priority fee, and the program's buy instruction. Set the compute unit limit from a simulation rather than a fixed guess, and set the priority fee from recent network conditions. Slippage tolerance belongs in the instruction arguments where the program supports it; otherwise enforce it in your own pre-trade check against the bonding-curve state.
- Simulate first with simulateTransaction to catch account or slippage errors before spending fees.
- Add ComputeBudgetProgram.setComputeUnitLimit and setComputeUnitPrice explicitly.
- Sign locally; never send a private key to an RPC provider.
- Track the signature with a confirmation strategy that distinguishes processed, confirmed, and finalized.
Runnable transaction submission with priority fee
This Python sketch shows the shape of a submission path: build the transaction, simulate, set a compute unit price, sign, and send with a retry loop. It uses placeholders for the program instruction because the exact accounts come from your decoded launch. The important engineering detail is that the send path is idempotent per launch and logs every attempt with a timestamp.
Keep the retry bounded. Rebroadcasting the same signed transaction is safe until its blockhash expires; rebuilding with a new blockhash and a higher fee is a different decision that should be logged separately so your measurement data stays clean.
import os, time, json
from solana.rpc.api import Client
from solana.rpc.commitment import Confirmed
from solana.transaction import Transaction
from solders.keypair import Keypair
from solders.compute_budget import set_compute_unit_limit, set_compute_unit_price
RPC_URL = os.environ['RPC_URL']
client = Client(RPC_URL)
payer = Keypair.from_base58_string(os.environ['PRIVATE_KEY'])
def submit(build_ix, cu_limit=200_000, micro_lamports=50_000, attempts=3):
for attempt in range(attempts):
tx = Transaction()
tx.add(set_compute_unit_limit(cu_limit))
tx.add(set_compute_unit_price(micro_lamports))
tx.add(build_ix())
tx.recent_blockhash = client.get_latest_blockhash(Confirmed).value.blockhash
tx.sign(payer)
sim = client.simulate_transaction(tx)
if sim.value.err:
print(json.dumps({'attempt': attempt, 'simErr': str(sim.value.err)}))
return None
sent = client.send_raw_transaction(tx.serialize())
print(json.dumps({'attempt': attempt, 'sentAt': time.time(), 'sig': str(sent.value)}))
time.sleep(0.2)
return NoneMeasuring detection and landing latency yourself
Vendor pages quote execution times in milliseconds, but those numbers are not comparable across bots, regions, or network conditions. Build your own harness instead. For each launch you detect, record four timestamps: the block time of the launch transaction, the time your detection callback fired, the time you submitted, and the confirmation time of your buy. The difference between block time and detection is your detection delay; between submission and confirmation is your landing delay.
Run at least a few dozen launches across different times of day and record the results in a table like the one below. Leave the cells empty until you have real data; do not fill them with estimates. Aggregate median and 90th percentile rather than mean, because latency distributions are skewed by outliers.
| Launch signature | Block time | Detected at | Submitted at | Confirmed at | Detection delay (ms) | Landing delay (ms) | Fill vs. first trade |
|---|---|---|---|---|---|---|---|
| (your run) |
- Use the same clock source for all timestamps; NTP-synced hosts only.
- Record failed and dropped submissions as their own rows, not as missing data.
- Compare fill price against the first trade in the same slot to judge whether you were early or late.
Expected verification results
A correctly wired detection loop produces a steady stream of create events during active periods, each with a signature you can look up on a Solana explorer. A correctly built transaction simulates without error and returns a signature on submission. A correctly measured run produces a table with non-empty timestamps and a mix of landed and failed attempts, which is normal in competitive launches.
If your detection loop is silent, check the WebSocket endpoint separately from the HTTP endpoint; many providers expose them on different hosts. If simulations fail with account errors, your IDL or account derivation is stale. If submissions return signatures but never confirm, your priority fee is likely below the current market and your blockhash may be expiring before inclusion.
Troubleshooting common failure modes
Most sniper bot failures fall into four buckets: detection, decoding, landing, and accounting. Detection failures look like silence or late events. Decoding failures look like account-not-found or invalid-instruction errors during simulation. Landing failures look like sent-but-unconfirmed signatures. Accounting failures look like trades that landed but were not recorded, which corrupts your measurement data.
Work through them in that order. Confirm the subscription delivers anything at all, then confirm the IDL matches the on-chain program, then tune fees and retry behavior, then reconcile your logs against on-chain history. Skipping to fee tuning while detection is broken produces misleading conclusions about endpoint performance.
- Silent subscription: verify WS_URL, program ID, and that the endpoint permits subscriptions.
- Simulation account errors: refresh the IDL and re-derive bonding-curve and token accounts.
- Sent but unconfirmed: raise compute unit price, refresh blockhash, and check slot status.
- Missing records: reconcile signatures against getSignaturesForAddress for your wallet.
Limitations, tradeoffs, and risk controls
Sniping is a negative-sum race at the margin: every participant's speed advantage is relative, and improvements in detection or fees are quickly matched. A bot that lands reliably still faces adverse selection, because the launches you win are often the ones other bots declined. Treat any strategy as experimental and cap exposure per launch and per day in code, not in discipline.
Operationally, earlier data costs more and breaks more often. Shred-level streams require custom parsing and tolerate unfinalized data, so your bot must handle rollbacks. Log subscriptions are simpler but slower. Choose based on measured detection delay for your workload, not on marketing claims. For capacity and endpoint choices, the dedicated node overview and the RPC endpoint guide explain the tradeoffs between shared and dedicated infrastructure.
- Hard caps on position size and daily spend enforced in the signing path.
- A kill switch that stops submissions when error rates exceed a threshold.
- Separate wallets for experimentation and for any capital you care about.
- Regular re-verification of the program IDL after upgrades.
Next steps
Once detection and submission are stable, the highest-leverage improvements are measurement discipline and infrastructure placement. Run the latency harness weekly, keep the results table, and change one variable at a time: endpoint, region, subscription type, or fee policy. That turns tuning from guesswork into an experiment.
For the concrete endpoint decision, hand off to RPC Assistant rather than copying a provider name from a listicle. If you are still choosing a network or planning capacity, review the supported networks and the RPC pricing tiers, and consider a dedicated node if your measurement shows shared endpoints are the bottleneck.
- Read the best Solana RPC provider guidance for endpoint selection.
- Review Solana devnet guidance before testing strategies off mainnet.
- Compare shared and dedicated capacity on the pricing page.
- Keep your measurement table versioned alongside your bot configuration.