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

battlerite-dev

v1.2.0

Published

a javascript wrapper for the battlerite API

Downloads

19

Readme

battlerite-api a javascript wrapper for the battlerite API

Contents

About

A modular API wrapper for the Battlerite Developer API. Currently there is a module that provides a simple endpoint querystring => json object function. (lib/node-api.js) I plan to write a function that provides the same interface for the browser. A second module (lib/lib.js) consumes the first and provides an fully featured JavaScript API interface. An entrypoint for inclusion in node.js programs is provided in index.js

Last known to be compatible with
Battlerite API v1.5.0
Gamelocker API v7.6.0

Prior Art

  • https://github.com/carlerikjohan/battlerite-api
  • https://github.com/sime1/battlerite-node

My approach is decidedly more minimal than either of those, using much less code and no dependencies. I don't think this is better, just different.

  • https://github.com/jlajoie/battlerite-api/

This is a tool which provides a wrapper around the internal API as used by the game itself, unfortunately that API is about a thousand times more useful than the official one, though to Stunlock's credit, they're updating quick.

Install

You're going to want to have a recent node.

npm i -s battlerite-dev

Usage Examples

Initiialize the API like so

const Battlerite_Dev = require('battlerite-dev')
const api = new Battlerite_Dev({key: "your_very_long_api_key"}) 

a function exists corresponding to each API endpoint, consuming an options object and returning a promise that resolves to the requested JSON, for example:

api.status().then(r => console.log(r))

or

let options = {
  filter: {
    gameMode: ['ranked','casual']
  }
} 
api.matches(options).then(r => console.log(r))

or

api.match('id_hash_as_string').then(r => console.log(r))

Documentation

Methods

api.matches(options: Options)

the options object is a simple JSON representation of the possibly filter queries for the API

interface Options {
  sort: "createdAt" | "-createdAt"
  page: {
    offset: number //number of matches to offset start of return data
    limit: number //max number of matches to report
  },
  filter: {
    createdAt: {
      start: //TODO look up what this is supposed to be 
      end: 
    },
    teamNames: any // no idea, anything i've tried returns a 404
    playerIds: string | string[] //returns matches that include ALL playersIds
    gameMode: number //only works with 1733162751, maybe there's anotherone for the battleground mode
  }
}

returns a promise that resolves to the API response

api.match(matchid: string)

returns a promise that resolves to the API response

api.status()

returns a promise detailing the API status, you don't need an API key for this one

api.player(playerid: string | string[])

takes a single playerid as a string or an array of up to 6 playerid strings returns a promise that resolves to the API response for the players endpoint

api.players(options: Options)

same as matches

api.teams(options: Options)

same as matches

api.telemetry(matchid: string, options: TelemetryOptions)

returns a promise that resolves to an array of telemetry objects be aware that this consumes a call to the battlerite API to fetch the telemetry URL

interface TelemetryOptions {
  url: boolean //if true returns just the URL
}

api.rawTelemetry(url: string)

returns a promise that resolves to an array of telemetry objects using the full url this is useful when you've already got match data retrieved somewhere as calls to the telemetry api are not rate-limited and do not require an API key

Battlerite API Notes

The matches endpoint doesn't quite behave as the docs state.
Not only that, but there's currently no way of getting a playerId <=> playerName relationship using the official api, if you hit the unofficial API though you can get the data

filter[gameMode] returns a 404 if you use ranked or casual as the filterstring, but it does work if you use 1733162751, which is sent as the data.attributes.gameMode with every(?) match right now
filter[teamName] returns a 404 regardless of query? i've tried the team name as a string, and also the long id hash that is provided in roster objects

