Retrieve baseball data in Python
Project description
polars-baseball
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.DataFrameunless an API reference explicitly documents a non-tabular contract. - Async-first engine: Data-fetching APIs are
async defand 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:
BaseballContextlets 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.fangraphs.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/:
examples/statcast_pitch_mix.py: Statcast pitch mix with Polars.examples/fangraphs_leaderboard.py: FanGraphs batting leaderboard.examples/mlb_schedule.py: MLB Stats API schedule query.examples/benchmark_statcast.py: Conservative Statcast timing and memory benchmark.
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 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
- Documentation
- API Use-Case Index: choose the right API by task.
- Traditional Chinese 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file polars_baseball-0.6.0.tar.gz.
File metadata
- Download URL: polars_baseball-0.6.0.tar.gz
- Upload date:
- Size: 110.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b37145f0ab70ab03b1b0bb01150043c28547343986c9e8b20c291b46c407b274
|
|
| MD5 |
26f24d8c37c468c63c6dff145ecd8c8a
|
|
| BLAKE2b-256 |
78ac31693d94c664d8b57b70a6994f3bfb41d8d14ad1d3b0aaf711d5d054fee3
|
Provenance
The following attestation bundles were made for polars_baseball-0.6.0.tar.gz:
Publisher:
python-publish.yml on nicko4o/polars-baseball
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
polars_baseball-0.6.0.tar.gz -
Subject digest:
b37145f0ab70ab03b1b0bb01150043c28547343986c9e8b20c291b46c407b274 - Sigstore transparency entry: 2188450192
- Sigstore integration time:
-
Permalink:
nicko4o/polars-baseball@31a9ad287022ad860aaaba6c92c79175a5db3a1a -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/nicko4o
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@31a9ad287022ad860aaaba6c92c79175a5db3a1a -
Trigger Event:
release
-
Statement type:
File details
Details for the file polars_baseball-0.6.0-py3-none-any.whl.
File metadata
- Download URL: polars_baseball-0.6.0-py3-none-any.whl
- Upload date:
- Size: 141.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a4e30ba8abc1322987d366cc9bb8814f82a16ed9e21782ffc68984bb453f0be9
|
|
| MD5 |
0715b912cdae52324bb44ad07e9de090
|
|
| BLAKE2b-256 |
04de53120e3baf8413a1f6b1d8170b16ccf44a2e91af4c284d05abcf0b36bd9e
|
Provenance
The following attestation bundles were made for polars_baseball-0.6.0-py3-none-any.whl:
Publisher:
python-publish.yml on nicko4o/polars-baseball
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
polars_baseball-0.6.0-py3-none-any.whl -
Subject digest:
a4e30ba8abc1322987d366cc9bb8814f82a16ed9e21782ffc68984bb453f0be9 - Sigstore transparency entry: 2188450195
- Sigstore integration time:
-
Permalink:
nicko4o/polars-baseball@31a9ad287022ad860aaaba6c92c79175a5db3a1a -
Branch / Tag:
refs/tags/v0.6.0 - Owner: https://github.com/nicko4o
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@31a9ad287022ad860aaaba6c92c79175a5db3a1a -
Trigger Event:
release
-
Statement type: