TL;DR: Connecting to the undocumented Xbox Live APIs can be an absolute headache of OAuth flows and obscure tokens. The xbx-api npm package abstracts this entirely. By generating an authentication token via the Xbox live login flow, you can query player profiles, achievements, and presence data using a clean, typed TypeScript interface.
Building tools or companion apps for Xbox games has always been a painful experience due to the lack of official, public-facing documentation for the Xbox Live API. Developers usually have to reverse-engineer network requests from the Xbox Windows app to figure out the authentication handshake (which involves standard Microsoft OAuth, Xbox Live device tokens, and XSTS tokens).
Fortunately, the open-source community has abstracted this pain away. If you’re building in Node.js or a full-stack framework like Astro or Next.js, the xbx-api library is the fastest path to production.
Here is exactly how to set it up, authenticate, and pull live player data.
Table of Contents
- Understanding the Authentication Flow
- Step 1: Installation and Setup
- Step 2: Authenticating with Microsoft
- Step 3: Fetching Player Profiles
- Handling Rate Limits
- Security Considerations
- Wrapping Up
Understanding the Authentication Flow
The Xbox Live API doesn’t use simple API keys. It requires an active Microsoft account tied to an Xbox Live profile.
sequenceDiagram
participant Dev as Your App
participant MS as Microsoft OAuth
participant XBL as Xbox Live Auth
participant API as Xbox Live API
Dev->>MS: 1. Request OAuth Token
MS-->>Dev: 2. Return Access Token
Dev->>XBL: 3. Exchange for User Token
XBL-->>Dev: 4. Return XSTS Token & Hash
Dev->>API: 5. Request Data (Header: X-Authorization)
API-->>Dev: 6. Return JSON Profile Data
Step 1: Installation and Setup
First, install the package. We’ll also need dotenv if you aren’t using a framework that handles it automatically.
npm install xbx-api
Step 2: Authenticating with Microsoft
To interact with xbx-api, you must first authenticate a Microsoft account. The easiest way to do this headlessly (e.g., for a background job or server) is using the Windows Live login flow to get an access token.
However, xbx-api simplifies this by handling the lower-level token exchanges if you provide it with an initial authentication configuration.
Here is how you initialize the client in TypeScript:
// src/lib/xbox.ts
import { XboxLiveAuth } from 'xbx-api';
export async function getXboxClient() {
const xstsToken = process.env.XBOX_XSTS_TOKEN;
const userHash = process.env.XBOX_USER_HASH;
if (!xstsToken || !userHash) {
throw new Error('Missing Xbox authentication environment variables.');
}
// The library instantiates a client using your XSTS and Hash directly
const auth = new XboxLiveAuth();
auth.xsts_token = xstsToken;
auth.user_hash = userHash;
return auth;
}
Note: Getting your initial XSTS token and User Hash is usually done via an interactive login script locally, which you then save to your .env file for your server to use.
Step 3: Fetching Player Profiles
Once you have your authentication headers constructed, you can ping the Peoplehub endpoints.
// src/services/playerService.ts
import { XboxLiveAuth } from 'xbx-api';
import { getXboxClient } from '../lib/xbox';
export interface XboxProfile {
xuid: string;
gamertag: string;
gamerpic: string;
presenceText: string;
}
export async function getPlayerProfile(gamertag: string): Promise<XboxProfile | null> {
// Use the xbx-api library we initialized earlier
const client = await getXboxClient();
try {
// 1. Resolve Gamertag to XUID
const xuidData = await client.profile.getSettingsForGamertag(gamertag);
const xuid = xuidData.profileUsers[0].id;
// 2. Fetch rich presence and profile data
const presenceData = await client.peoplehub.getPresenceForXuid(xuid);
const user = presenceData.people[0];
return {
xuid: user.xuid,
gamertag: user.gamertag,
gamerpic: user.displayPicRaw,
presenceText: user.presenceText,
};
} catch (error) {
console.error('Failed to fetch Xbox profile:', error);
return null;
}
}
Handling Rate Limits
The Xbox Live APIs are notorious for strict rate limiting, especially on presence endpoints.
If you are building a public-facing app, you must cache your responses. If you hit the API every time a user loads a page, Microsoft will IP-ban your server within minutes.
Caching Strategy (Astro Example)
If you’re building with Astro, you can use standard server-side rendering with a fast cache like Redis, or use static generation with scheduled revalidation.
---
// src/pages/player/[gamertag].astro
import { getPlayerProfile } from '../../services/playerService';
const { gamertag } = Astro.params;
// In a real app, wrap this in a Redis cache check
const profile = await getPlayerProfile(gamertag);
if (!profile) {
return Astro.redirect('/404');
}
---
<div class="profile-card">
<div class="w-20 h-20 bg-surface border border-border flex items-center justify-center text-2xl text-tertiary" aria-hidden="true">🎮</div>
<h2>{profile.gamertag}</h2>
<p>{profile.presenceText}</p>
</div>
Security Considerations
- Never expose tokens: Your XSTS token and User Hash are the keys to your Microsoft account. Never send them to the client-side. Always proxy requests through your backend.
- Use a dummy account: Create a secondary, blank Xbox account specifically for your app’s authentication. Do not use your personal Xbox account. If your app gets banned for API abuse, you don’t want to lose your game library.
Wrapping Up
Building tools around the Xbox ecosystem is incredibly rewarding, but the authentication layer is a massive hurdle. By isolating that complexity into a backend service and leveraging cached responses, you can build incredibly snappy gaming dashboards.
Happy shipping.