NEW: Live arbitrage across 10+ prediction markets.Arbitrage →
← Index
APIOct 15, 2026

Polymarket Top Holders API (2026): See Who Holds Each Market

Polymarket Top Holders API (2026): See Who Holds Each Market

The Short Answer

Polymarket publishes every market's largest holders through its public Data API at GET https://data-api.polymarket.com/v2/holders, with the market's condition id in condition. Holders come back grouped by outcome token, netted per wallet and sorted by shares held: 100 per outcome by default, up to 1,000 per page, with a cursor for the rest. Add include_pnl=true for each holder's entry price, current value and profit. No API key is needed, and the unified SDK wraps the endpoint as listMarketHolders(). In our checks on 3 October 2026, a full walk of the JD Vance 2028 market found 3,261 wallets holding at least one Yes share, and the ten largest held 68.5% of the net Yes position.

Key Takeaways

  • condition is required and takes up to 20 markets, or exactly one with include_pnl=true.
  • limit counts rows per outcome: 100 by default, 1,000 at most, or 100 with include_pnl. Deeper pages come only from the cursor.
  • Amounts are net per wallet by default, so a fully hedged wallet shows as zero. include_pnl=true switches to gross amounts per side.
  • To measure concentration, walk every page, sum each outcome's amounts and take the top holders' share of that total.
  • Compare sides in dollars rather than shares, and watch for addresses that hold the same side across a whole family of markets.

How do you get a market's top holders from the Polymarket API?

Pass the market's condition id, the 0x value Gamma returns as conditionId. Finding it is covered in how to find a Polymarket market ID. Then request the holders:

curl -s "https://data-api.polymarket.com/v2/holders?condition=0xYOUR_CONDITION_ID&limit=10"

The response holds one group per outcome token, each sorted by amount, largest first. Fields are trimmed here:

{
  "data": [
    {
      "token_id": "16040015440196279900485035793550429453516625694844857319147506590755961451627",
      "holders": [
        {
          "proxy_wallet": "0x...",
          "amount": 582055.217948,
          "outcome_index": 0,
          "name": "...",
          "pseudonym": "...",
          "verified": false,
          "display_username_public": true
        }
      ]
    }
  ],
  "pagination": { "limit": 10, "offset": 0, "has_more": true, "next_cursor": "eyJkYXRh..." }
}

amount is in shares. outcome_index follows the market's outcomes, so on a Yes or No market 0 is Yes and 1 is No. proxy_wallet is the account wallet, the address every wallet-keyed Data API endpoint accepts as user, so you can go straight from a holder to its positions and activity.

What parameters does the holders endpoint take?

ParameterWhat it does
conditionRequired. Comma-separated condition ids, at most 20, or exactly one with include_pnl
limitRows per outcome token. Default 100, maximum 1,000, or 100 with include_pnl
cursorThe previous page's next_cursor. It carries the page window and overrides limit
min_balanceMinimum balance in shares, applied after netting. Default 0
include_pnlAdds position economics and switches amounts to gross per side. Default false

Every holder row carries proxy_wallet, amount, outcome_index, token_id, name, pseudonym, bio, verified, display_username_public and profile image URLs. With include_pnl=true, rows add avg_price, entry_cost_usdc, current_price, current_value, realized_pnl, unrealized_pnl and total_pnl.

What limits apply to the holders endpoint?

  • Errors are explicit. In our checks, a missing condition returned a 400 saying the parameter was not provided, and a malformed id returned "invalid condition id". A limit over 1,000, or include_pnl with a limit over 100 or two markets, also returned 400s naming the problem. A valid market with no holdings returns an empty data array.
  • Paging is cursor-only. All outcome groups advance together, and a group drops out once its token runs out. In one five-page walk, the No group ended on page 2 while Yes ran to page 5, so merge pages by token_id, never by array position.
  • Responses are cached. Each response carried Cache-Control: public, max-age=120 in our checks, so a holder list can be up to two minutes old.
  • Rate limits are shared. As of October 2026, Polymarket lists 800 requests per 10 seconds across all /v2 endpoints, with no separate figure for holders.
  • Resolved markets thin out. Winners redeem and burn their tokens, so the list skews to the losing side. On the resolved "Fed rate hike in 2026?" market, 144 wallets still held 9,655 net Yes shares while 929 held 1.35 million No shares.

