Polymarket Arbitrage Finder: Dutch-Book Scanner
Pricing
Pay per event
Polymarket Arbitrage Finder: Dutch-Book Scanner
Scans live Polymarket order books for dutch-book arbitrage: outcomes on the same market whose combined best-ask cost is under $1, so buying every outcome locks in a profit before fees regardless of which one resolves true. No login, no API key.

What does Polymarket Arbitrage Finder: Dutch-Book Scanner do?
Polymarket Arbitrage Finder scans live order books across Polymarket's highest-volume active markets. Every market's outcomes always pay out exactly $1 to whichever one resolves true and $0 to the rest, so if you can buy every outcome's best ask for a combined total under $1, you have locked in a profit before fees no matter what happens. This Actor fetches the real best ask and size for every outcome (not the last-trade price, which is not something you can actually transact at), computes the combined cost and the profit percent, and reports the max number of complete sets the current book supports and the total guaranteed profit at that size. It works on binary Yes/No markets and multi-candidate markets alike.
Why use Polymarket Arbitrage Finder: Dutch-Book Scanner?
- Uses the real order book (best ask + size), not the last-trade price shown on Polymarket's site - a price you cannot actually transact at is not a real opportunity.
- Generalizes past Yes/No: a multi-candidate market (e.g. an election with 6 runners) is evaluated the same way, summing every outcome's best ask.
- Reports the max size the opportunity actually supports, not just that one exists - a $5-deep edge and a $5,000-deep edge look the same in a last-trade-only view.
- Honest about what it can't see: Polygon gas and execution slippage are not deducted, and this is stated on every row rather than implied away.
- No API key or login - Polymarket's Gamma and CLOB APIs are public. Billed only for opportunities returned.
What makes this different
Most odds/price tools show you what a market last traded at, which tells you nothing about what you could actually buy right now. This Actor reads the order book itself for every outcome of a market in one pass, so the number it reports - profitPercent, and the size behind it - is the one that determines whether an opportunity is actually worth acting on, not just interesting to look at.
How it works

- Your input — the Actor pulls the highest-volume active markets from Polymarket's public Gamma API (optionally filtered to one category).
- The Actor collects it — for every outcome it fetches the live order book and takes the best (lowest) ask and the size available there.
- Your output — when the outcomes' combined best-ask cost is under $1 by at least your minimum profit %, it reports the opportunity with every leg and the max size.
What data can you extract?
The dataset has 16 fields per row:
| Field | Type | Description |
|---|---|---|
type | string | Always "arbitrage". |
question | string | The market's question text. |
url | string | Best-effort link to the market on polymarket.com. |
endDate | string | The market's resolution date. |
volume | number | The market's total trading volume. |
liquidity | number | The market's current liquidity. |
outcomeCount | number | How many outcomes the market has (2 for Yes/No, more for multi-candidate). |
legs | array | Every outcome's label, best ask price, available size and bookAgeSeconds. |
totalCostPerSet | number | Combined best-ask cost of buying one of every outcome. |
profitPerSetUnits | number | 1 - totalCostPerSet: the guaranteed payout gap per complete set. |
profitPercent | number | profitPerSetUnits as a return on totalCostPerSet. |
maxCompleteSets | number | The largest number of complete sets the current book supports. |
maxGuaranteedProfitUnits | number | maxCompleteSets * profitPerSetUnits: the total profit at that size. |
note | string | Restates that this is before gas/slippage and the book can move. |
demo | boolean | True when the built-in sample was used. |
oldestLegBookAgeSeconds | number | The largest per-leg bookAgeSeconds (how long since the least-recently-traded leg last changed); high values flag an illiquid market, not stale data. |
How to use Polymarket Arbitrage Finder: Dutch-Book Scanner

- Open the Actor and go to the Input tab.
- Leave every field at its default to scan the 200 highest-volume active markets across all categories for at least 1% profit. Set Category tag to focus on one vertical (e.g. "politics", "sports", "crypto"), or raise Minimum profit % to see only larger edges. With no live markets reachable, it runs on a small built-in demo so you can see the output shape.
- Optionally set filters and a Max results limit.
- Click Start. A default run finishes in under a minute.
- Open the Output tab, then download the dataset or connect it to your tools.
Input Parameters
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
tagSlug | string | No | "" | Only scan markets under one Polymarket category, e.g. "politics", "sports", "crypto". Leave empty to scan the highest-volume markets across every category. |
maxMarketsToScan | integer | No | 200 | How many active markets (highest volume first) to fetch order books for. Set 0 for as many as the API returns. |
minProfitPercent | number | No | 1 | Only report a market whose best-ask outcomes leave at least this much profit per $1 payout, before Polygon gas and execution slippage. profitPercent = (1 / totalCostPerSet - 1) * 100. |
minimumValidPrice | number | No | 0.001 | An outcome's best ask below this is treated as bad data and excluded. |
maximumValidPrice | number | No | 0.999 | An outcome's best ask above this is treated as bad data and excluded. |
maxResults | integer | No | 20 | Maximum opportunities returned, highest profit % first. Set 0 to return everything found. |
Output Data

