Blog
Godot8 min read

How to Export a Godot 4 Game to the Web (HTML5 and itch.io)

A step-by-step guide to exporting a Godot 4 game to the web as HTML5 and WebAssembly: export templates, the single-threaded default that needs no special headers, hosting on itch.io, and how to fix a black screen.

Godot exports to the web as HTML5 and WebAssembly, which means your game runs in a browser tab with no download and no plugin. That is the fastest way to put a playable build in front of someone. You paste a link, they click, they play.

"Export to web" is two jobs, not one. Producing the files takes about a minute. Getting those files to run in a browser is where people hit a black screen, usually because of how the files are served or because an export option quietly switched on a requirement the host cannot meet. This guide covers both halves, the exact settings, and the errors behind most failed exports.

It applies to Godot 4.3 and later. Older 4.x versions always used a threaded build, so if you are still on 4.0, 4.1 or 4.2, read the headers section closely or update the editor.

{/* IMAGE: The Godot Export dialog open with a Web preset selected, the Export Project button highlighted. 1200x675 editor screenshot. */}

What "web export" actually produces

When you export, Godot does not create a single file. It writes a small folder of static assets.

  • index.html is the page that loads everything. This is what the browser opens.
  • A .wasm file is the Godot engine itself, compiled to WebAssembly. This is the largest piece.
  • A .pck file is your game data, meaning scenes, scripts and assets packed together.
  • A .js file is the loader glue that wires the engine to the page.
  • Sometimes an .audio.worklet.js and, for threaded builds, extra worker files.

All of these must sit together and must be served over HTTP. You cannot double click index.html and expect it to run, which is the first thing that trips people up.

Step 1. Install the export templates

Godot ships the editor and the export templates separately. The templates are the prebuilt engine binaries for each platform, including the WebAssembly build for the browser. A fresh install does not have them.

Go to Editor then Manage Export Templates, and click Download and Install. This pulls the templates for your exact engine version.

The templates must match your editor version exactly. A 4.4 editor cannot export with 4.3 templates, and the other way round. A mismatch is one of the most common causes of a broken web build. Every time you update the editor, reinstall the templates.

Step 2. Add a Web export preset

Open Project then Export. Click Add and choose Web.

The defaults are sensible. Three groups of options matter for the web.

  • Variant, Thread Support. Off by default since Godot 4.3. Leave it off unless you have measured a real need for threads. A single-threaded build runs on any static host and inside iframes on game portals. Turning it on requires the two Cross-Origin headers described in step 4.
  • Variant, Extensions Support. Only needed if your project uses GDExtension. It also requires the Cross-Origin headers, and each native extension needs its own web build.
  • VRAM Texture Compression. "For Desktop" is on by default and "For Mobile" is off. Enabling both makes the export larger but more compatible, which matters if you expect phone players, because phones generally do not support the desktop texture formats.

Leave Head Include and the custom HTML shell empty unless you have a reason to change them. The default shell handles loading and the progress bar.

Step 3. Export the project

Pick a destination folder. Create an empty one named something like web-build so the output files do not mix with anything else.

Name the main file index.html, not the name of your game. Most hosts, including itch.io, look for an index.html as the entry point. If you name it mygame.html, the host will not find it.

Click Export Project. In a few seconds the folder fills with the files listed earlier.

{/* IMAGE: A file explorer showing the exported web-build folder contents: index.html, .wasm, .pck, .js files. 1000x500. */}

Step 4. When you need the Cross-Origin headers

Most old tutorials say every Godot 4 web build needs special headers. That was true before 4.3. Today it depends on two checkboxes.

A build with Thread Support or Extensions Support enabled uses SharedArrayBuffer, and browsers only allow that when the page is served with these two response headers.

Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp

Without them the engine cannot start, and the console shows an error that mentions SharedArrayBuffer or crossOriginIsolated. You do not set these headers in Godot. You set them on whatever serves the files.

