Owls Insight Python SDK
Official Python SDK for the Owls Insight real-time sports betting odds API. Sync and async clients, fully typed with Pydantic v2, plus a Socket.io WebSocket client for live streams.
pip install owls-insight
Requires Python 3.9+. Get an API key at owlsinsight.com.
Quick start (sync)
from owls_insight import OwlsInsight
client = OwlsInsight(api_key="owlsinsight_...")
# REST: current NBA odds. `data` is keyed by sportsbook -> list of events.
odds = client.rest.get_odds("nba", books=["pinnacle", "fanduel"])
for book, events in odds.data.items():
for event in events:
print(book, event.home_team, "vs", event.away_team)
# WebSocket: stream live updates
client.ws.connect()
client.ws.subscribe(sports=["nba"], books=["pinnacle"])
client.ws.on("odds-update", lambda data: print("live:", data))
# or block for the next event
update = client.ws.wait_for("odds-update", timeout=15)
client.destroy()
Quick start (async)
import asyncio
from owls_insight import AsyncOwlsInsight
async def main():
async with AsyncOwlsInsight(api_key="owlsinsight_...") as client:
odds = await client.rest.get_odds("nba", books=["pinnacle"])
print(sum(len(events) for events in odds.data.values()), "games")
await client.ws.connect()
await client.ws.subscribe(sports=["nba"], books=["pinnacle"])
update = await client.ws.wait_for("pinnacle-realtime", timeout=30)
print("realtime:", update)
asyncio.run(main())
Authentication
Pass your API key to the constructor. REST uses the Authorization: Bearer header; the WebSocket uses the ?apiKey= query string. Both are handled for you.
import os
client = OwlsInsight(api_key=os.environ["OWLS_INSIGHT_API_KEY"])
REST
Method names are snake_case (the JS SDK's getOdds is get_odds here). Every method returns a typed Pydantic model; unknown fields from the evolving API are preserved (model_extra), never dropped.
Full parity with the TypeScript SDK — every endpoint is available on both client.rest (sync) and the async client.
| Area | Methods |
|---|---|
| Odds | get_odds, get_moneyline, get_spreads, get_totals, get_realtime, get_ps3838_realtime, get_esports_realtime, get_ev, list_events, get_one_x_bet_soccer, get_prophetx_odds |
| Props | get_props, get_book_props, get_props_history, get_props_stats, get_book_props_stats |
| Prop results & trends | get_prop_results (one game, or date= to list a day's graded games), get_prop_trends (hit rate / average / streak vs a line, or line="closing" + book) |
| Same-Game Parlay | get_sgp_events, build_sgp (FanDuel bet-slip price; Rookie/MVP/HoF) |
| Scores / schedule | get_scores, get_schedule, get_results, get_splits, normalize, normalize_batch |
| Stats | get_stats, get_match_stats, get_h2h, get_player_averages |
| Line history | get_odds_history, get_moneyline_history, get_spread_history, get_totals_history |
| Historical | get_history_games, get_history_odds, get_history_props, get_history_stats, get_history_tennis_stats, get_game_stats_detail, get_closing_odds, get_historical_player_props, get_public_betting, get_cs2_matches, get_cs2_match, get_cs2_players |
| v2 Source API | get_stake_v2, get_hard_rock_events/_leagues/get_hard_rock_ladder, get_bet365_v2/_leagues, get_draftkings_v2/_leagues, get_fanduel_v2/_leagues, get_mybookie_v2, get_thunderpick_v2, get_underdog_v2, get_bookmaker_v2/_leagues, get_kalshi_v2/_leagues, get_polymarket_v2/_leagues, get_pinnacle_v2/_leagues |
Methods whose response shape isn't individually modelled yet return a permissive
ApiResponseenvelope (success/data/meta, all fields preserved). Deep per-endpoint Pydantic typing is the remaining follow-on; the method surface is complete.
Hard Rock odds decoding
Hard Rock v2 selections carry a rootIdx, not inline odds. Decode it client-side:
from owls_insight import root_idx_to_american_odds
root_idx_to_american_odds(42) # -325
root_idx_to_american_odds(72) # 100 (even)
WebSocket events
odds-update, props-update (and per-book {book}-props-update), pinnacle-realtime, ps3838-realtime, esports-update, prophetx-update, and the v2 {book}-v2-update deltas.
client.ws.connect()
client.ws.subscribe(sports=["nba", "nhl"], books=["pinnacle", "fanduel"])
client.ws.subscribe_props(book="fanduel") # props stream
client.ws.update_subscription(prophetx=True) # merge, don't replace
client.ws.on("props-update", handle_props)
Errors
from owls_insight import AuthenticationError, RateLimitError, OwlsInsightError
try:
client.rest.get_odds("nba")
except AuthenticationError:
... # 401
except RateLimitError as e:
print("retry after", e.retry_after_ms, "ms")
except OwlsInsightError as e:
print(e.status, e.message)
License
MIT
Release files for owls-insight 0.12.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| owls_insight-0.12.0.tar.gz | 56.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| owls_insight-0.12.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 116.1 kB
Release files / owls_insight-0.12.0.tar.gz
| Download URL | owls_insight-0.12.0.tar.gz |
|---|---|
| Size | 56.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5fa21ba86181f9d841674d8a018e151ba471752492ce157e57d2828eca82e8e5
|
|
BLAKE2b-256 checksum How to use checksums |
78491d50c2d54e10f37fa57e3d70c82aa168aad5599c168ac495b39f40e1ee92
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.7
|
Release files / owls_insight-0.12.0-py3-none-any.whl
| Download URL | owls_insight-0.12.0-py3-none-any.whl |
|---|---|
| Size | 60.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
80424fdf579307bf5b7fd804d483661d70714d0fe9779044be92f41c995ff428
|
|
BLAKE2b-256 checksum How to use checksums |
3b812899e38cadc61ea6dec128cf38f597a91dd0d2d3b8e1c3e51a031cfdc0b9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.7
|