npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

owls-insight-ts

v0.23.0

Published

Official TypeScript SDK for the Owls Insight real-time sports betting odds API

Readme

Owls Insight SDK

Official TypeScript/JavaScript SDK for the Owls Insight real-time sports betting odds API.

Features

  • Full TypeScript types for all endpoints and events
  • REST client for odds, scores, props, history, and stats
  • WebSocket client for real-time streaming updates
  • Works in Node.js, Bun, Deno, and modern browsers
  • ESM and CommonJS support

Installation

npm install owls-insight-ts

Quick Start

import { OwlsInsight } from "owls-insight-ts";

const client = new OwlsInsight({ apiKey: process.env.OWLS_INSIGHT_API_KEY! });

// Get NBA odds from all books
const odds = await client.rest.getOdds("nba");

// odds.data is keyed by book: { pinnacle: [...], fanduel: [...], ... }
for (const [book, events] of Object.entries(odds.data)) {
  console.log(`${book}: ${events.length} events`);
}

// Get odds from specific books
const filtered = await client.rest.getOdds("nba", {
  books: ["pinnacle", "fanduel"],
});

REST API

Odds

// All markets (moneyline + spreads + totals)
const odds = await client.rest.getOdds("nba");

// Single market
const ml = await client.rest.getMoneyline("nba");
const spreads = await client.rest.getSpreads("nfl");
const totals = await client.rest.getTotals("nhl");

// With filters
const filtered = await client.rest.getOdds("soccer", {
  books: ["pinnacle", "bet365"],
  league: "England - Premier League",
  alternates: true,
});

Esports (CS2, Valorant, LoL)

const cs2 = await client.rest.getOdds("cs2");
const valorant = await client.rest.getOdds("valorant");
const lol = await client.rest.getOdds("lol");

CS2 odds from 1xBet. Valorant and LoL from both 1xBet and Pinnacle. Esports use a separate WebSocket event (esports-update).

Live Scores

// All sports
const allScores = await client.rest.getScores();

// Specific sport
const nbaScores = await client.rest.getScores("nba");

Player Props

// All books
const props = await client.rest.getProps("nba");

// Filtered
const filtered = await client.rest.getProps("nba", {
  player: "LeBron",
  category: "points",
  books: ["pinnacle", "fanduel"],
});

// Single book (typed per-book response)
const fdProps = await client.rest.getBookProps("nba", "fanduel");
const mgmProps = await client.rest.getBookProps("nba", "betmgm"); // BetMGMPropsResponse
const b365Props = await client.rest.getBookProps("nba", "bet365"); // Bet365PropsResponse

// Props line movement history
const propsHistory = await client.rest.getPropsHistory("nba", {
  game_id: "game_123",
  player: "LeBron James",
  category: "points",
  book: "pinnacle",
  hours: 24,
});

// Props cache statistics
const propsStats = await client.rest.getPropsStats();
const bet365Stats = await client.rest.getBookPropsStats("bet365");

Box Scores & Stats

// NBA box scores for today
const stats = await client.rest.getStats("nba");

// Filter by date and player
const filtered = await client.rest.getStats("nba", {
  date: "2026-03-05",
  player: "LeBron",
});

Real-Time Odds

Sub-second sharp Pinnacle odds via dedicated real-time pipeline. Available for all sports.

const realtime = await client.rest.getRealtime("nba");

console.log(realtime.meta.source);    // "pinnacle"
console.log(realtime.meta.events);    // number of events
console.log(realtime.meta.available); // true if data exists
console.log(realtime.meta.freshness); // { ageSeconds, stale }

The freshness object indicates data age. Data is considered stale after 30 seconds.

Odds History

// Line movement history
const history = await client.rest.getOddsHistory({
  eventId: "event_123",
  book: "pinnacle",
  market: "spreads",
  side: "home",
  hours: 24,
});

Historical Archive

// List completed games
const games = await client.rest.getHistoryGames({
  sport: "nba",
  startDate: "2026-03-01",
  endDate: "2026-03-06",
});

// Get archived odds snapshots
const snapshots = await client.rest.getHistoryOdds({
  eventId: "event_123",
  book: "pinnacle",
  market: "spreads",
});

// Get archived props snapshots
const propsSnapshots = await client.rest.getHistoryProps({
  eventId: "event_123",
  playerName: "LeBron James",
  propType: "points",
});

// Get archived player stats
const playerStats = await client.rest.getHistoryStats({
  sport: "nba",
  playerName: "LeBron James",
  startDate: "2026-01-01",
  endDate: "2026-03-01",
});

// Get archived tennis match stats
const tennisStats = await client.rest.getHistoryTennisStats("event_123");

// CS2 match history
const cs2Matches = await client.rest.getCS2Matches({
  team: "Natus Vincere",
  stars: 4,
});

// Full match detail with map scores and player stats
const matchDetail = await client.rest.getCS2Match(2374324);

