-
-
Notifications
You must be signed in to change notification settings - Fork 328
A deep dive on how the Roblox bootstrapper works
Bloxstrap essentially works by mimicking the behaviour of the official Roblox bootstrapper, and then expanding on it to provide additional useful functionality, much of which would not be possible otherwise. Thus, I would like to provide useful information on how the Roblox bootstrapper works, as I think it would be useful to many people.
I won't touch on history too much here unless necessary (which there is lots of, it dates back to 2008 after all). This will simply focus on the current state of how it functions.
This will also only concern Windows, as I actually have no idea how it works on Mac. I don't own a Mac. lol.
Roblox installs to %LOCALAPPDATA%\Roblox
, under a single user account only. It used to support being installed system-wide as Administrator, but not anymore, as it results in a lot of mess relating to permissions and stuff. I will only talk about functionality in the context of it being installed and ran in single-user mode only.
Each version of the Roblox game client has several identifiers. However, the only one that you need to worry about is the version GUID, which is what is used to identify versions on Roblox's deployment system. An example of one is version-824aa25849794d67
.
The latest version GUID can be fetched from https://clientsettingscdn.roblox.com/v2/client-version/WindowsPlayer, which delivers a JSON response, where the version GUID is attributed under clientVersionUpload
.
The bootstrapper keeps track of the version GUID for the version of Roblox it currently has installed. It will check that API whenever it's launched, and carry out a Roblox update if the latest version GUID has changed.
Roblox distributes the game client across several categorized .zip files called packages, and uploads them to Amazon S3. Roblox then mirrors their S3 storage across several different CDNs. Here's all of the domains of which you can download Roblox from.
Type | Base URL | Notes |
---|---|---|
Amazon S3 | https://s3.amazonaws.com/setup.roblox.com/ | Where everything is sourced from. Also the slowest, that's why the CDNs exist. |
Amazon S3 | http://setup.roblox.com/ | A direct alias for S3 above. Avoid using this, HTTPS doesn't work properly on it. |
Akamai | https://setup-ak.rbxcdn.com/ | CDN mirror for S3 |
Cachefly | https://roblox-setup.cachefly.net/ | CDN mirror for S3 |
Cachefly | https://setup-cfly.rbxcdn.com/ | A direct alias for the domain above on rbxcdn.com. |
Balanced | https://setup.rbxcdn.com/ | Preferred, CDN balancer that automatically chooses between Akamai and Cachefly. |
The bootstrapper uses the balanced one whenever it can. However, it will also used the other ones mentioned for redundancy in case setup.rbxcdn.com is inaccessible, if it's ever down or happens to be blocked or something.
You may have noticed that the latest version API supplies a version number for the bootstrapper. What's that about?
Aside from updating Roblox, the bootstrapper can also update itself. The bootstrapper is always built and deployed alongside a Roblox version. When the bootstrapper is about to install a new version of Roblox, it checks that latest bootstrapper version number against its own, and updates itself if it needs to, before updating Roblox.
You'll see this happening if you see a briefly-flashing "Please wait..." or "Getting the latest Roblox..." message when the bootstrapper is started.
Now, we'll get to actually downloading files. Alongside the packages, there are also files that contain manifest data, named rbxManifest.txt
, rbxPkgManifest.txt
.
How do you actually get these files? The files for every version GUID are stored at the root of the base URL, with their file names being prefixed with the version GUID. For example, rbxPkgManifest.txt
for version-824aa25849794d67
on the CDN balancer will be located at https://setup.rbxcdn.com/version-824aa25849794d67-rbxPkgManifest.txt.
rbxManifest.txt
records information of every single game client file, with data being grouped two lines at a time. It really just records the MD5 hash. As far as I'm aware, this is no longer used. At one point, it was used for checking the integrity of a Roblox installation, but the bootstrapper hasn't appeared to do that for years. Regardless, the file is still generated for new version deployments.
rbxPkgManifest.txt
records information of every single downloadable package, with data being grouped four lines at a time. It records compressed size, uncompressed size, and MD5 hash. File sizes are recorded as number of bytes. You can use this manifest for identifying what packages you need to download, or for determining how much disk space is needed to install/update Roblox.
The bootstrapper has a hardcoded table that records the associated extraction directory for each package. You can easily find these yourself using a hex editor or something. You can check them all out here.
Roblox installations are stored in %LOCALAPPDATA%\Roblox\Versions\<version GUID>\
. Downloaded packages are cached in %LOCALAPPDATA%\Roblox\Downloads
. These are (or should be) regularly cleaned out after a period of time or whenever it's suitable to do so, such as after an update.
In short, the bootstrapper will gather the list of packages to download from the package manifest, download them, and extract them accordingly. It's pretty simple.
One minor note: unlike every other package, WebView2RuntimeInstaller.zip
is only extracted conditionally, based on if the WebView2 runtime is not installed. It checks for that according to these registry keys.
If it's not installed, it extracts the package, which contains the runtime installer, and then runs it with the provided args of /silent /install
, so it automatically installs quietly in the background, while the bootstrapper shows its own indefinite progress dialog.
If the bootstrapper is being launched standalone (e.g. by being ran directly or through the 'Roblox Player' shortcut), Roblox will be started only with the --app
argument to indicate a desktop app launch.
Roblox registers two protocols: roblox
and roblox-player
. The former is relatively new and used only for universal deeplinking, whereas the latter is more traditional and is used for everything else. Here's some examples of launch URIs which use these protocols that you can try out by pasting them into your browser's URL bar:
roblox-player:1+launchmode:app
roblox://experiences/start?placeId=1818
The first one will simply launch the desktop app, the second one will launch and join Crossroads. This is essentially how Roblox launches itself from your web browser.
Brief disambiguation:
- The term "protocol" refers to protocol identifiers such as
roblox
androblox-player
- The term "launch URI" refers to the full string used for launching the application such as
roblox-player:1+blahblahblah
- The term "protocol handler" refers to the application that's launched to handle the protocol
I won't go in-depth on how Windows protocol handlers work. If you don't know how, it's fairly easy to grasp. If you have Roblox installed, just open the Registry editor, go to HKEY_CURRENT_USER\SOFTWARE\Classes\roblox-player
, and examine how it's structured.
Though, I'll explain this. Every protocol has a protocol handler, which is just an application. You can determine how the launch URI is fed to the protocol handler. in Windows, it's denoted as %1
, if you look in shell\open\command
under the protocol's registry key. From there, you can then process it. The Roblox game client is directly registered as the protocol handler, and is done whenever Roblox updates.
When the bootstrapper starts Roblox, it passes the protocol string directly into RobloxPlayerBeta.exe as the first launch argument. You don't really need to do anything, unless you want to manipulate the data given so you can control Roblox to behave in a certain way.
On that topic, I'd like to briefly mention something about how the roblox-player
protocol is handled. Here's a longer example URI:
roblox-player:1+launchmode:play+robloxLocale:en_us+gameLocale:en_us+LaunchExp:InApp
If you look closely at this, you may notice that this is designed to cleverly form a stream of key-value pairs, all delimited by '+' symbols. Even the protocol identifier itself is part of it! If we serialized this to JSON form for the sake of clarity, it would look something like this:
{"roblox-player": 1, "launchmode": "play", "robloxLocale": "en_us", "gameLocale": "en_us", "LaunchExp": "InApp"}
If you ever need to parse/modify the string, you don't need to do anything special or complicated, it's really simple.
So, remember when I said earlier that the Roblox game client is what's registered as the protocol handlers? That wasn't a typo, that's actually how it is - well, how it's recently been. Roblox did this in a effort to cut down on the time spent waiting for the game client to launch, by cutting out the bootstrapper completely from the launch process. Which is pretty clever, I won't deny. Good job client team!
Nonetheless, how the hell does that work? Well, when the game client is launched, it does the version check itself. Actually, it checks against the version number, not the version GUID. If there's an update available, then it launches the bootstrapper so an update can be carried about.
You can see this for yourself by cracking open a Roblox log file, where you'll see this at the top:
2023-12-27T08:37:46.538Z,0.538225,7544,6,Info [FLog::UpdateController] UpdateController: versionQueryUrl: https://clientsettingscdn.roblox.com/v2/client-version/WindowsPlayer/channel/zflag
2023-12-27T08:37:46.538Z,0.538225,7544,6,Info [FLog::UpdateController] WindowsUpdateController: updaterFullPath: C:\Users\pizzaboxer\AppData\Local\Roblox\Versions\version-48a28da848b7420d\RobloxPlayerInstaller.exe
2023-12-27T08:37:46.539Z,0.539225,792c,6,Info [FLog::UpdateController] Update thread: started with protStr roblox-player:1+roblox-player:1+launchmode:play+robloxLocale:en_us+gameLocale:en_us+LaunchExp:InApp
2023-12-27T08:37:46.539Z,0.539225,792c,6,Info [FLog::UpdateController] Checking if updater exists at C:\Users\pizzaboxer\AppData\Local\Roblox\Versions\version-48a28da848b7420d\RobloxPlayerInstaller.exe. Returning true
2023-12-27T08:37:46.730Z,0.730281,7544,6 [FLog::Output] Settings Date header was Wed, 27 Dec 2023 08:37:47 GMT
2023-12-27T08:37:46.730Z,0.730281,7544,6 [FLog::Output] Settings Date timestamp is 1703666267
2023-12-27T08:37:46.959Z,0.959281,792c,6,Debug [FLog::UpdateController] version response: {"version":"0.605.3.6050660","clientVersionUpload":"version-48a28da848b7420d","bootstrapperVersion":"1, 6, 3, 6050660"}
2023-12-27T08:37:46.960Z,0.960281,792c,6,Info [FLog::UpdateController] Update thread: isUpdateRequired FALSE
Fortunately for Bloxstrap, this check is completely skipped if RobloxPlayerInstaller.exe doesn't exist in the game client's folder.
If the game client was started with a launch URI, then it passes that URI back into the bootstrapper as an arg when starting it.
Thanks for reading. That's about all you need to know for how the Roblox bootstrapper works. Hopefully this isn't too long or too confusing, and that it's helped to clear up any questions you may have about it.
My friend made a website for downloading Roblox client versions, which is essentially just a web implementation of the bootstrapper's client download system that I described earlier. You can find it at rdd.latte.to. It's pretty cool, and sometimes very useful.
See something here on this page that is incorrect or you otherwise think should be changed? Please open an issue!