Arbitrage Opportunities
Find guaranteed-profit arbitrage opportunities across sportsbooks.
GET /api/v1/opportunities/arbitrageAuthentication
Requires API key. Hobby tier or higher required. Your account must have the arbitrage feature enabled.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
sport | string | all | Filter by sport(s), comma-separated (e.g. basketball, football) |
league | string | all | Filter by league(s), comma-separated (e.g. nba, nfl, nhl) |
sportsbook | string | tier-allowed | Filter by sportsbook(s), comma-separated. Tier limits enforced. |
market | string | all | Filter by market type(s), comma-separated |
min_profit | number | 0.5 | Minimum profit percentage (e.g. 1.0 = 1%) |
live | boolean | — | true = live only, false = prematch only, omit = both |
format | string | json | Response format: json or csv. CSV downloads as arbitrage_YYYY-MM-DD.csv. |
limit | integer | 50 | Results per page (max 500) |
offset | integer | 0 | Pagination offset (max 5000) |
Profit cap: Opportunities with profit above 10% are automatically filtered out. These are almost always phantom arbs caused by stale or suspended odds rather than real opportunities.
Filtering Multiple Values
Use comma-separated values for multi-select filters:
?sport=basketball,football&league=nba,nflExample Requests
cURL
curl -X GET "https://api.sharpapi.io/api/v1/opportunities/arbitrage?league=nba&min_profit=1" \
-H "X-API-Key: YOUR_API_KEY"Response
Success (200)
{
"success": true,
"data": [
{
"id": "arb_dk_pin_nba_lal_bos_ml",
"event_id": "evt_nba_lal_bos_20260208",
"event_name": "Los Angeles Lakers @ Boston Celtics",
"sport": "basketball",
"league": "nba",
"market_type": "moneyline",
"line": null,
"profit_percent": 1.83,
"implied_total": 98.2,
"is_live": false,
"start_time": "2026-02-08T19:00:00Z",
"is_alternate_line": false,
"possibly_stale": false,
"oldest_odds_age_seconds": 8,
"warnings": [],
"game_state": null,
"ev_available": true,
"ev_percentage": 3.5,
"is_player_prop": false,
"player_name": null,
"stat_category": null,
"legs": [
{
"sportsbook": "draftkings",
"selection": "Los Angeles Lakers",
"odds_american": 145,
"odds_decimal": 2.45,
"implied_probability": 0.408,
"stake_percent": 41.5,
"timestamp": "2026-02-08T14:22:05.000Z",
"external_event_id": "33483153",
"selection_id": "sel_lal_ml",
"market_id": "mkt_ml_33483153"
},
{
"sportsbook": "pinnacle",
"selection": "Boston Celtics",
"odds_american": -135,
"odds_decimal": 1.74,
"implied_probability": 0.574,
"stake_percent": 58.5,
"timestamp": "2026-02-08T14:22:08.000Z",
"external_event_id": null,
"selection_id": null,
"market_id": null
}
],
"detected_at": "2026-02-08T14:22:10.456Z"
}
],
"pagination": {
"limit": 50,
"offset": 0,
"total": 3,
"maxOffset": 5000
},
"meta": {
"source": "cache",
"summary": {
"count": 3,
"avg_profit": 1.23,
"max_profit": 1.83,
"by_market": { "moneyline": 2, "point_spread": 1 },
"by_sport": { "basketball": 3 }
},
"filters": {
"sport": null,
"league": ["nba"],
"sportsbook": null,
"market": null,
"live": null,
"min_profit": 1.0
},
"books_analyzed": 8
}
}Response Headers
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 297
X-RateLimit-Reset: 1707401000
X-Data-Delay: 0
X-Request-Id: req_arb789xyz012Error Responses
401 Unauthorized
{
"error": {
"code": "unauthorized",
"message": "Invalid or missing API key",
"docs": "https://sharpapi.io/docs/authentication"
}
}403 Tier Required
{
"error": {
"code": "tier_restricted",
"message": "Arbitrage detection requires Hobby tier or higher",
"docs": "https://sharpapi.io/docs/pricing"
}
}429 Rate Limited
{
"error": {
"code": "rate_limited",
"message": "Rate limit exceeded",
"docs": "https://sharpapi.io/docs/api-reference/overview"
}
}Response Fields
| Field | Type | Description |
|---|---|---|
id | string | Unique arbitrage identifier (hash) |
event_id | string | Event identifier |
event_name | string | Human-readable event name |
sport | string | Sport identifier (lowercase) |
league | string | League identifier |
market_type | string | Market type (moneyline, point_spread, total_points, etc.) |
line | number|null | Spread/total line (e.g., -3.5) |
profit_percent | number | Guaranteed profit as a percentage (e.g., 1.83 = 1.83%) |
implied_total | number | Sum of implied probabilities across all legs (below 100 = arb exists) |
is_live | boolean | Whether the event is currently live |
start_time | string|null | ISO 8601 event start time |
is_alternate_line | boolean | Whether this uses a non-standard line |
possibly_stale | boolean | Whether odds may have moved since detection |
oldest_odds_age_seconds | number|null | Age of the stalest leg’s odds in seconds |
warnings | string[] | Warning flags. Possible values: LIVE_GAME, LIVE_HIGH_PROFIT_SUSPICIOUS, LOW_IMPLIED_TOTAL, POTENTIALLY_STALE_ODDS, VERY_STALE_ODDS |
game_state | object|null | Live game state (period, clock, score_home, score_away) |
ev_available | boolean | Whether an EV opportunity exists on this market |
ev_percentage | number|null | EV percentage if available |
is_player_prop | boolean | Whether this is a player prop market |
player_name | string|null | Player name (if player prop) |
stat_category | string|null | Stat type (if player prop, e.g., points, rebounds) |
legs | array | Array of bet legs that form the arbitrage |
detected_at | string | ISO 8601 timestamp when the arb was first detected |
Leg Object
| Field | Type | Description |
|---|---|---|
sportsbook | string | Sportsbook for this leg |
selection | string | The selection (team name, Over/Under, etc.) |
odds_american | number | American odds for this leg |
odds_decimal | number | Decimal odds for this leg |
implied_probability | number | Implied probability (0.0 to 1.0) |
stake_percent | number | Percentage of total stake to place on this leg |
timestamp | string|null | When these odds were captured (ISO 8601) |
external_event_id | string|null | Sportsbook’s native event ID |
selection_id | string|null | Sportsbook’s selection/outcome ID |
market_id | string|null | Sportsbook’s market ID |
CSV Format
When ?format=csv, the response downloads as arbitrage_YYYY-MM-DD.csv with columns:
event,sport,market,line,profit%,implied_total,book1,selection1,odds1,stake1%,book2,selection2,odds2,stake2%,is_live,is_alternate_line,possibly_stale,warnings,detected_atHow Arbitrage Works
Arbitrage exploits price differences between sportsbooks to guarantee a profit regardless of the outcome. When the combined implied probabilities across all legs of a market total less than 100%, an arbitrage opportunity exists.
The Core Principle
Book A: Team X +150 (implied 40.0%)
Book B: Team Y -130 (implied 56.5%)
Total implied: 96.5% < 100% = ARBITRAGEWhen the total is below 100%, you can bet proportionally on every outcome and guarantee a profit.
Profit Calculation
Profit % = (100 / implied_total) - 100Using the example above:
Profit % = (100 / 96.5) - 100 = 3.63%This means for every $1,000 wagered, you are guaranteed approximately $36.30 in profit.
Calculating Optimal Stakes
To guarantee equal returns regardless of outcome, allocate stakes proportionally:
// Decimal odds: Team X = 2.50, Team Y = 1.77
const impliedX = 1 / 2.50; // 0.400
const impliedY = 1 / 1.77; // 0.565
const total = impliedX + impliedY; // 0.965
const stakeX = impliedX / total; // 41.5% of bankroll
const stakeY = impliedY / total; // 58.5% of bankrollFull Stake Example
Total bankroll for this arb: $1,000
| Leg | Stake | Odds | Payout if Wins |
|---|---|---|---|
| Team X @ DraftKings | $415 | +150 | $1,037.50 |
| Team Y @ Pinnacle | $585 | -130 | $1,035.00 |
Guaranteed profit: ~$35-38 (3.5-3.8%) regardless of outcome.
Three-Way Arbitrage
Sports like soccer and hockey have three-way markets (home/draw/away), which can also produce arbitrage:
Home Win: +200 (33.3%)
Draw: +250 (28.6%)
Away Win: +180 (35.7%)
Total implied: 97.6% -> 2.4% arbitrage profitThe same stake calculation applies — divide each leg’s implied probability by the total to determine the stake allocation.
Why Arbs Exist
- Timing differences - Sportsbooks update odds at different speeds
- Differing opinions - Books have different risk models and exposure
- Promotions - Boosted odds from one book create artificial gaps
- Errors - Occasionally, a book posts incorrect odds
Best Practices
Account Risk: Sportsbooks actively monitor for arbitrage activity. Accounts that exclusively place arb bets may be limited or restricted. Consider mixing arbitrage bets with recreational activity.
- Act fast - Arb windows are often short-lived (seconds to minutes)
- Round your stakes - A bet of $47.32 looks suspicious; round to $50
- Use pre-calculated stakes - The
stake_percentfield gives you optimal allocation - Verify odds before placing - Always confirm the odds at the sportsbook have not moved
- Start with larger arbs - Focus on
min_profit=1or higher to account for line movement - Track the
implied_total- Lower totals mean larger guaranteed profits - Diversify sportsbooks - Spreading activity across many books reduces individual account risk
Arb vs +EV Betting
| Aspect | Arbitrage | +EV Betting |
|---|---|---|
| Risk | Zero (guaranteed profit) | Variance exists |
| Profit per bet | 1-3% typical | 2-10% edge |
| Account risk | High (limits likely) | Lower |
| Capital required | High (bet both sides) | Lower |
| Sustainability | Limited by account health | Long-term viable |
Many experienced bettors prefer +EV betting over arbitrage because accounts last longer and the expected edges are often larger. See the +EV Opportunities endpoint for details.
Related Endpoints
- +EV Opportunities - Positive expected value bets
- Middles - Line discrepancy opportunities
- Arbitrage Concepts - Detailed arbitrage theory
- Arbitrage Scanner Example - Build a real-time scanner