NoLimitNodes
PricingDocsBlogAbout
SupportContact
Log in
Blog/Guides

Crypto Domination: Create a Trading Bot for Pump.fun That Knows When to Buy and Sell

A single-file Python bot that watches every Pump.fun launch, tracks live trades over WebSocket, and applies entry, take-profit, and stop-loss rules automatically. The capstone of our Pump.fun series.

N
NoLimitNodes Team
Community & Tutorials
Jan 29, 2025updated Jun 9, 202611 min read
On this page +
  • 01What we're building
  • 02What you need
  • 03Get an API key
  • 04How the WebSocket API works
  • 05Setting up the script
  • 06The trading logic
  • 07Running both sockets
  • 08Where to take it from here

This is the most requested follow-up to our Pump.fun WebSocket series: a bot that watches every new token launch, tracks the trades that follow, and decides when to buy and when to get out. We'll build it in Python, in one file, using two WebSocket subscriptions and three price thresholds. By the end you'll have a running signal engine you can extend into a real trading system.

01What we're building#

The bot does three things. It subscribes to Pump.fun coin creation events, so it knows about every token the moment it launches. It subscribes to the trade stream for all coins, so it sees every buy and sell as it happens. And it runs simple position logic on top: when a tracked coin trades at or above your entry price, it registers a buy; from there it watches for either a take-profit or a stop-loss and prints the exit.

One thing worth being upfront about: this version signals trades, it doesn't sign them. The printed BUY and SELL lines are where you'd wire in an actual swap if you want to trade with real funds. Keeping the detection logic separate from execution is also just good practice. You can paper-trade the strategy for a week and see how it behaves before risking a single lamport.

02What you need#

  • Python 3.x. Any recent version works. If you're somehow still on 2.x, this is your sign to upgrade.
  • The websocket-client package (pip install websocket-client).
  • A NoLimitNodes API key, which is free. That's next.

03Get an API key#

Head to nolimitnodes.com and click Start Building to create an account. A token is generated for you by default, and you can create another one from the dashboard with the Get button. Copy it somewhere handy; every connection in this guide uses it.

TIP / new to the WebSocket API?
If you haven't made a WebSocket connection to our API before, the earlier post in this series, Build a Real-Time Crypto Trading Bot with NoLimitNodes Price Data, walks through connecting and validating responses step by step.

04How the WebSocket API works#

Before writing any Python, it helps to see the raw requests and responses. Everything goes through one endpoint:

wss://api.nolimitnodes.com/pump-fun?api_key=YOUR_API_KEY

With the socket open, you subscribe to coin creation events by sending this:

subscribe: new coins
json
{
    "method": "pumpFunCreateEventSubscribe",
    "params": {
        "eventType": "coin",
        "referenceId": "litrally-anything-here-to-use-as-reference"
    }
}

The server confirms the subscription:

confirmation
json
{
    "status": "Create Event Subscribed",
    "subscription_id": "9c37a3e8-d39b-497c-902d-162e19a0bcda",
    "reference_id": "litrally-anything-here-to-use-as-reference"
}

From then on you receive a live stream of coins as they're created. Each event carries the mint address, the bonding curve accounts, the creator's wallet, and the metadata URI:

createEventNotification
json
{
  "method": "createEventNotification",
  "result": {
    "metadata": {
      "network": "solana",
      "chain": "mainnet-beta",
      "block": "308709941"
    },
    "timestamp": "1734713628",
    "name": "TRUMPCOIN",
    "symbol": "TRUMPCOIN",
    "uri": "https://ipfs.io/ipfs/QmSSme2anrzV4NWrofS3uzXTq9B1L5Jxy54FgvPcrAsrhe",
    "mint": "CWVtv9SQMVibEqzFBLy5FZdLhozzZzRDBbX9HGnypump",
    "bondingCurve": "HZzaNo92zpqqyTb3pBr5P9fAJ7GT9xnSAxygWLbgUV7X",
    "associatedBondingCurve": "BnNAk9AtBvQS3vmv9UpkEoAqPAC96PMUig9HtMdJescU",
    "creator_wallet": {
      "address": "91U3uKcD2EuC7eW8bbBtC7ftwrNpmgGmJQFpgBZbaBAB"
    },
    "event_type": "create_coin"
  },
  "subscription_id": "litrally-anything-here-to-use-as-reference"
}

