๐ŸŽฎ Get a game ยท $19

๐Ÿค Free game 3 of 20 ยท copy & paste

Flappy Bird Game in HTML & JavaScript: Free Code + Demo

A Flappy Bird-style game drawn entirely with the canvas (no images): tap to flap through the gaps in the pipes. It runs at the same speed on 60 Hz and 120 Hz screens. Copy the code below, save it as flappy-bird.html and open it in any browser.

Type
Arcade
Level
Easy
Code
126 lines, 1 file
Libraries
None
Works on
Phones & computers
You learn
Gravity, velocity and requestAnimationFrame

โ–ฒ Play it right here. Click, tap, Space or Arrow Up to flap.

What's in this free Flappy Bird game

The code (126 lines, one file)

flappy-bird.htmlโฌ‡ Download
<!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>Flappy Bird Game</title>
<!--
  Free HTML Flappy Bird-style game โ€” one file, no libraries, no images. Save it as flappy-bird.html and open it in a browser.
  From htmlgamescode.com (free to use in your own projects).
  Controls: click, tap or press Space / Arrow Up to flap.
-->
<style>
  * { box-sizing: border-box; margin: 0; padding: 0; }
  body {
    min-height: 100vh; display: flex; align-items: center; justify-content: center; background: #1b1446;
    font-family: system-ui, -apple-system, "Segoe UI", sans-serif; user-select: none; -webkit-user-select: none; touch-action: none;
  }
  canvas { display: block; width: min(96vw, 400px, calc((100vh - 16px) * 2 / 3)); aspect-ratio: 2 / 3; border-radius: 18px; cursor: pointer; box-shadow: 0 18px 40px rgba(0,0,0,.4); }
</style>
</head>
<body>
<canvas id="game" width="360" height="540"></canvas>

<script>
  // ---- settings: change these to make it your own ----
  const GRAVITY = 0.42;          // how fast the bird falls
  const FLAP = -7.2;             // jump strength (negative = up)
  const PIPE_GAP = 150;          // space between the top and bottom pipe
  const PIPE_SPEED = 2.4;        // how fast the pipes move
  const PIPE_EVERY = 95;         // frames between new pipes
  const COLORS = { sky: "#5ec8ff", pipe: "#36d35a", bird: "#ffd23f", ground: "#e8c27a" };   // every color in the game

  const canvas = document.getElementById("game"), ctx = canvas.getContext("2d");
  const W = canvas.width, H = canvas.height, GROUND = H - 60, PIPE_W = 62;
  const load = k => { try { return Number(localStorage.getItem(k)) || 0; } catch { return 0; } };
  const save = (k, v) => { try { localStorage.setItem(k, v); } catch {} };

  let state, bird, pipes, frame, score, best = load("flappy-best"), groundX = 0;

  function reset() {
    state = "ready"; frame = 0; score = 0; pipes = [];
    bird = { x: 90, y: H / 2 - 40, vy: 0, r: 15 };
  }

  function flap() {
    if (state === "over") { if (frame > 30) reset(); return; }   // short pause so a late tap doesn't restart
    if (state === "ready") state = "play";
    bird.vy = FLAP;
  }

  function update() {
    frame++;
    groundX = (groundX - (state === "over" ? 0 : PIPE_SPEED)) % 24;
    if (state === "ready") { bird.y = H / 2 - 40 + Math.sin(frame / 10) * 8; return; }
    bird.vy += GRAVITY; bird.y += bird.vy;
    if (bird.y + bird.r >= GROUND) { bird.y = GROUND - bird.r; if (state === "play") die(); }
    if (state !== "play") return;
    if (bird.y < bird.r) { bird.y = bird.r; bird.vy = 0; }

    if (frame % PIPE_EVERY === 0) pipes.push({ x: W, top: 60 + Math.random() * (GROUND - PIPE_GAP - 120), passed: false });
    for (const p of pipes) {
      p.x -= PIPE_SPEED;
      if (!p.passed && p.x + PIPE_W < bird.x) { p.passed = true; score++; }
      // the bird is a circle; test it against both pipe rectangles (a little forgiving)
      const inX = bird.x + bird.r - 4 > p.x && bird.x - bird.r + 4 < p.x + PIPE_W;
      if (inX && (bird.y - bird.r + 4 < p.top || bird.y + bird.r - 4 > p.top + PIPE_GAP)) die();
    }
    pipes = pipes.filter(p => p.x > -PIPE_W);
  }

  function die() {
    state = "over"; frame = 0;
    if (score > best) { best = score; save("flappy-best", best); }
  }

  function draw() {
    ctx.fillStyle = COLORS.sky; ctx.fillRect(0, 0, W, H);
    ctx.fillStyle = "rgba(255,255,255,.7)";                             // clouds
    [[60, 90], [220, 60], [300, 150]].forEach(([x, y]) => { ctx.beginPath(); ctx.arc(x, y, 22, 0, 7); ctx.arc(x + 24, y + 4, 18, 0, 7); ctx.arc(x - 22, y + 6, 16, 0, 7); ctx.fill(); });

    for (const p of pipes) {                                            // pipes with a cap
      ctx.fillStyle = COLORS.pipe;
      ctx.fillRect(p.x, 0, PIPE_W, p.top);
      ctx.fillRect(p.x, p.top + PIPE_GAP, PIPE_W, GROUND - p.top - PIPE_GAP);
      ctx.fillStyle = "rgba(0,0,0,.18)";
      ctx.fillRect(p.x - 4, p.top - 22, PIPE_W + 8, 22);
      ctx.fillRect(p.x - 4, p.top + PIPE_GAP, PIPE_W + 8, 22);
    }

    ctx.fillStyle = COLORS.ground; ctx.fillRect(0, GROUND, W, H - GROUND);  // scrolling ground
    ctx.fillStyle = "rgba(0,0,0,.12)";
    for (let x = groundX; x < W; x += 24) ctx.fillRect(x, GROUND, 12, 10);

    ctx.save();                                                          // bird, tilted by its speed
    ctx.translate(bird.x, bird.y);
    ctx.rotate(Math.max(-0.5, Math.min(1.2, bird.vy / 10)));
    ctx.fillStyle = COLORS.bird; ctx.beginPath(); ctx.arc(0, 0, bird.r, 0, 7); ctx.fill();
    ctx.fillStyle = "#fff"; ctx.beginPath(); ctx.arc(6, -5, 6, 0, 7); ctx.fill();
    ctx.fillStyle = "#222"; ctx.beginPath(); ctx.arc(8, -5, 3, 0, 7); ctx.fill();
    ctx.fillStyle = "#ff8a3d"; ctx.beginPath(); ctx.moveTo(12, 1); ctx.lineTo(24, 4); ctx.lineTo(12, 8); ctx.fill();
    ctx.fillStyle = "rgba(0,0,0,.15)"; ctx.beginPath(); ctx.ellipse(-5, 4, 8, 5, 0, 0, 7); ctx.fill();
    ctx.restore();

    ctx.textAlign = "center"; ctx.fillStyle = "#fff"; ctx.strokeStyle = "rgba(0,0,0,.35)"; ctx.lineWidth = 6;
    const text = (t, y, size) => { ctx.font = `900 ${size}px system-ui, sans-serif`; ctx.strokeText(t, W / 2, y); ctx.fillText(t, W / 2, y); };
    if (state === "play") text(score, 70, 48);
    if (state === "ready") { text("Flappy Bird", 150, 40); text("Tap or press Space", 330, 22); }
    if (state === "over") { text("Game over", 170, 42); text(`Score ${score} ยท Best ${best}`, 220, 24); if (frame > 30) text("Tap to play again", 330, 22); }
  }

  // fixed-step loop: the game runs at the same speed on 60 Hz and 120 Hz screens
  let last = 0, acc = 0;
  function loop(t) {
    acc += Math.min(100, t - (last || t)); last = t;
    while (acc >= 1000 / 60) { update(); acc -= 1000 / 60; }
    draw();
    requestAnimationFrame(loop);
  }

  canvas.addEventListener("pointerdown", e => { e.preventDefault(); flap(); });
  document.addEventListener("keydown", e => { if (e.key === " " || e.key === "ArrowUp") { e.preventDefault(); flap(); } });
  reset();
  requestAnimationFrame(loop);