when retrieving a match, you can only count on some of the data to be present in player.stats, things like the meaningless "attachment" or "emote" numbers are always there, damage is not :(

Telemetry API Notes

type TelemetryType =
  | 'Structures.UserRoundSpell'
  | 'Structures.RoundEvent'
  | 'Structures.DeathEvent'
  | 'Structures.MatchReservedUser'
  | 'Structures.RoundFinishedEvent'
  | 'Structures.MatchFinishedEvent'
  | 'Structures.MatchStart'
  | 'Structures.ServerShutdown'
  | 'com.stunlock.battlerite.team.TeamUpdateEvent'
  | 'com.stunlock.service.matchmaking.avro.QueueEven'

interface TelemetryObject {
  cursor: number //not sure
  type: TelemetryType 
  dataObject : TelemetryData
}

interface TelemetryData {
  matchID: string
  time: number
  [prop: string]: any
}

type Telemetry = TememetryObject[]

Structures.MatchStart

interface MatchStart extends TelemetryData {
  gameMode: number
  mapID: string
  matchID: string 
  region: string
  teamSize: number
  type: string //same as servertype in reserveduser
  version: string //"1.0"
}

Structures.MatchFinishedEvent

interface MatchFinishedEvent extends TelemetryData {
  region: string // "us_southwest", "us_southeast", "us_west"
  matchLength: number
  teamOneScore: number
  teamTwoScore: number
  leavers: array
}

Structures.RoundFinishedEvent

the most interesting data end up here, mostly per-round score for the players

interface RoundFinishedEvent extends TelemetryData {
  winningTeam: number //one indexed because fuck you
  round: number //zero indexed because zero consistency
  roundLength: number //in seconds, as an int
  playerStats: PlayerStats[]
}

interface PlayerStats {
  userID: string
  abilityUses: number
  damageDone: number
  damageReceived: number
  disablesDone: number
  disablesReceived: number
  healingDone: number
  healingReceived: number
  energyGained: number
  energyUsed: number
  kills: number // this may be some sort of binary encoding? it's not the # of player kills for sure
  deaths: number
  score: number
  timeAlive: number
}

Structures.RoundEvent

interface RoundEvent extends TelemetryData {
  character: number
  round: number
  timeIntoRound: number //as far as I can tell this is always zero
  type: string //"MOUNT_DURATION", "ENERGY_ABILITY_USED", "ENERGY_SHARD_PICKUP", "HEALTH_SHARD_PICKUP", "ULTIMATE_USED", "MOUNTS_AFTER_ELEVATOR", "RUNE_LASTHIT", "ALLY_DEATH_ENERGY_PICKUP"
  value: number
}

Structures.MatchReservedUser

some data about each user, there's one of these for every user in a match

interface MatchReservedUser extends TelemetryData {
  accountId: string //same as userID except with inconsistent caps
  attachment: number 
  character: number //character id same as actor?
  characterLevel: number
  characterTimePlayed: number
  division: number
  divisionRating: number
  emote: number
  league: number
  mount: number
  outfit: number
  rankingType: string //"RANKED" | "UNRANKED" | "NONE" maybe one more?
  seasonId: number
  serverType: string // "QUICK2V2" | "PRIVATE" | "QUICK3V3" there may also be additional ones
  team: number
  teamId: string 
  totalTimePlayed: number
}

Structures.DeathEvent

gives the death times of users, curiously it doesn't mention in which round the death occured

interface DeathEvent extends TelemetryData {
  userID: string
}

Structures.ServerShutdown

interface ServerShutdown extends TelemetryData {
  matchTime: number //a different number of seconds than matchLength, i think this is greater in all cases
  reason: string // only seen "EMPTY_SERVER" | "MATCH_COMPLETED" so far
}

Structures.UserRoundSpell

this one appears to be missing entries, there's on average ~60 of these per match which is way fewer than the actions I expect to happen, also the damage/healing totals don't add up to the ones in the other sources I can't really figure out what the selection criteria for these is, at some point I may screencap a private match where we test some things out, and then try and correlate the data

interface UserRoundSpell extends TelemetryData {
  scoreType: string //"USES", "DAMAGE_RECEIVED", "CONTROL_DONE", "CONTROL_RECEIVED", "DAMAGE_DONE", "ENERGY_RECEIVED", "HEALING_DONE", "HEALING_RECEIVED", "ENERGY_USED"
  scoreTypeId: number //presumably the id of the spell
  value: number
  round: number //zero indexed 
  character: number
  sourceTypeId: number
}

com.stunlock.battlerite.team.TeamUpdateEvent

this has how much MMR you won or lost

interface TeamUpdateEvent extends TelemetryData {
}

com.stunlock.service.matchmaking.avro.QueueEvent

this is the matchmaker data, some of it overkaps with reserved user

interface TeamUpdateEvent extends TelemetryData {
}

Todo/Wishlist

  • Rate Limiting
  • Proper code documentation (JSDoc?)
  • Rewrite the whole thing in typescript/purescript
  • Tests?

License

MIT