legs lists every outcome with its label, best ask price and the size available at that price. totalCostPerSet is the sum of every leg's best ask - the cost to buy one complete set (guaranteed to be paid exactly $1 back). profitPerSetUnits is 1 - totalCostPerSet; profitPercent is the same profit expressed as a return on capital deployed. maxCompleteSets is the largest number of complete sets the current book supports (capped by the thinnest leg's size); maxGuaranteedProfitUnits is maxCompleteSets * profitPerSetUnits. note restates that this is before Polygon gas and execution slippage, and that the book can move between the snapshot and your fill. bookAgeSeconds on each leg (and oldestLegBookAgeSeconds on the row) is how long since that outcome last traded, not data staleness - every ask here was just fetched live from the order book, so an old value means a quiet, illiquid market, not a stale price.

A real dataset item:
{"type": "arbitrage","question": "Will Team Alpha win the championship?","url": "https://polymarket.com/event/demo-team-alpha-championship","endDate": "2030-01-01T00:00:00Z","volume": 500000,"liquidity": 20000,"outcomeCount": 2,"legs": [{"outcome": "Yes","askPrice": 0.46,"availableShares": 300,"bookAgeSeconds": 0},{"outcome": "No","askPrice": 0.48,"availableShares": 150,"bookAgeSeconds": 0}],"totalCostPerSet": 0.94,"profitPerSetUnits": 0.06,"profitPercent": 6.383,"maxCompleteSets": 150,"maxGuaranteedProfitUnits": 9,"oldestLegBookAgeSeconds": 0,"note": "Before Polygon gas and execution slippage; the book can move between this snapshot and your fill. bookAgeSeconds is how long since that out…","demo": true}
Usage Examples
Scan everything, default 1% threshold
{"maxMarketsToScan": 200,"minProfitPercent": 1,"maxResults": 20}
Politics markets only
{"tagSlug": "politics","maxResults": 20}
Sports prediction markets only
{"tagSlug": "sports","maxResults": 20}
Crypto markets only
{"tagSlug": "crypto","maxResults": 20}
Larger edges only (5%+)
{"minProfitPercent": 5,"maxResults": 0}
Tips for Best Results
- profitPercent is a return on capital, not an annualized rate - a market can resolve in a day or a year, and this Actor does not estimate time-to-resolution.
- A high bookAgeSeconds does not mean the price is stale - the ask was fetched live - it means that outcome has not traded in a while, which usually also means less real depth than the size shown suggests.
- Check maxGuaranteedProfitUnits, not just profitPercent - a huge percent on a $2 max size is not worth acting on after gas.
- Thin, low-volume markets show wider (and less real) apparent edges because their books are shallow - check liquidity and volume alongside profitPercent.
- Run this on a schedule (every few minutes) rather than once, since opportunities are transient by nature.
- Default is 5 results for a fast test. Set the max to 0 to return everything available.
Known Limitations
- Reports the best ask and size at one snapshot; by the time you place real orders, the book may have moved or the size may be gone.
- Polygon gas cost and any execution slippage from partially filling deeper into the book are not deducted from profitPercent.
- Only markets Polymarket's Gamma API lists as active and not closed, with a live order book on every outcome, are evaluated - a market missing a book for any outcome is skipped, not guessed at.
- This is market analysis, not an execution service: it does not place orders, and does not require or store a wallet or API key.
- Polymarket's own matching (fee-free limit orders as of writing) can change; this Actor does not model taker fees if Polymarket introduces them.
Integrations
Run it from the Apify API, on a schedule, or from a webhook. Send results straight to Google Sheets, Make, Zapier, Slack or your own database with Apify's built-in integrations.
Export Formats
Download the dataset as JSON, CSV, Excel, XML, HTML table or RSS from the Output tab or the API.
Frequently Asked Questions
What is a dutch-book / arbitrage opportunity here?
A prediction market always pays exactly $1 to whichever outcome resolves true. If you can buy the best ask of every outcome for a combined total under $1, you lock in the $1 - total gap as profit no matter which one wins, before fees.
Does this use the price shown on Polymarket's website?
No. That is usually the last-trade price, which you cannot necessarily transact at. This Actor reads the live order book and uses the actual best ask you could buy at right now.
Does it work on markets with more than 2 outcomes?
Yes. Multi-candidate markets are evaluated the same way: summing every outcome's best ask against $1.
Is the profit really guaranteed?
Before Polygon gas and execution slippage, and only if you can fill every leg at the reported price and size before the book moves. This Actor states that caveat on every row rather than implying a guarantee.
Does this place trades for me?
No, it only reports the math. Trading on Polymarket is up to you, on your own wallet.
Am I charged for markets with no opportunity?
No, only for opportunities returned.
Do I need an account or login?
No. Polymarket's Gamma and CLOB APIs are public; no wallet, account or API key is used or required.
Am I charged for failed runs or empty results?
You are only charged for results that are actually written to the dataset.
Can I run it on a schedule?
Yes. Create a Task with your input and add a schedule in Apify Console. With monitor mode on, each scheduled run returns only what changed since the previous one.
Support
Questions or a missing field? Open an issue from the Issues tab on this Actor's page and it will be looked at.
Legal / Responsible Use
This Actor reads Polymarket's public market and order-book APIs. You are responsible for how you use it and for any trading you do. It is not financial advice or an execution service, and is not affiliated with Polymarket.