A build with both options off, which is the default, needs neither header. That is why the single-threaded export is the right choice for itch.io, game portals and plain static hosting. Threads can help performance in heavy games, but they cost you hosting flexibility and embed compatibility.

Step 5. Test it locally before you upload

Never debug a web export by uploading and refreshing. Test on your own machine first.

The quickest check is the editor's one-click deploy. Once a Web preset exists, a browser icon appears in the top-right corner of the editor. Clicking it starts a local web server, exports the project and opens it in your default browser. That server sends the Cross-Origin headers, so it runs threaded builds too.

For a build you already exported, any local server works if Thread Support and Extensions Support are off. With Python installed, run python -m http.server 8000 inside the web-build folder and open http://localhost:8000.

For a threaded build, serve it with both headers. Save this as serve.py inside the folder.

import http.server, socketserver

class Handler(http.server.SimpleHTTPRequestHandler):
    def end_headers(self):
        self.send_header("Cross-Origin-Opener-Policy", "same-origin")
        self.send_header("Cross-Origin-Embedder-Policy", "require-corp")
        super().end_headers()

with socketserver.TCPServer(("", 8000), Handler) as httpd:
    print("Serving on http://localhost:8000")
    httpd.serve_forever()

Run python serve.py and open http://localhost:8000. If the game loads here, the export is correct and any remaining problem is a host configuration issue.

Step 6. Host it

itch.io (easiest, free)

This is the recommended path for sharing and for game jams.

  1. Zip the contents of the web-build folder, not the parent folder, so index.html is at the top level of the zip.
  2. On itch.io, create a new project and set Kind of project to HTML.
  3. Upload the zip and tick This file will be played in the browser.
  4. In the embed options, set a viewport size that matches your game's resolution.

itch.io accepts up to 500 MB of extracted content, 200 MB for any single file and 1,000 files. A single-threaded build needs nothing else. For a threaded build, itch.io offers a SharedArrayBuffer support checkbox in the embed frame options, announced as an experimental feature that may break parts of the page, so test the published page in more than one browser.

Netlify, Vercel, GitHub Pages or your own server

A single-threaded build runs on any static host as is, including plain GitHub Pages. Make sure the server sends .wasm files with the application/wasm content type and compresses them, since WebAssembly shrinks to around a quarter of its size with gzip.

For a threaded build, the host must send the two headers. On Netlify, add a _headers file to the deploy root.

