TBO Broker Directory
Source-backed broker research. High-risk products are marked clearly.
Prediction market bots14 min readNot investment advice

How to build a trading bot for Polymarket

A practical guide to building a prediction-market bot: how to read Polymarket markets, design a safe execution loop, host the worker, and adapt the same architecture to Kalshi and Pariflow.

Core APIsGamma + CLOB
Best host typeWorker/VPS
Go-live rulePaper first

Before you automate trades

Prediction markets can be illiquid, volatile, restricted by geography, and sensitive to settlement rules. Build read-only first, then paper trade, then use tiny live limits.

  • Never store private keys in frontend code.
  • Add a manual kill switch from day one.
  • Log every skipped and placed order.

Step 1

Understand the Polymarket API layers

A solid Polymarket bot usually separates market discovery from order execution. The Gamma Markets API is useful for finding markets, events, metadata, descriptions, and close dates. The CLOB layer is where a trading bot reads order books, tracks trades, and works with order operations.

Gamma API

Use it to discover markets and enrich your database before deciding what is tradable.

CLOB API

Use it for order book data, prices, trades, order placement, cancels, and account-level execution flows.

WebSocket feeds

Use streaming updates when polling is too slow for your strategy or market-making logic.

Practical rule

Keep API adapters thin. Your strategy should not know whether prices came from Polymarket, Kalshi, or Pariflow. It should receive normalized markets, books, positions, and fills.

Step 2

Design the bot like a small trading system

The common mistake is writing one script that fetches a market, guesses a price, and immediately trades. That works in demos and fails in production. Use a small architecture with explicit boundaries.

Market scanner

Find active markets, filter by liquidity, spread, close time, category, and whether the market is still worth trading.

Signal engine

Estimate a fair probability from your model, external data, or cross-venue prices, then compare it with the live order book.

Risk engine

Cap exposure per market, total daily loss, order size, stale quotes, and repeated cancel-replace loops.

Execution engine

Place, cancel, or skip orders through the venue API. Keep this small, logged, and easy to disable.

State store

Persist markets, orders, fills, positions, signals, and errors so the bot can restart without forgetting risk.

Monitoring

Send health checks and alerts to Slack, Telegram, email, or your dashboard before a small issue becomes expensive.

Step 3

Build the first Polymarket bot

01

Pick one narrow strategy

Start with one behavior: spread alerts, passive market making, cross-venue monitoring, or position risk alerts. Avoid a bot that tries to trade every category on day one.

02

Create a worker project

Use TypeScript or Python. TypeScript is convenient if your dashboard is already Next.js, but Python is also common for research. The important part is separating the always-on worker from the public site.

.env.example
POLYMARKET_PRIVATE_KEY="0x..."
POLYMARKET_FUNDER_ADDRESS="0x..."
POLYMARKET_HOST="https://clob.polymarket.com"
DATABASE_URL="postgresql://..."
BOT_MODE="paper"
MAX_ORDER_USD="25"
MAX_DAILY_LOSS_USD="100"
ALERT_WEBHOOK_URL="https://hooks.slack.com/..."
03

Fetch markets from Gamma

Cache market metadata locally. It gives your bot stable IDs, close times, descriptions, and category context before it touches an order book.

market-discovery.ts
type PolymarketMarket = {
  id: string
  question: string
  slug?: string
  active?: boolean
  closed?: boolean
  endDate?: string
}

export async function findMarkets(query: string) {
  const url = new URL("https://gamma-api.polymarket.com/markets")
  url.searchParams.set("closed", "false")
  url.searchParams.set("limit", "20")
  url.searchParams.set("q", query)

  const response = await fetch(url)
  if (!response.ok) throw new Error(`Gamma API failed: ${response.status}`)

  const markets = (await response.json()) as PolymarketMarket[]
  return markets.filter((market) => market.active && !market.closed)
}
04

Normalize books and signals

Convert venue-specific data into one internal shape. The strategy should compare your fair value with best bid, best ask, spread, size, and last update time.

05

Run a risk gate before execution

Every signal should pass a risk gate. Check max order size, total exposure, market age, spread, daily loss, stale data, and whether the same market already has open orders.

bot-loop.ts
type Signal = {
  marketId: string
  tokenId: string
  side: "BUY" | "SELL"
  limitPrice: number
  sizeUsd: number
  reason: string
}

