All-in-one Python library for osu! beatmap parsing, mod handling, and pp calculation. The only osu! lib you'll ever need.
PyPI Version Python License Typing pre-commit Code Style Discord
- Beatmap Parsing - Full
.osufile parsing including all sections: General, Metadata, Difficulty, Events, Timing Points, Hit Objects, Colors, and Editor - Mod Handling - Complete mod system supporting all osu! game modes (osu!, Taiko, Catch, Mania) with legacy and modern mod representations
- Performance Calculation - PP calculation for all supported game modes (in active development)
- Type-safe - Fully typed codebase, mypy-checked
pip install parsecore
Or with uv:
uv add parsecore
Requires Python 3.10+
from parsecore.Beatmap import Beatmap beatmap = Beatmap.from_path("path/to/map.osu") print(beatmap.metadata.title) print(beatmap.metadata.version) print(beatmap.difficulty.approach_rate) print(beatmap.difficulty.circle_size) for obj in beatmap.hit_objects.objects: print(obj) for tp in beatmap.timing_points.control_points.timing_points: print(tp.bpm)
from parsecore.Mods import GameMods, GameMode, HardRockOsu, DoubleTimeOsu mods = GameMods([HardRockOsu(), DoubleTimeOsu()]) # Legacy bitfield conversion legacy = mods.to_legacy() print(legacy.value) # From acronym strings mods = GameMods.from_acronyms(["HD", "DT"], GameMode.OSU) # Intermode mods from parsecore.Mods import GameModsIntermode intermode = GameModsIntermode.from_acronyms(["HD", "NC"])
parsecore/
├── Beatmap/ # .osu file parsing and encoding
│ ├── beatmap.py
│ ├── reader.py
│ ├── encode.py
│ └── section/ # Individual section parsers
│ ├── general.py
│ ├── metadata.py
│ ├── difficulty.py
│ ├── timing_points.py
│ ├── hit_objects/
│ └── ...
└── Mods/ # Mod system
├── game_mod.py
├── game_mods.py
├── game_mode.py
├── generated_mods.py
└── ...
Contributions are welcome! Please read CONTRIBUTING.md before submitting a pull request.
To report a security vulnerability, see SECURITY.md.
© 2026-Present O!Lib Team