Polymarket Python Tutorial: Complete Developer Guide 2025
Python is the most popular language for building Polymarket trading bots and analytics tools. This comprehensive guide covers everything from initial setup to placing your first trade using the official py-clob-client library. Whether you're building a market maker, arbitrage bot, or portfolio tracker, this tutorial has you covered.
Getting Started: Installation and Setup
Install the Official Python Client
# Core dependencies
pip install py-clob-client
pip install web3==6.14.0 # Pin version to avoid dependency conflicts
pip install python-dotenv
# Optional: Better async support
pip install aiopolymarket
# Optional: Retry logic
pip install tenacityVersion Note
Pin web3==6.14.0 to avoid dependency conflicts with eth-typing. The latest py-clob-client version is v0.29.0 (released December 2025) with HTTP2 and Keep Alive support.
Requirements
- Python: 3.9.10 or higher
- Wallet: Ethereum-compatible wallet with USDC on Polygon
- Private Key: Exported from Polymarket (for authenticated trading)
Authentication: Two Methods
Polymarket uses two authentication levels:
L1 Authentication (Private Key)
Uses your wallet's private key to sign EIP-712 messages. This proves ownership without custodial control.
L2 Authentication (API Key)
Derived from L1 authentication, uses HMAC-SHA256 signatures for faster request signing. Requests expire after 30 seconds.
Step 1: Export Your Private Key
- Log in to Polymarket.com
- Navigate to "Cash" in the menu
- Click the 3-dot menu
- Select "Export Private Key"
- Remove the '0x' prefix before storing
Step 2: Create Environment File
# keys.env - NEVER commit this file to git!
# Your private key (without 0x prefix)
PK=your_private_key_here
# These will be generated - leave blank initially
API_KEY=
API_SECRET=
API_PASSPHRASE=
# For browser/Magic wallets, add funder address
FUNDER_ADDRESS=Step 3: Generate API Credentials
import os
from py_clob_client.client import ClobClient
from dotenv import load_dotenv
load_dotenv('keys.env')
def generate_api_credentials():
host = "https://clob.polymarket.com"
key = os.getenv("PK")
chain_id = 137 # Polygon Mainnet
if not key:
raise ValueError("Private key not found. Set PK in keys.env")
# Initialize client with private key
client = ClobClient(host, key=key, chain_id=chain_id)
# Create or derive API credentials
try:
api_creds = client.create_or_derive_api_creds()
print(f"API Key: {api_creds.api_key}")
print(f"Secret: {api_creds.api_secret}")
print(f"Passphrase: {api_creds.api_passphrase}")
return api_creds
except Exception as e:
print(f"Error: {e}")
return None
if __name__ == "__main__":
generate_api_credentials()Save Your Credentials
Add the generated API Key, Secret, and Passphrase to your keys.env file. You only need to do this once - credentials are deterministically derived from your private key.
Client Initialization Patterns
Read-Only Access (No Authentication)
from py_clob_client.client import ClobClient
# Level 0 - public data only
client = ClobClient("https://clob.polymarket.com")
# Test connection
ok = client.get_ok()
server_time = client.get_server_time()
print(f"Connected: {ok}, Server Time: {server_time}")Standard EOA Wallet (MetaMask Export)
from py_clob_client.client import ClobClient
import os
from dotenv import load_dotenv
load_dotenv('keys.env')
HOST = "https://clob.polymarket.com"
CHAIN_ID = 137
PRIVATE_KEY = os.getenv("PK")
# signature_type=0 for standard EOA
client = ClobClient(
HOST,
key=PRIVATE_KEY,
chain_id=CHAIN_ID,
signature_type=0
)
# Set API credentials for L2 authentication
client.set_api_creds(client.create_or_derive_api_creds())Email/Magic Wallet
# signature_type=1 for email/Magic wallet
client = ClobClient(
HOST,
key=PRIVATE_KEY,
chain_id=CHAIN_ID,
signature_type=1, # POLY_PROXY
funder=os.getenv("FUNDER_ADDRESS") # Proxy wallet address
)
client.set_api_creds(client.create_or_derive_api_creds())Browser Wallet (Coinbase Wallet, etc.)
# signature_type=2 for browser wallets
client = ClobClient(
HOST,
key=PRIVATE_KEY,
chain_id=CHAIN_ID,
signature_type=2, # GNOSIS_SAFE
funder=os.getenv("FUNDER_ADDRESS")
)
client.set_api_creds(client.create_or_derive_api_creds())See What Whales Are Trading Right Now
Get instant alerts when top traders make moves. Track P&L, win rates, and copy winning strategies.