// Player stats across matches
const cs2Players = await client.rest.getCS2Players({
  playerName: "s1mple",
  minRating: 1.3,
});

// Closing odds per sportsbook (9 books, 2016-present)
const closing = await client.rest.getClosingOdds({
  sport: "nba",
  startDate: "2026-03-01",
  endDate: "2026-03-10",
});

// Historical player props (4 books, 2022-present)
const histProps = await client.rest.getHistoricalPlayerProps({
  sport: "nba",
  player: "LeBron James",
  propType: "points",
});

// Public betting percentages (2019-present)
const publicBetting = await client.rest.getPublicBetting({
  sport: "nba",
  limit: 50,
});

Kalshi Prediction Markets

const markets = await client.rest.getKalshiMarkets("nba", {
  status: "open",
});

// Browse series (e.g., KXNBAGAME, KXNFLSBMVP)
const series = await client.rest.getKalshiSeries();

// Markets within a series
const nbaGame = await client.rest.getKalshiSeriesMarkets("KXNBAGAME");

Polymarket

Polymarket odds are also included as a bookmaker in the standard /odds response.

const markets = await client.rest.getPolymarketMarkets("nba");

Betting Splits

const splits = await client.rest.getSplits("nba");

WebSocket Streaming

Real-time odds updates via WebSocket.

Connect & Subscribe

const client = new OwlsInsight({ apiKey: process.env.OWLS_INSIGHT_API_KEY! });

await client.ws.connect();

// Subscribe to sports and books
client.ws.subscribe({
  sports: ["nba", "nfl"],
  books: ["pinnacle", "fanduel", "draftkings"],
});

// Listen for odds updates
client.ws.on("odds-update", (data) => {
  console.log(`Update at ${data.timestamp}`);
  // data.last_odds_change — when prices actually changed (vs heartbeat)
  for (const [sport, events] of Object.entries(data.sports)) {
    console.log(`${sport}: ${events.length} events`);
    for (const event of events) {
      console.log(`  ${event.away_team} @ ${event.home_team}`);
    }
  }
});

Update Subscription

// Update an existing subscription
client.ws.updateSubscription({ sports: ["nba", "nhl", "soccer"] });

Props Streaming

// Subscribe to Pinnacle props for specific sports
client.ws.subscribeProps({ sports: ["nba", "nhl"] });

// Subscribe to a specific book's props
client.ws.subscribeProps({ sports: ["nba"] }, "fanduel");

// Filter by categories
client.ws.subscribeProps({
  sports: ["nba"],
  categories: ["points", "rebounds", "assists"],
});

// Subscribe to all books
client.ws.subscribeProps({ sports: ["nba"] });                    // Pinnacle
client.ws.subscribeProps({ sports: ["nba"] }, "fanduel");         // FanDuel
client.ws.subscribeProps({ sports: ["nba"] }, "draftkings");      // DraftKings
client.ws.subscribeProps({ sports: ["nba"] }, "bet365");          // Bet365
client.ws.subscribeProps({ sports: ["nba"] }, "betmgm");          // BetMGM
client.ws.subscribeProps({ sports: ["nba"] }, "caesars");          // Caesars

client.ws.on("player-props-update", (data) => {
  console.log("Pinnacle props:", data.sports);
});

client.ws.on("fanduel-props-update", (data) => {
  console.log("FanDuel props:", data.sports);
});

// Confirmation events
client.ws.on("props-subscribed", (sub) => {
  console.log("Pinnacle props active:", sub);
});

// Unsubscribe
client.ws.unsubscribeProps();           // Pinnacle
client.ws.unsubscribeProps("fanduel");  // FanDuel

Real-Time Pinnacle

Pushed automatically — no subscription needed.

client.ws.on("pinnacle-realtime", (data) => {
  // data is keyed by sport: { nba: [...], tennis: [...], timestamp: "..." }
  for (const [sport, events] of Object.entries(data)) {
    if (sport === "timestamp" || !Array.isArray(events)) continue;
    console.log(`${sport}: ${events.length} events`);
    for (const event of events) {
      console.log(`  ${event.away_team} @ ${event.home_team}`);
      const pinnacle = event.bookmakers.find((b: any) => b.key === "pinnacle");
      for (const market of pinnacle?.markets || []) {
        console.log(`    ${market.key}:`, market.outcomes);
      }
    }
  }
});

Esports Updates

// Opt in to all esports via subscribe
client.ws.subscribe({
  sports: ["nba"],
  books: ["pinnacle"],
  esports: true,
});

// Or filter to specific esports
client.ws.subscribe({
  sports: ["nba"],
  esports: ["cs2", "valorant"],
});

client.ws.on("esports-update", (data) => {
  console.log(`CS2: ${data.sports.cs2?.length}`);
  console.log(`Valorant: ${data.sports.valorant?.length}`);
  console.log(`LoL: ${data.sports.lol?.length}`);
});

