Gamepad / controller tester
Plug in or pair a controller, then press any button on it. Every button, trigger, analog stick and D-pad direction lights up live, both sticks get a drift and deadzone readout, and — where your browser and controller support it — you can trigger a short rumble pulse. Nothing you do here leaves your browser.
How the Gamepad API works
The Gamepad API is a browser feature for reading input from connected game controllers directly in JavaScript, with no plugin. Three things about it trip people up, and all three are deliberate design choices, not bugs.
1. Nothing shows up until you press something
A page cannot see a connected gamepad the instant it loads. Browsers withhold the list until the page has focus and receives a real input event from that specific controller — a button press or a stick movement past its resting value. That is a privacy boundary: silently fingerprinting every gamepad plugged into your machine, with zero interaction, is exactly the kind of passive data collection browser vendors design against. Once you press a button, the browser fires a gamepadconnected event and the pad's data becomes readable for the rest of the page's lifetime (or until it disconnects).
2. Polling, not push events, for live values
After connection, button and axis values don't arrive as a stream of events — you have to ask for them. The standard pattern, and what this page does, is call navigator.getGamepads() once per animation frame inside a requestAnimationFrame loop, read the current button and axis arrays out of the returned snapshot, and update the display. This ties the refresh rate to your display's frame rate, not to the controller's own reporting rate — see the FAQ below on why this page can't tell you your controller's exact polling rate.
3. The "standard" mapping
Most controllers sold today report a mapping value of "standard", which means the browser has normalised the raw hardware report into a fixed, predictable order: 17 buttons and 4 axes in the same index positions regardless of brand. Button 0 is always the primary face button, buttons 12–15 are always the D-pad, axes 0/1 are always the left stick, axes 2/3 are always the right stick. This is what lets one tool label buttons sensibly across an Xbox pad, a DualSense, and a Switch Pro Controller without brand-specific code. A pad that reports anything other than "standard" hasn't been recognised against that normalisation table, so this tool falls back to a plain numbered button list rather than guessing names it can't verify.
| Index | Standard label | Typical role |
|---|---|---|
| 0 | A | Bottom face button |
| 1 | B | Right face button |
| 2 | X | Left face button |
| 3 | Y | Top face button |
| 4 | LB | Left shoulder / bumper |
| 5 | RB | Right shoulder / bumper |
| 6 | LT | Left trigger (analog 0–1) |
| 7 | RT | Right trigger (analog 0–1) |
| 8 | Back | Select / View / Share |
| 9 | Start | Start / Menu / Options |
| 10 | L3 | Left stick press |
| 11 | R3 | Right stick press |
| 12–15 | D-pad | Up / Down / Left / Right |
| 16 | Home | Guide / PS / Xbox button |
| Axes 0–1 | Left stick | X, Y (−1 to 1 each) |
| Axes 2–3 | Right stick | X, Y (−1 to 1 each) |
Stick drift and deadzone, explained
Stick drift is when an analog stick reports a position other than centre while nothing is touching it. Sticks work by moving a small potentiometer or Hall-effect sensor as you push them; over time the contact wears, dust gets in, or the sensor's magnetic reading shifts, and the resting reading drifts away from true zero. In a game this shows up as a character slowly walking or a camera slowly panning on its own.
Deadzone is the fix game engines and drivers apply for it: ignore any stick reading inside a small radius of centre, so minor drift or sensor noise doesn't register as intentional movement. It's a deliberate tolerance, not a fault. The tool above shows the raw values with no deadzone applied at all, plus a dim marker at the stick's last resting position, specifically so a small drift is visible here even though a game's deadzone might be hiding it from you during normal play.
How to read the test
- Let go of the stick completely and watch the dot. It should sit essentially on the centre crosshair, with the X/Y/Magnitude readout near 0.00.
- If the dot sits noticeably off-centre and stays there, and a "possible drift" badge appears after a moment, that stick's resting position has shifted.
- Move the stick through its full range in a circle. It should reach close to the edge of the circle in every direction — a stick that can't reach the edge in one direction, or that jumps rather than moving smoothly, points at a mechanical problem rather than pure drift.
- Release and re-check. Real drift is reproducible; a thumb resting lightly on the stick, or a one-off input mid-test, is not.
This is a heuristic, not a certified diagnosis. The drift flag triggers when a stick has gone still for roughly a second and its magnitude is still above a small threshold. A genuinely worn stick and a thumb resting lightly on an unworn one can look identical to this test — use the flag as a prompt to look closely, not as a final verdict.
Buying or returning a controller? Check this first
Return windows are short and secondhand listings rarely mention hidden faults. Run through this before the window closes:
- Every face button and shoulder button. Press each one individually and watch for a clean, immediate highlight with no double-registering.
- Both triggers through their full range. Pull slowly and watch the fill bar move smoothly from 0% to 100% — a trigger that jumps in steps or sticks partway has a worn potentiometer.
- Both sticks for drift, using the test above. Let go completely and check the resting dot; then run each stick around its full circular range.
- The D-pad in all four directions, and diagonals if your pad has them — a D-pad with a worn membrane often mis-registers diagonals as a single direction.
- Rumble, on the exact connection you'll actually use. Wired and Bluetooth can behave differently on the same pad.
- Both stick-click buttons (L3/R3). Easy to forget, and a common early failure point on heavily used pads.
- Test on the actual platform you'll use it with, if possible — a controller can behave differently over a proprietary USB dongle versus generic Bluetooth pairing.
Honest limits
- This tool sees post-driver data, not raw hardware. Your OS and browser have already interpreted the controller's electrical signals into the Gamepad API's numbers by the time this page reads them. A fault your OS's own driver silently corrects won't show up here.
- Rumble support is genuinely spotty. Not every browser implements
vibrationActuator, not every controller reports one over every connection type, and effect-type support (dual-rumbleversus others) varies. A disabled or non-functional rumble button here is not proof your controller's motors are dead. - Polling rate is not exposed by this API, at all — see the FAQ. This page's own refresh rate is capped near your display's frame rate, which is a separate number from how fast the controller itself reports.
- Non-standard mappings get raw index labels, not verified names. If your controller doesn't report the standard mapping, this tool can't promise button 3 really is the button you think it is — only that it's whichever one that index consistently represents.
- Drift detection is a heuristic, explained above — treat the flag as a prompt to look closer, not a certified fault report.
- This is a browser page, not a certification lab. It's a fast way to see whether a controller is behaving; for a manufacturer warranty claim, use the manufacturer's own diagnostic tool if one exists.
Frequently asked questions
Why do I have to press a button before my controller shows up?
Browsers deliberately withhold gamepad data from a page until they see a real input from it. A page that could silently enumerate every connected gamepad on load would learn a little about your hardware without you doing anything — so the Gamepad API stays empty until you press a button or move a stick, which counts as you telling the page “yes, use this one”. It is not a bug in this tool; every site built on this API works the same way.
Why don't the button names match my physical controller?
This tool labels buttons using the W3C “standard gamepad” mapping, which is a fixed index order (button 0, button 1, and so on) — not a picture of your specific pad. The labels A/B/X/Y/LB/RB/LT/RT follow Xbox-style naming because that is the most common reference point, but a PlayStation pad's Cross sits in the same index-0 slot as “A”, and a Nintendo pad physically swaps the position of its A/B and X/Y face buttons compared to Xbox. Trust the position and the highlight, not the printed letter, if your pad uses different shapes or letters.
What is stick drift, and how does this tool detect it?
Drift is when a stick reports a position away from centre even though nothing is touching it — usually from worn potentiometer contacts or debris inside the housing. This tool watches each stick's X/Y values; once a stick has gone at least a moment without moving by more than a small amount, it treats that as “at rest” and checks whether the magnitude reading is still above a small threshold. If it is, it shows a “possible drift” flag. That is a heuristic, not a certified diagnosis — a thumb resting lightly on the stick looks identical to real drift, so treat the flag as a prompt to let go completely and watch the dot, not as a verdict on its own.
What's the difference between deadzone and drift?
Deadzone is deliberate: games and the driver ignore a small range around centre so a stick that reads a tiny non-zero value at rest doesn't register as movement. Drift is the underlying problem a deadzone is often used to paper over — the raw resting value moving away from true centre as a stick wears. This tool shows the raw, unfiltered values with no deadzone applied, plus a dim marker at the stick's most recent resting position, so you can see exactly how far off-centre a stick sits before any game-side deadzone hides it.
Why doesn't the rumble button do anything?
Vibration support in the Gamepad API is inconsistent: some browsers don't implement the vibrationActuator interface at all, some controllers don't report a rumble motor over the connection you're using (Bluetooth support is spottier than wired/proprietary-dongle support for several major controllers), and some effect types aren't supported everywhere. If the button is disabled, this browser or controller didn't report a usable vibrationActuator. If it's enabled but you feel nothing, try a wired connection instead of Bluetooth before assuming the motor itself is faulty.
Can this tool tell me my controller's exact polling rate?
No. The Gamepad API doesn't expose polling rate, and this page only sees a new snapshot of button and axis values on each animation frame it requests — typically capped near your display's refresh rate, which is unrelated to how often the controller itself reports over USB or Bluetooth. Measuring true polling rate needs USB packet capture or a manufacturer's own utility, not a webpage.
Does this work for PlayStation, Xbox, Switch Pro, and third-party controllers?
Any controller your operating system and browser already recognise as a gamepad should register here, including DualSense, DualShock 4, Xbox pads, Switch Pro Controller, and most third-party or fight-stick-style USB pads. What you'll see if it doesn't report the “standard” mapping is a note that button order is unverified, with a plain numbered list instead of named buttons — the readings themselves still work, just without the name guesses.
Is my controller data sent anywhere?
No. Everything on this page runs from navigator.getGamepads(), read in your browser and discarded on the next animation frame — there is no server call this tool makes with that data.
Why does a button show partially filled instead of just on or off?
Every button in the Gamepad API reports both a boolean pressed state and an analog value from 0 to 1, even digital-feeling face buttons (most just jump straight from 0 to 1). The triggers (LT/RT on a standard mapping) are the ones that meaningfully use the whole range, which is why this tool draws a fill bar and a live percentage specifically for those two — a half-pulled trigger should show roughly a half-filled bar, not a hard on/off flip.