Profile
Back to NewsBack
GitHub Trending 5 min
Reader Mode
whanyu1212/gem-dota: Python replay parser for Dota 2

whanyu1212/gem-dota: Python replay parser for Dota 2

10 hours ago

gem: a Dota 2 replay parser for Python

Turn Dota 2 replays into analysis-ready Python data.
Parse Source 2 .dem files offline into typed models, pandas DataFrames, JSON, Parquet, and interactive HTML reports.

PyPI version Python versions CI status Coverage License

Documentation · Quickstart · API reference · Changelog


Install

Gem requires Python 3.10 or newer.

pip install gem-dota

Using another package manager? Run uv add gem-dota or poetry add gem-dota. Parquet export additionally requires pyarrow or fastparquet; see the DataFrame and export reference for current engine notes.

Quickstart

import gem

match = gem.parse("match.dem")

print(f"Score: {match.radiant_score}–{match.dire_score}") for player in match.players: hero = gem.constants.hero_display(player.hero_name) print(f"{hero:20} {player.kills}/{player.deaths}/{player.assists} {player.net_worth:,} NW")

Convert the same structured result to JSON.

json_payload = gem.to_json(match, indent=2)

Need tables instead?

frames = gem.parse_to_dataframe("match.dem")
players = frames["player_summary"]     # one row per player
series = frames["player_timeseries"]   # sampled gold/XP/net worth
positions = frames["positions"]
combat = frames["combat_log"]

Or use the CLI:

python -m gem match.dem
python -m gem match.dem --format json --output match.json
python -m gem batch replays/ --format parquet --output out/ --workers 4

Why Gem?

| | | |---|---| | 🐍 Python-native
Typed match objects plug directly into notebooks, pandas, ML pipelines, and ordinary Python code. | 🔎 Replay-first
Analyze local replays without depending on third-party match-history availability. | | ⚔️ Full-match context
Draft, combat, economy, vision, movement, objectives, items, chat, and fights in one model. | 📦 Flexible outputs
Work with dataclasses, DataFrames, JSON, Parquet, batch exports, or a self-contained HTML report. |

Gem is named after the Gem of True Sight: it reveals the structured match state hidden inside dense replay bytes. The parser is an independent Python implementation, cross-checked against Manta, Clarity, the OpenDota parser, and replay-derived validation fixtures.

Match reports

Gem can turn a parsed replay into a self-contained interactive report with overview, combat, laning, farming, fight, vision, economy, draft, and movement views.

Gem interactive Dota 2 match report overview
Interactive HTML report generated from a real .dem replay.

Gem interactive ward map at 16 minutes
Vision — scrub through observer and sentry ward activity.
Gem teamfight breakdown with map and combat statistics
Fights — inspect positions, damage, abilities, and reveals.
from gem.reports import write_html_report

write_html_report(match, "match-report.html")

Hero and item icons are optional local assets. See the asset-cache guide for setup and the report API for customization.

What you get

| Domain | Examples | |---|---| | Match and players | Scores, winner, duration, teams, K/D/A, level, GPM/XPM, final net worth | | Draft and objectives | Picks/bans, towers, barracks, Roshan, Aegis, Tormentor, building status | | Combat | Normalized combat log, damage/healing, kills, ability and item usage, fights | | Economy | Gold, XP, net-worth and minute-aligned advantage curves, purchases, buybacks | | Map state | Player positions, lane heatmaps, wards, smoke groups, courier snapshots | | Items | Final inventories, neutral-item finds, consumed upgrades, Roshan drops and banner plants | | Analysis | Nearby heroes, point-in-time lookups, ability levels, smoke lifecycles, vision, Roshan conversion | | Exports | DataFrames, JSON, Parquet, multi-replay processing, interactive HTML reports |

Useful entry points include:

  • gem.parse() → ParsedMatch
  • gem.parse_to_dataframe() / gem.to_json() / gem.to_parquet()
  • gem.parse_many*() for parallel replay batches
  • gem.find_player(), gem.position_at_tick(), and gem.fight_at_tick()
  • gem.fetch_replay() for OpenDota/Valve replay download and decompression
For current complete replays, Gem's minute curves are validated against OpenDota's effective sampling boundaries. Embedded MatchDetails data enables exact postgame duration, damage, healing, GPM, and XPM values. Older or incomplete replays use replay-derived fallbacks. Fields whose absence is meaningful—such as consumed-upgrade flags—remain None; other outputs use the documented defaults for their field type.

Documentation

The hosted documentation covers both the public API and the replay format itself:

New to replay internals? Start with the Bits & Bytes Primer, then continue into the parser and entity-system deep dives.

Performance and scope

Gem is a pure-Python parser optimized for research, batch analysis, and direct use in the Python data ecosystem. Multi-replay APIs distribute work across processes, while bounded Parquet export avoids retaining every completed match at once. The v0.8 performance study records the benchmark method, compatibility checks, and current optimization boundary without claiming an apples-to-oranges win over Go or Java parsers.

Some outputs are necessarily reconstructed:

  • Vision estimation, farming-pattern analysis, and Roshan conversion are
experimental evidence layers. Prefer Roshan's raw signed profile and status; the legacy aggregate score and exclusive label are deprecated.
  • Incomplete replays can return partial output, and some exact postgame fields require embedded match details.
  • Reliable versus unreliable gold and Healing Lotus pickups are not available from the replay event stream.
  • Hero/item icons and map imagery are optional assets and are not shipped in the wheel.
See Replay Edge Cases and the experimental-feature guides for the detailed boundaries.

Development

git clone https://github.com/whanyu1212/gem-dota.git
cd gem-dota
uv sync --group dev

uv run pytest uv run pytest -m "integration and not network" uv run ruff check src/ tests/ uv run mypy src/gem/

Contributions are welcome. Read CONTRIBUTING.md for the workflow and PR checklist. Parser changes should be checked against the pinned upstream reference revisions listed in CLAUDE.md and accompanied by focused regression tests. Additional tool guidance is available in AGENTS.md.

Acknowledgements

Gem builds on years of open work by the Dota replay community: Manta, Clarity, OpenDota parser, and dotaconstants.

No source code was copied from these projects; they are reference implementations used to understand protocol behavior and validate Gem's independent Python implementation. See THIRD_PARTY_LICENSES for license texts.

Sponsor Gem

Chat with me