Skip to main content

Retrieve baseball data in Python

Project description

polars-baseball

PyPI version Python versions CI Codecov License Downloads

Languages: English | Traditional Chinese

polars-baseball is The unified Polars-native baseball data SDK: a typed, async-first Python library for retrieving MLB and baseball analytics data from Statcast, Baseball Savant, FanGraphs, Baseball Reference, Lahman, Retrosheet, and the MLB Stats API.

If you searched for python baseball data, python statcast, fangraphs python, baseball savant api, pybaseball alternative, or polars dataframe baseball, this project is built for the workflow where data should land directly in polars.DataFrame instead of going through pandas first.

Why use polars-baseball instead of pybaseball?

pybaseball is useful and established. polars-baseball is aimed at a different execution model: async data ingestion, native Polars output, and one consistent entry point across multiple baseball data providers.

Feature pybaseball polars-baseball
Polars native No Yes
Async data fetching No Yes
Statcast / Baseball Savant Yes Yes
FanGraphs Yes Yes
MLB Stats API Limited Yes
Lahman / Retrosheet workflows Partial Yes
Built-in cache Partial Yes
Typed public API Partial Yes

Typical pandas-first workflow:

pybaseball -> pandas -> convert to Polars -> analysis

polars-baseball workflow:

polars-baseball -> Polars -> analysis

Key Features

  • Polars-native data: Public data-fetching APIs return polars.DataFrame unless an API reference explicitly documents a non-tabular contract.
  • Async-first engine: Data-fetching APIs are async def and can be composed with your own async workflows.
  • Multiple providers: Statcast, Baseball Savant, FanGraphs, Baseball Reference, Lahman, Retrosheet, MLB Stats API, and player ID workflows.
  • Built-in cache: Repeated network requests are cached as Parquet files for large workflows.
  • Service-ready context: BaseballContext lets long-running apps control HTTP and cache resources explicitly.

Installation

pip install polars-baseball

For local development:

git clone https://github.com/nicko4o/polars-baseball
cd polars-baseball
uv sync --all-extras

To run visualization examples:

pip install "polars-baseball[plot]"

Quick Start

Statcast pitch-level data

import asyncio

import polars_baseball as pb


async def main() -> None:
    df = await pb.statcast(start_date="2024-05-06", end_date="2024-05-06")
    print(df.head(5))


if __name__ == "__main__":
    asyncio.run(main())

Aggregate directly with Polars

import asyncio

import polars as pl
import polars_baseball as pb


async def main() -> None:
    df = await pb.statcast_pitcher(
        start_date="2024-05-06",
        end_date="2024-05-06",
        player_id=506433,
    )
    summary = df.group_by("pitch_type").agg(
        pl.col("release_speed").mean().alias("mean_speed"),
        pl.len().alias("pitch_count"),
    )
    print(summary.sort("pitch_count", descending=True))


if __name__ == "__main__":
    asyncio.run(main())

FanGraphs leaderboard

import asyncio

import polars_baseball as pb


async def main() -> None:
    df = await pb.fg_batting(
        start_season=2024,
        end_season=2024,
        qual=100,
        max_results=20,
    )
    print(df.head(10))


if __name__ == "__main__":
    asyncio.run(main())

Examples

Runnable examples live in examples/:

Benchmarking

Do not trust performance claims without a reproducible command. Start with:

python examples/benchmark_statcast.py --start-date 2024-04-01 --end-date 2024-04-07

The script reports row count, column count, wall time, and Python allocation peak measured by tracemalloc. Use the same date range, cache state, Python version, and machine when comparing against pandas-first workflows.

Web Services & Concurrency

Calling package functions without context uses the implicit package-level BaseballContext. That default context is convenient for scripts, but long-running concurrent services should manage their own context and pass it into every API call.

from contextlib import asynccontextmanager

from fastapi import FastAPI

import polars_baseball as pb


@asynccontextmanager
async def lifespan(app: FastAPI):
    async with pb.BaseballContext() as context:
        app.state.pb_context = context
        yield


app = FastAPI(lifespan=lifespan)


@app.get("/statcast")
async def get_statcast() -> dict[str, int]:
    df = await pb.statcast(
        start_date="2026-06-01",
        end_date="2026-06-02",
        context=app.state.pb_context,
    )
    return {"rows": df.height}

API Namespace Policy

The package root (import polars_baseball as pb) exposes stable public APIs, including provider specific data functions such as Lahman, Retrosheet, Baseball Reference, and player ID workflows. Provider namespaces such as pb.fangraphs, pb.savant, and pb.mlb expose shorter task-oriented aliases for new code while the existing root functions remain supported.

Modules prefixed with _, including _schemas, are internal implementation details and are not part of the compatibility contract.

Documentation

Showcase

Projects using polars-baseball:

  • MLB dashboard workflows
  • Chinese baseball website data jobs
  • Threads bot baseball data pipelines

Contributing

See CONTRIBUTING.md for development workflow and architecture notes.

Author

Created and maintained by Nick.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

polars_baseball-0.3.0.tar.gz (109.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

polars_baseball-0.3.0-py3-none-any.whl (138.1 kB view details)

Uploaded Python 3

File details

Details for the file polars_baseball-0.3.0.tar.gz.

File metadata

  • Download URL: polars_baseball-0.3.0.tar.gz
  • Upload date:
  • Size: 109.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for polars_baseball-0.3.0.tar.gz
Algorithm Hash digest
SHA256 4a5b1c5ef8e04eaf4ee024f11dc02e6116dc051fcd6202c4ad4e4eaba9a0f594
MD5 270b55dbd31bde1d125e32d460b69b7c
BLAKE2b-256 21f2af9ee7d5b788054c946cf0a66d070009012e08687ed75d9d761cfc60246b

See more details on using hashes here.

Provenance

The following attestation bundles were made for polars_baseball-0.3.0.tar.gz:

Publisher: python-publish.yml on nicko4o/polars-baseball

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file polars_baseball-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: polars_baseball-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 138.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for polars_baseball-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9b3ba97c6b7e6d362aa2f94861738335db6dcbc53a754987ad8cf0c61cafcb1d
MD5 2698e3ddb153c4bc1ce559733d5a7ba3
BLAKE2b-256 fcb6e2998343ca6f6fc0ce3e33e2b5b4404f9c934c9b9e39c41cd92144b45ffa

See more details on using hashes here.

Provenance

The following attestation bundles were made for polars_baseball-0.3.0-py3-none-any.whl:

Publisher: python-publish.yml on nicko4o/polars-baseball

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page