# Polymarket Trades Scraper & Whale Monitor - Wallets, Positions (`neverempty/polymarket-trades-whale-monitor`) Actor

Polymarket Trades, one row per fill: time, market, outcome, side, price, shares, USD amount, wallet, tx hash, URL. Filter by market, event, wallet, side or minimum USD. Monitoring returns only trades new since the last run, for whale alerts. Also lists a wallet's open positions.

- **URL**: https://apify.com/neverempty/polymarket-trades-whale-monitor.md
- **Developed by:** [NeverEmpty](https://apify.com/neverempty) (community)
- **Categories:** Developer tools, Automation, Other
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.10 / 1,000 trade returneds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Polymarket Trades Scraper & Whale Monitor - Wallets, Positions

Get **Polymarket trades** as one clean row per trade: when it happened, the market question, the outcome (Yes, No, a team, a candidate), buy or sell, the price, the number of shares, the amount in USD, the wallet address and its public display name, the transaction hash and the market URL. Filter by **market**, **event**, **wallet**, **side** and **minimum USD amount**. A **monitoring mode** returns only the trades that are new since the previous run, so a schedule plus a minimum of $10,000 gives you **whale trades as they happen**. A second data type lists the **open positions of any wallet**.

It reads Polymarket's official public Data API v2 (`data-api.polymarket.com/v2`), the one Polymarket's own documentation points developers and AI agents to. No login, no API key, no wallet, no proxy. It only reads; it never places or copies an order.

### Why this Actor

- **Built on Data API v2.** Polymarket retires the original Data API routes (`/trades`, `/positions` without `/v2`) on **October 24, 2026**. This Actor already uses the v2 routes, which page with a cursor instead of an offset, so it is not limited to the 10,000 most recent rows.
- **A whale monitor that does not drop or repeat trades.** Monitoring compares trades by identity, not by "newer than the last timestamp". Five large trades in the same second all come back; a trade that Polymarket lists a few minutes late still comes back; a trade you already received never comes back twice.
- **One Actor for the feed, a market, an event, or a wallet.** Follow every $10,000+ trade on Polymarket, every trade in one market or one event, or everything a list of wallets does. Filters can be combined.
- **Wallet positions too.** Set `dataType` to `positions` to get what a wallet holds right now: shares, average entry price, current price and value, realized and unrealized profit.
- **Filters are applied twice.** Minimum amount, side, market and wallet are sent to Polymarket and checked again on every row, so a trade outside your filters is never returned or charged.
- **Honest empty results.** An unknown market, a filter with no match, a refusal, a rate limit and a list cut off part-way each come back as a separate free row that says what happened. A value Polymarket does not give is `null`, never 0.

Sister Actors: **[Polymarket Markets Scraper & Monitor](https://apify.com/neverempty/polymarket-markets-monitor)** for prices, volume and newly listed markets on Polymarket, **[Kalshi Markets Scraper](https://apify.com/neverempty/kalshi-markets-scraper)** for market prices from Kalshi, and **[Polymarket Weather Markets](https://apify.com/neverempty/polymarket-weather-markets)** for temperature markets with the weather forecast on the same row.

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `dataType` | select | `trades` | `trades` (one row per trade) or `positions` (one row per open position of each wallet in `wallets`). |
| `markets` | list | (none) | Market slugs, `0x` condition ids, or polymarket.com market addresses. An event address or event slug is read as the whole event. Empty = every market. |
| `events` | list | (none) | Event slugs, numeric event ids, or polymarket.com/event/... addresses. Trades from every market of the event. |
| `wallets` | list | (none) | Wallet addresses (`0x` + 40 hex characters) or polymarket.com/profile/0x... addresses. Empty = every wallet. Required for positions. |
| `minUsd` | integer | (none; prefilled: 10000) | Trades: only trades of at least this many dollars. Positions: only positions currently worth at least this much. |
| `side` | select | `ANY` | `ANY`, `BUY` or `SELL`, from the point of view of the wallet in the row. Trades only. |
| `tradedWithinHours` | integer | (none) | Trades only: stop at trades older than this many hours. Not used in monitoring mode. |
| `maxResults` | integer | 1000 | The most rows returned and charged in one run (up to 50,000). Newest trades first. |
| `monitoringMode` | boolean | false | Return only the trades that are new since the previous run with the same filters. See below. |
| `resetMonitoringState` | boolean | false | Forget the saved starting point for these exact filters. |

No field is required. With an empty input you get the 1,000 most recent trades across all of Polymarket.

#### Examples

Whale trades of $10,000 or more, checked on a schedule:

```json
{ "minUsd": 10000, "monitoringMode": true }
```

The latest 500 trades of $1,000 or more in one market:

```json
{ "markets": ["https://polymarket.com/event/<event-slug>/<market-slug>"], "minUsd": 1000, "maxResults": 500 }
```

Everything two wallets bought in the last 24 hours:

```json
{ "wallets": ["0x1111111111111111111111111111111111111111", "0x2222222222222222222222222222222222222222"], "side": "BUY", "tradedWithinHours": 24 }
```

What a wallet holds now, positions worth $100 or more:

```json
{ "dataType": "positions", "wallets": ["0x1111111111111111111111111111111111111111"], "minUsd": 100 }
```

### Output

One row per trade (`recordType: "trade"`):

```json
{
  "source": "polymarket-data-api",
  "status": "ok",
  "recordType": "trade",
  "tradeId": "5f0c1d2e3a4b5c6d7e8f9a0b",
  "tradedAt": "2026-10-05T14:38:55.000Z",
  "marketQuestion": "Example market question?",
  "outcome": "Yes",
  "outcomeIndex": 0,
  "side": "BUY",
  "price": 0.42,
  "shares": 35000,
  "amountUsd": 14700,
  "wallet": "0x1111111111111111111111111111111111111111",
  "walletName": "example-trader",
  "walletPseudonym": null,
  "walletUrl": "https://polymarket.com/profile/0x1111111111111111111111111111111111111111",
  "transactionHash": "0x…",
  "transactionUrl": "https://polygonscan.com/tx/0x…",
  "marketUrl": "https://polymarket.com/event/example-event/example-market",
  "marketSlug": "example-market",
  "eventSlug": "example-event",
  "conditionId": "0x…",
  "tokenId": "7864…",
  "timestamp": 1791211135,
  "scrapedAt": "2026-10-05T14:47:10.000Z"
}
```

- `amountUsd` is **shares × price**, rounded to 4 decimals. It is the same number Polymarket's own minimum-amount filter uses (checked on 2026-10-05: with a $10,000 minimum, the smallest of 12,000 returned trades was exactly $10,000.00). It does **not** include fees: compared with the cash amount Polymarket shows in a wallet's activity for the same trade, 444 of 712 trades differed by 1% or more (up to about 5%).
- `side` is from the point of view of `wallet`. By default Polymarket lists each fill once, on the side of the wallet that took the order.
- `tradeId` is built from the transaction hash, token, wallet, side, shares, price and time. Polymarket does not publish a trade id.
- `walletName` and `walletPseudonym` are the public display names shown on the wallet's Polymarket profile; `null` when the wallet has none. Wallet addresses are public on the Polygon blockchain. This Actor does not look up real names, emails or any other identity for a wallet.
- `outcome` and `outcomeIndex` are `null` when Polymarket could not label the outcome; `marketQuestion` is `null` when Polymarket has not attached market details to the trade yet.

One row per position (`recordType: "position"`): `wallet`, `walletName`, `marketQuestion`, `outcome`, `shares`, `avgPrice`, `currentPrice`, `currentValueUsd`, `entryCostUsd`, `realizedPnlUsd`, `unrealizedPnlUsd`, `totalPnlUsd`, `percentPnl`, `positionStatus` (`OPEN` or `REDEEMABLE`: the market resolved and the tokens are still held, which includes losing sides), `redeemable`, `mergeable`, `negativeRisk`, `marketEndDate`, `firstEntryAt`, `lastEventAt`, `marketUrl`, `marketSlug`, `eventSlug`, `eventId`, `conditionId`, `tokenId`. Profit columns are Polymarket's own figures and are not recalculated.

Rows that are not data have a different `status` and a `note` in plain words. They are never charged:

| `status` | Meaning |
|---|---|
| `invalid-input` | The input was not accepted (for example a wallet that is not an address). Nothing was read. |
| `market-not-found` | Polymarket has no market or event with that slug. |
| `no-trades-matched` / `no-positions-matched` | Polymarket answered and nothing matches. Polymarket gives the same empty answer for a wallet address it has never seen. |
| `baseline-recorded` | First monitoring run: the starting point was saved. |
| `no-new-trades-since-last-run` | Monitoring: nothing new since the previous run. |
| `incomplete` | Part of the list could not be read, or more rows were ready than `maxResults` allows. |
| `budget-reached` | The run hit the maximum charge you set; the remaining rows were not charged. |
| `blocked` / `unreadable` / `disallowed-by-robots` | Polymarket refused, could not be read, or its robots.txt no longer allows the route. Never reported as "no trades". |

### Monitoring mode

1. The **first run** with a given set of filters saves a starting point and returns no trade. It is free.
2. Each **later run** with the same filters returns only the matching trades that appeared since the previous run, oldest first.
3. A run that finds nothing new returns one free `no-new-trades-since-last-run` row and is charged one scan check.

Details that matter:

- Each run reads back 10 minutes before the previous run and skips the trades it has already returned, so trades that share a second, and trades that Polymarket lists late, are neither dropped nor repeated. A trade that Polymarket lists more than 10 minutes after it happened can be missed.
- Because Polymarket's answers can be a few minutes behind (see Freshness below), the first run after the starting point can include trades from the last few minutes before it. They are trades you have not received yet.
- If a run stops at `maxResults` or at your maximum charge, the trades that were not returned are not marked as returned; the next run returns them.
- If Polymarket cannot be read, nothing is charged and the starting point does not move.
- The memory is kept per set of filters (markets, events, wallets, `minUsd`, `side`). Changing a filter starts a new first run. `maxResults` is not part of it.
- If more than 200,000 trades match between two runs (possible only without filters and with long gaps), the oldest ones are skipped and a free `incomplete` row says from when.

### Pricing

Pay per event, no start fee:

| Event | Free plan | Bronze | Silver | Gold and above |
|---|---|---|---|---|
| `trade-returned` (per 1,000 trade rows) | $3.00 | $2.70 | $2.40 | $2.10 |
| `position-returned` (per 1,000 position rows) | $3.00 | $2.70 | $2.40 | $2.10 |
| `scan-checked` (per 1,000 monitoring runs that found nothing new) | $0.50 | $0.50 | $0.50 | $0.50 |

The first monitoring run, runs that could not read Polymarket, and all rows with a `note` are free.

### Notes and limits

- **Freshness.** Polymarket's API answers may be cached for up to 5 minutes (`cache-control: max-age=300`), so the newest trades can appear a few minutes late. Monitoring picks them up at the next run.
- **How far back.** Polymarket serves the unfiltered feed for the current and previous month, and about three years for a market, an event or a wallet.
- **Up to 20 markets per request.** Longer lists are split into several requests by the Actor; you can pass up to 100 markets, 20 events and 50 wallets.
- **Rate.** The Actor sends at most about 8 requests per second; Polymarket documents 300 requests per 10 seconds for this route.
- **Wallets are addresses.** Polymarket user names cannot be used as input; paste the address from the profile link.
- **Not affiliated** with Polymarket. Data comes from Polymarket's public API as is.
- **Not investment advice.** This Actor reports what was traded. It does not recommend any trade, and following another wallet's trades can lose money. Trading on Polymarket is restricted in some countries; check the rules that apply to you.

### Thanks for using this Actor

We build these tools for people who run them every day, and we improve them from what users tell us.

- **Missing a field, or need another filter?** Tell us in the **Issues** tab. If the data is there, we add it.
- **Found a bug or a wrong value?** Post the run ID in the **Issues** tab. Wrong data is the thing we fix first.

If this Actor saved you time, a short review helps other people find it.

# Actor input Schema

## `dataType` (type: `string`):

trades = one row per trade (fill). positions = one row per open position held by each wallet listed under Wallets.

## `markets` (type: `array`):

Markets to read, one per line: a market slug, a 0x condition id, or a polymarket.com market address (polymarket.com/event/<event>/<market>). An event address or event slug is read as the whole event. Leave empty for every market. A slug Polymarket does not know comes back as a free row that says so.

## `events` (type: `array`):

Events to read (an event groups several markets), one per line: an event slug, a numeric event id, or a polymarket.com/event/<event> address. Trades from every market of the event are returned.

## `wallets` (type: `array`):

Wallet addresses to follow, one per line: 0x followed by 40 hex characters (the address in a polymarket.com/profile/0x… link, which can also be pasted). Leave empty for every wallet. Required for positions. User names are not accepted.

## `minUsd` (type: `integer`):

Trades: only trades of at least this many dollars (shares × price), filtered by Polymarket itself, for example 10000 for whale trades. Positions: only positions currently worth at least this much. Leave empty for no minimum.

## `side` (type: `string`):

Trades only: BUY, SELL or both, from the point of view of the wallet in the row.

## `tradedWithinHours` (type: `integer`):

Trades only: stop at trades older than this many hours. Leave empty for no time limit (reading then stops at Max rows). Not used in monitoring mode, which reads back to the previous run by itself.

## `maxResults` (type: `integer`):

Stop after this many rows (newest trades first; largest positions first). In monitoring mode: the most new trades to return in one run, oldest first; the rest are returned by the next run.

## `monitoringMode` (type: `boolean`):

Trades only. The first run with a given set of filters saves a starting point and returns no trade (free). Each later run with the same filters returns only the matching trades that appeared since the previous run. Schedule it hourly with a minimum amount to get whale trades as they happen. A run that finds nothing new is charged one small scan check.

## `resetMonitoringState` (type: `boolean`):

Forget the saved starting point for these filters before the run, so this run becomes a first run again.

## Actor input object example

```json
{
  "dataType": "trades",
  "minUsd": 10000,
  "side": "ANY",
  "maxResults": 1000,
  "monitoringMode": false,
  "resetMonitoringState": false
}
```

# Actor output Schema

## `results` (type: `string`):

One row per Polymarket trade: time, market question, outcome, side, price, shares, USD amount, wallet address and display name, transaction hash and market URL; in monitoring mode only the trades that are new since the previous run. With dataType positions, one row per open position of a wallet. Unknown markets, filters with no match, refusals and limits come back as free rows that say why.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "minUsd": 10000
};

// Run the Actor and wait for it to finish
const run = await client.actor("neverempty/polymarket-trades-whale-monitor").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "minUsd": 10000 }

# Run the Actor and wait for it to finish
run = client.actor("neverempty/polymarket-trades-whale-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "minUsd": 10000
}' |
apify call neverempty/polymarket-trades-whale-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,neverempty/polymarket-trades-whale-monitor"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/LAT43Uz4n8QjpIgvo/builds/EhapglWMNtBNXW0lw/openapi.json
