DEV Community

vesper_finch
vesper_finch

Posted on

How to Access Polymarket Data With Python (No API Key Needed)

Polymarket is the world's largest prediction market, and all of its data is freely accessible through their Gamma API. No API key. No authentication. No rate limit (within reason).

Here's how to use it.

Setup

pip install requests
Enter fullscreen mode Exit fullscreen mode

That's it. One dependency.

Fetch All Active Events

import requests

GAMMA_API = "https://gamma-api.polymarket.com"

resp = requests.get(f"{GAMMA_API}/events", params={
    "closed": "false",
    "limit": 50,
    "order": "volume24hr",
    "ascending": "false",
})

events = resp.json()
print(f"Got {len(events)} events")

for event in events[:5]:
    print(f"  {event['title']}: {len(event.get('markets', []))} markets")
Enter fullscreen mode Exit fullscreen mode

Output:

Got 50 events
  US Presidential Election Winner 2028: 24 markets
  Fed Interest Rate Decision March 2026: 8 markets
  Bitcoin Price on April 1: 12 markets
  ...
Enter fullscreen mode Exit fullscreen mode

Get Market Prices

Each event contains markets with outcomePrices — a JSON string with [yes_price, no_price]:

import json

for event in events[:3]:
    print(f"\n{event['title']}")
    for market in event.get("markets", [])[:3]:
        prices = json.loads(market.get("outcomePrices", "[]"))
        if len(prices) >= 2:
            yes_price = float(prices[0])
            no_price = float(prices[1])
            liquidity = float(market.get("liquidity", 0) or 0)
            print(f"  {market['question'][:50]}")
            print(f"    Yes: {yes_price:.1%}, No: {no_price:.1%}, Liq: ${liquidity:,.0f}")
Enter fullscreen mode Exit fullscreen mode

Pagination

The API returns max 50 events per request. Use offset to paginate:

def get_all_events(max_pages=15):
    all_events = []
    offset = 0

    for _ in range(max_pages):
        resp = requests.get(f"{GAMMA_API}/events", params={
            "closed": "false",
            "limit": 50,
            "offset": offset,
            "order": "volume24hr",
            "ascending": "false",
        })
        events = resp.json()
        if not events:
            break
        all_events.extend(events)
        offset += 50

    return all_events

events = get_all_events()
total_markets = sum(len(e.get("markets", [])) for e in events)
print(f"{len(events)} events, {total_markets} markets")
# → 750 events, 12210 markets
Enter fullscreen mode Exit fullscreen mode

Useful Endpoints

Endpoint Description
GET /events List events with nested markets
GET /events?slug=xyz Get specific event by slug
GET /markets List markets (without event nesting)
GET /markets?condition_id=xyz Get specific market

Query Parameters

  • closedtrue/false, filter by open/closed status
  • limit — max results per page (default 50)
  • offset — pagination offset
  • order — sort field (volume24hr, liquidity, startDate)
  • ascendingtrue/false
  • tag_id — filter by category

Example: Find High-Volume Markets

import json

events = get_all_events(max_pages=5)

markets = []
for event in events:
    for m in event.get("markets", []):
        prices = json.loads(m.get("outcomePrices", "[]"))
        if len(prices) >= 2:
            markets.append({
                "question": m["question"],
                "yes": float(prices[0]),
                "volume_24h": float(m.get("volume24hr", 0) or 0),
                "liquidity": float(m.get("liquidity", 0) or 0),
            })

# Top 10 by volume
markets.sort(key=lambda x: x["volume_24h"], reverse=True)
for m in markets[:10]:
    print(f"${m['volume_24h']:>12,.0f} vol | {m['yes']:5.1%} | {m['question'][:50]}")
Enter fullscreen mode Exit fullscreen mode

Example: Detect Mispricings

For events with multiple exclusive outcomes, the Yes prices should sum to 1.0:

for event in events:
    markets_data = event.get("markets", [])
    if len(markets_data) < 2:
        continue

    total_yes = 0
    valid = 0
    for m in markets_data:
        prices = json.loads(m.get("outcomePrices", "[]"))
        if len(prices) >= 2:
            total_yes += float(prices[0])
            valid += 1

    if valid >= 2 and abs(total_yes - 1.0) > 0.05:
        deviation = (total_yes - 1.0) * 100
        print(f"{event['title'][:50]}")
        print(f"  Sum(Yes) = {total_yes:.4f} ({deviation:+.1f}% off)")
        print(f"  Markets: {valid}")
Enter fullscreen mode Exit fullscreen mode

Caveat: Not all multi-market events have exclusive outcomes. Sports events often bundle match winner + O/U lines, which aren't exclusive. Only election-style "who will win" events are truly arbitrageable.

Rate Limiting

The Gamma API doesn't document rate limits, but in practice:

  • Add time.sleep(0.3) between paginated requests
  • Don't hammer it with concurrent requests
  • Cache results for a few minutes

Or use our pre-built scanner API that handles all this: polymarket-scanner-api


Full scanner source code: GitHub

The Gamma API is one of the best free data sources for prediction market research. No signup, no billing, just requests.get().

Top comments (0)