Does the holders endpoint show net or gross positions?

Net, by default. Each wallet's Yes and No balances are netted: in our checks, a wallet holding 15,725 Yes and 115,116 No shares appeared only as a No holder of 99,391. A fully hedged wallet nets to zero and still appears at the default min_balance of 0. In our walk of the JD Vance market, 1,244 of 4,884 Yes rows were zero, so set min_balance=1 to drop them along with dust.

include_pnl=true shows gross balances per side instead, so a wallet holding both outcomes appears under both tokens. That changes the picture. The two largest gross holders of the JD Vance market held 6,000,000 and 3,689,354 shares of each outcome, bought at an average of 50 cents, and both net to zero in the default view. Use net amounts for directional exposure and gross amounts for who holds the tokens and how their positions are doing.

For per-position rows sorted by value or profit, /v2/positions also accepts a market anchor. condition takes exactly one id there, rows are gross per side, sort_by accepts CURRENT_VALUE, TOKENS, TOTAL_PNL and more, and a page holds up to 1,000 rows.

How do you read holder concentration?

Concentration is the share of an outcome held by its largest wallets. You need the whole list for the denominator, so walk every page, then sum. This runs on Node 18 or newer, with the condition id as its argument:

const BASE = 'https://data-api.polymarket.com';

async function allHolders(conditionId, minBalance = 1) {
  const byToken = new Map();
  let cursor = null;
  do {
    const url = new URL('/v2/holders', BASE);
    url.searchParams.set('condition', conditionId);
    url.searchParams.set('min_balance', String(minBalance));
    if (cursor) url.searchParams.set('cursor', cursor);
    else url.searchParams.set('limit', '1000');

    const res = await fetch(url);
    if (!res.ok) throw new Error(`holders returned ${res.status}`);
    const { data, pagination } = await res.json();

    for (const group of data) {
      const rows = byToken.get(group.token_id) ?? [];
      rows.push(...group.holders);
      byToken.set(group.token_id, rows);
    }
    cursor = pagination.next_cursor;
  } while (cursor);
  return byToken;
}

const holders = await allHolders(process.argv[2]);

for (const rows of holders.values()) {
  const amounts = rows.map((h) => h.amount).sort((a, b) => b - a);
  const total = amounts.reduce((sum, x) => sum + x, 0);
  const share = (n) => amounts.slice(0, n).reduce((sum, x) => sum + x, 0) / total;
  const hhi = amounts.reduce((sum, x) => sum + (x / total) ** 2, 0) * 10_000;
  console.log({
    outcome: rows[0].outcome_index,
    holders: rows.length,
    netShares: Math.round(total),
    top1: share(1).toFixed(3),
    top10: share(10).toFixed(3),
    hhi: Math.round(hhi),
  });
}

top1 and top10 are the shares of the outcome's net total held by the largest wallet and the ten largest. hhi is the Herfindahl index on a 0 to 10,000 scale: near 0 for a widely held outcome, 10,000 for a single holder. On every open market we walked, the two sides' net totals agreed to within 0.001%, a quick check that a walk is complete.

Here is what it returned on 3 October 2026, counting wallets with at least one share:

MarketSideHoldersTop holderTop 10HHI
JD Vance wins 2028 electionYes3,26118.4%68.5%751
JD Vance wins 2028 electionNo1,18083.7%95.9%7,043
No Fed change in October 2026Yes1,4818.7%49.7%327
No Fed change in October 2026No42584.7%95.2%7,196
U.S. invades Iran before 2027Yes3,62113.8%61.4%588
U.S. invades Iran before 2027No2,7887.1%36.6%208

