Exporting Godot Games to HTML5
Web export is one of Godot's strongest features and a major reason developers choose it for browser-based games. Unlike Unity's WebGL export, which produces large binaries and has a reputation for slow loading, Godot's web export is compact by default and can be optimized further with texture compression and module stripping. The result is a game that loads and runs in the browser with minimal friction for players, requiring no downloads, no installations, and no app store approval.
Install Web Export Templates
Export templates are pre-compiled engine binaries for each target platform. To export for web, you need the HTML5 templates that match your Godot version. Open the Export dialog (Project menu, then Export), click "Add" to create a new export preset, and select "Web." If the templates are not installed, Godot displays a warning with a "Manage Export Templates" link. Click it, then "Download and Install" to fetch the templates from the official mirror.
The templates download is around 500 MB since it includes binaries for all platforms. You only need to download them once per Godot version, and they are stored in your Godot user directory. If you are on a slow connection, you can download the templates separately from the Godot website and install them manually through the same dialog by clicking "Install from File."
Two template variants exist: release and debug. The debug template includes extra error checking, the remote debugger, and is larger. The release template is optimized for size and speed. For testing, use debug to catch issues. For deployment, always use release. The Export dialog lets you choose between them, and you should verify that "Release" is selected before your final export.
Configure the Web Export Preset
The Web export preset has several important settings. Under "HTML," you can set a custom HTML shell that wraps the game, controlling the page layout, loading screen, and additional HTML around the game canvas. The default shell works fine for most cases, but a custom shell lets you add branding, instructions, or embed the game within a larger webpage.
The "Thread Support" option enables WebAssembly threads, which allow Godot to use multiple CPU cores for rendering, physics, and game logic. Threading improves performance significantly for complex games, but requires specific HTTP headers on your web server (covered in a later step). If your hosting does not support these headers, disable threads to ensure compatibility. The game will still run, just limited to a single CPU core.
The "Experimental Virtual Keyboard" option enables a mobile-friendly keyboard for text input on touchscreen devices. If your game requires text input (like the LLM dialogue system covered elsewhere in this pillar), enable this for mobile web players. The "Progressive Web App" section lets you configure a service worker and manifest file that allow players to install the game as an app-like shortcut on their device, with offline support if your game does not require network access.
Under "Resources," configure which file formats are exported. The default exports everything in your project directory. If you have development files, documentation, or unused assets, exclude them using the filter options to reduce the export size. Every megabyte matters for web games because players are waiting for the download to complete before they can play.
Optimize Textures with Basis Universal
Textures are typically the largest component of a Godot web export. Basis Universal is a texture compression format that produces files roughly the size of JPEG images but transcodes to GPU-native formats (like BC7 or ASTC) at runtime. This means dramatically smaller download sizes without the quality loss of reducing texture resolution.
Enable Basis Universal in Project Settings: go to Rendering, Textures, VRAM Compression, and enable "Import Basis Universal." With this enabled, all imported textures use Basis Universal compression in the web export. The compression ratio is excellent, often reducing texture data by 75 percent or more compared to raw formats, with minimal visual quality loss.
For additional size reduction, audit your textures for unnecessary resolution. A background image viewed from a distance does not need to be 4096x4096. Resize textures to the minimum resolution that looks acceptable in-game. Godot's import system lets you set per-texture compression settings and size limits, so you can optimize aggressively for web while keeping full-resolution assets for desktop exports.
Audio is the other major contributor to export size. Use OGG Vorbis format for music and sound effects instead of WAV. OGG files are typically 10 to 20 times smaller than equivalent WAV files. Set the quality parameter based on the content: music can use a higher quality setting (0.6 to 0.8) while short sound effects can use lower quality (0.3 to 0.5) without noticeable degradation.
Reduce WASM Binary Size
The WASM binary contains the compiled Godot engine and your GDScript bytecode. The default binary includes every engine module whether your game uses it or not. You can strip unused modules to reduce the binary size significantly. In the export settings, disable modules your game does not need: if you are making a 2D game, disable all 3D modules. If you do not use GI probes, lightmaps, or specific rendering features, disable those as well.
The rendering backend choice has the largest impact on binary size. The Compatibility renderer (OpenGL) produces a smaller binary than the Forward+ renderer (Vulkan), and it has better browser support since it targets WebGL 2.0 which is universally available. Unless your game specifically needs Forward+ features like volumetric fog, screen-space reflections, or the full Vulkan rendering pipeline, use Compatibility for web exports.
Enable "Strip Debug Symbols" in the export options for release builds. Debug symbols add substantial size to the WASM binary and are only useful during development. With all optimizations applied, a minimal 2D Godot web game can have a WASM binary under 10 MB, and a moderately complex game typically stays under 25 MB. Combined with texture optimization, total download sizes of 15 to 40 MB are achievable for most web games.
Configure Server Headers
Godot web exports with threading enabled require two HTTP headers on every response from your web server: Cross-Origin-Opener-Policy: same-origin and Cross-Origin-Embedder-Policy: require-corp. These headers enable SharedArrayBuffer, which is the browser API that WebAssembly threads rely on. Without them, the browser blocks thread creation and the game either falls back to single-threaded mode or fails to load entirely.
How you set these headers depends on your hosting provider. For Nginx, add the headers in your server block configuration. For Apache, add them in your .htaccess file. For CDN services like CloudFront, configure custom response headers in the distribution settings. For static hosting platforms like Netlify, Vercel, or GitHub Pages, use their respective configuration files (netlify.toml, vercel.json, or _headers file) to add the headers.
Be aware that these headers affect how your page interacts with cross-origin resources. Images, scripts, and fonts loaded from other domains must include CORS headers (Access-Control-Allow-Origin) or be served with crossorigin attributes. If your game page embeds third-party ads, analytics scripts, or fonts, verify they work correctly with these headers enabled. If compatibility issues arise, you may need to disable threading in the export settings as a tradeoff.
Your server also needs correct MIME types for the exported files. The .wasm file must be served as application/wasm, the .pck file as application/octet-stream, and the .js files as application/javascript. Most modern web servers handle these correctly by default, but verify if you encounter loading errors. Incorrect MIME types cause browsers to reject the files with cryptic error messages in the console.
Test and Deploy
After exporting, you cannot open the HTML file directly from the filesystem because browsers block WASM loading from file:// URLs for security reasons. You need a local web server for testing. The simplest option is Python's built-in server: navigate to the export directory in a terminal and run python -m http.server 8000. Then open http://localhost:8000 in your browser. For testing with the SharedArrayBuffer headers, use a server that can add custom headers, or test directly on your hosting environment.
Test in multiple browsers. Chrome, Firefox, Safari, and Edge all have slightly different WebAssembly implementations, and edge cases in rendering, audio, and input handling can produce different behavior. Test on mobile browsers as well if your game targets mobile web players. Pay attention to the initial loading time, since this is where you lose most players. If loading takes more than five to eight seconds on a broadband connection, look for additional size optimizations.
For deployment, upload all the exported files to your web server or static hosting. Set up caching headers to improve return visits: the .wasm and .pck files should have long cache durations (one year) with cache-busting filenames that change with each build. The HTML and JavaScript files should have shorter cache durations since they reference the specific WASM and PCK filenames. Enable gzip or brotli compression on your server for all text-based files (HTML, JS, JSON) to further reduce transfer sizes.
A well-optimized Godot HTML5 export uses Basis Universal textures, stripped engine modules, the Compatibility renderer, and proper server configuration to deliver games that load fast, run at 60 FPS, and work across all major browsers without plugins or installations.