# Polymarket Scraper: Markets, Order Books & Top Holders (`omaraw/polymarket-scraper`) Actor

Polymarket markets ranked by 24h volume or liquidity, or any market in depth: order book per outcome, 24h price range, recent trades, top holders and open interest. $1.75 per 1,000 results, one flat rate, error rows free.

- **URL**: https://apify.com/omaraw/polymarket-scraper.md
- **Developed by:** [itnlab](https://apify.com/omaraw) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.20 / 1,000 items

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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 Scraper: Markets, Order Books & Top Holders

Get Polymarket prediction-market data as clean dataset rows, in one of two ways:

- **Market list.** Every open market ranked by 24-hour volume (or by liquidity), as many as you want, up to 10,000 per run.
- **Market insight.** The markets you name, each read in depth. You get the order book for every outcome, the 24-hour price range, the latest trades, the biggest holders and the open interest, all in one row.

It costs **$1.75 per 1,000 results**, one flat rate for every plan. Rows that explain a failure are free.

### What you get

**Market list rows** (`type: "market"`) carry, for each market:

- the question, event, URL, slug and ids;
- outcome names and prices;
- 24-hour and all-time volume;
- liquidity, best bid and ask, and spread;
- the last trade price and the 1-hour and 24-hour price change;
- start and end dates and status.

**Insight rows** (`type: "insight"`) carry all of the above, plus:

- **`outcomeStats`**, per outcome:
  - `book`: best bid and ask, spread, mid, notional depth on each side, and the top price levels (5 by default, up to 50);
  - `price24h`: open, close, change, low and high over the last day.
- **`recentTrades`**: the newest trades (15 by default, up to 500), with time, side, outcome, price, size, wallet and the public name Polymarket shows.
- **`topHolders`**: the largest positions per outcome (10 by default, up to 20), by wallet and public name.
- **`openInterest`**: the value of all open positions in USDC.
- **`sectionErrors`**: any section that could not be read this time. The rest of the row is still delivered.

### How to use

1. Pick **What to collect**: *Market list* or *Market insight*.
2. For a list, set **Markets to list** and **Rank by**. For insight, paste market URLs such as `https://polymarket.com/event/<event>/<market>`, market slugs or numeric ids.
3. Run it, then download the dataset as JSON, CSV or Excel, or read it through the Apify API.

An event URL works when the event holds a single market. For an event with several markets, such as an election with one market per candidate, open the candidate you want and paste that URL.

### Pricing

**$1.75 per 1,000 results**, charged as each row lands in your dataset:

| You collect | You pay |
| --- | --- |
| The top 100 markets by 24h volume | $0.175 |
| 1,000 markets | $1.75 |
| 10 markets in depth | $0.0175 |

The spending limit you set on a run is respected before a row is written, never after. An insight row counts as one result however many trades and holders are nested in it. Error rows are not charged.

### Input example

```json
{
  "mode": "insight",
  "markets": [
    "https://polymarket.com/event/nba-2027-champion/will-oklahoma-city-thunder-win-the-2027-nba-finals"
  ],
  "bookDepth": 5,
  "tradesLimit": 15,
  "holdersLimit": 10
}
```

### Output example

A real row from 2026-09-30, cut down to one price level, one trade and one holder. Wallets are shortened here and the public names replaced; the dataset has them in full.

```json
{
  "type": "insight",
  "id": "2243320",
  "question": "Will Oklahoma City Thunder win the 2027 NBA Finals?",
  "url": "https://polymarket.com/event/nba-2027-champion/will-oklahoma-city-thunder-win-the-2027-nba-finals",
  "eventTitle": "NBA: 2027 Champion",
  "outcomes": ["Yes", "No"],
  "outcomePrices": [0.185, 0.815],
  "volume": 651438.30,
  "volume24h": 80452.79,
  "liquidity": 295013.75,
  "bestBid": 0.18,
  "bestAsk": 0.19,
  "oneDayPriceChange": -0.01,
  "endDate": "2027-07-01T03:59:00Z",
  "openInterest": 109722.04,
  "outcomeStats": [
    {
      "outcome": "Yes",
      "price": 0.185,
      "book": {"bestBid": 0.18, "bestAsk": 0.19, "spread": 0.01, "mid": 0.185,
               "bidDepth": 16615.85, "askDepth": 10935.50,
               "bids": [{"price": 0.18, "size": 41765.54}], "asks": [{"price": 0.19, "size": 49649.18}]},
      "price24h": {"points": 25, "open": 0.195, "close": 0.185, "change": -0.01, "low": 0.185, "high": 0.195}
    }
  ],
  "recentTrades": [{"time": "2026-09-30T07:02:03Z", "side": "SELL", "outcome": "Yes", "price": 0.18,
                    "size": 30895.0, "wallet": "0x2b51…", "name": "trader-a"}],
  "topHolders": [{"outcome": "Yes", "wallet": "0xcbba…", "name": "trader-b", "amount": 81651.53}],
  "sectionErrors": [],
  "collectedAt": "2026-09-30T15:05:49Z"
}
```

### FAQ

**Where does the data come from?** From Polymarket's own public market-data APIs, read live at run time. Nothing is served from a cache. `collectedAt` says when each row was read.

**Do I need a Polymarket account or an API key?** No. Everything here is public and read-only. The Actor never trades.

**How fresh is it?** Prices and books are read when your run asks for them, usually a second or two before the row lands.

**What about wallets?** Trades and holders show the wallet address and the public name Polymarket displays next to it. Nothing else about the person is collected: no bios and no pictures.

**Why did a market come back as an error row?** The error row says why, for example a URL that names an event with several markets, or a market that does not exist. Error rows are free. A line that is not a Polymarket URL, slug or id at all is refused by the input form before the run starts, so it costs nothing.

# Changelog

This Actor's version history is a separate document: https://apify.com/omaraw/polymarket-scraper/changelog.md

# Actor input Schema

## `mode` (type: `string`):

'markets' returns the market list, one row per market, ranked by the order below. 'insight' reads the markets you name in depth, one row per market with its order books, 24-hour price range, recent trades, top holders and open interest nested.

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

Market list only. How many markets to return, from the top of the ranking. Polymarket has tens of thousands of open markets; each row is one result.

## `sortBy` (type: `string`):

Market list only. 24-hour trading volume or current liquidity, highest first.

## `includeClosed` (type: `boolean`):

Market list only. Off lists open markets only. On also admits resolved markets; they rank low by 24-hour volume because nobody trades them.

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

Insight mode only. Polymarket market URLs (https://polymarket.com/event/<event>/<market>), market slugs or numeric market ids, up to 500. An event URL works when the event holds a single market; for an event with several, give the URL of the one you want. Anything else is refused before the run starts.

## `bookDepth` (type: `integer`):

Insight mode only. Price levels kept on each side of each outcome's order book, best first.

## `tradesLimit` (type: `integer`):

Insight mode only. How many of the market's most recent trades to nest. 0 skips them.

## `holdersLimit` (type: `integer`):

Insight mode only. The biggest position holders per outcome, by wallet and the public name Polymarket shows. 0 skips them.

## Actor input object example

```json
{
  "mode": "markets",
  "maxResults": 100,
  "sortBy": "volume24hr",
  "includeClosed": false,
  "markets": [
    "https://polymarket.com/event/nba-2027-champion/will-oklahoma-city-thunder-win-the-2027-nba-finals"
  ],
  "bookDepth": 5,
  "tradesLimit": 15,
  "holdersLimit": 10
}
```

# Actor output Schema

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

One row per market.

# 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 = {
    "mode": "markets",
    "maxResults": 100,
    "markets": [
        "https://polymarket.com/event/nba-2027-champion/will-oklahoma-city-thunder-win-the-2027-nba-finals"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("omaraw/polymarket-scraper").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 = {
    "mode": "markets",
    "maxResults": 100,
    "markets": ["https://polymarket.com/event/nba-2027-champion/will-oklahoma-city-thunder-win-the-2027-nba-finals"],
}

# Run the Actor and wait for it to finish
run = client.actor("omaraw/polymarket-scraper").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 '{
  "mode": "markets",
  "maxResults": 100,
  "markets": [
    "https://polymarket.com/event/nba-2027-champion/will-oklahoma-city-thunder-win-the-2027-nba-finals"
  ]
}' |
apify call omaraw/polymarket-scraper --silent --output-dataset

```

## MCP server setup

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

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/hm8qX4h0fwBvx82jv/builds/G2u9MrJcJ8ksv5zne/openapi.json