/*
  Cross-Origin-Opener-Policy: same-origin
  Cross-Origin-Embedder-Policy: require-corp

On Vercel, set the same two headers in vercel.json under a headers rule. On nginx or Apache, add them to the location block. GitHub Pages cannot send custom headers, so threaded builds there need a service worker workaround such as coi-serviceworker, which not every browser respects. If you do not need threads, the simpler answer is to turn Thread Support off.

Fixing a black screen, the checklist

If you see a black canvas, open the browser's developer console (press F12, then the Console tab) and read the first red error. Work through these in order.

  1. Did you open the file directly? If the URL starts with file://, serve it over HTTP instead.
  2. Is SharedArrayBuffer or crossOriginIsolated in the error? Thread Support or Extensions Support is on and the host is not sending the headers. Turn both options off and re-export, or add the headers on the host.
  3. Does the error mention a version or a failed template load? Your export templates do not match your editor version. Reinstall them in Manage Export Templates.
  4. Is it a C# project? Godot 4 cannot export C# projects to the web. The web build needs a GDScript project.
  5. Is the .wasm file served with the wrong type? Some hosts send it as a generic download. Set the application/wasm content type.

Most failed web exports are one of these five.

What does not carry over to the browser

A web build is not desktop with a URL. A few things behave differently.

  • Save data goes to the browser's IndexedDB, not a folder on disk, and players must allow site storage for it to persist. Inside an iframe on a portal that can require third-party storage, so test saving on the host you will use.
  • Audio only starts after the player clicks, taps or presses a key, because browsers block autoplay. A "click to start" screen solves it.
  • Native plugins (GDExtension libraries compiled for desktop) do not load unless they ship a web build and Extensions Support is on.
  • C# does not export to the web in Godot 4.
  • Rendering uses the Compatibility renderer (WebGL 2) on the web, so a project authored with Forward+ or Mobile looks different. Effects such as SDFGI, volumetric fog and screen-space reflections do not render. Author web-first games in Compatibility from the start so what you see in the editor is what ships. Summer's own web template is different, because it uses WebGPU with Forward+ or Mobile.
  • Load size matters more than anywhere else. The player downloads the engine, the data pack and every asset before the game starts. Poki's developer guide notes that players typically move on if loading takes longer than ten seconds, so keep the first download small.

Summer Engine and web export

Summer Engine is a desktop engine for macOS and Windows that keeps Godot 4 workflows, with an AI that builds scenes, scripts and assets from plain language. It builds desktop versions of your game, which you can sell on Steam or upload to itch.io as a download, and it exports web builds too.

Since engine 0.7 the editor ships Summer's own web export template, which uses WebGPU with the Forward+ or Mobile renderer. Web export works for GDScript projects. Projects that use C# cannot export to the web, the same Godot 4 limitation. The web build is a standard static .zip with index.html at the root. You publish it on Summer Games, where people play it in the browser. Summer Games also accepts the standard Godot Web export described above, made with the Compatibility renderer. Agents can do both steps with the MCP tools summer_export_game (target web) and then summer_publish_build.

If you want to start a game in Summer today, begin from a template that already has movement and a camera wired up, describe the mechanics you want on top, and export a build when it plays well.

Frequently asked questions

Can you export a Godot game to the web?

Yes. Godot 4 exports to HTML5 using WebAssembly, so the game runs in a modern browser with no plugin or install. You add a Web export preset, install the matching export templates, and Godot writes a folder of static files you can host anywhere. Projects written in C# cannot export to the web in Godot 4, and native GDExtension plugins need a web build of their own.

Why is my Godot web export a black screen?

Open the browser console and read the first red error. It is usually one of three things. You opened index.html from your file system instead of serving it over HTTP. You enabled Thread Support or Extension Support, which need the Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers, and your host does not send them. Or your export templates do not match your editor version. Turning Thread Support off (the default since Godot 4.3) removes the header problem entirely.

Do I need SharedArrayBuffer or special headers for a Godot web export?

Not for the default export. Since Godot 4.3 the Web preset exports a single-threaded build, which runs without SharedArrayBuffer and without any special headers. Only a build with Thread Support or Extension Support enabled needs Cross-Origin-Opener-Policy set to same-origin and Cross-Origin-Embedder-Policy set to require-corp.

How do I host a Godot web game for free?

itch.io is the easiest free host. Zip the exported folder so index.html sits at the top level, create an HTML project, upload the zip and tick the option to play it in the browser. itch.io allows up to 500 MB of extracted files, 200 MB per file and 1,000 files. GitHub Pages and Netlify also work for a single-threaded build, because it needs no custom headers.

Is a Godot web export smaller than a desktop build?

Rarely. The player downloads the WebAssembly engine, your data pack and every asset before the game starts. The engine file alone is tens of megabytes uncompressed and several megabytes once your host compresses it, and a 3D game with large textures can add far more. Compress textures, strip unused assets and keep the scope tight if the web is your main target.

Does Summer Engine export to the web?

Yes. Summer Engine exports web builds for GDScript projects. Since engine 0.7 the desktop editor ships Summer's own web export template, which uses WebGPU with the Forward+ or Mobile renderer. The web build is a standard static .zip with index.html at the root, and you publish it on Summer Games (summer.games), where people play it in the browser. Projects that use C# cannot export to the web, the same Godot 4 limitation. The steps in this guide describe the web export of stock Godot 4.

  • Godot
  • Web Export
  • HTML5
  • Tutorial