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.
  • Opt-in file cache: Large workflows can cache repeated network requests as Parquet files.
  • Service-ready context: BaseballContext lets long-running apps control HTTP and cache resources explicitly.
  • Explicit HTTP policy: HttpClient exposes timeout, retry, and BRef rate-limit settings.

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="2026-06-01", end_date="2026-06-01")
    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="2026-06-01",
        end_date="2026-06-01",
        # Use pb.playerid_lookup("Judge", "Aaron") to find player IDs
        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.fangraphs.batting(
        start_season=2026,
        end_season=2026,
        qual=100,
        max_results=20,
    )
    print(df.head(10))


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

Examples

Scripts (CLI-ready)

Runnable .py examples live in examples/:

Notebooks (interactive)

Interactive Jupyter notebooks live in notebooks/:

Benchmarking

Do not trust performance claims without a reproducible command:

python -m benchmarks run statcast_1week

List available profiles:

python -m benchmarks run list

Full command reference:

python -m benchmarks run <profile> [--json] [--json-file PATH] [--baseline] [--fail-if-regression]
python -m benchmarks baseline show
python -m benchmarks baseline clear

The runner reports wall time, CPU time, peak Python memory (via tracemalloc), GC collections, and result shape. Use the --baseline flag to save results and compare against historical data. 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 and does not write cache files unless configure_cache() has been called. 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 core convenience APIs and provider namespaces. Use pb.fangraphs, pb.savant, and pb.mlb for provider-specific workflows. Lahman, Retrosheet, Baseball Reference, and player ID workflows remain available from the package root.

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.8.1.tar.gz (116.5 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.8.1-py3-none-any.whl (147.2 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for polars_baseball-0.8.1.tar.gz
Algorithm Hash digest
SHA256 490efe5429c2d912bfd595d7a7fea3ef05b4ca58f762075191677454449ddacb
MD5 7cfa4c11ecff926d416adfd02875ad1f
BLAKE2b-256 727dd77f0030acb8e97e1136700847f86a3299f33a00be9c3f07c798b12b7849

See more details on using hashes here.

Provenance

The following attestation bundles were made for polars_baseball-0.8.1.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.8.1-py3-none-any.whl.

File metadata

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

File hashes

Hashes for polars_baseball-0.8.1-py3-none-any.whl
Algorithm Hash digest
SHA256 9ef5fc69ca4719fc7cae011fa666fa665448743d45e2717b8b59d42578322d1c
MD5 fecbc14656ed8ce9d8e87a7ad660c25e
BLAKE2b-256 43cf096ce7cb6a145abeafe3b8f99278298b57080a5335075a18dddb65f042bd

See more details on using hashes here.

Provenance

The following attestation bundles were made for polars_baseball-0.8.1-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