The easiest way to install is downloading it from either Microsoft Edge-Add-Ons or the Chrome Web Store.
- Download / clone this repository
- Run
npm install
andnpm run build
- Open your browsers extensions (
edge://extensions/
/chrome://extensions/
) - Enable
Developer mode
(in the left sidebar in Edge, at the top right in Chrome) - Click
Load Unpacked
and select thedist
directory of this repository
Note that Edge / Chrome version 111 or higher is required due to this feature being used.
Select the region and IP version as desired, then quit any active Xbox Cloud Gaming session and reload Xbox Cloud Gaming to apply the changes.
Install this extension, select e.g. IPv6 as IP version. Then start a capture in Wireshark and a game on xbox.com/play. You'll see lots of UDP packets via IPv6 instead of IPv4. You can also select a different region - preferably far away from your actual location for testing - and start a Traceroute to the IP you see in the Wireshark capture. You'll see the packets being routed towards the selected region.
This extension overwrites the fetch
method to intercept requests to the Xbox servers.
When loading xbox.com/play, a POST request is made to https://xgpuweb.gssv-play-prod.xboxlive.com/v2/login/user
for Game Pass Ultimate users or https://xgpuwebf2p.gssv...
for Free to Play users.
The response contains a list of all regions with one of them marked as the default region (shortened):
{
"offeringSettings": {
"regions": [
{
"name": "WestEurope",
"baseUri": "https://weu.core.gssv-play-prod.xboxlive.com",
"networkTestHostname": "weu.gssv-fastlane-prod.xboxlive.com",
"isDefault": true,
"systemUpdateGroups": null,
"fallbackPriority": -1
}
]
}
}
It can be manipulated to force only a specific region to be available to the client.
After starting starting a game, a session will be created. Right after the Xbox logo and sound appear, the ICE candidates are requested from https://[region].core.gssv-play-prod.xboxlive.com/v5/sessions/cloud/[session UUID]/ice
.
The response contains two candidates, one for IPv4 (with a higher priority of 100) and one for IPv6 (with a lower priority of 1).
{
"exchangeResponse": "[{\"candidate\":\"a=candidate:1 1 UDP 100 13.104.106.140 1071 typ host \",\"messageType\":\"iceCandidate\",\"sdpMLineIndex\":\"0\",\"sdpMid\":\"0\"},{\"candidate\":\"a=candidate:2 1 UDP 1 2603:1020:703:66::ADB:1931 9002 typ host \",\"messageType\":\"iceCandidate\",\"sdpMLineIndex\":\"0\",\"sdpMid\":\"0\"},{\"candidate\":\"a=end-of-candidates\",\"messageType\":\"iceCandidate\",\"sdpMLineIndex\":\"0\",\"sdpMid\":\"0\"}]",
"errorDetails": null
}
It can be manipulated so that e.g. the IPv4 candidate is dropped and the session can only be established via the remaining IPv6 candidate.