You don't need a computer science degree to build a Kalshi trading bot. You need Python, an API key, and about an hour. This tutorial takes you from zero to a working bot that monitors markets and places trades automatically — with real code you can run today.

By the end of this guide, you'll have a Python bot that authenticates with Kalshi, fetches market data, evaluates a simple strategy, and places orders. We'll build it step by step, explaining every line.

Prerequisites

  • Python 3.9+ installed on your machine
  • A Kalshi account with API access enabled
  • Your Kalshi API key (key ID + secret) from your account settings
  • Basic Python knowledge (variables, functions, loops)

If you've never used Python, this tutorial will still work — but consider running through a quick Python basics course first. If you'd rather skip coding entirely, our no-code bot builder lets you create bots visually.

Project Setup

Create a new project directory and install the required packages:

mkdir kalshi-bot && cd kalshi-bot
python3 -m venv venv
source venv/bin/activate
pip install requests python-dotenv

Create a .env file for your credentials (never hardcode API keys):

KALSHI_API_KEY_ID=your-key-id-here
KALSHI_API_KEY_SECRET=your-key-secret-here
KALSHI_BASE_URL=https://api.elections.kalshi.com/trade-api/v2

Step 1: Authentication

Kalshi uses API key authentication. Here's a clean client class that handles auth and request signing:

import os
import time
import requests
from dotenv import load_dotenv

load_dotenv()

class KalshiClient:
    def __init__(self):
        self.base_url = os.getenv("KALSHI_BASE_URL")
        self.key_id = os.getenv("KALSHI_API_KEY_ID")
        self.key_secret = os.getenv("KALSHI_API_KEY_SECRET")
        self.session = requests.Session()

    def _headers(self):
        # Kalshi uses key-based auth headers
        return {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.key_id}:{self.key_secret}",
        }

    def get(self, path, params=None):
        url = f"{self.base_url}{path}"
        resp = self.session.get(url, headers=self._headers(), params=params)
        resp.raise_for_status()
        return resp.json()

    def post(self, path, data=None):
        url = f"{self.base_url}{path}"
        resp = self.session.post(url, headers=self._headers(), json=data)
        resp.raise_for_status()
        return resp.json()

Test your connection:

client = KalshiClient()
balance = client.get("/portfolio/balance")
print(f"Account balance: ${balance['balance'] / 100:.2f}")

If you see your balance printed, you're connected. If you get an auth error, double-check your API credentials in the .env file.

Step 2: Fetching Market Data

Let's fetch available markets and find one to trade:

def get_markets(client, status="open", limit=20):
    """Fetch open markets from Kalshi."""
    params = {"status": status, "limit": limit}
    data = client.get("/markets", params=params)
    return data.get("markets", [])

def find_market(client, ticker):
    """Fetch a specific market by ticker."""
    data = client.get(f"/markets/{ticker}")
    return data.get("market", {})

# Example: list some markets
markets = get_markets(client)
for m in markets[:5]:
    print(f"{m['ticker']}: {m['title']} — YES: {m.get('yes_ask', 'N/A')}¢")

Each market object contains the ticker, title, current prices (yes_bid, yes_ask, no_bid, no_ask), volume, and settlement details. The prices are in cents (1-99).

Step 3: Building a Simple Strategy

Let's build a simple mean-reversion strategy: when a market's YES price drops sharply (more than 10 cents below its recent average), we buy — betting that the drop is an overreaction.

class SimpleStrategy:
    def __init__(self, ticker, lookback=10, threshold=10, max_position=5):
        self.ticker = ticker
        self.threshold = threshold  # cents below average to trigger buy
        self.max_position = max_position  # max contracts to hold
        self.price_history = []
        self.lookback = lookback

    def update(self, yes_price):
        """Add a new price observation."""
        self.price_history.append(yes_price)
        if len(self.price_history) > self.lookback:
            self.price_history = self.price_history[-self.lookback:]

    def should_buy(self, current_price, current_position):
        """Return True if we should buy."""
        if len(self.price_history) < self.lookback:
            return False  # not enough data yet
        if current_position >= self.max_position:
            return False  # position limit reached
        avg = sum(self.price_history) / len(self.price_history)
        return current_price < (avg - self.threshold)

    def should_sell(self, current_price, entry_price):
        """Return True if we should take profit."""
        return current_price >= entry_price + 15  # take 15¢ profit

