Leaderboards
Display global and friend rankings with EOS leaderboard integration
Leaderboards compare player progression. In EOS, leaderboards are tied to statistics and automatically update when stat values change.
Leaderboards require setup in the EOS Developer Portal. Create leaderboards and link them to stats before using the API.
You cannot directly write to leaderboards. All updates flow through the linked statistic.
Portal Setup
- Go to the EOS Developer Portal
- Navigate to Game Services → Leaderboards
- Click + New Leaderboard
- Configure the leaderboard:
| Field | Description |
|---|---|
| Leaderboard Name | Unique identifier (UPPERCASE, no spaces) |
| Stat Name | The stat that drives rankings |
| Aggregation | How scores combine (Sum, Max, Min, Latest) |
| Timespan | Never Expire, Daily, Weekly, Monthly, or custom |
Set Timespan to "Never Expire" for all-time leaderboards, or use time-based spans for seasonal competitions.
Read Around Rank
Get leaderboard entries centered around a specific rank. Use rank 1 to get the global top players.

- Leaderboard Id: The leaderboard name from portal
- Rank: Center rank (1 for top of leaderboard)
- Limit: Maximum entries to return
#include "EIKCore/Public/Interfaces/IEIKLeaderboards.h"
void UMyClass::ReadTopPlayers()
{
TSharedPtr<IEIKLeaderboards> Leaderboards = GetLeaderboardsInterface();
if (!Leaderboards.IsValid()) return;
FEIKReadLeaderboardAroundRankParams Params;
Params.LeaderboardId = TEXT("HIGH_SCORES");
Params.Rank = 1; // Start from top
Params.Limit = 10;
Leaderboards->ReadEntriesAroundRank(0, Params,
FEIKAsyncCallback<FEIKLeaderboardResult>::CreateLambda(
[](const TEIKAsyncResult<FEIKLeaderboardResult>& Result)
{
if (Result.IsSuccessful())
{
for (const FEIKLeaderboardEntry& Entry : Result.GetValue().Entries)
{
UE_LOG(LogTemp, Log, TEXT("#%d %s: %lld"),
Entry.Rank, *Entry.DisplayName, Entry.Score);
}
}
}));
}#include "Online/OnlineServices.h"
#include "Online/Leaderboards.h"
using namespace UE::Online;
void UMyClass::ReadTopPlayers()
{
IOnlineServicesPtr Services = GetServices(EOnlineServices::Epic);
ILeaderboardsPtr Leaderboards = Services->GetLeaderboardsInterface();
FReadEntriesAroundRank::Params Params;
Params.LocalAccountId = GetLocalAccountId();
Params.BoardName = TEXT("HIGH_SCORES");
Params.Rank = 1;
Params.Limit = 10;
Leaderboards->ReadEntriesAroundRank(MoveTemp(Params))
.OnComplete([](const TOnlineResult<FReadEntriesAroundRank>& Result)
{
if (Result.IsOk())
{
for (const FLeaderboardEntry& Entry : Result.GetOkValue().Entries)
{
UE_LOG(LogTemp, Log, TEXT("#%d: %lld"),
Entry.Rank, Entry.Score);
}
}
});
}#include "OnlineSubsystem.h"
#include "Interfaces/OnlineLeaderboardInterface.h"
void UMyClass::ReadTopPlayers()
{
IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get(FName(TEXT("EIK")));
IOnlineLeaderboardsPtr Leaderboards = OnlineSub->GetLeaderboardInterface();
FOnlineLeaderboardReadRef ReadObject = MakeShared<FOnlineLeaderboardRead>();
ReadObject->LeaderboardName = FName(TEXT("HIGH_SCORES"));
Leaderboards->ReadLeaderboardsAroundRank(1, 10, ReadObject);
Leaderboards->AddOnLeaderboardReadCompleteDelegate_Handle(
FOnLeaderboardReadCompleteDelegate::CreateLambda(
[ReadObject](bool bWasSuccessful)
{
if (bWasSuccessful)
{
for (const FOnlineStatsRow& Row : ReadObject->Rows)
{
UE_LOG(LogTemp, Log, TEXT("#%d %s"),
Row.Rank, *Row.NickName);
}
}
}));
}Read Around User
Get leaderboard entries centered around a specific player's rank. Shows the player's position relative to nearby competitors.

