How Browser Game Engines Work: Phaser, Three.js, and the Canvas API
You open a game in a browser tab and a world appears. Here is what is actually happening under the hood — no programming experience required to follow along.
Every browser game you have ever played runs on the same small stack of web technologies. Understanding that stack does not require knowing how to code — it requires knowing what each layer does, why it exists, and how the layers connect. Once you understand the stack, the experience of playing a browser game changes slightly: you start to notice the choices developers make, the tradeoffs they accept, and the ingenuity required to make something feel effortless inside a browser tab.
The Canvas Element: Where Pixels Are Drawn
At the bottom of every 2D browser game is an HTML element called the canvas. It is a rectangular area in the web page where JavaScript code can draw anything it wants: shapes, images, text, gradients, lines. Unlike regular HTML elements that persist on screen until you remove them, the canvas is more like a whiteboard. The game's engine erases it completely and redraws everything on it sixty times per second. Each redraw is called a frame.
The Canvas API is the set of commands JavaScript uses to draw on the canvas. You can draw a rectangle, fill it with a color, draw a circle, load an image sprite and paste it at specific coordinates, apply rotation and scaling transforms, and clip regions for masking effects. These are the fundamental operations. Everything you see in a 2D browser game — every character, background, particle, and UI element — is the result of combining these simple operations at high speed.
The key metric is frames per second. At 60 frames per second, the engine has 16.67 milliseconds per frame to complete all game logic, physics calculations, and drawing operations. This is a tight deadline. Much of browser game engine design is about fitting everything into that window without dropping frames.
WebGL: The GPU Shortcut
The Canvas API draws using the CPU, which is capable but limited in pixel throughput. WebGL is a different interface to the canvas that uses the GPU directly. Graphics Processing Units have thousands of small processing cores designed to operate on pixels in parallel — exactly what rendering a game frame requires. A task that takes the CPU 14 milliseconds might take the GPU 0.3 milliseconds.
The tradeoff is complexity. WebGL's programming interface is extremely low-level: you write programs called shaders in a C-like language (GLSL), and you manage memory buffers manually. No browser game developer writes raw WebGL for a game jam. They use a library like Three.js, Babylon.js, or PixiJS that wraps WebGL in a saner programming interface. These libraries handle shader compilation, buffer management, and the dozens of initialization steps WebGL requires before you can draw a single triangle.
Three.js is the dominant 3D library for browser games. It provides cameras, lights, materials, mesh objects, raycasting, and a scene graph — all the concepts you need to describe a 3D world. Krunker.io, one of the highest-performing browser shooters ever made, was built on Three.js before switching to a custom WebGL renderer when they needed the final ounce of performance.
WebAssembly: Near-Native Performance
JavaScript is fast but it is still an interpreted language with overhead from dynamic typing and garbage collection. WebAssembly (Wasm) is a binary instruction format that browsers execute much more efficiently. You do not write WebAssembly directly; you write in C, C++, Rust, or another compiled language and then compile that code to WebAssembly. The resulting binary loads in the browser and runs at close to native application speed.
The practical impact is significant. The Ruffle Flash emulator is written in Rust and compiled to WebAssembly, which is why it can run complex ActionScript-based games in real time inside a browser tab. The Godot game engine, a major open-source 2D and 3D game engine, can export games directly to WebAssembly, meaning that a game built for PC can be deployed to the browser with minimal modification. Unity also exports to WebAssembly. This has dramatically expanded the range of browser-playable games.
Game Engines: Phaser and Its Peers
Most browser game developers do not work with the Canvas API or WebGL directly. They use a game engine that handles the repetitive work: the game loop, sprite management, physics simulation, input handling, scene management, and audio. The most widely used browser-native engine for 2D games is Phaser.
Phaser is an open-source JavaScript framework that can render using either Canvas or WebGL, automatically choosing based on what the browser supports. It provides a physics engine, a camera system, tilemap loading for level design, a particle system for effects, and built-in support for common game patterns like sprite animation, tweening, and collision detection. A developer who knows Phaser can build a working platformer in a weekend.
Phaser games are identifiable to attentive players because of certain default behaviors: the physics feel similar, the way sprites are handled produces a recognizable collision response, and the particle effects use the same default parameters unless deliberately overridden. This is the inevitable result of any successful shared framework. It is not a criticism; it reflects how much work Phaser is doing for developers.
Other Engines Worth Knowing
Babylon.js is Microsoft-backed and focuses on 3D. It competes with Three.js but is more opinionated and includes more built-in tools for physics, materials, and inspector debugging. The Babylon.js Playground is one of the best in-browser 3D development environments available for free.
PixiJS focuses exclusively on 2D rendering and is the fastest 2D WebGL renderer available for browsers. It does not provide game logic, physics, or input — only rendering. Many developers pair PixiJS for rendering with a separate library for game logic. This makes PixiJS games harder to identify because the rendering layer is decoupled from the game architecture.
GDevelop is a no-code browser game development platform that exports HTML5 games. Games built with GDevelop run in the browser as standard HTML5 applications and are indistinguishable to the player from hand-coded games. GDevelop has produced a surprising number of commercially viable browser games.
The Game Loop
Every game, regardless of engine or platform, runs a game loop. The loop is the heartbeat of the game: it runs once per frame and does three things in order. First, it reads all input (keyboard state, mouse position, gamepad buttons, touch events). Second, it updates the game world (moves characters, applies physics, checks collisions, runs AI logic, updates timers). Third, it renders everything to the screen.
In the browser, the game loop is driven by a function called requestAnimationFrame. When you call requestAnimationFrame with a callback function, the browser executes that callback before the next screen repaint, which happens at the display's refresh rate (usually 60 times per second, sometimes 120 on high-refresh monitors). Every browser game engine wraps requestAnimationFrame in its own timing logic to account for variable frame rates, long frames, and tab backgrounding (when a browser tab is not in focus, requestAnimationFrame slows down to save battery, which engines must handle gracefully).
Sound: The Overlooked Layer
The Web Audio API is the browser's sound system. It allows game developers to load audio files, apply effects (reverb, pitch shift, spatial positioning), mix multiple sounds simultaneously, and synchronize audio to game events with millisecond accuracy. Early browser games used the HTML5 audio element directly, which had enough latency to make sound effects feel disconnected from the actions that triggered them. The Web Audio API solved this; a sound triggered in response to a collision now plays with sub-10-millisecond latency on modern hardware.
Many browser games still have mediocre audio not because the technology is limited but because audio implementation is the last thing developers optimize. The best browser games treat audio as part of the game design rather than an afterthought, and it shows in how satisfying they feel to play.
Understanding these layers will not change what you play, but it will change how you understand it. That subtle smoothness in a well-built Phaser game, the way a WebGL renderer handles a thousand particles without dropping frames, the instant-load feeling of a game built on WebAssembly — all of it is deliberate and technically interesting, even when it is invisible.