Trades work the same way, over the same endpoint. To follow a single coin, pass its address:

subscribe: trades for one coin
json
{
    "method": "pumpFunTradeSubscribe",
    "params": {
        "coinAddress": "abcxxx...pump",
        "referenceId": "REF#1"
    }
}

To follow every coin on the platform at once, pass "all":

subscribe: all trades
json
{
    "method": "pumpFunTradeSubscribe",
    "params": {
        "coinAddress": "all",
        "referenceId": "REF#1"
    }
}
NOTE / referenceId
The referenceId is just a string you choose. It comes back in the confirmation so you can match responses to the requests that caused them. Use anything you like.

After the confirmation:

confirmation
json
{
  "status": "Trade Subscribed",
  "subscription_id": "9d4a3756-f3de-464d-ae05-c36297984f90",
  "reference_id": "REF#1"
}

you'll get a continuous stream of tradeEventNotification messages. Note the parts our bot will care about: token_out.token (which coin was traded) and price.sol (what it traded at):

tradeEventNotification
json
{
  "method": "tradeEventNotification",
  "result": {
    "metadata": {
      "network": "solana",
      "chain": "mainnet-beta",
      "block": "308693304"
    },
    "timestamp": 1734706766,
    "type": "Buy",
    "price": { "sol": "0.0000000780" },
    "token_in": {
      "token": "So11111111111111111111111111111111111111112",
      "amount": 21340983
    },
    "token_out": {
      "token": "4HTXweoVWfRdXTpvrWCctdED6KUi7Ah1aGq76ubMpump",
      "amount": 273799880742
    },
    "wallet": {
      "address": "BNArZsgokea5BxYzhzB9BKqhz7C54fYWkL7CPSPCMP8X"
    }
  },
  "subscription_id": "9d4a3756-f3de-464d-ae05-c36297984f90"
}

05Setting up the script#

Open your editor of choice (I use PyCharm) and create trading_bot_pumpFun.py. Three imports cover everything:

trading_bot_pumpFun.py
python
import websocket
import json
import threading

Next, the three numbers that define the whole strategy. Prices on Pump.fun are tiny because supply is huge, so don't let the zeros throw you:

thresholds + endpoint
python
## Variables
buyPrice =        float(0.0000001000)  # entry threshold
takeProfitPrice = float(0.0000001500)  # exit with profit
stopLossPrice =   float(0.0000000800)  # exit with a controlled loss

url1 = "wss://api.nolimitnodes.com/pump-fun?api_key=YOUR_API_KEY"

The logic these encode: buy when a tracked coin trades at buyPrice or better, take profit at 50% above entry, and cut the loss if price drops 20% below entry. Tune all three to your own appetite.

Then the two subscription messages from earlier, as Python dicts:

subscriptions
python
# Subscription messages
subscribe_new_coin = {
    "method": "pumpFunCreateEventSubscribe",
    "params": {
        "eventType": "coin",
        "referenceId": "hello" # your unique reference id
    }
}

subscribe_pump_fun_trade = {
    "method": "pumpFunTradeSubscribe",
    "params": {
        "referenceId": "hello", # your unique reference id
        "coinAddress": "all"
    }
}

Finally, two dictionaries to hold state. buyDict is the watchlist: every newly created coin lands here. sellDict holds coins we've "bought" and are now managing toward an exit. Both are keyed by mint address:

state
python
## Dictionaries to store data
buyDict = {}   # Key: mint address, Value: coin details
sellDict = {}  # Key: mint address, Value: coin details

06The trading logic#

Two message handlers do the actual work. The first one is simple: every time a coin is created, add it to the watchlist.

The second is the interesting one. For every trade on the network, it checks whether the coin is on our watchlist and whether the price satisfies the entry condition. If so, the coin moves from buyDict to sellDict and we print the buy. For coins we already hold, it checks the exits: take-profit hit, stop-loss hit, or neither.

