← Developer blog

Find tennis markets on Polymarket (Gamma API)

Discover live Polymarket tennis markets in Python with the free Gamma API: tag 864, filtering, market shape and parsing prices. Runnable code.

· · By the Live Tennis API team

Polymarket exposes every tennis market through its free, keyless Gamma API at https://gamma-api.polymarket.com. Tennis markets carry tag id 864. Query /markets (or /events) with tag_id=864&active=true&closed=false and you get the questions, outcomes and current market prices as plain JSON. No wallet or account is needed to read them.

This article covers the read side. How to list tennis markets, and what a market object looks like. How to filter down to the ones you care about (live singles moneylines vs. tournament futures). Then how to parse the price fields, which are not what you'd expect. The Gamma API is public and rate-friendly for polite polling. You do not need our API or anyone's key to fetch market prices. You need it later, for the live match state you'll join against these prices.

One request with curl

Start by confirming the endpoint works. This returns two live tennis markets:

curl -s "https://gamma-api.polymarket.com/markets?tag_id=864&active=true&closed=false&limit=2" | python3 -m json.tool

The important query parameters:

The market shape (and the price gotcha)

A Gamma market object carries the fields you need to build a signal. Trimmed to the useful ones:

{
  "id": "1088471",
  "question": "Will Jannik Sinner win the 2026 Men's US Open?",
  "slug": "will-jannik-sinner-win-the-2026-mens-us-open",
  "conditionId": "0x65bbe9ee...",
  "outcomes": "[\"Yes\", \"No\"]",
  "outcomePrices": "[\"0.435\", \"0.565\"]",
  "volumeNum": 257002.62,
  "liquidityNum": 87623.83,
  "endDate": "2026-09-13T00:00:00Z",
  "active": true,
  "closed": false,
  "enableOrderBook": true,
  "groupItemTitle": "Jannik Sinner"
}

The gotcha: outcomes and outcomePrices are JSON-encoded strings, not arrays. You have to json.loads() them a second time. A price of "0.435" means the market implies a ~43.5% probability of that outcome. The two prices in a binary market sum to roughly 1.0. Treat them as market-implied probabilities in the 0-1 range, not a decimal price format.

List and filter tennis markets in Python

import json
import requests

GAMMA = "https://gamma-api.polymarket.com"
TENNIS_TAG = 864


def fetch_tennis_markets(limit=500):
    """Page through all currently-open tennis markets on Polymarket."""
    markets, offset, page = [], 0, 100
    while True:
        resp = requests.get(
            f"{GAMMA}/markets",
            params={
                "tag_id": TENNIS_TAG,
                "active": "true",
                "closed": "false",
                "limit": page,
                "offset": offset,
            },
            timeout=15,
        )
        resp.raise_for_status()
        batch = resp.json()
        if not batch:
            break
        markets.extend(batch)
        offset += page
        if len(batch) < page or len(markets) >= limit:
            break
    return markets


def parse_prices(market):
    """outcomes / outcomePrices arrive as JSON strings — decode both."""
    outcomes = json.loads(market.get("outcomes") or "[]")
    prices = json.loads(market.get("outcomePrices") or "[]")
    return dict(zip(outcomes, (float(p) for p in prices)))


markets = fetch_tennis_markets()
print(f"{len(markets)} open tennis markets")

for m in markets[:10]:
    prices = parse_prices(m)
    quote = "  ".join(f"{name} {p:.3f}" for name, p in prices.items())
    print(f"- {m['question']}\n    {quote}  (vol ${m.get('volumeNum', 0):,.0f})")

Separating live moneylines from futures

A tag_id=864 sweep mixes three kinds of market. Head-to-head moneylines are "Player A vs Player B" for a specific match. Futures are "Will X win the US Open?" markets. Props are set winner and total games. For an automated bot that reacts to live scores, you usually want the two-player moneylines. There's no single flag for that, so filter heuristically:

