Every endpoint has two entry points: a resource method on the connector, which sends and
returns the DTO, and the request class behind it, which you send yourself. Both take the
same arguments, except the concurrency that summaries() and bans() add. Every argument
that identifies a user is a SteamId; the
shapes coming back are documented in Data objects.
Badges list what a request throws on its own. On top of that, any request can raise
SteamRateLimitException, SteamConnectionException or SteamApiException from the
connector, and every request that needs a key can raise InvalidApiKeyException, or
ApiKeyNotConfiguredException when the config carries no key at all — see
Exceptions.
Both layers are namespaced by the Steam interface they belong to — one resource per interface, and one request class per endpoint:
Directorysrc/Http
DirectoryRequests
DirectoryIPlayerService
- GetBadgesRequest.php
- GetCommunityBadgeProgressRequest.php
- GetOwnedGamesRequest.php
- GetRecentlyPlayedGamesRequest.php
- GetSteamLevelRequest.php
DirectoryISteamApps
- GetSdrConfigRequest.php
- GetServersAtAddressRequest.php
- UpToDateCheckRequest.php
DirectoryISteamNews
- GetNewsForAppRequest.php
DirectoryISteamUser
- GetFriendListRequest.php
- GetPlayerBansRequest.php
- GetPlayerSummariesRequest.php
- GetUserGroupListRequest.php
- ResolveVanityUrlRequest.php
DirectoryISteamUserStats
- GetGlobalAchievementPercentagesForAppRequest.php
- GetNumberOfCurrentPlayersRequest.php
- GetPlayerAchievementsRequest.php
- GetSchemaForGameRequest.php
- GetUserStatsForGameRequest.php
DirectoryISteamWebAPIUtil
- GetServerInfoRequest.php
- GetSupportedApiListRequest.php
DirectoryResources
- AppsResource.php
- NewsResource.php
- PlayersResource.php
- StatsResource.php
- UsersResource.php
- WebApiResource.php
| Request | Resource method | Returns |
|---|---|---|
GetBadgesRequest |
players()->badges() |
PlayerBadges |
GetCommunityBadgeProgressRequest |
players()->communityBadgeProgress() |
list<CommunityBadgeQuest> |
GetOwnedGamesRequest |
players()->ownedGames() |
list<OwnedGame> |
GetRecentlyPlayedGamesRequest |
players()->recentlyPlayedGames() |
RecentlyPlayedGames |
GetSteamLevelRequest |
players()->steamLevel() |
int |
GetSdrConfigRequest |
apps()->sdrConfig() |
SdrConfig |
GetServersAtAddressRequest |
apps()->serversAtAddress() |
list<GameServer> |
UpToDateCheckRequest |
apps()->upToDateCheck() |
AppVersionCheck |
GetNewsForAppRequest |
news()->appNews() |
AppNews |
GetFriendListRequest |
users()->friends() |
list<Friend> |
GetPlayerBansRequest |
users()->bans() |
list<PlayerBan> |
GetPlayerSummariesRequest |
users()->summaries() |
list<PlayerSummary> |
GetUserGroupListRequest |
users()->groups() |
list<UserGroup> |
ResolveVanityUrlRequest |
users()->resolveVanityUrl() |
SteamId |
GetGlobalAchievementPercentagesForAppRequest |
stats()->globalAchievements() |
list<GlobalAchievement> |
GetNumberOfCurrentPlayersRequest |
stats()->currentPlayers() |
int |
GetPlayerAchievementsRequest |
stats()->achievements() |
PlayerAchievements |
GetSchemaForGameRequest |
stats()->schema() |
GameSchema |
GetUserStatsForGameRequest |
stats()->userStats() |
UserStats |
GetServerInfoRequest |
webApi()->serverTime() |
DateTimeImmutable |
GetSupportedApiListRequest |
webApi()->supportedApis() |
list<WebApiInterface> |
IPlayerService
Section titled “IPlayerService”GetBadgesRequest
Section titled “GetBadgesRequest”$connector->players()->badges(SteamId $steamId)
new GetBadgesRequest($steamId)throws ProfileNotPublicException
Every badge a player has earned, plus the experience behind their community level.
Badges that come from trading cards name the app they belong to; the rest — event and
milestone badges — leave appId null, which is what separates the two kinds.
$badges = $connector->players()->badges($steamId);
echo $badges->playerLevel, ' — ', $badges->xpNeededToLevelUp, ' XP to go', PHP_EOL;
foreach ($badges->badges as $badge) { echo $badge->badgeId, ' level ', $badge->level, PHP_EOL;}badgeId is not unique on its own: trading card badges repeat the same ID across
different apps and are told apart by appId, so the result stays a list rather than a map.
GetCommunityBadgeProgressRequest
Section titled “GetCommunityBadgeProgressRequest”$connector->players()->communityBadgeProgress(SteamId $steamId)
new GetCommunityBadgeProgressRequest($steamId)throws ProfileNotPublicException
The quests behind the Steam community badge, each with the flag saying whether the
account finished it. Steam publishes no schema mapping questId to a name, so the IDs
stay opaque.
$quests = $connector->players()->communityBadgeProgress($steamId);
foreach ($quests as $quest) { echo $quest->questId, $quest->completed ? ' — done' : ' — pending', PHP_EOL;}Steam’s badgeid filter is not exposed. 0 behaves as a wildcard, and every other ID
answers with the same empty payload Steam sends for a hidden profile and for a SteamID64
that belongs to no account — a valid filter would be indistinguishable from the failure
that raises the exception.
GetOwnedGamesRequest
Section titled “GetOwnedGamesRequest”$connector->players()->ownedGames( SteamId $steamId, list<int> $appIdsFilter = [], bool $includeAppInfo = false, bool $includePlayedFreeGames = false,)
new GetOwnedGamesRequest($steamId, $appIdsFilter, $includeAppInfo, $includePlayedFreeGames)throws ProfileNotPublicException
The games a player owns. appIdsFilter narrows the result to specific app IDs;
includeAppInfo adds names and icons; includePlayedFreeGames includes free games
the player has launched.
$library = $connector->players()->ownedGames( steamId: $steamId, appIdsFilter: [381210], includeAppInfo: true,);GetRecentlyPlayedGamesRequest
Section titled “GetRecentlyPlayedGamesRequest”$connector->players()->recentlyPlayedGames(SteamId $steamId, ?int $count = null)
new GetRecentlyPlayedGamesRequest($steamId, $count)throws ProfileNotPublicException
What a player launched in the last two weeks. count caps how many games come back,
while totalCount on the result stays the full figure — that is how you tell a truncated
list from a complete one.
$recent = $connector->players()->recentlyPlayedGames(steamId: $steamId, count: 2);
foreach ($recent->games as $game) { echo $game->name, ' — ', $game->playtimeTwoWeeks, ' min', PHP_EOL;}GetSteamLevelRequest
Section titled “GetSteamLevelRequest”$connector->players()->steamLevel(SteamId $steamId)
new GetSteamLevelRequest($steamId)throws ProfileNotPublicException
The player’s Steam community level, as a plain int rather than a DTO. Hiding game
details leaves it readable — only a profile Steam withholds altogether comes back empty,
and that is what raises the exception.
$level = $connector->players()->steamLevel($steamId);ISteamApps
Section titled “ISteamApps”GetSdrConfigRequest
Section titled “GetSdrConfigRequest”$connector->apps()->sdrConfig(int $appId)
new GetSdrConfigRequest($appId)throws AppNotFoundException
The Steam Datagram Relay map a game connects through: every point of presence, where it
stands, and the IPv4 addresses and ports its relays answer on. A game without a map of its
own gets Valve’s default one, and app ID 0 returns the whole network. Steam serves it
anonymously, so the SDK strips the configured key from the query, and a connector built
without one can send it.
$config = $connector->apps()->sdrConfig(730);
foreach ($config->pointsOfPresence['waw']->relays as $relay) { echo $relay->ipv4, ':', $relay->minPort, '-', $relay->maxPort, PHP_EOL;}GetServersAtAddressRequest
Section titled “GetServersAtAddressRequest”$connector->apps()->serversAtAddress(string $address)
new GetServersAtAddressRequest($address)throws InvalidServerAddressException
Every game server Steam knows at an IPv4 address, or only the one behind ip:queryport. An
address with no servers returns an empty list. Steam serves it anonymously, so the SDK strips
the configured key from the query, and a connector built without one can send it.
foreach ($connector->apps()->serversAtAddress('108.181.62.21') as $server) { echo $server->address, ' runs app ', $server->appId, PHP_EOL;}UpToDateCheckRequest
Section titled “UpToDateCheckRequest”$connector->apps()->upToDateCheck(int $appId, int $version)
new UpToDateCheckRequest($appId, $version)throws AppVersionUnavailableException
Whether a game server’s build is still the one Steam accepts, and which version to update to if not. Steam serves it anonymously, so the SDK strips the configured key from the query, and a connector built without one can send it.
$check = $connector->apps()->upToDateCheck(440, $installedVersion);
if (! $check->isUpToDate) { echo 'Update to ', $check->requiredVersion, ': ', $check->message, PHP_EOL;}ISteamNews
Section titled “ISteamNews”GetNewsForAppRequest
Section titled “GetNewsForAppRequest”$connector->news()->appNews( int $appId, ?int $count = null, ?int $maxLength = null, ?DateTimeInterface $endDate = null, list<string> $feeds = [], list<string> $tags = [],)
new GetNewsForAppRequest($appId, $count, $maxLength, $endDate, $feeds, $tags)throws AppNewsUnavailableException
A game’s news, newest first: Steam’s own announcements next to blog and press feeds. count
sets the page size, 20 by default, and 0 returns nothing; feeds and tags filter by feed
name and tag. Without maxLength, or with 0, each body comes in its feed’s own markup, BBCode
or HTML; any positive value flattens it, even when it fits, and cuts a longer one to an excerpt
ending in ..., keeping HTML links and bold. Steam serves it anonymously, so the SDK strips the
configured key from the query, and a connector built without one can send it. Every 403
covers two causes — an app ID Steam does not know, or an app whose news it does not publish,
such as Spacewar — because both answer identically.
The SDK ships no pager. Pass the last item’s publishedAt back as endDate:
use Fkrzski\SteamApiSdk\Dto\NewsItem;
$seen = [];$endDate = null;
do { $page = $connector->news()->appNews(440, count: 50, endDate: $endDate); $fresh = array_filter($page->items, fn (NewsItem $item): bool => ! isset($seen[$item->id]));
foreach ($fresh as $item) { $seen[$item->id] = true; $endDate = $item->publishedAt;
echo $item->publishedAt->format('Y-m-d'), ' ', $item->title, PHP_EOL; }} while ($fresh !== []);endDate is inclusive, so every page opens with the last item of the one before, and the loop
drops it by ID. Stepping a second back instead would lose posts published in that same second.
ISteamUser
Section titled “ISteamUser”GetFriendListRequest
Section titled “GetFriendListRequest”$connector->users()->friends(SteamId $steamId, ?FriendRelationship $relationship = null)
new GetFriendListRequest($steamId, $relationship)throws ProfileNotPublicException
The player’s friends. Pass a FriendRelationship to filter; omit it for all
relationships. A private friend list is refused with a 401, not an empty payload.
use Fkrzski\SteamApiSdk\Enums\FriendRelationship;
$friends = $connector->users()->friends($steamId, FriendRelationship::Friend);GetPlayerBansRequest
Section titled “GetPlayerBansRequest”$connector->users()->bans(list<SteamId> $steamIds, int $concurrency = 5)
new GetPlayerBansRequest($steamIds)throws InvalidArgumentException throws TooManySteamIdsException
VAC, game, community and economy ban status. The request takes 1 to 100 players;
bans() takes any number and splits a longer list.
Unlike the other batch endpoint this one needs no public profile — bans come back for private
profiles too.
$bans = $connector->users()->bans([$steamId]);
foreach ($bans as $ban) { echo $ban->steamId, ' — VAC bans: ', $ban->numberOfVacBans, PHP_EOL;}GetPlayerSummariesRequest
Section titled “GetPlayerSummariesRequest”$connector->users()->summaries(list<SteamId> $steamIds, int $concurrency = 5)
new GetPlayerSummariesRequest($steamIds)throws InvalidArgumentException throws TooManySteamIdsException
Public profile summaries. The request takes 1 to 100 players and checks both limits in
the constructor, so a bad batch costs no quota; summaries() takes any number and
splits a longer list.
$summaries = $connector->users()->summaries([$steamId]);
foreach ($summaries as $summary) { echo $summary->personaName, ' — ', $summary->profileUrl, PHP_EOL;}GetUserGroupListRequest
Section titled “GetUserGroupListRequest”$connector->users()->groups(SteamId $steamId)
new GetUserGroupListRequest($steamId)throws ProfileNotPublicException
The Steam groups a player belongs to. Only group IDs come back — Steam exposes no group metadata on this endpoint.
$groups = $connector->users()->groups($steamId);
foreach ($groups as $group) { echo $group->gid, PHP_EOL;}ResolveVanityUrlRequest
Section titled “ResolveVanityUrlRequest”$connector->users()->resolveVanityUrl(string $vanityName)
new ResolveVanityUrlRequest($vanityName)throws SteamUserNotFoundException
Resolves a vanity slug — the <name> in steamcommunity.com/id/<name> — to a
SteamId. Working from a full URL? Run it through
SteamId::extractVanityName() first.
$steamId = $connector->users()->resolveVanityUrl('gabelogannewell');ISteamUserStats
Section titled “ISteamUserStats”GetGlobalAchievementPercentagesForAppRequest
Section titled “GetGlobalAchievementPercentagesForAppRequest”$connector->stats()->globalAchievements(int $gameId)
new GetGlobalAchievementPercentagesForAppRequest($gameId)throws StatsUnavailableException
How much of the playerbase has unlocked each achievement in a game, ordered from the most
common down. Steam serves it anonymously, so the SDK strips the configured key from the
query, a connector built without one can send it, and no key error can land here. Every 403 is about the game, and covers two
causes — a game carrying no achievements, or a game ID Steam does not know — because both
answer identically.
$achievements = $connector->stats()->globalAchievements(381210);
foreach ($achievements as $achievement) { echo $achievement->apiName, ' — ', $achievement->percent, '%', PHP_EOL;}GetNumberOfCurrentPlayersRequest
Section titled “GetNumberOfCurrentPlayersRequest”$connector->stats()->currentPlayers(int $appId)
new GetNumberOfCurrentPlayersRequest($appId)throws AppNotFoundException
How many people are playing a game right now, as a plain int rather than a DTO. Steam
serves it anonymously, so the SDK strips the configured key from the query, and a
connector built without one can send it.
$players = $connector->stats()->currentPlayers(381210);GetPlayerAchievementsRequest
Section titled “GetPlayerAchievementsRequest”$connector->stats()->achievements(SteamId $steamId, int $appId, ?Language $language = null)
new GetPlayerAchievementsRequest($steamId, $appId, $language)throws StatsUnavailableException
A player’s achievements for one game, each with its unlock state and time. The exception covers two causes — no achievements on the app, or a hidden profile — because Steam reports them identically.
use Fkrzski\SteamApiSdk\Enums\Language;
$result = $connector->stats()->achievements( steamId: $steamId, appId: 381210, language: Language::English,);
foreach ($result->achievements as $achievement) { echo $achievement->apiName, ' — ', $achievement->achieved ? 'unlocked' : 'locked', PHP_EOL;}GetSchemaForGameRequest
Section titled “GetSchemaForGameRequest”$connector->stats()->schema(int $appId, ?Language $language = null)
new GetSchemaForGameRequest($appId, $language)throws AppNotFoundException
Every stat and achievement a game publishes, with the display names and descriptions a
player’s own achievements are read against. language
localises them; see the Language enum.
use Fkrzski\SteamApiSdk\Enums\Language;
$schema = $connector->stats()->schema(appId: 381210, language: Language::Polish);
foreach ($schema->achievements as $achievement) { echo $achievement->apiName, ' — ', $achievement->name, PHP_EOL;}GetUserStatsForGameRequest
Section titled “GetUserStatsForGameRequest”$connector->stats()->userStats(SteamId $steamId, int $appId, ?Language $language = null)
new GetUserStatsForGameRequest($steamId, $appId, $language)throws ProfileNotPublicException
A player’s stats and achievement flags for one game. language localises achievement
metadata; see the Language enum.
$stats = $connector->stats()->userStats(steamId: $steamId, appId: 381210);
foreach ($stats->stats as $stat) { echo $stat->name, ' = ', $stat->value, PHP_EOL;}ISteamWebAPIUtil
Section titled “ISteamWebAPIUtil”GetServerInfoRequest
Section titled “GetServerInfoRequest”$connector->webApi()->serverTime()
new GetServerInfoRequestSteam’s clock, as a DateTimeImmutable in UTC rather than a DTO. Steam serves it
anonymously, so the SDK strips the configured key from the query, and a connector built
without one can send it. The servertimestring Steam sends beside it is left out: it is US
Pacific local time with no offset.
$skew = $connector->webApi()->serverTime()->getTimestamp() - time();GetSupportedApiListRequest
Section titled “GetSupportedApiListRequest”$connector->webApi()->supportedApis()
new GetSupportedApiListRequestthrows InvalidApiKeyException
Every Web API method Steam lets the caller see, grouped by interface. The key is optional:
the configured one goes along and adds the methods it can call, and a connector built
without one gets the anonymous list. Steam refuses a bad key here with a JSON 403 rather
than its usual HTML, and the request still raises it as the exception.
foreach ($connector->webApi()->supportedApis() as $interface) { foreach ($interface->methods as $method) { echo $interface->name, '/', $method->name, '/v', $method->version, PHP_EOL; }}