Tutorial · Kalshi · Python

How to Build a Kalshi Trading Bot with Python (2026 Guide)

Published May 20, 2026 · 14 min read · By WatchDog Bot Team

Kalshi is the first regulated prediction market in the United States — a CFTC-registered exchange where you can trade event contracts on everything from elections to weather to economic indicators. This guide shows you how to build a fully working Python trading bot that connects to Kalshi, fetches market data, places orders, and runs unattended 24/7.

What you'll build

  1. Prerequisites & account setup
  2. Authenticating with the Kalshi API
  3. Fetching market data
  4. Your first trading bot (full code)
  5. Placing and managing orders
  6. Deploying with WatchDog Bot (the easy way)
  7. Handling errors, dependencies & uptime
  8. Where to go from here

1. Prerequisites & account setup

Before writing any code, you'll need three things:

One-time tip: Kalshi's API uses RSA-PSS signed requests, not bearer tokens. This is more secure but adds a small wrinkle compared to most REST APIs. Don't worry — the code below handles it for you.

2. Authenticating with the Kalshi API

Every authenticated Kalshi request needs four headers:

Here's a minimal, copy-paste auth helper:

# kalshi_client.py
import time, base64
from pathlib import Path
import requests
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding

BASE_URL = "https://api.elections.kalshi.com/trade-api/v2"

class KalshiClient:
    def __init__(self, access_key, private_key_path):
        self.access_key = access_key
        self.private_key = serialization.load_pem_private_key(
            Path(private_key_path).read_bytes(), password=None
        )

    def _sign(self, method, path):
        ts = str(int(time.time() * 1000))
        msg = (ts + method + path).encode()
        sig = self.private_key.sign(
            msg,
            padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.DIGEST_LENGTH),
            hashes.SHA256(),
        )
        return ts, base64.b64encode(sig).decode()

    def _headers(self, method, path):
        ts, sig = self._sign(method, path)
        return {
            "KALSHI-ACCESS-KEY": self.access_key,
            "KALSHI-ACCESS-TIMESTAMP": ts,
            "KALSHI-ACCESS-SIGNATURE": sig,
            "Content-Type": "application/json",
        }

    def get(self, path, params=None):
        r = requests.get(BASE_URL + path, headers=self._headers("GET", path), params=params, timeout=10)
        r.raise_for_status()
        return r.json()

    def post(self, path, body):
        r = requests.post(BASE_URL + path, headers=self._headers("POST", path), json=body, timeout=10)
        r.raise_for_status()
        return r.json()

Save that as kalshi_client.py. Test it with a quick balance check:

from kalshi_client import KalshiClient

client = KalshiClient(
    access_key="YOUR_ACCESS_KEY",
    private_key_path="./private_key.pem"
)
print(client.get("/portfolio/balance"))
# {'balance': 100000, 'payout': 0}  # cents

3. Fetching market data

Markets on Kalshi are organized as events (a question) containing one or more markets (the YES/NO contracts you actually trade). Each market has a unique ticker.

# List open markets in the weather series
markets = client.get("/markets", params={"series_ticker": "KXHIGHNY", "status": "open"})
for m in markets["markets"][:5]:
    print(f"{m['ticker']:30}  YES bid {m['yes_bid']:>3}  YES ask {m['yes_ask']:>3}")

# Get a specific market's full orderbook
ob = client.get("/markets/KXHIGHNY-26MAY20-T75/orderbook")
print(ob)

Prices on Kalshi are in cents (1–99), representing the implied probability of YES. A market at 73¢ implies the market thinks YES has a 73% chance.

4. Your first trading bot — full working code

Here's a complete, runnable bot that monitors a weather market and buys YES when the price drops below your threshold. It's intentionally simple — the goal is to see the full loop end to end.

# my_first_bot.py
import time
from kalshi_client import KalshiClient

ACCESS_KEY = "YOUR_ACCESS_KEY"
PRIVATE_KEY_PATH = "./private_key.pem"
MARKET_TICKER = "KXHIGHNY-26MAY20-T75"
BUY_BELOW = 40   # buy YES if price drops below 40 cents
MAX_CONTRACTS = 10
POLL_SECONDS = 30