def is_binary_moneyline(market):
    outcomes = json.loads(market.get("outcomes") or "[]")
    # H2H match markets have exactly two player outcomes and a live order book;
    # "Yes/No" futures also have two outcomes, so also require the order book
    # and exclude the Yes/No pair.
    if len(outcomes) != 2 or not market.get("enableOrderBook"):
        return False
    return {o.lower() for o in outcomes} != {"yes", "no"}


live_h2h = [m for m in markets if is_binary_moneyline(m)]
print(f"{len(live_h2h)} head-to-head moneyline markets")

Grouped tournament futures (like the US Open winner) come back as many Yes/No markets that share an event. The /events endpoint (same tag_id=864) groups those under one title if you want to present the whole field together.

The proof point: this is a real, active category

This isn't a thin niche. On 2026-08-18, a live tag_id=864 sweep of the Gamma API returned 400+ open tennis moneyline markets trading at the same time. That board held live Cincinnati Open singles, Challengers, ITF matches and US Open futures. Tennis runs close to year-round across the ATP, WTA, Challenger and ITF tours, so there is almost always a live board to work against.

Skip the boilerplate: the discovery module

Our open-source toolkit, livetennisapi/polymarket-tennis (MIT), wraps everything above in a discovery module. It calls Gamma, decodes the string-encoded price fields, classifies each market (match / futures / doubles), and hands you normalized Python objects instead of raw dicts. It's observe-only: no order execution, no wallets, no keys.

pip install git+https://github.com/livetennisapi/polymarket-tennis
pmtennis discover --matches-only --moneyline-only

Or from Python:

from polymarket_tennis import GammaClient, discover_tennis_markets

with GammaClient() as gamma:
    for market in discover_tennis_markets(gamma, market_types={"moneyline"},
                                          matches_only=True):
        print(market.question, market.prices)

Next: from prices to a signal

Market prices alone aren't a signal. You need the live match state (score, server, break point) to know whether a price is stale or ripe. Gamma gives you the price. The Live Tennis API gives you the live score. The free tier covers live matches and current scores. Grab a free key (no card). Then read the companion guide, Match a Polymarket tennis market to a live match, to join the two by player name. Placing orders (wallets, keys, the CLOB client) is your own responsibility and out of scope here.

Frequently asked questions

What is the Polymarket Gamma API?

Gamma is Polymarket's free, keyless public data API at https://gamma-api.polymarket.com. Its /markets and /events endpoints return questions, outcomes, current market prices, volume and liquidity as JSON. It's read-only market data. Placing orders uses a separate authenticated CLOB client.

How do I find tennis markets on Polymarket?

Query the Gamma API with the tennis tag id 864: GET https://gamma-api.polymarket.com/markets?tag_id=864&active=true&closed=false. Add limit and offset to paginate. This returns every currently open tennis market (moneylines, futures and props) with no API key required.

Do I need an API key to read Polymarket tennis prices?

No. Polymarket's Gamma API is public and keyless for reading market data, including prices. You only need authentication and a wallet to place orders.

Why are Polymarket outcome prices returned as strings?

Gamma returns the outcomes and outcomePrices fields as JSON-encoded strings (e.g. "[\"Yes\", \"No\"]"). So you must call json.loads() on them a second time after parsing the response. A price like "0.435" is the market-implied probability (~43.5%), and the outcomes in a binary market sum to about 1.0. Treat them as probabilities in the 0-1 range, not a decimal price format.

How many tennis markets are on Polymarket?

It's a large, active category. On 2026-08-18 a live Gamma API sweep with tag id 864 returned 400+ open tennis moneyline markets, all trading at once. They spanned ATP, WTA, Challenger and ITF events plus tournament futures. Because tennis runs nearly year-round, there is almost always a live board available.

Built with the Live Tennis API, which serves real-time scores, players, odds and model win-probability for ATP, WTA, Challenger and ITF.

API reference SDKs on GitHub Plans from $9.99/mo