steam-go Wiki | Steam Keys and Access Tokens | 中文文档 | Steam Key 与 Access Token
steam-go is a lightweight Go SDK focused on the official Steam Web API.
v1.0.0 is the first stable release of steam-go, positioned as a production-oriented Go SDK for the official Steam Web API.
v1.1.0 adds a read-only client.Web.* layer for high-value Steam Storefront, Community, and Market JSON endpoints outside api.steampowered.com.
- Root
Clientwith grouped service access underclient.API.* - Read-only
client.Web.*access for Storefront app/package details, reviews, community inventory, and market price overview - Functional options for API key, access token, timeout, retry, rate limit, and proxy selection
- Buffered response bodies are capped by default and can be tuned with
WithMaxResponseBodyBytes(...) keyandaccess_tokenare treated as different credentials and can be configured independently- API key is optional and can be supplied through a rotating key provider
WithSafeDefaults()enables a conservative retry + rate-limit preset for real external trafficWithHealthCheckedAPIKeys(...)adds temporary cooldown for keys that repeatedly hit401/429- Typed responses by default with matching raw response methods
401/429can automatically retry with the next API key whenWithAPIKeys(...)andWithRetry(...)are used together- Independent addons can extend the SDK without bloating the core Web API client
go get github.com/gofurry/steam-go@latestpackage main
import (
"context"
"fmt"
"time"
steam "github.com/gofurry/steam-go"
)
func main() {
client, err := steam.NewClient(
steam.WithAPIKey("your-key"),
steam.WithTimeout(10*time.Second),
steam.WithRetry(2),
)
if err != nil {
panic(err)
}
defer client.Close()
resp, err := client.API.SteamUser.GetPlayerSummaries(
context.Background(),
[]string{"76561198370695025"},
)
if err != nil {
panic(err)
}
for _, player := range resp.Response.Players {
fmt.Printf("%s: %s\n", player.SteamID, player.PersonaName)
}
}Detailed API group references live in docs/api/reference.md. Read-only web endpoint notes live in docs/web/reference.md. Project governance documents:
client.API.WishlistService currently covers the main wishlist lookup flows:
GetWishlistfor the wishlist item list of a Steam accountGetWishlistItemCountfor the total wishlist countGetWishlistItemsOnSalefor detailed on-sale wishlist items with configurableinput_jsonfields
GetWishlist and GetWishlistItemCount use typed lightweight responses. GetWishlistItemsOnSale keeps each store_item as raw JSON so the SDK can tolerate Steam's very large and frequently changing store payload.
client.API.PlayerService already covers a useful mix of public and authenticated profile/gameplay endpoints, including:
- badges, community badge progress, favorite badge, Steam level, and Steam level distribution
- animated avatars, avatar frames, profile backgrounds, mini-profile backgrounds, equipped items, and owned profile items
- profile customization, purchased customizations, purchased/upgraded customization summaries, and available profile themes
- nickname lists, player link details, friends gameplay info, recently played games, last played times, and top achievements for games
When a method signature explicitly asks for accessToken or key, that credential must be passed to the method itself. Client-level credentials remain useful as defaults for endpoints that do not require caller-specific credentials in the method signature.
addons/a2sis a lightweight bridge togithub.com/gofurry/a2s-gov1.0.1addons/openidprovides Steam OpenID login verification for browser-based sign-in flows- OpenID only confirms Steam identity and returns
SteamID64; it does not replace Web API credentials - detailed addon notes live in docs/addons/reference.md
client.Web.* covers a small set of high-value read-only JSON endpoints outside the official api.steampowered.com surface:
client.Web.Storefront.GetAppDetailsclient.Web.Storefront.GetPackageDetailsclient.Web.Storefront.GetAppReviewsclient.Web.Community.GetInventoryclient.Web.Market.GetPriceOverview
These methods are part of the stable Go API surface in v1.x, but the upstream Store / Community / Market payloads remain unofficial or volatile web surfaces. client.Web.* never injects Steam Web API key or access_token; inventory access relies on caller-supplied cookies when required.
steam-go keeps proxy support centered on WithProxySelector(...).
NewStaticProxySelector(...)for one fixed proxyNewRoundRobinProxySelector(...)for simple rotationNewHealthCheckedRoundRobinProxySelector(...)for failure-based cooldown in one proxy poolNewStickyProxySelector(...)for explicit session-key based sticky proxy selectionNewRoutingProxySelector(...)for host/path-based routingNewHTTPClientWithProxySelector(...)for addon or standalone HTTP flowsWithProxySessionKey(ctx, key)for attaching one sticky session key to request contextProxyMetricsProviderfor one in-memory health snapshot of a health-checked proxy pool- no external metrics integration or heavy proxy-pool management
Static example:
selector, err := steam.NewStaticProxySelector("http://127.0.0.1:7897")
if err != nil {
panic(err)
}
client, err := steam.NewClient(
steam.WithAPIKey("your-key"),
steam.WithProxySelector(selector),
)
if err != nil {
panic(err)
}Routing example:
selector, err := steam.NewRoutingProxySelector(
steam.ProxyRoute{
Host: "api.steampowered.com",
PathPrefix: "/ISteamUser/",
ProxyURL: "http://127.0.0.1:7897",
},
steam.ProxyRoute{
Host: "steamcommunity.com",
PathPrefix: "/openid/",
ProxyURL: "",
},
)
if err != nil {
panic(err)
}Sticky example:
baseSelector, err := steam.NewRoundRobinProxySelector(
"http://127.0.0.1:7897",
"http://127.0.0.1:7898",
)
if err != nil {
panic(err)
}
client, err := steam.NewClient(
steam.WithAPIKey("your-key"),
steam.WithProxySelector(steam.NewStickyProxySelector(baseSelector)),
)
if err != nil {
panic(err)
}
ctx := steam.WithProxySessionKey(context.Background(), "browser-session-1")
_, err = client.API.SteamUser.GetPlayerSummaries(ctx, []string{"76561198370695025"})
if err != nil {
panic(err)
}Health-checked round-robin example:
selector, err := steam.NewHealthCheckedRoundRobinProxySelector(
steam.DefaultProxyHealthConfig(),
"http://127.0.0.1:7897",
"http://127.0.0.1:7898",
)
if err != nil {
panic(err)
}
client, err := steam.NewClient(
steam.WithAPIKey("your-key"),
steam.WithProxySelector(selector),
)
if err != nil {
panic(err)
}
metrics := selector.(steam.ProxyMetricsProvider).ProxyMetricsSnapshot()
fmt.Printf("healthy=%d cooling=%d\n", metrics.HealthyProxies, metrics.CoolingProxies)steam-go now supports per-class request policy routing so official Steam Web API traffic and the built-in client.Web.* surfaces can use different request strategies.
TrafficClassOfficialAPIis the default for existing typedclient.API.*methodsTrafficClassPublicStorePageis used byclient.Web.Storefront.*TrafficClassCommunityWebis used byclient.Web.Community.*TrafficClassMarketWebis used byclient.Web.Market.*WithTrafficPolicy(...)overrides proxy, cookie jar, retry, rate limit, short-cache, block detection, header profile, and Referer strategy per classTransportHookandTransportHookFuncreserve one per-class HTTP execution extension point for future TLS customization or browser-backed fallbackWithTrafficClass(ctx, class)lets one request opt into a non-default classDefaultPublicStoreHeaderProfileZH()andDefaultPublicStoreHeaderProfileEN()provide stable browser-like header presetsWithRefererSource(ctx, rawURL)plusNewStaticRefererSelector(...),NewRoutingRefererSelector(...), andNewContextRefererSelector(...)support fixed, routed, and context-driven Referer policiesTrafficCachePolicy{TTL: ...}enables per-class in-memory short caching withETag/Last-Modifiedrevalidation forGETrequestsTrafficBlockPolicy{HTMLSniffBytes: ...}enables public store-page block detection for429,403, and HTML challenge responses
Example:
client, err := steam.NewClient(
steam.WithAPIKey("your-key"),
steam.WithTrafficPolicy(steam.TrafficClassPublicStorePage, steam.TrafficPolicy{
RateLimiter: &steam.TrafficRateLimiterPolicy{
Limit: 10,
Burst: 10,
},
}),
)
if err != nil {
panic(err)
}
// Keep typed Steam Web API calls on the default OfficialAPI class.
_, _ = client.API.SteamUser.GetPlayerSummaries(context.Background(), []string{"76561198370695025"})
// Web requests route automatically by method.
_, _ = client.Web.Market.GetPriceOverview(context.Background(), 440, "Mann Co. Supply Crate Key", nil)Public store-page profile example:
profile := steam.DefaultPublicStoreHeaderProfileZH()
refererSelector, err := steam.NewStaticRefererSelector("https://store.steampowered.com/search/")
if err != nil {
panic(err)
}
client, err := steam.NewClient(
steam.WithAPIKey("your-key"),
steam.WithTrafficPolicy(steam.TrafficClassPublicStorePage, steam.TrafficPolicy{
Cache: &steam.TrafficCachePolicy{TTL: time.Minute},
BlockPolicy: &steam.TrafficBlockPolicy{},
HeaderProfile: &profile,
RefererSelector: refererSelector,
}),
)
if err != nil {
panic(err)
}Public store-page transport hook example:
client, err := steam.NewClient(
steam.WithAPIKey("your-key"),
steam.WithTrafficPolicy(steam.TrafficClassPublicStorePage, steam.TrafficPolicy{
TransportHook: steam.TransportHookFunc(func(class steam.TrafficClass, base *http.Client) (*http.Client, error) {
cloned := *base
if transport, ok := base.Transport.(*http.Transport); ok {
custom := transport.Clone()
custom.TLSHandshakeTimeout = 5 * time.Second
cloned.Transport = custom
}
return &cloned, nil
}),
}),
)
if err != nil {
panic(err)
}On China-region networks, browser login may succeed while the server-side Steam OpenID check_authentication request still times out. The OpenID example supports --proxy http://127.0.0.1:7897 for that case and also demonstrates cookie-backed state verification on the callback.
go run ./examples/a2s -server 1.2.3.4:27015 -query infogo run ./examples/a2s -server 1.2.3.4:27015 -query playersgo run ./examples/a2s -server 1.2.3.4:27015 -query rulesgo run ./examples/openidgo run ./examples/openid --proxy http://127.0.0.1:7897go run ./examples/proxygo run ./examples/trafficgo run ./examples/steamusergo run ./examples/playerservicego run ./examples/steamuserstatsgo run ./examples/steamnewsgo run ./examples/live/steamusergo run ./examples/live/playerservicego run ./examples/live/wishlistservice- full live smoke list: examples/live/README.md
SDK errors use *steam.APIError with these kinds:
request_buildtransporthttp_statusdecodeapi_response
Use errors.As(err, &apiErr) to inspect kind, status code, and raw body.
Steam Web API credentials are injected through query parameters by default because that matches Steam's HTTP interface.
Avoid logging raw request URLs in production. Use steam.RedactSensitiveURL(...) before sending URLs to logs, traces, or monitoring systems.