This guide covers how to interact with the Worlds Edge Link API to build custom lobby browsers and spectator tools for Age of Empires games.
The Worlds Edge Link API provides two main approaches for accessing lobby data:
For simpler integration, you can also use the aoe2lobby.com WebSocket API which provides real-time updates without polling.
For a simple lobby browser, use the community endpoint /advertisement/findAdvertisements :
GET https://aoe-api.worldsedgelink.com/community/advertisement/findAdvertisements?title=age2
Features:
This is sufficient for most lobby browsing use cases.
For accessing ongoing matches and spectator features, you'll need to authenticate using Steam.
We provide a reference implementation written in Python that you may want to have a look at.
steam-user npm package for Steam authenticationconst SteamUser = require('steam-user'); const client = new SteamUser(); // Login to Steam first (with your credentials) await client.logOn({...}); // Create encrypted app ticket const APP_ID = 813780; // AoE2:DE const eticket = await client.createEncryptedAppTicket( APP_ID, Buffer.from("RLINK") // Important: Include RLINK buffer ); // Encode for API use const auth = encodeURIComponent( eticket.encryptedAppTicket.toString('base64') );
Important Notes:
Buffer.from(“RLINK”) as the second parameterconst url = `https://aoe-api.worldsedgelink.com/game/login/platformlogin?` + `accountType=STEAM` + `&activeMatchId=-1` + `&alias=${alias}` + `&appID=${APP_ID}` + `&auth=${auth}` // Your encoded ticket from Step 1 + `&callNum=0` + `&clientLibVersion=190` // Update as game updates + `&country=US` + `&installationType=windows` + `&language=en` + `&macAddress=DE-AD-D0-0D-00-00` // Can be any value + `&majorVersion=4.0.0` + `&minorVersion=0` + `&platformUserID=${steamID}` + `&timeoutOverride=0` + `&title=age2`; const response = await axios.post(url); const sessionId = response.data.sessionID; // Save this!
Key Parameters:
clientLibVersion - Currently 190+ (changes with game updates)macAddress - Can be any valid formatauth - Your encoded ticket from Step 1sessionID needed for subsequent requests
The appBinaryChecksum parameter requires the current game build version. You can obtain this programmatically:
const getBuildVersion = async (appId) => { const rss = await fetch( `https://store.steampowered.com/feeds/news/app/${appId}/` ); const parser = new XMLParser(); const feed = parser.parse(await rss.text()); let lastUpdateTitle = feed?.rss?.channel?.item ?.map(e => e.title) .find(e => e.match(/(update.[0-9]+)/gi)); return parseInt( lastUpdateTitle.slice( lastUpdateTitle.search(/update/gi) + "update".length ) ); }
Alternatively, check the bottom-left corner when launching the game.
Once authenticated, query ongoing games:
const url = `https://aoe-api.worldsedgelink.com/game/advertisement/findObservableAdvertisements?` + `appBinaryChecksum=${gameVersion}` + `&callNum=0` + `&count=50` + `&dataChecksum=0` + `&desc=1` + `&matchType_id=0` + `&modName=INVALID` + `&modDLLChecksum=0` + `&modDLLFile=INVALID` + `&modVersion=INVALID` + `&start=0` + `&sortOrder=1` + `&versionFlags=56950784` + `&sessionID=${sessionId}` + `&connect_id=${sessionId}`; const response = await axios.get(url);
&profile_ids=[123456,789012]
Filter matches to only show games with specific player profile IDs.
&numericTagNames=["HasPassword"] &numericTagValues=[0]
Common tags include:
HasPassword - Filter by password-protected statusWarning: The Game API returns responses in an obscured array format that is not user-friendly.
// Example response structure [ someMetadata, [ // Array of matches [lobbyId, platformSessionId, ...otherFields], [lobbyId, platformSessionId, ...otherFields], // etc. ] ]
Parsing Help:
For simpler integration, consider using the aoe2lobby.com WebSocket API:
WebSocket URL:
wss://data.aoe2lobby.com/ws/
The API supports subscribing to different data feeds by sending JSON subscription messages.
Subscribe to spectate matches:
{"action":"subscribe","type":"matches","context":"spectate"}
Subscribe to lobby matches:
{"action":"subscribe","type":"matches","context":"lobby"}
Subscribe to specific Elo types:
{"action":"subscribe","type":"elotypes","context":"lobby","ids":["1223","3","4"]}
Subscribe to specific players:
{"action":"subscribe","type":"players","context":"lobby","ids":["3920944"]}
Player status updates include current status, match ID, and Steam lobby ID:
{
"player_status": {
"19501096": {
"status": "lobby",
"matchid": "412015195",
"steam_lobbyid": "109775244730862406"
}
}
}
Read the Age of Empires API Usage Guidelines!
clientLibVersion changes with game updatesThis documentation is community-maintained. If you discover new endpoints, parameters, or corrections, please contribute back to help other developers!
Last updated: December 2025
Based on community research and shared knowledge