The Gamepad API works in Chrome 21+, Edge 12+, Firefox 29+, Safari 10.1+ on macOS, Safari 10.3+ on iOS, and Samsung Internet 4+. Learn the features and code.

Prince Dewani
May 1, 2026
The Gamepad API is a W3C JavaScript interface that lets web pages read button presses and joystick movement from connected gamepads through navigator.getGamepads and connection events. It works in Chrome 21+, Edge 12+, Firefox 29+, Opera 24+, Safari 10.1+ on macOS, Safari 10.3+ on iOS, and Samsung Internet 4+, while Internet Explorer never added support.
This guide covers what the Gamepad API is, which browsers support it, key features, how to connect to a gamepad, use cases, and known issues.
The Gamepad API is a W3C web standard that lets a web page read input from USB and Bluetooth game controllers without a plugin. The browser exposes connected devices through navigator.getGamepads, the Gamepad object, and the gamepadconnected and gamepaddisconnected events on the window.
The Gamepad API ships in every modern browser, with global support near 96% across desktop and mobile. Internet Explorer and the legacy stock Android Browser are the only mainstream targets without support.
Chrome supports the Gamepad API from Chrome 21 on Windows, macOS, Linux, ChromeOS, and Android. Chrome ships the standard Xbox-style mapping and the GamepadHapticActuator for dual-rumble feedback from Chrome 89 on. Modern Chrome restricts navigator.getGamepads to secure (HTTPS) contexts and waits for a user gesture before exposing connected devices.
Microsoft Edge supports the Gamepad API from Edge 12 on Windows. Pre-Chromium EdgeHTML 12 to 18 used the Microsoft implementation, and Chromium-based Edge 79 and later track the upstream Chromium stack. Behavior matches Chrome on every Edge release still in support.
Firefox supports the Gamepad API from Firefox 29 on Windows, macOS, Linux, and Android. Firefox 24 to 28 had it disabled by default behind the dom.gamepad.enabled flag, and Firefox 23 and earlier did not support it. Firefox only exposes connected gamepads after the user presses a button on a controller while the page is visible.
Safari supports the Gamepad API from Safari 10.1 on macOS and from Safari 10.3 on iOS and iPadOS. Apple ships the standard Xbox-style mapping on every supported version and added GamepadHapticActuator support for dual-rumble in newer Safari builds. Safari 10 and earlier did not support the Gamepad API.
Opera supports the Gamepad API from Opera 24 on Windows, macOS, and Linux. Opera Mobile 80 and later expose the same Chromium-backed implementation on Android phones and tablets. Opera 9 to 23 did not support the Gamepad API at all.
Samsung Internet supports the Gamepad API from Samsung Internet 4 on Galaxy phones and tablets. The browser tracks the Chromium gamepad stack, so it ships the standard mapping and connection events on every current Galaxy device. Samsung Internet 1 to 3 did not support the Gamepad API.
The legacy stock Android Browser based on the old WebView did not support the Gamepad API at all. Modern Android devices use Chrome for Android, Samsung Internet, or Firefox for Android instead, all three of which expose the API. Test gamepad-driven web games on Chrome for Android and Samsung Internet, not on the legacy WebView.
Internet Explorer does not support the Gamepad API in any version. Internet Explorer 5.5 through 11 never shipped navigator.getGamepads, and Microsoft has retired Internet Explorer. Move gamepad-driven workloads to Chromium-based Edge or any other modern browser.
Note: The Gamepad API behaves differently across browsers, controllers, and operating systems. Test it on real browsers and OS with TestMu AI. Try TestMu AI free!
The Gamepad API exposes connected controllers through one navigator method, two window events, and a small set of objects. Most browsers ship the same standard Xbox-style mapping, while extensions add haptic feedback and touch surfaces.
You attach gamepadconnected and gamepaddisconnected listeners on the window, store the controller index when the event fires, and poll navigator.getGamepads inside requestAnimationFrame to read button and axis state every frame.
Paste this snippet into the DevTools console of a page on HTTPS, then press any button on a connected controller to confirm support and watch button and axis values stream in.
// Paste this into the DevTools console of a page on HTTPS, then press any button on a connected controller.
let activeGamepadIndex = null;
window.addEventListener("gamepadconnected", (event) => {
activeGamepadIndex = event.gamepad.index;
console.log(
"Gamepad connected at slot",
event.gamepad.index,
event.gamepad.id,
event.gamepad.buttons.length,
"buttons,",
event.gamepad.axes.length,
"axes."
);
});
window.addEventListener("gamepaddisconnected", (event) => {
if (event.gamepad.index === activeGamepadIndex) activeGamepadIndex = null;
console.log("Gamepad disconnected from slot", event.gamepad.index);
});
function pollLoop() {
if (activeGamepadIndex !== null) {
const pad = navigator.getGamepads()[activeGamepadIndex];
if (pad) {
const pressed = pad.buttons.findIndex((button) => button.pressed);
if (pressed !== -1) {
console.log(
"Button",
pressed,
"pressed; left stick at",
pad.axes[0].toFixed(2),
pad.axes[1].toFixed(2)
);
}
}
}
requestAnimationFrame(pollLoop);
}
requestAnimationFrame(pollLoop);If the page never receives gamepadconnected, the most common cause is a missing user gesture on Chrome or a non-secure (HTTP) context that newer browsers block. Reload on HTTPS and ask the user to press any button.
The Gamepad API lets browser-based games, accessibility tools, and creative apps read controller input without a plugin. Any product whose users already own a console-grade controller wins by accepting it on the web.
The Gamepad API works on every modern browser, but the rough edges cluster around platform-specific button maps, stricter security gates, and inconsistent haptic support.
In my experience, the bug that bites teams hardest is the secure-context gate on Chrome. A controller that worked perfectly on localhost goes silent on a staging URL served over HTTP because navigator.getGamepads quietly returns an empty array. Move staging to HTTPS first, then debug.
All Gamepad API version numbers and platform notes in this guide come from these primary sources:
Did you find this page helpful?
More Related Hubs
TestMu AI forEnterprise
Get access to solutions built on Enterprise
grade security, privacy, & compliance