handlers
python
1def on_message_new_coin(ws, message):
2    global buyDict
3    data = json.loads(message)
4
5    if data.get("method") == "createEventNotification":
6        coin_details = data["result"]
7        coin_mint = coin_details["mint"]
8        coin_name = coin_details["name"]
9        coin_symbol = coin_details["symbol"]
10
11        # Add coin to buyDict if it's not already there
12        if coin_mint not in buyDict:
13            buyDict[coin_mint] = {
14                "name": coin_name,
15                "symbol": coin_symbol,
16                "details": coin_details
17            }
18
19
20def on_message_transaction(ws, message):
21    global buyDict, sellDict
22    data = json.loads(message)
23
24    if data.get("method") == "tradeEventNotification":
25        trade_details = data["result"]
26        trade_token_out = trade_details["token_out"]["token"]
27        trade_price = float(trade_details["price"]["sol"])
28
29        # Handle buy condition
30        if ((trade_token_out in buyDict) and (trade_price >= buyPrice) and (trade_price < takeProfitPrice)):
31            coin = buyDict.pop(trade_token_out)
32            sellDict[trade_token_out] = coin
33            print(f"BUY  -  Condition met      : [{coin['symbol']}] at price [{trade_price:.10f}] (Address: {trade_token_out})")
34
35        # Handle sell conditions
36        else:
37            if trade_token_out in sellDict:
38                coin = sellDict[trade_token_out]
39
40                if buyPrice <= trade_price < takeProfitPrice:
41                    print(f"SELL -  Target Achieved    : [{coin['symbol']}] at TakeProfit Price [{trade_price:.10f}] (Address: {trade_token_out})")
42                    del sellDict[trade_token_out]
43                elif trade_price < stopLossPrice:
44                    print(f"SELL -  Stop loss triggered: [{coin['symbol']}] at StopLoss Price [{trade_price:.10f}] (Address: {trade_token_out})")
45                    del sellDict[trade_token_out]
46                else:
47                    del sellDict[trade_token_out]
48
49def on_error(ws, error):
50    print(f"Error: {error}")
51
52def on_close(ws, close_status_code, close_msg):
53    print("WebSocket closed")
54
55def on_open_new_coin(ws):
56    print("New coin webSocket connection opened")
57    ws.send(json.dumps(subscribe_new_coin))
58    print(f"Subscription message sent (WS1): {subscribe_new_coin}")
59
60def on_open_transcation(ws):
61    print("Transaction webSocket connection opened")
62    ws.send(json.dumps(subscribe_pump_fun_trade))
63    print(f"Subscription message sent (WS2): {subscribe_pump_fun_trade}")
WARNING / this state lives in memory
Both dictionaries vanish when the process dies. If the bot restarts mid-position, it forgets what it was holding. For anything beyond experimentation, persist sellDict to disk or a database so a restart can pick up where it left off.

07Running both sockets#

A small helper builds and runs a WebSocketApp with the right callbacks:

connection helper
python
## Function to create and run a WebSocket connection
def run_websocket(url, on_open, on_message):
    ws = websocket.WebSocketApp(
        url,
        on_message=on_message,
        on_error=on_error,
        on_close=on_close
    )
    ws.on_open = on_open
    ws.run_forever()

The coin stream and the trade stream are two separate connections, and both need to run at the same time, so each gets its own thread:

run it
python
## Run both WebSockets in parallel using threading
thread_new_coin = threading.Thread(target=run_websocket, args=(url1, on_open_new_coin, on_message_new_coin))
thread_transaction = threading.Thread(target=run_websocket, args=(url1, on_open_transcation, on_message_transaction))

thread_new_coin.start()
thread_transaction.start()

thread_new_coin.join()
thread_transaction.join()

Run the script and you'll see both connections open, the two subscription confirmations, and then the output starts flowing: new coins joining the watchlist silently, BUY lines as entries trigger, and SELL lines as positions resolve one way or the other.

08Where to take it from here#