Promise-Based Waiting

// Wait for the next odds update
const update = await client.ws.waitFor("odds-update", 10_000);

// Wait for subscription confirmation
client.ws.subscribe({ sports: ["nba"], books: ["pinnacle"] });
const sub = await client.ws.waitFor("subscribed");
console.log("Subscribed to:", sub.sports);

Error Handling

client.ws.on("error", (err) => {
  console.error("WebSocket error:", err.message, err.code);
});

client.ws.on("disconnect", (reason) => {
  console.log("Disconnected:", reason);
});

Cleanup

// Disconnect WebSocket
client.ws.disconnect();

// Or destroy everything
client.destroy();

Error Handling

The SDK throws typed errors for different failure modes:

import {
  OwlsInsightError,
  AuthenticationError,
  ForbiddenError,
  RateLimitError,
} from "owls-insight-ts";

try {
  const odds = await client.rest.getOdds("nba");
} catch (err) {
  if (err instanceof RateLimitError) {
    console.log(`Rate limited. Retry in ${err.retryAfterMs}ms`);
  } else if (err instanceof AuthenticationError) {
    console.log("Invalid API key");
  } else if (err instanceof ForbiddenError) {
    console.log("Upgrade required for this endpoint");
  } else if (err instanceof OwlsInsightError) {
    console.log(`API error ${err.status}: ${err.message}`);
  }
}

The API returns rate limit headers on every response:

  • X-RateLimit-Remaining-Minute — requests left this minute
  • X-RateLimit-Remaining-Month — requests left this month
  • X-RateLimit-Reset-Minute — Unix timestamp (ms) when the minute limit resets
  • X-RateLimit-Reset-Month — ISO 8601 timestamp when the month limit resets

Configuration

const client = new OwlsInsight({
  apiKey: process.env.OWLS_INSIGHT_API_KEY!,  // Required
  baseUrl: "https://api.owlsinsight.com", // Optional (default)
  wsUrl: "https://api.owlsinsight.com",   // Optional (default, same as baseUrl)
  timeout: 30000,                  // Optional request timeout in ms (default: 30s)
});

Supported Sports

| Sport | Key | Props | Scores | |-------|-----|-------|--------| | NBA | nba | Yes | Yes | | NCAAB | ncaab | Yes | Yes | | NFL | nfl | Yes | Yes | | NHL | nhl | Yes | Yes | | NCAAF | ncaaf | Yes | Yes | | MLB | mlb | - | Yes | | Soccer | soccer | - | Yes | | Tennis | tennis | - | Yes | | MMA | mma | - | - | | CS2 | cs2 | - | Yes | | Valorant | valorant | - | Yes | | LoL | lol | - | Yes |

Sportsbooks & Coverage

| Book | Game Odds | Player Props | Notes | |------|-----------|-------------|-------| | Pinnacle | NBA, NCAAB, NFL, NHL, NCAAF, MLB, Soccer, Tennis | NBA, NCAAB, NFL, NHL, NCAAF | Sharp/reference line | | FanDuel | NBA, NCAAB, NFL, NHL, NCAAF, MLB, Soccer | NBA, NCAAB, NFL, NHL, NCAAF | | | DraftKings | NBA, NCAAB, NFL, NHL, NCAAF, MLB, Soccer | NBA, NCAAB, NFL, NHL, NCAAF | | | BetMGM | NBA, NCAAB, NFL, NHL, NCAAF, MLB | NBA, NCAAB, NFL, NHL, NCAAF | | | Bet365 | NBA, NCAAB, NFL, NHL, NCAAF, Soccer | NBA, NCAAB, NFL, NHL, NCAAF | | | Caesars | NBA, NCAAB, NFL, NHL, NCAAF, MLB | NBA, NCAAB, NFL, NHL, NCAAF | | | BetOnline | MMA | - | UFC/MMA only | | 1xBet | CS2, Valorant, LoL, Soccer, MLB | - | Esports + soccer + MLB | | Circa Sports | NBA, NCAAB, NFL, NHL, NCAAF, MLB | - | Vegas sharp book | | South Point | NBA, NCAAB, NFL, NHL, NCAAF, MLB | - | Vegas | | Westgate SuperBook | NBA, NCAAB, NFL, NHL, NCAAF, MLB | - | Vegas | | Wynn | NBA, NCAAB, NFL, NHL, NCAAF, MLB | - | Vegas | | Stations Casinos | NBA, NCAAB, NFL, NHL, NCAAF, MLB | - | Vegas | | Kalshi | NBA, NCAAB, NFL, NHL, MLB | - | Prediction market | | Polymarket | NBA, NCAAB, NFL, NHL, MLB, Soccer | - | Decentralized exchange | | Novig | NBA, NCAAB, NFL, NHL, NCAAF, MLB, Soccer, Tennis | - | Peer-to-peer exchange |

Pricing

See owlsinsight.com for current plans and pricing.

License

MIT