DEV Community

abdul rahman
abdul rahman

Posted on

How to Publish a Unity Game on Itch.io: WebGL, ZIP & HTML5 Setup (Step-by-Step)

πŸ“– Original Article / Read Full Guide:
For the complete original version of this guide, visit Publish a Unity Game on Itch.io: WebGL & ZIP Guide.

Exhaustive release engineering masterclass on how to publish a Unity game on itch.io. Covers root-level ZIP archive hierarchies, solving WebGL black screens via Decompression Fallback, fixing browser memory crashes, automating delta updates with the Butler CLI, and high-converting storefront design.πŸ“Œ The Short Answer: How Do You Upload a Unity Game to itch.io?To publish a Unity game on itch.io, build your project for WebGL (for instant in-browser play) or Standalone Windows/Mac (for downloadable play). For WebGL, compress the build files directly so that index.html sits at the absolute root of the ZIP file (not inside a nested folder). In Unity Player Settings, enable Decompression Fallback to prevent black loading screens. On itch.io, set the project kind to HTML, tick "This file will be played in the browser", and configure canvas dimensions (1280Γ—720). For standalone builds, upload the executable alongside its entire _Data folder and UnityPlayer.dll inside a single structured ZIP.πŸ’‘ Architect's Field Notes: A Pipeline, Not a Folder Upload"The most common mistake indie developers make when publishing to itch.io is treating their build as a loose desktop folder. Itch.io is an automated server environment. If your WebGL ZIP contains a parent folder that hides index.html, the player gets a 404 or an unplayable canvas.Build your project cleanly, verify your root directory structure before zipping, and automate your patch pipeline using Butler. That is the difference between a frustrating release and a seamless launch."⚑ Quick Release Checklist: Unity to itch.ioWebGL Root Invariance: index.html must sit directly in the root of the ZIP file, never in a subfolder.Decompression Fallback: Enable Gzip/Brotli fallback in Unity to eliminate black loading screens on itch.io.Standalone Integrity: Package the .exe, UnityPlayer.dll, and *_Data folder together. Never upload the .exe alone.Automated Updates: Use the Butler CLI to push binary delta patches directly from your terminal.πŸ“‘ Table of ContentsDo You Need to Upload Every File? (Correct ZIP Structure)Unity WebGL Build ArchitectureHow to Add a Browser Playable Game to itch.ioComprehensive Troubleshooting GuideStandalone Desktop PackagingAutomated Deployment: Mastering the Butler CLIitch.io Project Distribution MatrixFull C# Implementation: WebGL Canvas Viewport & Focus AdapterStorefront Conversion EngineeringFrequently Asked Questions (FAQ)πŸ“ 1. Do You Need to Upload Every File?One of the most frequent questions from developers publishing a unity-build to upload on itch.io is: "Do I need to upload every single file from the build folder, and how should it be packaged?"The short answer: Yes, you must upload all compiled files, but HOW you compress them makes the difference between an instant success and a broken launch.A. The WebGL HTML5 ZIP Architecture (The Root Index.html Rule)When Unity exports a WebGL project, it creates an output directory containing:index.html (The entry web document)Build/ (Contains the .wasm, .data, and .framework.js binaries)TemplateData/ (Contains loading bars, icons, and CSS formatting)❌ THE #1 MISTAKE: Zipping the Parent FolderPlaintextMyGame.zip
└── WebGL_Build_Folder/ <-- WRONG! Itch.io cannot see index.html here
β”œβ”€β”€ index.html
β”œβ”€β”€ Build/
└── TemplateData/
Result on itch.io: "There was an issue loading your game. No index.html found at root level."βœ… THE CORRECT WAY: Zipping the Contents DirectlyPlaintextMyGame.zip
β”œβ”€β”€ index.html <-- PERFECT! Directly in the root of the ZIP
β”œβ”€β”€ Build/
β”‚ β”œβ”€β”€ MyGame.data.unityweb
β”‚ β”œβ”€β”€ MyGame.framework.js.unityweb
β”‚ └── MyGame.wasm.unityweb
└── TemplateData/
How to do it: Open your WebGL build folder, select all items inside (Ctrl+A or Cmd+A), right-click > Compress to ZIP. Name the ZIP whatever you like; itch.io will parse it instantly.B. The Standalone Desktop Rule (Windows / Mac)If you are uploading a downloadable Windows game, do not upload only the .exe file. A Unity executable cannot run without its runtime dependencies. You must compress:MyGame.exeUnityPlayer.dll (The core rendering dynamic link library)UnityCrashHandler64.exeMyGame_Data/ (Contains all scenes, 3D models, and C# scripts)MonoBleedingEdge/ (Required if your build uses Mono runtime instead of IL2CPP)βš™οΈ 2. Unity WebGL Build ArchitectureWhen you build for WebGL, your compiled C# code is converted via IL2CPP into optimized WebAssembly (Wasm). To ensure smooth execution inside browser sandboxes without crashing:Switch Platform: Navigate to File > Build Settings, select WebGL, and click Switch Platform.Configure Compression & Decompression Fallback: Open Project Settings > Player > Publishing Settings.Set Compression Format to Gzip (or Disabled for debugging).Crucial: Check the box for Decompression Fallback. Since itch.io servers do not always serve custom Content-Encoding: gzip headers, enabling this fallback bundles an internal JavaScript decompressor into your build, completely preventing the fatal black loading screen error.Tune Memory Allocation: Under Publishing Settings, set WebGL Memory Size between 256 MB and 512 MB. Setting this above 1024 MB causes out-of-memory crashes on Chrome and mobile devices.🌐 3. How to Add a Browser Playable Game to itch.ioTo configure your project so players can click "Play Game" immediately in their web browser:Log into your itch.io dashboard and click Create New Project.Under Classification, select Games.Under Kind of project, change the dropdown from Downloadable to HTML ("You have a ZIP or HTML file that will be played in the browser").Scroll down to the Uploads section and click Upload files. Select your root-level WebGL .zip archive.Once the upload completes, tick the checkbox: "This file will be played in the browser".Configure Viewport Embed Dimensions:Set Manual size: 1280 px width by 720 px height (or matching your Unity canvas resolution).Enable Fullscreen button to let players expand the canvas.Enable Automatically start on page load or tick Click to launch if you want a splash screen.Under Visibility & access, set the project to Draft or Restricted to test it before public release.πŸ› οΈ 4. Comprehensive Troubleshooting Guide🚨 Problem 1: "There was an issue loading your game. No index.html found"The Cause: You compressed the enclosing folder instead of compressing the files inside it. Itch.io looks strictly for /index.html in the ZIP root.The Fix: Extract your ZIP, open the folder so you see index.html right in front of you, select all files, and create a fresh ZIP archive. Re-upload to itch.io.🚨 Problem 2: Unity WebGL Stuck on Black ScreenThe Cause: The browser attempted to load Gzip or Brotli compressed WebAssembly files (.unityweb), but itch.io's server did not send the decompression header.The Fix: In Unity, go to Project Settings > Player > Publishing Settings and check Decompression Fallback. Alternatively, set Compression Format = Disabled.🚨 Problem 3: "Out of Memory" (OOM) or JavaScript Heap ExhaustionThe Cause: The Unity WebGL memory pool was configured too high (e.g., 2048 MB), or large uncompressed textures flooded browser VRAM.The Fix: Reduce WebGL Memory Size in Unity Player Settings to 384 MB or 512 MB. Compress all textures to ASTC or Crunch compression.🚨 Problem 4: Windows Standalone Crashes with "Failed to Load Mono"The Cause: You uploaded only the .exe file or the user extracted the .exe without the accompanying *_Data folder and UnityPlayer.dll.The Fix: Ensure your ZIP archive contains the entire directory payload.πŸ“¦ 5. Standalone Desktop PackagingIf your game relies on complex graphics shaders, compute shaders, or high-fidelity assets that exceed WebGL browser capabilities, standalone downloadable builds are essential.Root Archive Packaging: Compress the executable together with its UnityPlayer.dll and *_Data folder into a single ZIP.Separate Architectures: Upload distinct packages for Windows 64-bit, macOS, and Linux.macOS Gatekeeper Workaround: Remind Mac players in your page description that if macOS displays a developer verification error, they can run xattr -cr /path/to/game.app in Terminal to bypass Gatekeeper quarantine.πŸ€– 6. Automated Deployment: Mastering the Butler CLIProfessional studios and game jam veterans automate their pipeline using Butler, itch.io's official command-line deployment tool:Bash# 1. Authenticate Butler with your itch.io account
butler login

2. Push an optimized WebGL build to your html5 channel

butler push ./Builds/WebGL yourusername/my-game:html5

3. Push a Windows standalone build with automatic version tagging

butler push ./Builds/Windows yourusername/my-game:windows-beta --userversion 1.0.4
Binary Delta Patching: Butler uploads only modified file differences. If you adjust a few balance numbers in a C# script, Butler pushes a tiny 2MB diff instead of re-uploading a 400MB archive.πŸ“Š 7. itch.io Project Distribution MatrixProject FormatPlayer FrictionHardware OverheadShader & Graphics LimitsOptimal Game ScopeHTML5 / WebGL (In-Browser)Zero (Instant 1-Click Play)Low (Browser Sandbox)WebGL 2.0 / URP OnlyGame Jams, Web Demos & 2D TitlesWindows Standalone (.zip)Moderate (Download & Unzip)Full Desktop GPU AccessDirectX 12 / Vulkan / HDRP3D Action, Deep RPGs & Steam DemosmacOS Universal Bundle (.app)Moderate (Security Check)Apple Silicon NativeMetal Native APICross-Platform Indie ReleasesπŸ’» 8. Full C# Implementation: WebGL Canvas Viewport & Focus AdapterAttach this production C# adapter to a persistent GameObject in your starting scene to lock the canvas resolution, capture inputs exclusively, and handle tab blurring cleanly:C#using System;
using UnityEngine;

///


/// Production-grade WebGL Viewport and Browser Focus Synchronization Adapter.
/// Prevents webpage scrolling on arrow keys and manages background tab muting.
///
public class WebGLResolutionAdapter : MonoBehaviour
{
public static event Action OnWindowFocusChanged;
[Header("Viewport Resolution Lock")]
[Tooltip("Target fixed render width inside itch.io iframe.")]
[SerializeField] private int targetWidth = 1280;
[Tooltip("Target fixed render height inside itch.io iframe.")]
[SerializeField] private int targetHeight = 720;
[Tooltip("Automatically freeze Time.timeScale and mute AudioListener on tab blur.")]
[SerializeField] private bool autoPauseOnUnfocus = true;

private void Awake()
{
    #if UNITY_WEBGL && !UNITY_EDITOR
    // Lock aspect ratio resolution inside the browser canvas
    Screen.SetResolution(targetWidth, targetHeight, false);

    // Prevent WebGL from capturing mouse scroll wheel for webpage scrolling
    WebGLInput.captureAllKeyboardInput = true;
    #endif
}

private void OnApplicationFocus(bool hasFocus)
{
    if (autoPauseOnUnfocus)
    {
        Time.timeScale = hasFocus ? 1.0f : 0.0f;
        AudioListener.pause = !hasFocus;
    }

    OnWindowFocusChanged?.Invoke(hasFocus);
    Debug.Log($"[WebGLAdapter] Application Window Focus State: {hasFocus}");
}

}

  • 🎨 **9. Storefront Conversion EngineeringUploading your Unity game successfully takes ten minutes; convincing players to click 'Play Game' requires visual conversion engineering.The 630x500 Cover Image: Your cover banner is your primary billboard. Feature high-contrast typography, recognizable character silhouettes, and zero unreadable micro-text.Embed an Animated Gameplay GIF: In your page description, embed an animated 5-second GIF right above the fold. Animated gameplay captures player attention ten times faster than text paragraphs.The 3-Second Control Map: Document your control scheme directly underneath the game canvas (e.g., [WASD] to Move | [SPACE] to Jump | [E] to Interact).
  • ❓ 10. Frequently Asked Questions (FAQ)Do I need to upload every file from the build folder for an itch.io game?Yes. For WebGL builds, you must upload all files (index.html, Build folder, TemplateData folder) compressed into a single ZIP where index.html sits at the root. For standalone Windows builds, you must upload the .exe alongside the entire _Data folder and UnityPlayer.dll inside the ZIP archive.** - ---

Top comments (0)