Front-end and static sites
Where to host a browser game: HTML5, Phaser, Godot or Unity WebGL
In short
A browser game is hosted like a static site: index.html sits at the root of the folder, next to the scripts, the .wasm files and the assets, and all of it is served over an HTTPS link. A plain HTML5 or Phaser game just needs its ready folder uploaded, while Godot and Unity each have one export setting that decides whether the game starts on a regular host: threads in Godot and compression in Unity. On Netrun such a game is published by uploading an archive, and the free plan fits it well, because a site with no visitors goes to sleep and wakes up on its own when someone opens the game.
- Since Godot 4.3, the web export is single-threaded by default and runs without the Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers.
- A Godot export with Thread Support enabled only works on a server that sends the Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers.
- A compressed Unity WebGL build (.br or .gz files) needs the server to send a Content-Encoding header, and without it only starts when Decompression Fallback is enabled.
- Godot and Unity WebGL games do not start when index.html is opened straight from disk: they have to be loaded through a web server.
- Real-time multiplayer does not work on static files alone: a separate server has to hold the player connections.
The game is built, everything runs in the editor, and now you want to send friends a link instead of an archive with instructions. The good news: to a host, a browser game is just a static site. There is an index.html, the scripts next to it, a WebAssembly file with the engine, and the game assets. The server computes nothing, it only hands out files, and the player’s browser does the rest.
There are two catches, and both live in the export settings. Godot in multi-threaded mode needs special headers from the server, and Unity compresses its files by default in a way that will not unpack unless the server is set up for it. Below is how to build the game so it starts on an ordinary host, and what to do if you need multiplayer. If HTML hosting is new to you, start with the guide on a static site.
| Engine | What to upload | What to watch out for |
|---|---|---|
| Plain HTML5 and Canvas | The folder with index.html, scripts, images and sounds | File paths are relative, and letter case in file names matches the code |
| Phaser with a bundler (Vite, webpack) | The build output after npm run build, usually dist | Upload the built folder, not the sources; index.html must be at its root |
| Godot 4.3 and newer | index.html plus the .js, .wasm, .pck and image files from the export folder | Thread Support is off, so no special server headers are needed |
| Godot 4.0 to 4.2 | The same export files | Needs COOP and COEP headers; re-exporting from 4.3 or newer is simpler |
| Unity WebGL | index.html plus the Build and TemplateData folders | Compression Format set to Disabled, or Decompression Fallback enabled |
| Multiplayer on any engine | The client as static files, the server as a separate project | The server listens on 0.0.0.0 and the port from the PORT variable |
Build the web version of the game#
A plain HTML5 game needs no build: it already is a folder with index.html. If your Phaser project was created from a template with a bundler, run npm run build and take the build folder, usually dist, not the sources. In Godot, export through the Web preset and name the file index.html; in Unity, switch the platform to Web (WebGL) and build into a separate folder. Do not bother double-clicking index.html before uploading: Godot and Unity will not start from disk, they need a web server.
Make sure index.html is at the root#
The host opens index.html from the root of the uploaded folder, so it must not be tucked away in a subfolder like game or build. Paths to images, sounds and scripts should be relative, with no references to your own drive. On servers, letter case in file names matters: Hero.png and hero.png are different files, and what worked on Windows may not be found on the server. Check the names in the code and in the folder once more.
Turn off threads in Godot#
Since Godot 4.3 the web export is built without threads by default, and such a game needs no special server headers at all. If Thread Support is enabled in the Web preset, the game needs the Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers, and without them it stops with a SharedArrayBuffer error. For most games the easiest fix is to disable Thread Support and export again. If you really need threads, there are two ways: the Progressive Web App option with Ensure Cross Origin Isolation Headers enabled, which adds the headers through a service worker, or your own Dockerfile with nginx that sends the headers itself.
Set up compression in Unity#
By default Unity compresses build files with Brotli or Gzip, and the server is expected to serve them with a Content-Encoding header. Netrun serves static files as they are and does not add that header to .br and .gz files, so in Player Settings, under Publishing Settings, choose Compression Format: Disabled or enable Decompression Fallback. The first option gives larger files, the second unpacks them with a script in the browser and loads a little slower. If every megabyte counts, serve the build with your own Dockerfile running nginx with the right headers.
Upload the game and open the link#
Zip the game folder or upload it as is: Netrun recognizes a static site and gives you an HTTPS link. Open the game on a computer and on a phone, and if the screen stays black, look at the browser console, which usually names the file that could not be found. Uploads have a size limit, shown when you upload, so heavy Unity games are best built without unused assets. On the free plan the game sleeps when nobody plays, and the first open after a sleep takes a few seconds.
Move multiplayer and high scores to a server#
As long as the whole game runs in the browser, static hosting is enough. As soon as you need a shared room, player chat or a high score table, you need a server that holds connections and stores results. That server is published as a separate project, listens on 0.0.0.0 and the port from the PORT variable, and keeps results in the /data folder, which survives code updates. For a game people play all the time, the server needs the Pro plan so it runs around the clock.
A browser game without a server is about the simplest project you can put online: build the web version, check the threads setting in Godot or compression in Unity, upload the folder and get a link. If your game needs an audience, take an honest look at itch.io too: it is a game catalog with real players, free HTML5 publishing and a checkbox for SharedArrayBuffer support. Your own link makes sense when the game lives outside a catalog: a portfolio, your own domain, a game for an event, or your own multiplayer server. On Netrun a static game runs on the free plan, while a custom domain and a server that never sleeps come with Pro. Try Netrun.
Common questions
Can I host a browser game for free?
Yes, if the whole game runs in the browser. To a host it is a static site, and a site on the Netrun free plan stays online as long as you like: it sleeps when nobody plays and wakes up when someone opens the game. You will need to pay for a custom domain, a multiplayer server, or a game with no wake-up pause.
Why does my Godot game complain about SharedArrayBuffer or cross-origin isolation?
That is what an export with Thread Support enabled does: a multi-threaded build needs the Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers, and an ordinary host does not send them. Disable Thread Support in the Web preset and export again, since in Godot 4.3 and newer the single-threaded build runs without special headers. Godot 4.0 to 4.2 have no single-threaded web export, so upgrading the engine is the better route.
What should I do when a Unity game says Unable to parse and mentions Content-Encoding?
It means the build is compressed with Brotli or Gzip, while the server sends the files without a Content-Encoding header. In Player Settings, under Publishing Settings, choose Compression Format: Disabled or enable Decompression Fallback, then rebuild. After you upload it again, the game will start.
Is my own link better than itch.io?
Neither is better, they solve different problems. itch.io has players, comments and a storefront, which is a strong argument for an indie game. Your own link is for a game that lives on its own: in a portfolio, on your domain, or next to your own server for multiplayer or high scores. Plenty of people do both.
Can a static browser game have multiplayer?
Only with a separate server. Static hosting just hands out the game files, while moves between players travel through a server that holds the connections, usually over WebSocket. That server is published as a second project and has to run all the time, so it needs the Pro plan.
Why does the game take long to load the first time?
There are usually two reasons. Godot and Unity builds weigh tens of megabytes, and the browser downloads them in full before starting. And on the free plan a site with no visitors goes to sleep, so the first open after a sleep adds a few seconds. A build without unused assets and the Pro plan, where the site never sleeps, both help.
How do I put a website online?
Upload your site code as a ZIP archive or from GitHub — Netrun builds it and gives you a working link with HTTPS. A static site (HTML, CSS, JS), a React app or a Python site all work. There is no domain to buy and no server or certificates to set up.
Why does my website sometimes sleep?
On the free plan, websites sleep after being idle and wake up in a couple of seconds on the first request. On the Pro plan your project runs without sleeping.
Is there a limit on project size?
Yes, uploads have a size limit. Larger projects may need a paid plan, and the current limit is shown in your account when you upload.