npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@astefanski/storm-parser

v0.0.10

Published

Storm Parser is a tool for parsing Heroes of the Storm replays.

Readme

@astefanski/storm-parser

A tool for parsing Heroes of the Storm (.StormReplay) replay files. Extract valuable match data including players, heroes, builds, match results, and more.

Installation

This is a private scoped package. Ensure you have access and are authenticated with npm, then install it via:

npm install @astefanski/storm-parser
# or using pnpm
pnpm add @astefanski/storm-parser
# or using yarn
yarn add @astefanski/storm-parser

Note: During installation, a postinstall script automatically downloads protocol definitions from the Blizzard/heroprotocol GitHub repository. This requires internet access and may take 1-2 minutes on first install.

Usage

The package exports two main classes: ReplayParser and ReplayAnalyzer.

ReplayParser

Used for reading the replay file and extracting the raw protocol data and events.

import { ReplayParser } from "@astefanski/storm-parser";
import * as fs from "fs";

// Read the replay file into a buffer
const replayBuffer = fs.readFileSync("path/to/your/replay.StormReplay");

// Initialize the parser
const parser = new ReplayParser(replayBuffer);
parser.init();

// Access the parsed replay data
console.log("Details:", parser.getDetails());
console.log("Init Data:", parser.getInitData());
console.log("Tracker Events Count:", parser.getTrackerEvents().length);

ReplayAnalyzer

Used for higher-level analysis, transforming the raw replay data into structured match information, team compositions, and player stats.

import { ReplayAnalyzer } from "@astefanski/storm-parser";

const result = await ReplayAnalyzer.analyze("path/to/your/replay.StormReplay");

if (result.status === 1) {
  console.log("Map Name:", result.match?.map);
  console.log("Match Length (seconds):", result.match?.length);
  console.log("Winning Team:", result.match?.winner);
}

Retrievable Data

The ReplayAnalyzer provides a comprehensive AnalysisResult containing structured data about the match, teams, and players.

Match Metadata

  • Basic Info: Map name, match date (UTC), match length (seconds), game mode, game type, and region.
  • Result: Winning team ID and a list of winning player handles.
  • Draft:
    • Hero picks for both teams.
    • Hero bans for both teams (including ban order).
    • First pick team identification.

In-Game Events

  • Takedowns: Detailed kill events including killers, victim, time, and map coordinates (X, Y).
  • XP Breakdown: Periodic and end-of-game breakdown of XP sources (Minion, Creep, Structure, Hero, and Trickle XP).
  • Mercenaries:
    • Capture events (camp type, team, time).
    • Unit tracking (locations over time and total active duration).
  • Structures: Tracking of all destroyed structures (Forts, Keeps, Towers, Wells) with destruction time and team ownership.
  • Objectives: Map-specific objective progress, scores, and event types (e.g., Cursed Hollow Tributes, Volskaya Protectors).

Player Statistics

Each player object contains:

  • Profile: Name, BattleTag, Hero played, Team, and Win/Loss status.
  • Game Stats: All standard end-of-game stats (Damage, Healing, Deaths, Assists, Experience Contribution, Time Spent Dead, etc.).
  • Computed Analytics:
    • DPM/HPM/XPM: Damage/Healing/Experience per minute.
    • KDA: Kill/Death/Assist ratio.
    • Kill Participation: Percentage of team kills the player participated in.
    • Per-Death Stats: Damage taken/done and healing per death.
  • Build: Full talent choices for all tiers (Tier 1-7).
  • Awards: Match awards (e.g., MVP, Siege Master).
  • Position Tracking: Movement paths and life cycles of the player's hero unit.

Team Analytics

  • Performance Totals: Aggregated stats for the entire team (Total Hero Damage, Self Healing, protection given, etc.).
  • Combat Stats: KDA, average time spent dead, team wipes, and aces (enemy team wipes).
  • Level Dynamics:
    • Level-up timestamps.
    • Level advantage timeline (who had the lead and by how much).
    • Time spent with level/hero advantage.
  • Passive XP: Passive XP gain rates and differences between teams.
  • Structure Control: Counts of lost/destroyed Forts and Keeps, and identification of who destroyed the first Fort/Keep.

Technical Reference

After calling ReplayAnalyzer.analyze(), you receive an AnalysisResult object. Below are examples of how to access specific data points.

Accessing Player Data

Player data is stored in the players map, keyed by a unique ToonHandle (format: region-programId-realm-id).

const result = await ReplayAnalyzer.analyze("replay.StormReplay");

if (result.status === 1 && result.players) {
  // result.match.playerIDs contains the list of all ToonHandles
  const firstPlayerHandle = result.match.playerIDs[0];
  const player = result.players[firstPlayerHandle];

  console.log(`Hero: ${player.hero}`);
  console.log(`BattleTag: ${player.name}#${player.tag}`);

  // Accessing specific game stats
  console.log(`Hero Damage: ${player.gameStats.HeroDamage}`);
  console.log(`Deaths: ${player.gameStats.Deaths}`);

  // Computed analytics
  console.log(`DPM: ${player.gameStats.DPM}`);
  console.log(`Kill Participation: ${player.gameStats.KillParticipation}`);
}

Accessing Team Analytics

Team-specific data is located under result.match.teams, separated into "0" (Blue) and "1" (Red).

const team0 = result.match.teams["0"];

console.log(`Team Level: ${team0.level}`);
console.log(`Team Takedowns: ${team0.takedowns}`);

// Aggregated totals for the whole team
console.log(`Total Team Healing: ${team0.stats.totals.Healing}`);

// Team-level advantage stats
console.log(`Level Adv Time: ${team0.stats.levelAdvTime} seconds`);
console.log(`Average Heroes Alive: ${team0.stats.avgHeroesAlive}`);

Accessing Match Events

The match object contains timelines for various game events.

// Takedowns (kills) with coordinates and participants
result.match.takedowns.forEach((event) => {
  console.log(
    `[${event.time}s] ${event.killers[0].hero} killed ${event.victim.hero} at (${event.x}, ${event.y})`,
  );
});

// XP Breakdown over time
result.match.XPBreakdown.forEach((entry) => {
  console.log(
    `[${entry.time}s] Team ${entry.team} Level ${entry.teamLevel} - Minion XP: ${entry.breakdown.MinionXP}`,
  );
});

// Mercenary captures
result.match.mercs.captures.forEach((capture) => {
  console.log(
    `Team ${capture.team} captured ${capture.type} at ${capture.time}s`,
  );
});

Accessing Draft Information

Draft data is split between picks and bans.

// Hero Bans by team and order
const team0Bans = result.match.bans["0"]; // Array of { hero: string, order: number }

// Hero Picks by team
const team1Picks = result.match.picks["1"]; // Array of hero names

// Which team had the first pick (0 or 1)
const firstPickTeam = result.match.picks.first;

Features

  • Parses replay.details, replay.initData, replay.tracker.events, and more.
  • Extracts detailed player information, including BattleTags and selected heroes.
  • Decodes tracker events for in-depth match analysis (e.g., score screens, talent choices).
  • Protocols are downloaded on install — package stays lightweight (~15KB).
  • Provides a clean, typed API for easy integration.

License

ISC