What you have now is an engine that:

  • Knows about every Pump.fun launch within moments of it happening
  • Tracks live prices for every coin on the platform over a single connection
  • Applies entry, take-profit, and stop-loss rules automatically

The obvious next steps are the ones that turn signals into a real system: wire the BUY and SELL prints into actual swap execution, persist state across restarts, and add reconnect logic so a dropped socket doesn't take the bot down with it. The rest of the series covers smarter exit strategies like trailing stop-losses and drawdown-based entries if you want to push the strategy further.

///

A closing word of caution, because it matters: meme coin markets are brutal, and a bot that buys every new launch will buy a lot of garbage. Thresholds alone are not a strategy. Treat this as infrastructure for testing your own ideas, paper-trade it before funding it, and never risk money you can't afford to lose.

///Related resources
Enhanced Streams

Decoded Solana events for bots, dashboards, and analytics.

PumpFun data

Launches, trades, graduations, and creator-wallet signals.

Solana RPC nodes

Private Solana RPC endpoints for builders and trading systems.

Yellowstone gRPC nodes

Low-latency real-time Solana streams over gRPC.

#pumpfun#websocket#trading#python#tutorial
N
NoLimitNodes Team
Community & Tutorials

Tutorials, market notes, and product walkthroughs from across the NoLimitNodes team.

On this page
  • 01What we're building
  • 02What you need
  • 03Get an API key
  • 04How the WebSocket API works
  • 05Setting up the script
  • 06The trading logic
  • 07Running both sockets
  • 08Where to take it from here
↑ back to top
///Read next
GuidesJun 19, 2026

Yellowstone gRPC in Python (2026): Setup, 5 Core Patterns & a Real-Time PumpFun Detector

A complete Python guide to Yellowstone gRPC: proto generation, a reusable auth helper, five working patterns from wallet watcher to memcmp filter, a full PumpFun token-launch detector, and production reconnect with exponential backoff.

#yellowstone#grpc#python
18 min read
GuidesMay 19, 2026

Yellowstone gRPC vs WebSockets: choosing a real-time Solana data pipeline

Both transports stream the same chain, but they come from different places inside the validator and fail in different ways. A field guide to choosing and operating the right pipeline for your workload.

#yellowstone#grpc#websocket
16 min read
← Older
Pump.fun WebSocket Tutorial: Master Drawdown Strategies for Maximizing Pullback Gains
Newer →
Pump.fun WebSocket Guide: Build a Crypto Trading Bot for Popular Coins
Run it yourself

Every benchmark in this blog runs against our public endpoints.

Spin up an RPC, WebSocket, or gRPC endpoint in under a minute. Flat pricing, no request caps. Reproduce the numbers for your own workload.

See pricing

Ready to get started?

Get your free API key and start building in under 30 seconds.

Talk to Sales
NoLimitNodes

Solana RPC infrastructure built for performance and scale.

RPC Access
  • HTTP RPC
  • WebSocket
  • gRPC
Infrastructure
  • Compute Platform
  • VPS
  • VDS
  • Bare Metal
  • Geyser Plugin Hosting
Enhanced Streams
  • PumpFun
  • PumpSwap
  • Raydium
  • Orca
  • Meteora
  • System Events
  • Browse All →
Program Streams
  • PumpFun
  • PumpSwap
  • Raydium CLMM
  • Orca Whirlpool
  • Meteora DLMM
  • Jupiter Swap
  • Jupiter Perps
  • Kamino Lending
  • Browse All 37 →
Trading
  • EZWallet
Analytics
  • Historical Datasets
  • Historical Raw Blocks
Company
  • About
Resources
  • Pricing
  • Custom Development
  • Documentation
  • Blog
  • Support
  • Contact Sales
Compare
  • Yellowstone gRPC vs LaserStream
  • Triton vs Helius
  • Raydium API vs Helius
  • PumpSwap API vs Bitquery
  • QuickNode Streams vs NLN
  • All comparisons →
Legal
  • Terms & Conditions
  • Privacy Policy
© 2026 CLR3 Inc., operating as NoLimitNodes. Registered in Ontario, Canada. All rights reserved.solana mainnet