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.
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
- 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.
- Opt-in file cache: Large workflows can cache repeated network requests as Parquet files.
- Service-ready context:
BaseballContextlets long-running apps control HTTP and cache resources explicitly. - Explicit HTTP policy:
HttpClientexposes timeout, retry, and BRef rate-limit settings.
pip install polars-baseballFor local development:
git clone https://github.com/nicko4o/polars-baseball
cd polars-baseball
uv sync --all-extrasTo run visualization examples:
pip install "polars-baseball[plot]"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())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())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())Runnable .py 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.
Interactive Jupyter notebooks live in notebooks/:
notebooks/statcast_pitch_mix_demo.ipynb: Statcast pitch mix, velocity leaders, batted-ball outcomes.notebooks/fangraphs_leaderboard_demo.ipynb: FanGraphs batting leaderboard with sabermetric filters.notebooks/mlb_schedule_demo.ipynb: MLB schedule, standings, rosters, and team metadata.
Do not trust performance claims without a reproducible command:
python -m benchmarks run statcast_1weekList available profiles:
python -m benchmarks run listFull 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.
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}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.
Typed enums such as Position, MlbStatsGroup, MlbRosterType, FangraphsStatsCategory,
FangraphsMonth, FangraphsLeague, FangraphsPositions, and FangraphsStatColumn are exported from
the package root for use in typed parameters.
Modules prefixed with _, including _schemas, are internal implementation details and are not part
of the compatibility contract.
- Official Documentation Portal
- API Use-Case Index: Choose the right API by task.
- Maintaining Guide: Package publishing and maintenance steps.
Projects using polars-baseball:
- MLB dashboard workflows
- Chinese baseball website data jobs
- Threads bot baseball data pipelines
We welcome contributions! Please review our repository policies before submitting PRs or issues:
- Contributing Guidelines (Includes AI-Assisted Contribution Policy)
- Code of Conduct
- Security Policy
polars-baseball is a data retrieval library and does not claim ownership of upstream datasets:
- Retrosheet: The information used here was obtained free of charge from and is copyrighted by Retrosheet. Interested parties may contact Retrosheet at www.retrosheet.org.
- Statcast & MLB Stats API: Data provided courtesy of Major League Baseball / Baseball Savant.
- FanGraphs & Baseball Reference: Data provided courtesy of FanGraphs and Baseball Reference. Please respect upstream terms of service and rate limits.
- Lahman: Lahman's Baseball Database by Sean Lahman.
If you use polars-baseball in research, academic work, or software projects, please cite it using CITATION.cff.
Created and maintained by Nick.
This project is licensed under the MIT License.