This is intentionally simple. The point isn't to run this strategy in production — it's to show the pattern. Your real strategy should be based on your own research and edge.

Step 4: Placing Orders

def place_order(client, ticker, side, quantity, price_cents, order_type="limit"):
    """Place an order on Kalshi.

    side: 'yes' or 'no'
    price_cents: price in cents (1-99)
    """
    order = {
        "ticker": ticker,
        "action": "buy",
        "side": side,
        "type": order_type,
        "count": quantity,
        "yes_price": price_cents if side == "yes" else None,
        "no_price": price_cents if side == "no" else None,
    }
    result = client.post("/portfolio/orders", data=order)
    print(f"Order placed: {side.upper()} x{quantity} @ {price_cents}¢")
    return result

Step 5: The Bot Loop

Now let's tie it all together into a bot that runs continuously:

import time

def run_bot(ticker, check_interval=30):
    """Main bot loop."""
    client = KalshiClient()
    strategy = SimpleStrategy(ticker, lookback=10, threshold=10, max_position=5)
    current_position = 0
    entry_price = None

    print(f"Bot started — watching {ticker}")
    print(f"Checking every {check_interval} seconds")

    while True:
        try:
            market = find_market(client, ticker)
            yes_price = market.get("yes_ask", 0)

            if yes_price == 0:
                print("Market closed or no price available")
                time.sleep(check_interval)
                continue

            strategy.update(yes_price)
            print(f"[{ticker}] YES: {yes_price}¢ | Position: {current_position}")

            # Check buy signal
            if strategy.should_buy(yes_price, current_position):
                print(f"BUY SIGNAL at {yes_price}¢")
                place_order(client, ticker, "yes", 1, yes_price)
                current_position += 1
                entry_price = yes_price

            # Check sell signal
            elif entry_price and strategy.should_sell(yes_price, entry_price):
                print(f"SELL SIGNAL at {yes_price}¢ (entry: {entry_price}¢)")
                place_order(client, ticker, "no", 1, 100 - yes_price)
                current_position -= 1
                if current_position == 0:
                    entry_price = None

        except Exception as e:
            print(f"Error: {e}")

        time.sleep(check_interval)

# Run the bot
if __name__ == "__main__":
    run_bot("YOUR-MARKET-TICKER-HERE")

Step 6: Adding Risk Controls

Never run a bot without risk controls. Here's a simple risk manager:

class RiskManager:
    def __init__(self, max_daily_loss=500, max_position_size=10):
        self.max_daily_loss = max_daily_loss  # cents
        self.max_position_size = max_position_size
        self.daily_pnl = 0

    def can_trade(self, position_size):
        if self.daily_pnl <= -self.max_daily_loss:
            print("RISK: Daily loss limit reached. Stopping.")
            return False
        if position_size >= self.max_position_size:
            print("RISK: Position limit reached.")
            return False
        return True

    def record_trade(self, pnl):
        self.daily_pnl += pnl

Integrate this into your bot loop by checking risk_manager.can_trade() before every order.

Running Your Bot

# Activate your virtual environment
source venv/bin/activate

# Run the bot
python bot.py

For production deployment tips (running 24/7), see our complete bot guide.

Next Steps

You now have a working Kalshi bot. Here's where to go from here:

Or skip the coding entirely:

Build Bots Without Code

Our visual bot builder lets you create the same multi-step strategies — without writing Python.

Try Bot for Kalshi Free →

PC

Priya Chakraborty

Lead Developer & Technical Writer

Priya Chakraborty is Lead Developer at Bot for Kalshi. A former backend infrastructure engineer at Stripe, she now builds automated trading systems that process 10,000+ daily market signals across prediction markets.