Polymarket trades and volume
Every Polymarket trade with the wallet behind it, read from the chain since 2026-01-01, and the taker tape recorded from the order-book feed since 2026-07-25. Query them, get them live over WebSocket, or download a day as Parquet.
“Show the biggest trades in this market today, with the wallet behind each (paste a link)”
polymarket_market_trades“Who bought the most Yes in this market in the last hour, and do they usually win?”
polymarket_market_trades polymarket_walletTwo sets of trades
The chain’s view and the order-book feed’s view of the same market.
| Compare | On-chain trades | Recorded tape |
|---|---|---|
| What it is | every fill settled on Polygon | the taker prints the order-book feed sent |
| Wallet | yes, with maker or taker role | no |
| From | 2026-01-01 | 2026-07-25 |
| API | /markets/{condition_id}/trades | /events?event_type=trade |
| Live | WebSocket pm.trades | — |
| Download | — | trades.parquet, one file a day |
| CLI | vike-data pm market-trades | vike-data pm tape --event-type trade |
| AI | polymarket_market_trades | polymarket_tape |
Who traded, how much, at what price
Every fill settled on Polygon, with the wallet and whether it was the maker or the taker.
Market trades
One market's on-chain trades with the wallet behind each, newest first.
- Route
GET /v1/polymarket/markets/{condition_id}/trades- Cadence
- Continuous; the newest trades are a few minutes behind the chain
- Coverage
- API: one market's trades, newest first, keyset-paged — pass next_cursor back as cursor, limit up to 10,000 (the MCP tool too; its default page is 100); from_ms and to_ms bound the window. From 2026-01-01 to a few minutes ago. A row is one order's fill, so a match is several rows (role maker | taker): never add both roles' volume. A few percent of fills are merged away. The recorded order book, which has no wallets, is the Order-book events dataset.
- Rows
Fields
| Field | Type | Description |
|---|---|---|
ts | integer | The block's time, epoch milliseconds (whole seconds) |
tx_hash | string | Transaction hash, 0x-prefixed |
log_index | integer | Position of the fill in the block; orders the fills of one transaction |
block_number | integer | Polygon block |
proxy_wallet | string | The Polymarket proxy wallet that placed the order, 0x-prefixed |
name | string | Polymarket display name; empty when unset |
pseudonym | string | Polymarket-generated pseudonym; empty when unset |
side | string | BUY | SELL of the outcome token |
role | string | maker (a resting order that was hit) | taker (the order that hit it) |
outcome | string | The outcome this token is, e.g. Up |
outcome_index | integer | Position of the outcome in the market's outcome list |
token_id | string | The outcome token traded |
size | number | Shares traded |
price | number | Outcome price, 0–1 |
Real rows
Market trades · rows
Load it
# replace each {placeholder} with your own value
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/polymarket/markets/{condition_id}/trades?limit=50"
import os, requests
r = requests.get(
"https://data.vike.io/v1/polymarket/markets/{condition_id}/trades?limit=50",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
timeout=30,
)
r.raise_for_status()
body = r.json()
import os, requests
import polars as pl
body = requests.get(
"https://data.vike.io/v1/polymarket/markets/{condition_id}/trades?limit=50",
headers={"X-API-KEY": os.environ["VIKE_API_KEY"]},
timeout=30,
).json()
rows = body if isinstance(body, list) else next(v for v in body.values() if isinstance(v, list))
df = pl.DataFrame(rows)
print(df.head())
Full reference for /v1/polymarket/markets/{condition_id}/trades → · back to the catalog
The taker tape, as the order-book feed sent it
Trade prints in time order, recorded alongside the book. No wallet; one file a day in the archive.
Trades
The taker tape alone — trade prints without the book.
- Route
GET /v1/polymarket/events- Cadence
- Continuous; archive one partition per UTC day
- Coverage
- API: /events?event_type=trade, up to 24 hours per call, from 2026-07-25. Archive: trades.parquet per UTC day from 2026-07-25 (CC BY 4.0) — the same prints, with condition_id, and price/size as Float64.
- Rows
Fields
| Field | Type | Description |
|---|---|---|
token_id | string | The outcome token |
ts | integer | Trade time, epoch milliseconds |
local_ts | integer | Receive time, epoch milliseconds |
seq | integer | Feed sequence number; order trades on ts |
event_type | string | trade |
side | string | buy | sell |
price | number | Outcome price, 0–1 |
size | number | Shares traded |
Real rows
Trades · rows
Load it
# replace each {placeholder} with your own value
curl -H "X-API-KEY: $VIKE_API_KEY" \
"https://data.vike.io/v1/polymarket/events?token_id={token_id}&from_ms={from_ms}&to_ms={to_ms}&event_type=trade&limit=50"
# Full history is the Parquet archive. Pick a date from manifest.json (no key needed),
# download the whole file, then read it locally:
DAY=YYYY-MM-DD
curl -H "X-API-KEY: $VIKE_API_KEY" -O \
"https://data.vike.io/archive/venue=polymarket/date=$DAY/trades.parquet"
# Or the free sample — one complete market, no key:
curl -O https://data.vike.io/archive/samples/trades.parquet
import os, requests
import pyarrow.parquet as pq
H = {"X-API-KEY": os.environ["VIKE_API_KEY"]}
day = "YYYY-MM-DD" # any date listed in https://data.vike.io/archive/manifest.json
url = f"https://data.vike.io/archive/venue=polymarket/date={day}/trades.parquet"
# Download the whole file once, then read it locally — a remote Parquet
# reader re-fetches the footer and column chunks on every query.
with requests.get(url, headers=H, stream=True, timeout=600) as r:
r.raise_for_status()
with open("trades.parquet", "wb") as f:
for chunk in r.iter_content(1 << 20):
f.write(chunk)
table = pq.read_table("trades.parquet")
print(table.num_rows, table.schema.names)
import polars as pl
df = pl.read_parquet("trades.parquet") # downloaded first — see the cURL tab
df = df.with_columns(pl.from_epoch("ts", time_unit="ms").alias("time"))
vwap = (
df.group_by("token_id")
.agg(((pl.col("price") * pl.col("size")).sum() / pl.col("size").sum()).alias("vwap"),
pl.len().alias("prints"))
.sort("prints", descending=True)
)
print(vwap.head())
-- trades.parquet downloaded first (see the cURL tab), then read locally
SELECT token_id,
count(*) AS prints,
sum(size) AS shares,
sum(price * size) / sum(size) AS vwap,
epoch_ms(min(ts)) AS first_print
FROM 'trades.parquet'
GROUP BY token_id
ORDER BY prints DESC
LIMIT 10;
Download whole files, then read them locally — do not point a Parquet reader at the remote URL. Archive downloads need a key but do not count against the hourly limit.
Full reference for /v1/polymarket/events → · back to the catalog
Every big trade the moment it lands
Subscribe once; filter by market, wallet, size, side, role or the wallet’s P&L tier.
import json, os
from websockets.sync.client import connect
with connect("wss://stream.vike.io/v1/stream/polymarket",
additional_headers={"X-API-KEY": os.environ["VIKE_API_KEY"]}) as ws:
ws.send(json.dumps({"action": "subscribe", "id": "s1", "channel": "pm.trades",
"filter": {"min_usd": 1000}}))
for message in ws:
frame = json.loads(message)
if frame["type"] == "ping":
ws.send(json.dumps({"action": "pong"}))
elif frame["type"] == "event":
e = frame["event"]
print(e["subject"]["title"], e["subject"]["outcome"], e["data"]["side"], e["data"]["usd"])
vike-data stream polymarket --channel pm.trades --filter min_usd=1000
{
"action": "subscribe",
"id": "big",
"channel": "pm.trades",
"filter": {
"min_usd": 1000,
"pnl_tier": ["top1", "top5"]
}
}
- Filters:
market,min_usd,pnl_tier,role,side,volume_tier,wallet. pnl_tiertop1/top5follows the best wallets;volume_tierwhalethe biggest.- Every event carries the market, the outcome, the wallet, the side, the size, the price and its dollar value.
- Every channel, its fields and a subscription builder: WebSocket. Volume and buy and sell pressure as studies: Strategies.