- Leaderboard Id: The leaderboard name from portal
- Target Account Id: User to center around (leave empty for local player)
- Offset: Positions to shift from user's rank
- Limit: Maximum entries to return
void UMyClass::ReadAroundLocalPlayer()
{
TSharedPtr<IEIKLeaderboards> Leaderboards = GetLeaderboardsInterface();
FEIKReadLeaderboardAroundUserParams Params;
Params.LeaderboardId = TEXT("HIGH_SCORES");
// Leave AccountId invalid to use local player
Params.Offset = 0;
Params.Limit = 10;
Leaderboards->ReadEntriesAroundUser(0, Params,
FEIKAsyncCallback<FEIKLeaderboardResult>::CreateLambda(
[](const TEIKAsyncResult<FEIKLeaderboardResult>& Result)
{
if (Result.IsSuccessful())
{
for (const FEIKLeaderboardEntry& Entry : Result.GetValue().Entries)
{
UE_LOG(LogTemp, Log, TEXT("#%d %s: %lld"),
Entry.Rank, *Entry.DisplayName, Entry.Score);
}
}
}));
}void UMyClass::ReadAroundLocalPlayer()
{
ILeaderboardsPtr Leaderboards = GetLeaderboardsInterface();
FReadEntriesAroundUser::Params Params;
Params.LocalAccountId = GetLocalAccountId();
Params.AccountId = GetLocalAccountId();
Params.BoardName = TEXT("HIGH_SCORES");
Params.Offset = 0;
Params.Limit = 10;
Leaderboards->ReadEntriesAroundUser(MoveTemp(Params))
.OnComplete([](const TOnlineResult<FReadEntriesAroundUser>& Result)
{
if (Result.IsOk())
{
for (const FLeaderboardEntry& Entry : Result.GetOkValue().Entries)
{
UE_LOG(LogTemp, Log, TEXT("#%d: %lld"),
Entry.Rank, Entry.Score);
}
}
});
}void UMyClass::ReadAroundLocalPlayer()
{
IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get(FName(TEXT("EIK")));
IOnlineLeaderboardsPtr Leaderboards = OnlineSub->GetLeaderboardInterface();
FUniqueNetIdPtr UserId = OnlineSub->GetIdentityInterface()->GetUniquePlayerId(0);
FOnlineLeaderboardReadRef ReadObject = MakeShared<FOnlineLeaderboardRead>();
ReadObject->LeaderboardName = FName(TEXT("HIGH_SCORES"));
Leaderboards->ReadLeaderboardsAroundUser(UserId.ToSharedRef(), 10, ReadObject);
Leaderboards->AddOnLeaderboardReadCompleteDelegate_Handle(
FOnLeaderboardReadCompleteDelegate::CreateLambda(
[ReadObject](bool bWasSuccessful)
{
if (bWasSuccessful)
{
for (const FOnlineStatsRow& Row : ReadObject->Rows)
{
UE_LOG(LogTemp, Log, TEXT("#%d %s"),
Row.Rank, *Row.NickName);
}
}
}));
}Read For Users
Get leaderboard entries for specific players. Useful for showing friends' scores or comparing with party members.

- Leaderboard Id: The leaderboard name from portal
- Account Ids: Array of users to query
void UMyClass::ReadFriendsScores(const TArray<FEIKAccountId>& FriendIds)
{
TSharedPtr<IEIKLeaderboards> Leaderboards = GetLeaderboardsInterface();
FEIKReadLeaderboardForUsersParams Params;
Params.LeaderboardId = TEXT("HIGH_SCORES");
Params.AccountIds = FriendIds;
Leaderboards->ReadEntriesForUsers(0, Params,
FEIKAsyncCallback<FEIKLeaderboardResult>::CreateLambda(
[](const TEIKAsyncResult<FEIKLeaderboardResult>& Result)
{
if (Result.IsSuccessful())
{
for (const FEIKLeaderboardEntry& Entry : Result.GetValue().Entries)
{
UE_LOG(LogTemp, Log, TEXT("%s: #%d with %lld"),
*Entry.DisplayName, Entry.Rank, Entry.Score);
}
}
}));
}void UMyClass::ReadFriendsScores(const TArray<FAccountId>& FriendIds)
{
ILeaderboardsPtr Leaderboards = GetLeaderboardsInterface();
FReadEntriesForUsers::Params Params;
Params.LocalAccountId = GetLocalAccountId();
Params.BoardName = TEXT("HIGH_SCORES");
Params.AccountIds = FriendIds;
Leaderboards->ReadEntriesForUsers(MoveTemp(Params))
.OnComplete([](const TOnlineResult<FReadEntriesForUsers>& Result)
{
if (Result.IsOk())
{
for (const FLeaderboardEntry& Entry : Result.GetOkValue().Entries)
{
UE_LOG(LogTemp, Log, TEXT("#%d: %lld"),
Entry.Rank, Entry.Score);
}
}
});
}void UMyClass::ReadFriendsScores(const TArray<FUniqueNetIdRef>& FriendIds)
{
IOnlineSubsystem* OnlineSub = IOnlineSubsystem::Get(FName(TEXT("EIK")));
IOnlineLeaderboardsPtr Leaderboards = OnlineSub->GetLeaderboardInterface();
FOnlineLeaderboardReadRef ReadObject = MakeShared<FOnlineLeaderboardRead>();
ReadObject->LeaderboardName = FName(TEXT("HIGH_SCORES"));
Leaderboards->ReadLeaderboards(FriendIds, ReadObject);
Leaderboards->AddOnLeaderboardReadCompleteDelegate_Handle(
FOnLeaderboardReadCompleteDelegate::CreateLambda(
[ReadObject](bool bWasSuccessful)
{
if (bWasSuccessful)
{
for (const FOnlineStatsRow& Row : ReadObject->Rows)
{
UE_LOG(LogTemp, Log, TEXT("#%d %s"),
Row.Rank, *Row.NickName);
}
}
}));
}