Two checks keep the numbers honest:

  • Look for holders that recur across markets. The dominant No holder in both of the first two markets was the same unnamed address. It held No shares in all 16 negative-risk markets we sampled, was the largest No holder in 15, and held the same 2,649,746 No shares in each of the nine 2028 election markets we checked. It held nothing in the seven standard markets we checked. An identical position across candidates is not a view on any one of them. Leave it out and the top No holder's share falls to 33.7% in the JD Vance market and 16.0% in the Fed market.
  • Compare sides in dollars. In the Iran market, trading at 15.5 cents, the largest Yes position held 1.06 million shares worth about $164,000, while the largest No position held 546,000 shares worth about $461,000. The current_value field on /v2/positions gives the dollar view directly.

How do you get holders with Polymarket's SDK?

The unified TypeScript SDK returns the same groups through a paginator:

import { createPublicClient } from '@polymarket/client';

const client = createPublicClient();
const conditionId = '0xYOUR_CONDITION_ID';

const pages = client.listMarketHolders({ conditionIds: [conditionId], pageSize: 10, minBalance: 1 });
const { items } = await pages.firstPage();

for (const group of items) {
  for (const holder of group.holders) {
    console.log(holder.outcomeIndex, holder.wallet, holder.amount, holder.name ?? holder.pseudonym);
  }
}

Each item is one outcome group with an assetId and its holders. The SDK renames proxy_wallet to wallet and returns amount as a decimal string. pageSize applies to each outcome separately, and includePnl: true adds the position economics for one market at up to 100 rows. The Python SDK's equivalent is list_market_holders().

How do you get holders on other prediction markets?

The Predictefy API serves holders on Polymarket, Myriad and Limitless in one row shape, next to normalized market data from 15+ venues:

import Predictefy from '@predictefy/sdk';

const client = new Predictefy({ apiKey: process.env.PREDICTEFY_API_KEY });

const polymarketHolders = await client.polymarket.fetchHolders('0xYOUR_CONDITION_ID', { limit: 20 });
const limitlessHolders = await client.limitless.fetchHolders('your-market-slug', { limit: 20 });

for (const row of [...polymarketHolders, ...limitlessHolders]) {
  console.log(row.outcomeId, row.wallet, row.displayName ?? '', row.shares, row.usdValue);
}

Each row carries wallet, displayName, outcomeId, shares and usdValue, whichever venue it came from, and client.myriad.fetchHolders() works the same way. Pair it with fetchWalletProfile() to score the wallets behind a concentrated outcome.

Frequently Asked Questions

Does Polymarket have a top holders API?

Yes. GET /v2/holders on data-api.polymarket.com returns the largest holders of each outcome in a market, sorted by shares held, with no API key. Pass the market's condition id as condition, and follow the cursor for more than one page.

How many holders can I get per request?

Up to 1,000 per outcome token on each page, with 100 as the default. With include_pnl=true the maximum is 100. Deeper pages come only from the cursor, and a full walk of a large market took four or five requests in our checks.

Why do some holders show an amount of 0?

Because amounts are netted per wallet. A wallet holding equal Yes and No shares nets to zero and still appears while min_balance is 0, its default. Set min_balance=1 to drop those rows and dust.

Why does the same wallet appear under both outcomes?

You requested include_pnl=true, which switches to gross balances per side. A wallet holding both outcomes then appears under each token with that side's size and economics, matching what /v2/positions reports for the same wallet.

Can I see holders' profit and loss?

Yes. Add include_pnl=true for one market at a time, with a limit of 100 or less. Each row then carries avg_price, entry_cost_usdc, current_price, current_value, realized_pnl, unrealized_pnl and total_pnl.

How do I measure how concentrated a Polymarket market is?

Walk every holders page for the market, sum the amounts for each outcome, and divide the largest holders' amounts by that total. Check whether a dominant address recurs across related markets, and compare sides in dollars rather than shares before drawing conclusions.