def run():
    client = KalshiClient(ACCESS_KEY, PRIVATE_KEY_PATH)
    bought = 0

    while bought < MAX_CONTRACTS:
        try:
            market = client.get(f"/markets/{MARKET_TICKER}")["market"]
            ask = market["yes_ask"]
            print(f"[{time.strftime('%H:%M:%S')}] YES ask = {ask}  target < {BUY_BELOW}")

            if ask > 0 and ask < BUY_BELOW:
                order = client.post("/portfolio/orders", {
                    "ticker": MARKET_TICKER,
                    "action": "buy",
                    "side": "yes",
                    "count": 1,
                    "type": "limit",
                    "yes_price": ask,
                    "client_order_id": f"bot-{int(time.time())}",
                })
                print(f"  BOUGHT 1 YES at {ask}  order id: {order['order']['order_id']}")
                bought += 1
        except Exception as e:
            print(f"  ! error: {e}")

        time.sleep(POLL_SECONDS)

    print(f"Done — bought {bought} contracts")

if __name__ == "__main__":
    run()

That's a complete, working trading bot in ~40 lines. Run it locally with python my_first_bot.py and watch it tick.

Important: Test with tiny sizes first (MAX_CONTRACTS = 1) until you're confident in the logic. Real money moves on every order.

5. Placing and managing orders

The order API supports limit and market orders, plus the full portfolio lifecycle:

# Place a limit order
client.post("/portfolio/orders", {
    "ticker": "KXHIGHNY-26MAY20-T75",
    "action": "buy",          # or "sell"
    "side": "yes",            # or "no"
    "count": 5,
    "type": "limit",          # or "market"
    "yes_price": 42,          # cents
    "client_order_id": "my-order-1",
})

# List your open orders
open_orders = client.get("/portfolio/orders", params={"status": "resting"})

# Cancel an order via DELETE on /portfolio/orders/{order_id}
# Check positions
positions = client.get("/portfolio/positions")

6. Deploying with WatchDog Bot (the easy way)

Running python my_first_bot.py on your laptop works fine — until you close the lid, your laptop sleeps, or the bot crashes at 3 AM because cryptography wasn't installed in the right environment. This is where most beginner traders give up.

WatchDog Bot solves this. Paste your bot code into WatchDog Bot and:

The bot above, ported to WatchDog Bot's built-in SDK, becomes this:

import time
import wd  # built-in WatchDog SDK — no install needed

# Pull credentials from the encrypted connection store
conn = wd.connection("Kalshi")
ACCESS_KEY = conn.api_key
PRIVATE_KEY = conn.api_secret  # PEM string

# ...rest of your bot code, using wd.log.info(...) for structured logging
wd.log.info("Bot started, watching %s", MARKET_TICKER)

That's it — no credentials in code, structured logs that show up in the dashboard, and the bot reconnects automatically if Kalshi's API hiccups.

7. Handling errors, dependencies & uptime

Three things kill more trading bots than bad strategy combined: missing dependencies, crashed processes, and silent errors. Here's how to handle each.

Missing dependencies

The single most common bot failure mode: ModuleNotFoundError: No module named 'cryptography'. WatchDog Bot v1.1.13+ catches this, runs uv pip install cryptography in your bot's isolated venv, and retries up to 3 times. You never see the error.

Crashed processes

Wrap the main loop in a top-level try/except and restart on any non-fatal exception:

while True:
    try:
        run_one_iteration()
    except Exception as e:
        wd.log.error("iteration failed: %s — retrying in 60s", e)
        time.sleep(60)

Silent errors

Always log key actions with structured fields. WatchDog's log dashboard lets you filter on level, message, and time — silent bugs are visible bugs.

8. Where to go from here

You now have a working Kalshi bot. The hard part is over. From here, the interesting questions are strategic, not technical:

The bot is the easy part. The strategy is everything.

Ready to ship your Kalshi bot?

WatchDog Bot is the trading bot platform built for Python developers. Free trial, no credit card. Your bot up and running in under 5 minutes.

Start Free Trial →