DEV Community

PolyOrderbooks
PolyOrderbooks

Posted on • Originally published at polyorderbooks.com

Polymarket Price History: How to Download Historical Prices with Python

If you want Polymarket price history in a notebook or CSV, you do not need a paid data vendor to get started. Polymarket documents a public /prices-history endpoint on the CLOB API — no API key, no signup. This article shows how to download Polymarket historical prices with Python using that official path first, then when a hosted archive is worth considering.

That order matters. Many researchers only need implied-probability time series for charts or signal work. Others eventually need unified Polymarket price data alongside metrics or historical L2 depth. We will cover both — without skipping the free option.

What Polymarket price history actually is

Each Polymarket outcome trades as a token on the CLOB. Historical prices are stored per token ID (the asset id in Polymarket's docs), not per market slug. A binary market has two series — typically YES and NO — and each point is a timestamp t plus an implied probability p between 0 and 1.

This is Polymarket price data suited to time-series analysis: repricing before events, correlation across markets, coarse backtests. It is not the same as an archived order book — you get a price line, not bid/ask ladders with size at each level.

Step 1: resolve token IDs with the Gamma API

The CLOB /prices-history endpoint requires a token ID. The Gamma API exposes market metadata, including clobTokenIds — a JSON-encoded array of outcome token IDs for each market.

Typical flow: search or list markets on Gamma, pick one, parse clobTokenIds, then pass the YES (or NO) token id to /prices-history. Polymarket's prices and order books docs walk through the same pattern in more detail.

Step 2: download history from Polymarket's CLOB API

The documented endpoint is GET https://clob.polymarket.com/prices-history. Important parameters:

  • market (required) — outcome token ID.
  • interval — relative window such as 1h, 1d, 1w, or max. Mutually exclusive with an absolute range.
  • startTs / endTs — Unix timestamps for a fixed window (use these when you need a specific date range).
  • fidelity — sampling interval in minutes (default 1). Higher fidelity means more points.

The response shape is {"history": [{"t": ..., "p": ...}, ...]}. Public access — Polymarket applies IP-based rate limits and throttling, so pace bulk downloads and design for backoff rather than hammering the API.

Python example: official Polymarket price history

This script uses only Polymarket's public Gamma + CLOB APIs. Install requests if you need it (pip install requests).

import json
import time
from datetime import datetime, timezone

import requests

GAMMA = "https://gamma-api.polymarket.com"
CLOB = "https://clob.polymarket.com"

# 1. Resolve a market and its outcome token IDs (Gamma — public, no API key)
markets = requests.get(
    f"{GAMMA}/markets",
    params={"limit": 5, "active": True, "closed": False},
    timeout=60,
)
markets.raise_for_status()
market = markets.json()[0]
token_ids = json.loads(market["clobTokenIds"])
yes_token_id = token_ids[0]

print(market["question"])
print("YES token:", yes_token_id[:12], "...")

# 2. Pull Polymarket price history (CLOB /prices-history — public, no API key)
history = requests.get(
    f"{CLOB}/prices-history",
    params={
        "market": yes_token_id,
        "interval": "1w",   # or use startTs + endTs for an absolute window
        "fidelity": 60,     # minutes between points
    },
    timeout=60,
)
history.raise_for_status()
points = history.json().get("history", [])

for point in points[:5]:
    ts = datetime.fromtimestamp(point["t"], tz=timezone.utc).isoformat()
    print(ts, "implied prob", point["p"])

# 3. Export to CSV (polymarket price data download)
# with open("prices.csv", "w") as f:
#     f.write("timestamp,price\n")
#     for point in points:
#         f.write(f"{point['t']},{point['p']}\n")

time.sleep(0.2)  # pace yourself — IP-based rate limits apply
Enter fullscreen mode Exit fullscreen mode

Practical tips:

  • For long windows at fine fidelity, chunk with startTs / endTs instead of relying on interval=max alone — community reports suggest very fine granularity on resolved markets can return sparse data unless you bound the range explicitly.
  • Loop one request per outcome token (YES and NO) if you need both sides.
  • Add a short sleep between markets when downloading many series — respect documented rate limits.

When the official API is enough

Stay on Polymarket's /prices-history when:

  • You are exploring one market or a small set of markets.
  • You need implied probability over time, not full book depth.
  • You are fine resolving token IDs through Gamma yourself.
  • Hourly or daily fidelity is sufficient for the question.

For many charting and research tasks, that is the right stopping point — and it costs nothing beyond your time.

When a historical archive helps

A third-party archive (or your own recorder) becomes useful when Polymarket historical data needs to look like a product API rather than a script that stitches Gamma + CLOB:

  • Unified queries — discover markets by slug and pull /prices, /metrics, or /books on the same start_ts / end_ts window without token-id plumbing each time.
  • Both outcomes in one response — archive APIs often key price series by outcome label (YES / NO) for a market slug.
  • Historical L2 order books — if price history stops being enough and you need bid/ask ladders, see How to Get Historical Polymarket Order Book Data for Backtesting.
  • Bulk polymarket data download — warehouse exports (Parquet, CSV) or scheduled pulls across hundreds of markets.

For the broader map of prices vs trades vs books vs API access, see Polymarket Historical Data: Prices, Trades, Order Books, and API Access.

Optional: same window through an archive API

If you already use a hosted historical API, the shape is similar — market discovery, then a prices route — but keyed by slug and paginated. Example with PolyOrderbooks (requires a free API key from the dashboard):

import os
from datetime import datetime, timedelta, timezone

import requests

BASE = "https://api.polyorderbooks.com"
HEADERS = {"X-API-Key": os.environ["POLYORDERBOOKS_API_KEY"]}

markets = requests.get(
    f"{BASE}/v1/markets",
    params={"search": "bitcoin", "limit": 1, "status": "active"},
    headers=HEADERS,
    timeout=60,
)
markets.raise_for_status()
slug = markets.json()["data"][0]["slug"]

end = datetime.now(timezone.utc)
start = end - timedelta(days=7)

prices = requests.get(
    f"{BASE}/v1/markets/{slug}/prices",
    params={
        "start_ts": start.isoformat().replace("+00:00", "Z"),
        "end_ts": end.isoformat().replace("+00:00", "Z"),
        "resolution": "60s",
        "limit": 500,
    },
    headers=HEADERS,
    timeout=120,
)
prices.raise_for_status()

for outcome, series in prices.json()["data"].items():
    print(outcome, len(series), "points")
Enter fullscreen mode Exit fullscreen mode

This is optional. Start with Polymarket's official endpoint; move here when unified history, metrics, or book depth justify it. Docs: quickstart and historical overview.

Summary

Polymarket price history is available today through documented public APIs: resolve token IDs on Gamma, call /prices-history on the CLOB, export the series. That covers a large share of polymarket historical prices and polymarket price data use cases with no vendor lock-in.

Reach for an archive when you need one interface for prices, metrics, and stored L2 books — or when IP limits and multi-market orchestration become the bottleneck. Either way, you are downloading real market history, not guessing from live quotes alone.


Originally published on PolyOrderbooks.

Top comments (0)