How to place a prediction market order from code
Five clients that actually submit orders, and the three things between a working script and a fill — the key, the wallet approvals and the eligibility check.
Pick the venue first, because there is no portable order. Kalshi has an official generated Python client and a better third-party one; Polymarket has its own SDK for the on-chain exchange and a separate one for the US exchange, which share nothing; Limitless publishes its own async client. The library is the easy part. The credential, the wallet approvals and whether you may place an order at all are the rest.
The short way
Pick the venue, then the client. There is no portable order here: Kalshi and Polymarket are unrelated systems with different identifiers, different price units, different signing schemes and different answers to who may place an order at all.
For Kalshi, the current official Python SDK is
kalshi_python_sync or kalshi_python_async — not the older kalshi-python package, which
Kalshi's own documentation marks as deprecated. For Polymarket's on-chain exchange,
polymarket-client is the package Polymarket's documentation names, and
the import is polymarket rather than the distribution name. For
Polymarket US it is a different SDK entirely, against a different
host, with a different credential.
The credential comes out of the environment, never out of the file:
# Kalshi: the API key id, plus the path to the RSA private key it was registered against.
export KALSHI_API_KEY_ID="..."
What the options are
Kalshi, official. Seventeen API modules covering markets, events, orders, order groups, portfolio, historical and live data, generated from the OpenAPI specification and released on a weekly cadence — thirty-one versions since December 2025. Authentication is an API key id plus an RSA private key, with RSA-PSS request signing. Two things to know before you plan around it: it requires Python 3.13 or newer, which rules out most production images in use today, and it ships no WebSocket at all, because the streaming half of the Kalshi API lives in a separate specification.
Kalshi, third-party. pykalshi is MIT and exists largely because of that
gap: an OrderbookManager that applies the WebSocket deltas and hands back the current book,
automatic retries, pandas output, typed exceptions, Python 3.9 and up, and five runtime
dependencies a person can actually check. It reads KALSHI_API_KEY_ID and a path to your key file
from the environment and signs in process. It is one person's library, it does not cover the whole
API by its own admission, and it learns about an API change when something breaks.
Polymarket, on-chain. polymarket-client ships four clients, and the split is the useful part:
PublicClient and AsyncPublicClient need no credentials at all, while SecureClient and
AsyncSecureClient take a local private key and can trade. SecureClient.create() derives the
Level 2 API credentials and the wallet address from the signer key, classifies the account as a
plain EOA, a Polymarket proxy, a Gnosis Safe or a Deposit Wallet, and picks the signature type from
that. Orders are EIP-712 typed data signed in your process; the package posts signatures rather
than credentials.
Polymarket, US. polymarket-us-python is a thinner, different
animal: httpx for transport, pynacl for Ed25519 signing, sync and async clients, and a
credential that is an exchange API key id plus a base64-encoded Ed25519 secret. There is no wallet
key and no on-chain signing, because the US exchange settles in dollars — which removes the whole
class of approval failures below, and adds an identity check instead.
Limitless. limitless-sdk is async throughout, on aiohttp and
python-socketio, with GTC, FAK and FOK orders on both the CLOB and NegRisk multi-outcome markets,
signed locally with eth-account against a cached copy of the venue contract addresses. It is one
of the few official venue clients here whose last release and last commit are the same day.
Where this breaks
The key is three different objects wearing one word. An RSA private key registered against a Kalshi account, used to sign each request. An Ed25519 secret issued from a developer page on a Polymarket US account. And, on the on-chain venues, a Polygon signing key which is the key that can move the collateral — there is no read-only version of it to hand over. Where your key lives when software trades for you is the page for that decision rather than a paragraph here. The practical rule from the cards: prefer a library that separates reading from trading the way polymarket-client does in its type system, and know which of the three you are handing over.
The wallet and its approvals are work, and they are where a first order actually fails. On
Polymarket the allowance step used to be a linked gist; polymarket-client now carries
approve_erc20, approve_erc1155_for_all, get_trading_approvals_state, a gasless relayer path
and split_position, merge_positions and redeem_positions inside the library. On-chain
operations still cost gas. Polymarket US has none of this, which is the single largest difference
between two SDKs published by the same vendor.
The eligibility check is not in the library and cannot be worked around by it. The limitless-sdk README states that Limitless restricts order placement from US locations for regulatory and sanctions reasons and asks builders to check their location before placing an order — reading is not what is restricted, placing an order is. Polymarket US issues API keys only from the developer page of an account that has completed identity verification, and that gate sits on the WebSocket streams as well as on the writes. What you have to prove about yourself to trade is where that whole question lives.
The package a search result gives you is archived.
py-clob-client is MIT, archived, and carries Polymarket's own notice that
it is no longer functional and should not be used for new or existing integrations. The PyPI page
carries no warning at all, so the install succeeds with nothing to tell you. The replacement is
polymarket-client. Two other names on PyPI make this worse: the bare polymarket distribution is
an unrelated 2024 package and polymarket-sdk is an unrelated 2026 one, and both install cleanly.
Which Python client to write against Polymarket is the head
to head.
A 200 is not always a fill. On Polymarket US the per-entry outcome of a batch create is
delivered on the private order stream rather than in the HTTP response, and canceledOrderIds is
an echo of the request rather than a confirmation — if you are not holding the socket, you do not
know what happened. Tools with a streaming feed covers which
venues put what on which channel.
If you outgrow this
If the strategy needs more than one venue, CCXT and PMXT are the two abstractions in this catalogue, and tools that cover more than one venue is the listing with what each of them flattens to get there.
And before writing the loop that runs it unattended, read what running a bot does not solve. The things that break a production order path are rate limits, trading hours, a market clarification changing the question under an open position, and resolution taking days — none of which is a property of the client you picked above.
The approaches, in order
Cards in the catalogue that do this, ordered editorially. Paid placement does not affect this order.
1.Kalshi Python SDK (sync and async)
Kalshi's current official client, regenerated from the OpenAPI spec on a weekly cadence. REST only, Python 3.13 or newer, no public source.
Kalshi's current official Python client - weekly releases, Python 3.13 only, no source.
FreeFree tier
2.pykalshi
The MIT third-party Kalshi client with what the generated one leaves out — WebSocket streaming, a local order book, retries and typed errors.
Unofficial Kalshi client with what the generated SDK leaves out - streams and retries.
FreeFree tierOpen source
3.polymarket-client
Polymarket's own SDK for the on-chain exchange, with reads and trading split across separate classes so a price script never holds key material.
Polymarket's own unified Python SDK - sync and async, data through order signing.
FreeFree tierOpen source
4.Polymarket US Python SDK
The US exchange from Python. An Ed25519 exchange credential rather than a wallet key, and none of the on-chain approval steps in the way.
Official SDK for Polymarket US - installs as polymarket-us, unreleased since January.
FreeFree tierOpen source
5.limitless-sdk
Limitless's own async client, signing CLOB and NegRisk orders in process; its README asks builders to check their location before placing one.
Limitless Exchange's own async Python SDK - CLOB and NegRisk orders, WebSocket, MIT.
FreeFree tierOpen source
FAQ
Is there one library that places orders on every venue?
Two try. CCXT implements order placement across all seven venues in its prediction namespace, and PMXT covers hosted writes on Polymarket, Opinion and Limitless with Kalshi writes needing its self-hosted path. Both cost you exchange-shaped errors in exchange for one vocabulary, and neither removes the per-venue credential, approval or eligibility work below.
Can I test an order without real money?
On Kalshi, yes — it runs a full demo environment on separate hosts with separate credentials, which is the only sandbox in this catalogue. pykalshi has no paper mode of its own and wiring it to the demo is your job. Limitless states plainly that there is no sandbox, no testnet and no mock mode, and suggests minimum-size live orders on a low-volume market instead.
Why does pip install py-clob-client still work?
Because PyPI carries no warning even though the repository does. py-clob-client is archived and its README says the client is no longer functional and should not be used for new or existing integrations; the migration target is polymarket-client. The install succeeds today with nothing to tell you, which is why it is still the answer most search results give.
Does the SDK ever see my private key?
On the on-chain venues it holds it in process to sign locally, which is the design rather than a lapse — polymarket-client and limitless-sdk both build and sign the payload in your program and post the signature. On the US exchange there is no wallet key at all — the credential is an exchange API key id plus a base64-encoded Ed25519 secret, issued from a developer page.
Sources
- Python quickstart — Polymarket, read
- kalshi-python-sync project page — Python Package Index, read
- limitless-sdk repository — Limitless Exchange, read
- Environments — Polymarket US, read
The catalogue next door
This page names a handful of cards. The rest of them are in Trading Clients, SDKs & Bots, each filled in against the same schema, with the fields to narrow it yourself.
Last updated . Corrected in place: this is a reference page, not a dated post.