Developer and API

Gamma pages by offset, and passing a page number fails silently

Gamma pages by offset, not page number. Pass page= and it repeats slice one. The recipe, the 300 second cache, the price field.

Last checked 20 August 2026 · 3 sources

Polymarket's Gamma API is the catalogue: what markets exist, what they are called, what they are priced at. It needs no key, it answered in 122ms on 20 August 2026, and it will hand you a complete market list if you page it correctly.

The trap is that it pages by row offset, not by page number, and passing page=2 does not return an error. It is ignored. You get the first slice again, and again, and your collector reports thousands of markets that are the same hundred rows repeated. This is the single most common way a Polymarket collector produces confident nonsense.

The collection recipe

GET https://gamma-api.polymarket.com/markets?limit=100&offset=0&closed=false
GET https://gamma-api.polymarket.com/markets?limit=100&offset=100&closed=false
GET https://gamma-api.polymarket.com/markets?limit=100&offset=200&closed=false

Increase offset by your limit each time. Stop when a response comes back with fewer rows than you asked for. We confirmed on 20 August that offset=100 returns different markets from offset=0, which is the check worth running before you trust any collector you write.

Four things to get right:

  • Response is a bare JSON array. Not an object with a data key. The CLOB

API on the same platform wraps its rows, so code moved between them breaks.

  • Deduplicate anyway. Markets can shift position between calls as volumes

change, so a market can appear twice or be skipped entirely across a paging run. Key on conditionId.

  • closed=false is not enough. A market can be open and not accepting

orders. Check acceptingOrders and active as well, which are three separate booleans that do not mean the same thing.

  • Cap your loop. There is no total count in the response.

Our own collector pulls 600 markets across 6 pages with a tag filter of politics, economics, crypto and sports. That is a deliberate slice. Polymarket carries far more than 600 live markets, and any claim about "all of Polymarket" built on six pages is false. We say 600 because that is what we collected, not because that is what exists.

Five minutes of cache means polling faster is pointless

Gamma sends Cache-Control: public, max-age=300.

Our scanner runs a 60 second cycle, so roughly four scans in five see Polymarket prices that have not changed, because the edge is serving the same cached copy. That is not a rate limit and we have never been throttled for it. It just means the extra requests are answered with the same bytes.

If you need Polymarket prices fresher than five minutes, Gamma will not give them to you at any polling rate. The CLOB caches at max-age=30. Kalshi's API caches at max-age=15. Gamma is the slowest-moving of the three by an order of magnitude, which is worth knowing before you design around it.

outcomePrices is not what you would pay

Here is a real market, the first row returned when we sorted by volume descending on 20 August 2026:

question              Game 1: Any Player Ultra Kill?
outcomePrices         ["0.1", "0.9"]
bestAsk               0.2
spread                0.2
liquidity             157.29
orderMinSize          5
orderPriceMinTickSize 0.01

outcomePrices says 10 cents. bestAsk says 20 cents. You would pay double the displayed price, because the spread on that book is 20 cents wide and the displayed figure is a midpoint, not an offer.

That is not a rare edge case. It was the top market by volume. Any edge calculated from outcomePrices on a thin book is fiction, and the thinner the book the wider the gap. Read bestAsk for what a taker pays and bestBid for what a maker receives, and treat outcomePrices as a display value only.

liquidity at 157.29 on that market tells the rest of the story: a book with $157 behind it and a $5 order minimum. A 20 cent spread is what a book that thin looks like from outside.

The fields worth reading

  • bestAsk and bestBid, your actual prices.
  • spread, which is the fastest way to reject a market. A wide spread means

the mid you are looking at is not tradeable.

  • liquidity, the ceiling on what any of this is worth. A 5% edge on $157 of

book is not a 5% opportunity, it is about $8 before fees.

  • orderMinSize and orderPriceMinTickSize, the CLOB's minimum_order_size

and minimum_tick_size under different names on the same platform.

  • conditionId, your dedup key.
  • clobTokenIds, the bridge to the order book if you need depth.
  • active, closed, acceptingOrders. Three booleans, three meanings.

Fees are by category and Gamma will not tell you the category

Polymarket's taker rate depends on the market's category, and the market object does not carry the rate:

CategoryTaker rate
crypto0.07
sports, economics, culture, weather, other0.05
finance, politics, mentions, tech0.04
geopolitical0.00

Makers pay 0.00. We confirmed this independently on the CLOB, where maker_base_fee was 0 across all 1,000 markets in a page sampled the same day.

The fee is rate x contracts x P x (1 - P). Your collector has to map each market to a category itself. Guess high and you under-report edges, which is safe. Guess low and every number you publish is too good, which is how a competitor came to assert a flat 0.0625 coefficient for five months while Polymarket's own schedule specified 0.04 to 0.07 by category.

What we could not verify

  • Rate limits. Never throttled at 60 second polling, never probed for the

ceiling. We have no number and will not invent one.

  • Whether the tag filter covers every market. We filter to four tags and

collect 600. We have not established what proportion of the venue that is.

  • Field stability. Gamma market objects carried over forty fields on the

day we sampled. We have not tracked whether fields are added or removed over time, so write your parser defensively.

Questions people actually ask

How do I get all markets from the Polymarket Gamma API? Page with limit and offset, adding your limit to the offset each call, and stop when a response returns fewer rows than requested. Deduplicate on conditionId, because markets can move between pages during a run. Never pass page, which is ignored silently.

Why is my Gamma collector returning duplicate markets? Two likely causes. You passed page instead of offset, which returns slice one every time without erroring. Or markets shifted position between calls as volume changed, which is normal and is why you deduplicate on conditionId.

Does the Gamma API need an API key? No. Unauthenticated reads returned HTTP 200 in 122ms on 20 August 2026. We have not established the rate limits, so no key does not mean no ceiling.

Why is the API price different from the Polymarket website? The website shows a midpoint or last traded price. bestAsk is what a taker pays. On one live market on 20 Aug 2026 the displayed price was 0.1 and the best ask was 0.2, because the spread was 20 cents wide.

How fresh are Gamma prices? Up to five minutes old. Gamma sends Cache-Control: public, max-age=300. The CLOB caches for 30 seconds and Kalshi's API for 15, so Gamma is the slowest source of the three regardless of how often you ask.

What is the minimum order on Polymarket? orderMinSize was 5 on the market we sampled, and the CLOB reported a minimum_order_size of 15 on 962 of 1,000 markets the same day. It varies per market, so read the field rather than assuming a site-wide floor.

Sources

The market used as a worked example was the first row returned when sorting by volume descending on 20 Aug 2026 at 11:45 UTC. Its prices will have moved since. The point it illustrates is structural, not about that market.

  1. https://gamma-api.polymarket.com/markets Polymarket Gamma API, markets endpoint. Called direct 20 Aug 2026 at 11:42 and 11:45 UTC. HTTP 200, 122ms to 166ms, Cache-Control public max-age=300. offset=100 confirmed to return a different slice from offset=0.
  2. https://docs.polymarket.com/ Polymarket developer documentation, published category fee schedule.
  3. PredictionEdge scanner, scanner/market_intel.py : our own Gamma client. 600 markets across 6 pages with a four-tag filter, collected 19 and 20 Aug 2026.