Free forever. No credit card required.
Fetching Market Data
Get All Markets
from py_clob_client.client import ClobClient
client = ClobClient("https://clob.polymarket.com")
# Get first page of markets
markets = client.get_markets()
print(f"Found {len(markets['data'])} markets")
# Print first market
first = markets['data'][0]
print(f"Market: {first.get('question')}")
print(f"Condition ID: {first.get('condition_id')}")Fetch All Markets with Pagination
import csv
import json
from py_clob_client.client import ClobClient
client = ClobClient("https://clob.polymarket.com")
markets_list = []
next_cursor = None
while True:
try:
if next_cursor is None:
response = client.get_markets()
else:
response = client.get_markets(next_cursor=next_cursor)
if 'data' not in response:
break
markets_list.extend(response['data'])
next_cursor = response.get("next_cursor")
print(f"Fetched {len(markets_list)} markets...")
if not next_cursor:
break
except Exception as e:
print(f"Error: {e}")
break
print(f"Total markets: {len(markets_list)}")
# Export to CSV
with open("markets.csv", 'w', newline='') as f:
if markets_list:
writer = csv.DictWriter(f, fieldnames=markets_list[0].keys())
writer.writeheader()
writer.writerows(markets_list)Get Prices and Order Book
from py_clob_client.clob_types import BookParams
token_id = "YOUR_TOKEN_ID_HERE"
# Get midpoint price
mid = client.get_midpoint(token_id)
print(f"Midpoint: $" + str(mid))
# Get best bid/ask
bid_price = client.get_price(token_id, side="BUY")
ask_price = client.get_price(token_id, side="SELL")
print(f"Bid: $" + str(bid_price) + ", Ask: $" + str(ask_price))
# Get full order book
book = client.get_order_book(token_id)
print(f"Bids: {book['bids'][:3]}")
print(f"Asks: {book['asks'][:3]}")
# Get multiple order books at once
books = client.get_order_books([
BookParams(token_id=token_id),
BookParams(token_id="ANOTHER_TOKEN_ID")
])
# Get last trade price
last_price = client.get_last_trade_price(token_id)
print(f"Last Trade: $" + str(last_price))Placing Orders
Market Order (Dollar Amount)
from py_clob_client.clob_types import MarketOrderArgs, OrderType
from py_clob_client.order_builder.constants import BUY, SELL
# Buy $25 worth of shares at market price
market_order = MarketOrderArgs(
token_id="YOUR_TOKEN_ID",
amount=25.0, # Dollar amount
side=BUY, # BUY or SELL
order_type=OrderType.FOK # Fill-or-Kill
)
# Sign and submit
signed_order = client.create_market_order(market_order)
response = client.post_order(signed_order, OrderType.FOK)
print(f"Order response: {response}")Limit Order (Price and Quantity)
from py_clob_client.clob_types import OrderArgs, OrderType
from py_clob_client.order_builder.constants import BUY, SELL
# Buy 100 shares at $0.45 each
limit_order = OrderArgs(
token_id="YOUR_TOKEN_ID",
price=0.45, # Price per share (0.00 - 1.00)
size=100.0, # Number of shares
side=BUY
)
# Sign and submit as Good Till Cancelled
signed_order = client.create_order(limit_order)
response = client.post_order(signed_order, OrderType.GTC)
print(f"Order ID: {response.get('id')}")Order Types Explained
- GTC (Good Till Cancelled): Stays open until filled or cancelled
- FOK (Fill or Kill): Must fill entirely or cancel immediately
- GTD (Good Till Date): Expires at specified time
Managing Orders and Positions
Get Open Orders
from py_clob_client.clob_types import OpenOrderParams
# Get all open orders
open_orders = client.get_orders(OpenOrderParams())
print(f"Open orders: {len(open_orders)}")
for order in open_orders:
print(f" {order['id']}: {order['side']} {order['original_size']} @ {order['price']}")Cancel Orders
# Cancel specific order
order_id = "YOUR_ORDER_ID"
client.cancel(order_id)
# Cancel all open orders
client.cancel_all()
print("All orders cancelled")Get Trade History
# Get your trades
trades = client.get_trades()
for trade in trades:
print(f"Trade: {trade['side']} {trade['size']} @ {trade['price']}")
print(f" Status: {trade['status']}")Error Handling and Rate Limits
Rate Limits
- Public endpoints: ~100 requests/minute
- Authenticated endpoints: Higher limits based on trading volume
- HTTP 429: Rate limit exceeded - implement backoff
Exponential Backoff Pattern
from tenacity import retry, wait_random_exponential, stop_after_attempt
@retry(
wait=wait_random_exponential(min=1, max=60),
stop=stop_after_attempt(5)
)
def fetch_with_retry(client, token_id):
"""Fetch data with automatic retry and exponential backoff."""
return client.get_midpoint(token_id)
# Usage
try:
price = fetch_with_retry(client, token_id)
except Exception as e:
print(f"Failed after 5 retries: {e}")Safe Order Placement
import time
def place_order_safe(client, order_args, max_retries=3):
"""Place order with error handling and retry logic."""
for attempt in range(max_retries):
try:
signed = client.create_order(order_args)
response = client.post_order(signed, OrderType.GTC)
return response
except Exception as e:
error_str = str(e)
if "429" in error_str:
# Rate limited - exponential backoff
wait_time = 2 ** attempt
print(f"Rate limited. Waiting {wait_time}s...")
time.sleep(wait_time)
elif "insufficient" in error_str.lower():
# Insufficient funds
print("Insufficient funds for order")
return None
else:
print(f"Order failed: {e}")
if attempt == max_retries - 1:
return None
time.sleep(1)
return NoneComplete Trading Bot Example
import os
import time
from py_clob_client.client import ClobClient
from py_clob_client.clob_types import OrderArgs, OrderType, OpenOrderParams
from py_clob_client.order_builder.constants import BUY, SELL
from dotenv import load_dotenv
load_dotenv('keys.env')
class SimplePolymarketBot:
def __init__(self):
self.client = ClobClient(
"https://clob.polymarket.com",
key=os.getenv("PK"),
chain_id=137,
signature_type=1,
funder=os.getenv("FUNDER_ADDRESS")
)
self.client.set_api_creds(self.client.create_or_derive_api_creds())
def get_market_price(self, token_id):
"""Get current bid/ask spread."""
try:
bid = float(self.client.get_price(token_id, side="BUY") or 0)
ask = float(self.client.get_price(token_id, side="SELL") or 1)
mid = (bid + ask) / 2
return {"bid": bid, "ask": ask, "mid": mid, "spread": ask - bid}
except Exception as e:
print(f"Error fetching price: {e}")
return None
def place_limit_buy(self, token_id, price, size):
"""Place a limit buy order."""
try:
order = OrderArgs(
token_id=token_id,
price=price,
size=size,
side=BUY
)
signed = self.client.create_order(order)
response = self.client.post_order(signed, OrderType.GTC)
print(f"Buy order placed: {size} @ {price}")
return response
except Exception as e:
print(f"Buy order failed: {e}")
return None
def place_limit_sell(self, token_id, price, size):
"""Place a limit sell order."""
try:
order = OrderArgs(
token_id=token_id,
price=price,
size=size,
side=SELL
)
signed = self.client.create_order(order)
response = self.client.post_order(signed, OrderType.GTC)
print(f"Sell order placed: {size} @ {price}")
return response
except Exception as e:
print(f"Sell order failed: {e}")
return None
def cancel_all_orders(self):
"""Cancel all open orders."""
try:
self.client.cancel_all()
print("All orders cancelled")
except Exception as e:
print(f"Cancel failed: {e}")
def run_market_maker(self, token_id, spread=0.02, size=10):
"""Simple market making strategy."""
print(f"Starting market maker for {token_id}")
while True:
try:
# Cancel existing orders
self.cancel_all_orders()
# Get current price
prices = self.get_market_price(token_id)
if not prices:
time.sleep(5)
continue
mid = prices["mid"]
# Place orders on both sides
buy_price = round(mid - spread/2, 2)
sell_price = round(mid + spread/2, 2)
self.place_limit_buy(token_id, buy_price, size)
self.place_limit_sell(token_id, sell_price, size)
print(f"Orders placed: Buy {buy_price} / Sell {sell_price}")
# Wait before refresh
time.sleep(30)
except KeyboardInterrupt:
print("Stopping bot...")
self.cancel_all_orders()
break
except Exception as e:
print(f"Error: {e}")
time.sleep(10)
if __name__ == "__main__":
bot = SimplePolymarketBot()
# bot.run_market_maker("YOUR_TOKEN_ID", spread=0.02, size=10)Risk Warning
Automated trading carries significant risks. Always test with small amounts first, implement proper risk controls, and never trade more than you can afford to lose. Review common mistakes before deploying.
Alternative Python Libraries
aiopolymarket (Async Client)
# pip install aiopolymarket
from aiopolymarket import GammaClient, MarketNotFoundError, RateLimitError
async with GammaClient() as client:
try:
market = await client.get_market("market-id")
print(f"Market: {market.question}")
except MarketNotFoundError as e:
print(f"Market not found: {e.market_id}")
except RateLimitError:
print("Rate limit exceeded")quantpylib (Async SDK)
# Fully asynchronous Polymarket wrapper
# Docs: quantpylib.hangukquant.com/wrappers/polymarket/
from quantpylib.wrappers.polymarket import PolymarketClient
async def main():
client = PolymarketClient()
markets = await client.get_markets()
print(f"Found {len(markets)} markets")Security Best Practices
- Never commit keys: Add
keys.envand*.envto.gitignore - Use environment variables: Load credentials with python-dotenv
- Rotate credentials: Periodically regenerate API keys
- Minimize permissions: Only enable trading when needed
- Monitor activity: Log all API calls and responses
- Production secrets: Use AWS Secrets Manager, Azure Key Vault, or similar
Resources and Documentation
Official Resources
- py-clob-client GitHub: github.com/Polymarket/py-clob-client
- Polymarket Docs: docs.polymarket.com
- API Authentication: docs.polymarket.com/developers/CLOB/authentication
- Your First Order: docs.polymarket.com/quickstart/orders/first-order
Example Bots on GitHub
- poly-maker: github.com/warproxxx/poly-maker - Market making bot
- Polymarket Agents: github.com/Polymarket/agents - Official AI trading framework
- Polymarket Spike Bot: github.com/Trust412/Polymarket-spike-bot-v1
Track Your Bot's Performance
PolyTrack provides portfolio tracking, P&L analytics, and whale alerts. Monitor your bot's performance alongside the smartest traders on Polymarket.
Next Steps
- WebSocket Tutorial - Stream real-time data
- API Guide - Complete REST API reference
- Trading Bot Strategies - Advanced bot architectures
- Arbitrage Guide - Find and exploit price discrepancies
Frequently Asked Questions
Run: pip install py-clob-client web3==6.14.0 python-dotenv. Pin web3 to version 6.14.0 to avoid dependency conflicts with eth-typing.
Related Articles
Stop Guessing. Start Following Smart Money.
Get instant alerts when whales make $10K+ trades. Track P&L, win rates, and copy winning strategies.