๐ Free game ยท copy & paste
Free HTML Game Code (Copy and Paste): Snake
A complete Snake game in a single HTML file: no libraries, no images, no setup. Copy the code below, save it as snake.html and open it in any browser.
โฒ Play it right here. Arrow keys, swipe, or the buttons.
What's in this free Snake game
- Arrow keys / WASD, swipe and on-screen buttons
- Score and best score (saved in the browser)
- Gets faster with every apple
- Pause with Space, works on phones
- About 150 lines, commented, easy to change
The code (151 lines, one file)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<title>Snake Game</title>
<!--
Free HTML Snake game โ one file, no libraries. Copy it, save as snake.html, open in a browser.
From htmlgamescode.com (free to use in your own projects).
Controls: arrow keys / WASD, swipe on phones, or the on-screen buttons. Space = pause.
-->
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
min-height: 100vh; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
background: #1b1446; color: #fff; font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
user-select: none; -webkit-user-select: none; touch-action: none; padding: 12px;
}
.bar { width: min(92vw, 420px); display: flex; justify-content: space-between; align-items: center; font-weight: 700; }
.bar span { background: #2a2170; padding: 6px 12px; border-radius: 10px; }
canvas { width: min(92vw, 420px); aspect-ratio: 1; border-radius: 16px; background: #120d35; box-shadow: 0 0 0 4px #382c8f, 0 18px 40px rgba(0,0,0,.4); }
.pad { display: grid; grid-template-columns: repeat(3, 64px); gap: 8px; }
.pad button {
height: 56px; border: 0; border-radius: 14px; background: #382c8f; color: #fff; font-size: 24px; cursor: pointer;
box-shadow: 0 4px 0 #20185a;
}
.pad button:active { transform: translateY(3px); box-shadow: 0 1px 0 #20185a; }
.pad .up { grid-column: 2; } .pad .left { grid-column: 1; grid-row: 2; } .pad .down { grid-column: 2; grid-row: 2; } .pad .right { grid-column: 3; grid-row: 2; }
.msg { position: fixed; inset: 0; display: grid; place-items: center; background: rgba(10, 6, 36, .7); }
.msg[hidden] { display: none; }
.card { text-align: center; background: #2a2170; padding: 26px 30px; border-radius: 20px; }
.card h1 { font-size: 30px; margin-bottom: 6px; }
.card p { opacity: .85; margin-bottom: 16px; }
.card button { border: 0; border-radius: 14px; padding: 12px 28px; font-size: 18px; font-weight: 700; color: #fff; background: #36d35a; box-shadow: 0 4px 0 #1d9a3a; cursor: pointer; }
</style>
</head>
<body>
<div class="bar"><span>Score: <b id="score">0</b></span><span>Best: <b id="best">0</b></span></div>
<canvas id="game" width="400" height="400"></canvas>
<div class="pad">
<button class="up" data-dir="up" aria-label="Up">โฒ</button>
<button class="left" data-dir="left" aria-label="Left">โ</button>
<button class="down" data-dir="down" aria-label="Down">โผ</button>
<button class="right" data-dir="right" aria-label="Right">โถ</button>
</div>
<div class="msg" id="msg"><div class="card"><h1 id="title">๐ Snake</h1><p id="text">Eat the apples, don't hit the walls or yourself.</p><button id="play">Play</button></div></div>
<script>
// ---- settings: change these to make it your own ----
const GRID = 20; // cells per side
const START_SPEED = 140; // ms per move (lower = faster)
const SPEED_UP = 3; // ms faster after each apple
const MIN_SPEED = 60; // fastest allowed
const COLORS = { snake: "#36d35a", head: "#7dff5a", apple: "#ff5f8f", grid: "rgba(255,255,255,.04)" };
const canvas = document.getElementById("game"), ctx = canvas.getContext("2d");
const CELL = canvas.width / GRID;
const $ = id => document.getElementById(id);
const DIRS = { up: [0, -1], down: [0, 1], left: [-1, 0], right: [1, 0] };
let snake, dir, nextDir, apple, score, speed, timer = null, paused = false;
let best = Number(localStorage.getItem("snake-best") || 0);
$("best").textContent = best;
function reset() {
snake = [{ x: 8, y: 10 }, { x: 7, y: 10 }, { x: 6, y: 10 }];
dir = nextDir = "right";
score = 0; speed = START_SPEED; $("score").textContent = 0;
placeApple();
}
function placeApple() {
do { apple = { x: Math.floor(Math.random() * GRID), y: Math.floor(Math.random() * GRID) }; }
while (snake.some(s => s.x === apple.x && s.y === apple.y));
}
function turn(d) {
const opposite = { up: "down", down: "up", left: "right", right: "left" };
if (d && d !== opposite[dir]) nextDir = d; // no instant reverse into yourself
}
function step() {
dir = nextDir;
const head = { x: snake[0].x + DIRS[dir][0], y: snake[0].y + DIRS[dir][1] };
const hitWall = head.x < 0 || head.y < 0 || head.x >= GRID || head.y >= GRID;
const hitSelf = snake.some(s => s.x === head.x && s.y === head.y);
if (hitWall || hitSelf) return gameOver();
snake.unshift(head);
if (head.x === apple.x && head.y === apple.y) {
score++; $("score").textContent = score;
speed = Math.max(MIN_SPEED, speed - SPEED_UP);
placeApple();
} else snake.pop();
draw();
timer = setTimeout(step, speed);
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = COLORS.grid; // checkerboard
for (let y = 0; y < GRID; y++) for (let x = (y % 2); x < GRID; x += 2) ctx.fillRect(x * CELL, y * CELL, CELL, CELL);
ctx.fillStyle = COLORS.apple; // apple
ctx.beginPath(); ctx.arc(apple.x * CELL + CELL / 2, apple.y * CELL + CELL / 2, CELL * 0.4, 0, Math.PI * 2); ctx.fill();
snake.forEach((s, i) => { // snake
ctx.fillStyle = i === 0 ? COLORS.head : COLORS.snake;
ctx.beginPath();
if (ctx.roundRect) ctx.roundRect(s.x * CELL + 1, s.y * CELL + 1, CELL - 2, CELL - 2, 5); else ctx.rect(s.x * CELL + 1, s.y * CELL + 1, CELL - 2, CELL - 2);
ctx.fill();
});
}
function start() { $("msg").hidden = true; paused = false; reset(); draw(); clearTimeout(timer); timer = setTimeout(step, speed); }
function gameOver() {
clearTimeout(timer); timer = null;
if (score > best) { best = score; localStorage.setItem("snake-best", best); $("best").textContent = best; }
$("title").textContent = "Game over";
$("text").textContent = `You scored ${score}. Best: ${best}.`;
$("play").textContent = "Play again";
$("msg").hidden = false;
}
function togglePause() {
if (!timer && !paused) return;
paused = !paused;
if (paused) { clearTimeout(timer); timer = null; } else timer = setTimeout(step, speed);
}
// keyboard
document.addEventListener("keydown", e => {
const map = { ArrowUp: "up", ArrowDown: "down", ArrowLeft: "left", ArrowRight: "right", w: "up", s: "down", a: "left", d: "right" };
if (map[e.key]) { e.preventDefault(); turn(map[e.key]); }
if (e.key === " ") { e.preventDefault(); $("msg").hidden ? togglePause() : start(); }
});
// on-screen buttons
document.querySelectorAll(".pad button").forEach(b => b.addEventListener("pointerdown", e => { e.preventDefault(); turn(b.dataset.dir); }));
// swipe
let sx = 0, sy = 0;
canvas.addEventListener("touchstart", e => { sx = e.touches[0].clientX; sy = e.touches[0].clientY; }, { passive: true });
canvas.addEventListener("touchend", e => {
const dx = e.changedTouches[0].clientX - sx, dy = e.changedTouches[0].clientY - sy;
if (Math.max(Math.abs(dx), Math.abs(dy)) < 20) return;
turn(Math.abs(dx) > Math.abs(dy) ? (dx > 0 ? "right" : "left") : (dy > 0 ? "down" : "up"));
});
$("play").addEventListener("click", start);
reset(); draw();
</script>
</body>
</html>
How to use it
- Click Copy code (or Download).
- Paste it into any text editor and save it as
snake.html. - Open the file in Chrome, Safari, Firefox or Edge. That's it, it runs offline.
Make it your own
All the settings are at the top of the script:
| Setting | Default | What it does |
|---|---|---|
GRID | 20 | Cells per side of the board |
START_SPEED | 140 | Milliseconds per move at the start (lower is faster) |
SPEED_UP | 3 | How much faster after each apple |
MIN_SPEED | 60 | The fastest the snake can go |
COLORS | snake, head, apple, grid | Every color of the game |
FAQ
Is this HTML game code really free?
Yes. You can copy it and use it in your own website, school project or app, change it as much as you like, and publish it. A link back to HTML Games Code is welcome but not required.
How do I run the game?
Copy the code, paste it into a text editor, save the file as snake.html and double-click it. It opens in your browser and works offline; there is nothing to install.
Does it work on phones?
Yes. Swipe on the board or use the on-screen arrow buttons. On a computer use the arrow keys or WASD, and Space to pause.
Can I turn it into an Android app?
Yes. Any HTML game can be packaged as an Android APK. Our HTML Games APK Builder does it for our premium games, or you can use a tool like htmltoapk.com for this file.