Guide

Setting up Steam leaderboards

Steam leaderboards give you global and friends rankings, a community hub page, and even replay attachments, all hosted by Valve for free. Setup takes minutes. The part to think through is trust: by default the game client submits scores, which is fine for casual boards and a problem for competitive ones.

What you get

LimitValue
Leaderboards per gameUp to 10,000
Entries per playerOne per leaderboard
Players per leaderboardUnlimited
ScoreOne 32-bit integer, plus up to 64 extra integers of your own data (not sorted by Steam)
Update speedRankings are readable immediately after a score is uploaded

1. Create the leaderboard

In App Admin, go to Stats & Achievements → Leaderboards. (You can also create them from code with FindOrCreateLeaderboard, but defining them in Steamworks keeps settings in one place.)

FieldWhat to set
NameThe internal name your code looks up, e.g. fastest_run.
Community NameThe public name. Leave it empty and the board won't appear on your community hub.
Sort MethodDescending for high scores, Ascending for times and positions.
Display TypeNumeric, Seconds or Milliseconds. Only affects how the hub formats the score.
WritesTrusted means only your server can submit scores through the Web API. See below.
ReadsFriends limits the game to reading friends' scores.
Publish your Steamworks changes after creating leaderboards, as with any other setting.

2. Upload a score

Look up the board once, keep the handle, then upload. This example uses Steamworks.NET in Unity; the C++ API has the same calls on ISteamUserStats.

using Steamworks;
using UnityEngine;

public class Leaderboard : MonoBehaviour
{
    SteamLeaderboard_t board;
    CallResult<LeaderboardFindResult_t> onFind;
    CallResult<LeaderboardScoreUploaded_t> onUpload;

    void Start()
    {
        onFind = CallResult<LeaderboardFindResult_t>.Create(OnFound);
        onUpload = CallResult<LeaderboardScoreUploaded_t>.Create(OnUploaded);
        onFind.Set(SteamUserStats.FindLeaderboard("fastest_run"));
    }

    void OnFound(LeaderboardFindResult_t r, bool ioFailure)
    {
        if (!ioFailure && r.m_bLeaderboardFound != 0) board = r.m_hSteamLeaderboard;
    }

    public void Submit(int score)
    {
        var call = SteamUserStats.UploadLeaderboardScore(board,
            ELeaderboardUploadScoreMethod.k_ELeaderboardUploadScoreMethodKeepBest,
            score, null, 0);
        onUpload.Set(call);
    }

    void OnUploaded(LeaderboardScoreUploaded_t r, bool ioFailure)
    {
        if (!ioFailure && r.m_bSuccess != 0)
            Debug.Log("New global rank: " + r.m_nGlobalRankNew);
    }
}
Upload methodUse it when
KeepBestPersonal bests. Steam keeps the better of old and new scores.
ForceUpdateThe latest result should always replace the old one, e.g. a current-season rating.

3. Show the rankings

Call DownloadLeaderboardEntries with the handle, a request type and a range, then read each entry with GetDownloadedLeaderboardEntry. Read everything you need straight away, because the downloaded data is freed once you've gone through the entries.

Request typeShows
GlobalA range of ranks, e.g. 1–10
GlobalAroundUserEntries around the player's own rank, e.g. 5 above and 5 below
FriendsOnly the player's friends

Each entry gives you the player's Steam ID, global rank and score. Use SteamFriends.GetFriendPersonaName for display names.

4. Attach replays or ghosts (optional)

After uploading a score, call AttachLeaderboardUGC with a file shared through Steam Cloud, such as a replay or a ghost to race against. Other players can download it with the entry, and it stays available even if the original cloud file is later changed or deleted. See the Cloud guide for the storage side.

Cheating and trusted writes

By default the game client submits scores, so anyone who edits memory or intercepts the call can post whatever they like. For casual or friends-only boards that's usually acceptable. For anything competitive or prize-bearing:

1
Set Writes to Trusted

Clients can no longer submit scores at all.

2
Submit from your server

Your server validates the run, then posts the score with the SetLeaderboardScore Web API using your publisher key. The key never goes in the game.

Players will find the top of any client-written board and fill it with impossible scores within days of launch. Either use trusted writes, or be ready to reset and moderate from App Admin.
Next step: leaderboards live under the same Stats & Achievements section as achievements, so set both up together.