Proudlock_Technology-GsValheimStatsClient icon

GsValheimStatsClient

Client companion for the gs dashboard: posts your Valheim combat (weapon & boss damage, DPS, hardest hit), kills, crafts, materials, skills, trophies and per-life deaths. Multiplayer-aware. Pairs with the server-side gs emitter.

Last updated 4 days ago
Total downloads 273
Total rating 0 
Categories Misc Client-side
Dependency string Proudlock_Technology-GsValheimStatsClient-0.2.9
Dependants 0 other packages depend on this package

This mod requires the following mods to function

denikson-BepInExPack_Valheim-5.4.2333 icon
denikson-BepInExPack_Valheim

BepInEx pack for Valheim. Preconfigured with the correct entry point for mods and preferred defaults for the community.

Preferred version: 5.4.2333

README

GsValheimStatsClient

A client companion that posts your personal Valheim stats to an HTTP endpoint - by default the self-hosted gs dashboard, but it'll post to any URL you point it at, so you can ingest your stats however you like.

Pairs with the server-side GsValheimStatsEmitter. Both POST to the same endpoint; the dashboard merges them.

Ingesting the data into your own dashboard? See the Data format & self-hosting wiki for the complete payload schema, key conventions, and merge rules.


What it tracks

Read from your own game (the things only the client knows), accumulated and persisted across sessions:

  • Profile counters - Valheim's own PlayerProfile stats: kills, deaths, builds, crafts, jumps, distances (walked / run / sailed / air), trees chopped, items picked up, ...
  • Skills - every weapon/utility skill level
  • Per-creature kills - what you're killing and how much
  • Crafts - which items you've crafted (+ counts)
  • Materials gathered - Wood, Stone, ores, ...
  • Weapons - per weapon category: total damage, kills, hardest single hit, biggest total swing (cleave/AoE)
  • Specific weapons - same, per actual item (Bronze Sword vs Iron Sword)
  • Boss damage + DPS - your damage to each boss and your active engagement time (DPS = damage / fightSec), incl. fire/poison damage-over-time credited to whoever applied it
  • Trophies - collected trophies
  • Deaths - cause (incl. felled-by-your-own-tree, Deathsquito), biome, life length, kills before dying
  • Multiplayer-aware - whichever client owns a creature records the damage every player deals to it, so combat totals are exact across a group
  • Boss self-damage - damage a boss takes from the world (lava / its own fire / falls), with no player to blame

Setup

  1. Install via r2modman / Thunderstore (depends on denikson-BepInExPack_Valheim).

  2. Launch the game once to generate the config, then edit BepInEx/config/net.cproudlock.gsvalheimstatsclient.cfg:

    [General]
    World = vhserver3          # must match the server's world name
    EmitIntervalSeconds = 120  # how often it POSTs
    
    [Ingest]
    Url = https://gs.proudtech.net/api/valheim/ingest
    Token = <bearer token from the dashboard owner>
    
  3. Restart Valheim. It POSTs every EmitIntervalSeconds (and on death).

Stats are filed under World, so set it to whatever you want to group your runs by (typically the server's -world name).


Ingesting the stats yourself

The mod just does an authenticated POST of a JSON snapshot. You don't need the gs dashboard - point Url at anything that speaks HTTP.

Request:

  • POST <Url>
  • Authorization: Bearer <Token> (omitted if Token is blank)
  • Content-Type: application/json

Payload (source: "client"):

{
  "schemaVersion": 1,
  "game": "valheim",
  "source": "client",
  "reporter": "Erebus",
  "world": "vhserver3",
  "emittedAtUtc": "2026-06-09T18:00:00Z",
  "snapshotIdLocal": "5e2f...",
  "players": [{
    "name": "Erebus",
    "platformId": "-1285113746",
    "kills": 312, "bossKills": 1, "deaths": 4,
    "longestLifeSec": 7200, "bestKillsBeforeDeath": 150,
    "stats":   { "vh_EnemyKills": 312, "vh_Builds": 540, "vh_DistanceSail": 4200 },
    "skills":  [{ "skill": "Knives", "level": 42 }],
    "creatureKills": [{ "creature": "$enemy_greydwarf", "kills": 140 }],
    "crafts":  [{ "item": "$item_club", "count": 3 }],
    "materials": [{ "material": "Wood", "amount": 3400 }],
    "weapons": [{ "weapon": "Knives", "damageDealt": 493, "kills": 29, "hardestHit": 79, "biggestSwing": 121 }],
    "weaponItems": [{ "item": "$item_knife_bronze", "damageDealt": 400, "kills": 25, "hardestHit": 79 }],
    "boss":    [{ "boss": "Eikthyr", "damageDealt": 1450, "fightSec": 95 }],
    "pickups": [{ "item": "$item_trophy_boar", "count": 11 }]
  }, {
    "name": "Pridetoes",
    "weapons": [{ "weapon": "Bows", "damageDealt": 220, "kills": 3, "hardestHit": 60, "biggestSwing": 60 }],
    "boss":    [{ "boss": "Eikthyr", "damageDealt": 700, "fightSec": 95 }]
  }],
  "deathEvents": [{
    "playerName": "Erebus", "killer": "tree", "biome": "BlackForest",
    "posX": 120, "posY": 30, "posZ": -44, "lifeSec": 1800, "killsThisLife": 40,
    "tsUtc": "2026-06-09T17:30:00Z"
  }],
  "bossSelfDamage": [{ "boss": "Fader", "damage": 210 }]
}

Notes:

  • All counters are cumulative running totals (idempotent - re-posting the same snapshot is safe). snapshotIdLocal lets a receiver dedupe.
  • Creature / craft / item keys are Valheim localization tokens ($enemy_*, $item_*); stats keys are vh_<PlayerStatType>.
  • reporter is who captured this payload. Valheim simulates each creature on the nearest client, so in multiplayer a client also records the combat it witnesses for other players on creatures it owns - those appear as extra, combat-only entries in players[] (just weapons/weaponItems/boss). Source-separate weapon/boss rows by reporter and sum across reporters: each hit is seen by exactly one owner, so it's an exact total with no double-count. Fire/poison damage-over-time is credited to whoever applied it.
  • bossSelfDamage is per-boss damage taken with no player attacker (lava, the boss's own fire, fall) - a curiosity stat, not attributed to anyone.

Minimal receiver (Node):

import express from 'express';
const app = express();
app.use(express.json({ limit: '1mb' }));
app.post('/api/valheim/ingest', (req, res) => {
  if (req.get('authorization') !== 'Bearer my-secret') return res.sendStatus(401);
  for (const p of req.body.players ?? [])
    console.log(`${p.name}: ${p.kills} kills, ${p.deaths} deaths`);
  res.json({ status: 'ok' });
});
app.listen(3001);

Then set Url = http://<host>:3001/api/valheim/ingest and Token = my-secret.

Quick test with curl:

curl -X POST http://localhost:3001/api/valheim/ingest \
  -H 'Authorization: Bearer my-secret' -H 'Content-Type: application/json' \
  -d '{"game":"valheim","source":"client","world":"test","players":[{"name":"You","kills":1}]}'

Privacy: the mod sends your stats to whatever Url you configure. Only install with a Url/Token you trust.