Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
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.
| Date uploaded | a month ago |
| Version | 0.2.3 |
| Download link | Proudlock_Technology-GsValheimStatsClient-0.2.3.zip |
| Downloads | 15 |
| Dependency string | Proudlock_Technology-GsValheimStatsClient-0.2.3 |
This mod requires the following mods to function
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.2333README
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.
What it tracks
Read from your own game (the things only the client knows), accumulated and persisted across sessions:
- Profile counters — Valheim's own
PlayerProfilestats: 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
-
Install via r2modman / Thunderstore (depends on
denikson-BepInExPack_Valheim). -
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> -
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-worldname).
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 ifTokenis 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).
snapshotIdLocallets a receiver dedupe. - Creature / craft / item keys are Valheim localization tokens (
$enemy_*,$item_*);statskeys arevh_<PlayerStatType>. reporteris 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 inplayers[](justweapons/weaponItems/boss). Source-separate weapon/boss rows byreporterand 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.bossSelfDamageis 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
Urlyou configure. Only install with aUrl/Tokenyou trust.
CHANGELOG
Changelog
0.2.10
- Fixed grossly inflated (and in other cases under-counted) "materials gathered" totals. Materials now come from Valheim's own cumulative, character-persistent pickup counter (PlayerProfile m_itemPickupStats), filtered to Material-type items, instead of a hook on Inventory.AddItem. The old hook fired on every inventory add, so hauling a resource between chests or recovering it from your tombstone re-counted the whole stack (silver was the worst offender), and it was session-only so anything gathered in a previous play session was lost.
0.2.9
- Per-life stats (time alive, kills that life, longest life, best streak) now measure a life from the game's own cumulative counters (active play time + kills) instead of the per-session clock, and the start-of-life snapshot persists across logins. A life that spans multiple sessions is now counted correctly, and offline time is excluded. Previously these reset every launch, so a death only logged the final session's slice.
0.2.8
- Boss-kill detection moved client-side: every kill emits a per-fight event (first blood, top damage, DPS, participants), so the boss-fight chronicle and repeat-kill history work. Fixed the headline boss-kill count.
0.2.7
- Docs: plain-text README (removed em-dashes and emoji).
0.2.6
- Docs: dropped em-dashes and emoji from the changelog and wiki for a plainer style.
0.2.5
- Docs: link to the new Data format & self-hosting wiki.
0.2.4
- Docs: refreshed README ingest examples (
reporter, multiplayer combat-only entries,bossSelfDamage) and bundled this changelog.
0.2.2
- Fire / poison / spirit damage-over-time is now credited to the player who applied it - works even when several players stack burns on one boss (each application is attributed at the moment of the hit).
- Capture boss self / environmental damage (lava, the boss's own fire, falls) - damage a boss takes with no player attacker, reported per boss.
0.2.1
- Emit-on-milestone: a new hardest hit or a kill flushes a post within ~15s instead of waiting the full interval, so big moments show up fast.
0.2.0
- Multiplayer weapon attribution: whichever client owns a creature now records the damage every player deals to it, attributed to the real attacker and source-separated by reporter. Combat totals are exact across a group, no double-counting.
0.1.9
- Removed debug logging.
0.1.8
- Fixed hardest hit. Now hooks
Character.RPC_Damage(where backstab/crit/armor are actually applied) instead of theDamageforwarder, so post-backstab numbers are captured correctly.
0.1.7
- Boss DPS (active engagement timing), specific weapon items (Bronze Sword vs Iron Sword), trophies, and biggest total swing (cleave/AoE).
0.1.6
- Weapon damage / kills / hardest hit, captured client-side.
0.1.x
- Initial release: Valheim
PlayerProfilecounters, skills, per-creature kills, per-item crafts, materials gathered, and per-life death details (cause incl. felled-by-tree, biome, life length, kills before dying).