# How to Find Polymarket Whales Making Millions and Copy Them

Pull any Polymarket wallet's full record from the free Data API and pick the whales worth copying in about two minutes each. One Python script shows the real win rate with every loser counted, and the top monthly wallet went from 87.7% to 42.2% once we did.

From the book: [Polymarket Profits](https://youcanbuildthings.com/books/polymarket-profits.md)

Web page: https://youcanbuildthings.com/articles/polymarket-whale-tracker

Hello builders,

You can copy the Polymarket wallets that are making millions this month, and you can pick them yourself in about two minutes each, for free. The post that sold a lot of people on copy trading promised a bot that "makes ~$65k per month", through referral links in a paid partnership. When I checked the wallet behind it, `blue-walnut`, for the book, its best month was +$63,389, its lifetime realized profit was $108,193, and it stopped trading within a month of the post. This Polymarket whale tracker is the script from my book that pulls a wallet's whole record before you put a dollar behind it.

## Four free endpoints

Every Polymarket trade is public, and the Polymarket Data API serves it with no key. We only need four endpoints, all under `https://data-api.polymarket.com/v2`.

The four:

- `leaderboard?time_period=month` for the top 100 wallets by profit (`day`, `week`, `month` or `all`)
- `user-stats?user=<wallet>` for trade count and biggest win
- `positions?user=<wallet>` for every position with its profit, plus `status=closed` for the ones sold or cashed out
- `trades?user=<wallet>` for the latest trades, which the alert script in the book watches

The [monthly leaderboard](https://data-api.polymarket.com/v2/leaderboard?time_period=month) shows profit and volume for each wallet and nothing about how many bets it lost. The top wallet when I ran it, `BreakTheBank`, shows **$8,377,431** of profit, and #5 shows **$2,219,768** on a volume of **4,602.99**, and the script below shows that same wallet with 27 trades against 5,000-plus resolved positions, which is a wallet I skip. So we pull the positions ourselves.

Save this as `whales.py` (Python 3, `pip install requests`):

```python
import requests

DATA = "https://data-api.polymarket.com/v2"

def get(path, **params):
    r = requests.get(f"{DATA}/{path}", params=params, timeout=30)
    r.raise_for_status()
    return r.json()

def leaderboard(period="month"):
    return get("leaderboard", time_period=period)["data"]

def positions(wallet, status=None, max_pages=10):
    rows, cursor = [], None
    for _ in range(max_pages):
        params = {"user": wallet, "limit": 500}
        if status:
            params["status"] = status
        if cursor:
            params["cursor"] = cursor
        page = get("positions", **params)
        rows += page["data"]
        cursor = page["pagination"].get("next_cursor")
        if not page["pagination"].get("has_more"):
            return rows, True    # the whole history
    return rows, False           # capped: win rate reads high

def vet_wallet(wallet):
    stats = get("user-stats", user=wallet)["data"]
    closed, ok1 = positions(wallet, "closed")
    rest, ok2 = positions(wallet)
    # a bet that resolved at $0 is never cashed out: it sits
    # in REDEEMABLE, so count it or every loser vanishes
    done = closed + [p for p in rest if p["status"] == "REDEEMABLE"]
    pnls = sorted((p["total_pnl"] for p in done), reverse=True)
    wins = sum(1 for x in pnls if x > 0)
    return {"trades": stats["trades"], "resolved": len(pnls),
            "complete": ok1 and ok2,
            "win_rate": wins / len(pnls) if pnls else 0.0,
            "pnl_ex_best": sum(pnls[1:])}

if __name__ == "__main__":
    for row in leaderboard("month")[:5]:
        v = vet_wallet(row["user_id"])
        flag = "" if v["complete"] else " *"
        print(f"#{row['rank']} {row['user_name'][:16]} trades={v['trades']:,} "
              f"resolved={v['resolved']:,} win={v['win_rate']:.0%} "
              f"ex-best=${v['pnl_ex_best']:,.0f}{flag}")
        print(f"   https://polymarket.com/profile/{row['user_id']}")
```

Run `python3 whales.py`. Five wallets took me about 40 seconds:

```
#1 BreakTheBank trades=1,266 resolved=1,317 win=42% ex-best=$8,231,518
#2 joseph00677 trades=23 resolved=23 win=43% ex-best=$3,739,479
#3 e46m3 trades=58,255 resolved=5,035 win=100% ex-best=$3,277,831 *
#4 Diabolical-Prize trades=411 resolved=399 win=48% ex-best=$115,172
#5 0xb0e74DF9430A08 trades=27 resolved=5,000 win=100% ex-best=$544,295 *
```

(I left out the profile link it prints under each row.) `ex-best` is the profit of the wallet with its single best win taken out. `trades` comes from user-stats and `resolved` counts positions, two different counters, so they won't match.


## Count the losers too

#1 won 42% of 1,317 resolved bets and is up $8,231,518 with its best win removed, which tells us its winners were bigger than its losers. #2 has 23 resolved bets, too few to judge. The `*` rows hit the ten-page cap, and since the API returns the biggest winners first, a capped row reads too high, which is why both show 100%. We skip those or raise `max_pages`.

The comment in `vet_wallet` matters most. A bet that resolved at $0 never gets sold or cashed out, so it never shows up under `status=closed`. I ran #1 both ways: its 633 closed positions were 87.7% winners, and adding its 684 `REDEEMABLE` positions, where the losers sit, took it to 42.2%.

![Polymarket whale tracker win rates versus profit, monthly leaderboard of other people's wallets: #1 1,186 trades, 1,223 resolved, 43% win, $7,756,273 profit without best win; #2 22 trades, 22 resolved, 45%, $5,363,534; #3 411, 399, 48%, $115,172; #4 57,136 trades, 5,022 resolved, 100%, $2,969,459, partial, win rate reads too high; #5 45,312, 9,444, 54%, $58,897,911, partial; count only closed positions and #1 shows 87%, count the losers too: 43%](https://youcanbuildthings.com/images/articles/polymarket-whale-tracker/polymarket-whale-win-rate-count-the-losers.png)

That is the same script on the test run in the book, in an earlier month, when #1 went from 87% to 43% the same way.

## The two-minute vetting

For each wallet that survives the script, I open the profile link it prints and answer three questions. What is its profit without its best single trade? How many market categories does it trade profitably? Does the profile show at least one losing month in the last six? A wallet goes on my copy list when all three come back good, with 100+ resolved positions and 90+ days of profit.

Then we size each copy to your own bankroll. In the book's made-up example, a whale puts about 2.5% of a $500,000 portfolio on No at $0.62. With $2,000 you put in 2.5%, or $50, and you get filled at $0.64 because the price moved. If it resolves No, the 78 shares pay $1 each and the profit is $0.36 a share, $28.08. The taker fee you paid to buy them, at the 0.04 rate the book uses for this example, is 0.04 × 0.64 × 0.36 per share, about $0.72 in all, which leaves $27.36. If the price has moved more than 3-5 cents from the entry the whale got, we skip the trade, and we spread the copies across 3-5 vetted whales so one bad actor cannot wreck the account.

Now go build something this weekend!

John Cook

---

Get the book: Polymarket Profits, $12.99 on Amazon: https://amzn.to/4taBIo7