</script>
</body>
</html>

How to use it

  1. Click Copy code (or Download).
  2. Paste it into any text editor and save it as flappy-bird.html.
  3. Open the file in Chrome, Safari, Firefox or Edge. That's it, it runs offline.

How the code works

Gravity

Every frame GRAVITY is added to the bird's vertical speed, and the speed to its position. A flap sets the speed to a negative number, so the bird jumps up and falls back.

Pipes

A new pipe pair appears every PIPE_EVERY frames with a random gap height and moves left. Passing one adds a point.

Collision

The bird is a circle; it is tested against the top and bottom pipe rectangles with a few pixels of forgiveness.

Make it your own

All the settings are at the top of the script. Change a value, save and reload:

SettingDefaultWhat it does
GRAVITY0.42how fast the bird falls
FLAP-7.2jump strength (negative = up)
PIPE_GAP150space between the top and bottom pipe
PIPE_SPEED2.4how fast the pipes move
PIPE_EVERY95frames between new pipes
COLORSa list of valuesevery color in the game

Put it on your website

Upload flappy-bird.html next to your page and add this where the game should appear:

<iframe src="flappy-bird.html" width="460" height="620" style="border:0;max-width:100%" title="Flappy Bird game"></iframe>

FAQ

Is this Flappy Bird code really free?

Yes. Copy it and use it in your own website, school project or app, change it as much as you like and publish it, even commercially. A link back to HTML Games Code is welcome but not required.

How do I run the Flappy Bird game?

Copy the code, paste it into a text editor, save the file as flappy-bird.html and double-click it. It opens in your browser and works offline; there is nothing to install.

What are the controls?

Click, tap, Space or Arrow Up to flap.

Does it work on phones?

Yes. It has touch controls and fits a phone screen, and it works with a keyboard and mouse on a computer.

Can I put it on my website?

Yes. Upload flappy-bird.html and link to it, or show it inside an iframe on any page (see "Put it on your website" above).

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.

More free HTML games