export async function runBotTick() {
  const markets = await scanner.findLiquidMarkets()

  for (const market of markets) {
    const book = await orderbooks.get(market.tokenId)
    const signal = await strategy.evaluate({ market, book })

    if (!signal) continue
    if (!risk.canTrade(signal)) {
      await logger.info("signal_skipped", { signal, reason: "risk_limit" })
      continue
    }

    if (process.env.BOT_MODE === "paper") {
      await paperBroker.record(signal)
      continue
    }

    await execution.placeLimitOrder(signal)
  }
}
06

Paper trade before live mode

Let the bot record hypothetical fills for several days. Compare paper results with realistic fill assumptions, not just mid-price screenshots.

Step 4

Host the bot as an always-on worker

A trading bot is usually a background service, not a web page. The dashboard can live on Vercel, but the bot loop should run somewhere designed for long-lived processes and WebSockets.

VPS or Docker host

Best when you want predictable uptime, direct logs, Docker Compose, and full control over secrets.

Managed workers

Fly.io, Railway, Render workers, Cloud Run jobs, or similar platforms can run a worker plus health checks.

Dockerfile
FROM node:22-slim AS base
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .

CMD ["node", "dist/worker.js"]
docker-compose.yml
services:
  polymarket-bot:
    build: .
    restart: unless-stopped
    env_file: .env
    depends_on:
      - postgres

  postgres:
    image: postgres:16
    restart: unless-stopped
    environment:
      POSTGRES_PASSWORD: change-me
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

Production checklist

  • Use a separate wallet or exchange account for the bot.
  • Keep private keys out of the repo and out of client-side code.
  • Start with read-only data collection before placing any live order.
  • Set hard notional limits per market, per category, and per day.
  • Log every decision: market, price, model probability, spread, size, and reason.
  • Add a kill switch that cancels open orders and stops the worker.
  • Respect venue terms, rate limits, geography rules, and local law.

Secrets and safety

Use host-level secrets, not committed files. Rotate keys after testing. Prefer limited-permission API keys when the venue supports them. Keep one account for research and a separate account for live automation.

Venue adapters

Extending the bot to Kalshi and Pariflow

The same system can support multiple prediction market venues if you keep each venue behind an adapter. The scanner, strategy, risk engine, and monitoring stay mostly the same. The authentication, endpoints, order model, and settlement rules change.

Kalshi adapter

Kalshi has official REST and WebSocket API docs, demo and production environments, and its own authentication flow. Build a separate adapter for markets, books, orders, fills, and positions, then reuse your shared risk engine.

Pariflow API, MCP, and CLI

Pariflow-style tooling can expose market search, order book reads, portfolio reads, and quote previews through API, MCP, and CLI workflows. MCP is especially useful for agent research flows, while CLI commands are good for smoke tests, market inspection, and operations.

Adapter contract example

Use one internal interface: searchMarkets(), getOrderBook(), getPositions(), previewOrder(), placeOrder(), and cancelOrder(). Some venues or permission levels may only support read and quote-preview methods.

Bot ideas

Useful bots you can build

Cross-venue odds monitor

Track similar markets across Polymarket, Kalshi, and Pariflow, then alert when probabilities diverge enough to deserve manual review.

Liquidity and spread assistant

Watch wide spreads, estimate a fair midpoint, and post passive orders only when size, spread, and time-to-close fit your limits.

News reaction bot

Subscribe to trusted news feeds or internal research notes, tag affected markets, and create a trade candidate queue instead of firing blindly.

Portfolio hedge bot

Read current positions and reduce concentrated exposure when several markets depend on the same event, team, candidate, or macro variable.

Settlement watchdog

Track markets close to resolution, compare source updates with rule text, and flag markets where final settlement risk is high.

Research copilot

Use an MCP client to search markets, inspect order books, summarize sources, and prepare a trade note for a human operator.

References

API docs and source notes

FAQ

Common questions

Can I host a Polymarket bot on Vercel?

Vercel is fine for a dashboard or webhook endpoint, but it is not ideal for an always-on trading loop or WebSocket listener. Use a worker host, VPS, container platform, or managed job runner for the bot itself.

Should the bot use REST polling or WebSockets?

Use REST for discovery, reconciliation, and backfills. Use WebSockets when you need low-latency order book or trade updates. Many reliable bots use both.

Can the same bot work on Kalshi?

The architecture can, but the adapter must be venue-specific. Kalshi has its own authentication model, endpoints, product rules, settlement model, and regulated exchange requirements.

Where does Pariflow fit?

Pariflow-style API, MCP, and CLI tooling is useful for market search, order book inspection, quote previews, and agent workflows. Keep trading execution permission separate from read and quote tools.

Build the bot slowly, then automate carefully.

The safest path is read-only scanner, paper trading, tiny live limits, monitoring, and only then more advanced execution logic.

More guides