Propheseer Python SDK
Official Python SDK for the Propheseer prediction markets API. Access normalized data from Polymarket, Kalshi, and Gemini through a single, type-safe interface.
Installation
pip install propheseer
For WebSocket support (real-time market updates):
pip install propheseer[websocket]
Quick Start
from propheseer import Propheseer
client = Propheseer(
api_key="pk_test_...", # or set PROPHESEER_API_KEY env var
)
# List prediction markets
page = client.markets.list(source="polymarket", limit=10)
for market in page.data:
print(f"{market.question}: {market.outcomes[0].probability:.0%}")
# Check your API key usage
result = client.keys.me()
print(f"Plan: {result.data.plan}, Daily usage: {result.data.usage.daily}")
Async Support
import asyncio
from propheseer import AsyncPropheseer
async def main():
async with AsyncPropheseer(api_key="pk_test_...") as client:
page = await client.markets.list(source="polymarket")
for market in page.data:
print(market.question)
asyncio.run(main())
Configuration
client = Propheseer(
api_key="pk_test_...", # Required (or PROPHESEER_API_KEY env var)
base_url="https://api.propheseer.com", # Default
timeout=30.0, # Request timeout in seconds (default: 30)
max_retries=2, # Retries on 429/5xx errors (default: 2)
)
Resources
Markets
# List markets with filters
page = client.markets.list(
source="polymarket", # "polymarket" | "kalshi" | "gemini"
category="politics", # "politics" | "sports" | "finance" | ...
status="open",
q="election", # search query
limit=50,
offset=0,
)
# Get a single market
result = client.markets.get("pm_12345")
market = result.data
# Auto-paginate through all markets
for market in client.markets.list_auto_paginate(source="kalshi"):
print(market.question)
Categories
result = client.categories.list()
# [Category(id='politics', name='Politics', subcategories=['elections', ...]), ...]
Arbitrage (Pro+)
result = client.arbitrage.find(min_spread=0.05, category="politics")
for opp in result.data:
print(f"{opp.question}: spread={opp.spread}, return={opp.potential_return}")
Unusual Trades (Pro+)
page = client.unusual_trades.list(
reason="high_amount",
since="2025-01-01T00:00:00Z",
limit=20,
)
for trade in page.data:
print(f"${trade.trade.usdc_value} {trade.trade.side} on \"{trade.market.question}\"")
# Auto-paginate
for trade in client.unusual_trades.list_auto_paginate():
print(trade.detection.reason, trade.detection.anomaly_score)
History (Business+)
# Market price history
result = client.history.list(market_id="pm_12345", days=7)
# Available snapshot dates
result = client.history.dates()
Ticker (Public)
# No auth required
result = client.ticker.list(limit=10)
Pagination
Paginated endpoints return a SyncPage[T] (or AsyncPage[T]) object:
page = client.markets.list(limit=50)
print(page.data) # list[Market]
print(page.meta.total) # total matching markets
print(page.has_more()) # bool
print(page.next_offset()) # int | None
For automatic pagination:
for market in client.markets.list_auto_paginate(limit=50, max_items=200):
# yields individual items, fetching new pages as needed
pass
Error Handling
All API errors are raised as typed exceptions:
from propheseer import PermissionDeniedError, RateLimitError, AuthenticationError
try:
client.arbitrage.find()
except PermissionDeniedError as err:
print(f"Upgrade to {err.required_plan} plan")
except RateLimitError as err:
print(f"Rate limited, retry after {err.retry_after}s")
except AuthenticationError:
print("Invalid API key")
| Error Class | Status | When |
|---|---|---|
AuthenticationError |
401 | Missing or invalid API key |
InsufficientCreditsError |
402 | Not enough credits |
PermissionDeniedError |
403 | Plan upgrade required |
NotFoundError |
404 | Resource not found |
RateLimitError |
429 | Rate limit exceeded |
InternalServerError |
5xx | Server error |
APIConnectionError |
- | Network/timeout error |
WebSocket (Real-Time Updates)
from propheseer import PropheseerWebSocket
ws = PropheseerWebSocket(
api_key="pk_test_...",
reconnect=True, # Auto-reconnect (default: True)
max_reconnect_attempts=5, # Default: 5
ping_interval=25.0, # Keepalive interval (default: 25s)
)
@ws.on("connected")
def on_connected(msg):
print(f"Connected: {msg['sessionId']} ({msg['plan']})")
ws.subscribe(["pm_12345", "ks_67890"])
@ws.on("market_update")
def on_update(msg):
print("Market update:", msg["market"])
@ws.on("error")
def on_error(err):
print("Error:", err)
ws.connect()
# Later:
ws.unsubscribe(["pm_12345"])
ws.close()
Async WebSocket
import asyncio
from propheseer import AsyncPropheseerWebSocket
async def main():
ws = AsyncPropheseerWebSocket(api_key="pk_test_...")
ws.on("connected", lambda msg: print(f"Connected: {msg['sessionId']}"))
ws.on("market_update", lambda msg: print("Update:", msg))
await ws.connect()
ws.subscribe(["pm_12345"])
await asyncio.sleep(60)
await ws.close()
asyncio.run(main())
Rate Limit Information
Every API response includes rate limit info:
page = client.markets.list()
print(page.rate_limit)
# RateLimitInfo(
# plan='pro',
# billing_type='subscription',
# limit_day=10000,
# remaining_day=9950,
# limit_minute=100,
# remaining_minute=98,
# )
Requirements
- Python >= 3.9
- httpx >= 0.24.0
- websockets >= 11.0 (optional, for WebSocket support)
License
MIT
Release files for propheseer 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| propheseer-1.0.0.tar.gz | 26.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| propheseer-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 60.5 kB
Release files / propheseer-1.0.0.tar.gz
| Download URL | propheseer-1.0.0.tar.gz |
|---|---|
| Size | 26.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5ed1b877d3aedc459d53ecd7723ad0f663dd39e422b82c58e785b44ecc9f6bb6
|
|
BLAKE2b-256 checksum How to use checksums |
aa1b57e85899ba867de8022e10414bed1c8818ba5051ecbd108f1b75fb1d3c61
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 24, 2026.
Transparency logRelease files / propheseer-1.0.0-py3-none-any.whl
| Download URL | propheseer-1.0.0-py3-none-any.whl |
|---|---|
| Size | 34.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a3c7d7a76ac48d8a792718a81b80495a935fd42631bae167e643787935136c8d
|
|
BLAKE2b-256 checksum How to use checksums |
632d00f1fa70b705eb4ff55c36e747207578392b8f3f7c445556119e926f8eca
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 24, 2026.
Transparency log