Gamepad Tester

Test any game controller in your browser. Live button, trigger and stick readouts, stick-drift detection with adjustable deadzone, and a vibration test.

🌐 Español

No controller detected

Connect a controller, then press any button.

Plug in or pair an Xbox, PlayStation, or generic USB/Bluetooth gamepad. Most browsers (including Chrome and Edge) don't reveal a controller until you press a button or move a stick on it — so if nothing shows up here, give a button a tap.

🔒 Private by design: everything runs locally in your browser and never uploaded to any server.

Polling every frame, because the Gamepad API has no events

The Gamepad API is the odd one out among browser input APIs. There is no button-down event to listen for. The only two events window ever fires are gamepadconnected and gamepaddisconnected; the actual state of every button and axis has to be asked for, over and over.

So this page runs a requestAnimationFrame loop that calls navigator.getGamepads() once per frame, walks the array it gets back (which is sparse, with empty slots showing up as nulls), and rebuilds a fresh display snapshot for every pad it finds. That loop is the whole engine. The connect and disconnect handlers are registered but do nothing at all, because the running loop notices a new or vanished pad on its next frame anyway.

Two consequences follow from that design. Readouts update as fast as your display refreshes, which is what makes a trigger pull look continuous rather than stepped. And if a browser does not expose navigator.getGamepads, the loop is never started, so the counter stays on “No controller detected” no matter what you plug in.

Standard mapping versus the raw-index fallback

Every connected pad gets its own panel, headed by its slot number and the identification string the browser reports for it, with a badge beside it reading either “standard mapping” or “non-standard mapping”. That badge decides everything underneath.

Standard mapping is the W3C layout: seventeen buttons at fixed indices and four axes at fixed indices. When the browser promises it, the tiles carry real names, and the face buttons carry two of them at once (A / Cross, B / Circle, X / Square, Y / Triangle) because index 0 genuinely is both the Xbox A button and the PlayStation Cross button. Anything a pad reports past index 16 falls back to a plain numbered label instead of inventing a name for it.

When the badge says non-standard, the panel changes shape. Button names become bare indices, the two stick boxes are replaced by a “Raw axes” list printing each axis to three decimal places, and a warning paragraph spells out that the browser cannot say which physical control is which. It is deliberately less pretty. A wrong label on a diagnostic tool is worse than no label, and the raw axis numbers still answer the only question that matters, which is whether the control moves.

The deadzone slider and the three stick states

The control at the top reads “Deadzone” followed by the current value to two decimals. It slides from 0.05 to 0.30 in steps of 0.01 and starts at 0.15. Changing it takes effect on the very next frame, because the polling loop reads the live value rather than restarting.

Each stick is collapsed to a single number, its magnitude, the straight-line distance from centre. That magnitude is then classified three ways:

The dot in each box tracks the raw axis pair, and the vertical axis is positive downward in the Gamepad API, so pushing a stick down moves the dot down. The readout underneath prints X, Y and magnitude to three decimals, which is fine enough to watch a worn stick settle at a small non-zero resting value instead of a true zero after you let go.

Working through a controller you have just unboxed

  1. Connect the pad by USB cable or pair it over Bluetooth, then press any button on the controller itself so the browser reveals it.
  2. Confirm the counter has changed from “No controller detected” to a controllers-connected count, and check whether the badge says standard mapping before you trust any of the printed names.
  3. Walk the whole pad in order: both stick clicks, all four D-pad directions, both bumpers, the face buttons, and Start and Back. Each tile fills with the accent colour while its button is held, so a dead button is a tile that never changes.
  4. Pull the left and right triggers slowly to the stop. Only those two tiles print a number and a bar, and a healthy trigger walks smoothly from 0.00 to 1.00 rather than jumping straight to the top.
  5. Take both thumbs off the pad, drag “Deadzone” down toward 0.05, and read both stick status lines. A stick that will not settle to “centered” at a small deadzone is drifting.
  6. Press “Test vibration” last, if the button is present at all.

The 500 millisecond rumble test, and when the button is missing

The vibration button is feature-detected per pad, not per browser. It renders only when that specific controller exposes a callable vibration actuator; otherwise the panel shows a short explanatory note in its place, since rumble is mainly a Chromium plus compatible-pad combination and Firefox and Safari frequently expose nothing.

When it is there, pressing it fires one dual-rumble effect: no start delay, 500 milliseconds long, both the weak and the strong motor requested at full magnitude. There is no intensity slider and no repeat. Worth knowing before you read anything into a quiet controller: if the pad rejects the effect, that rejection is caught and ignored, so nothing appears on screen to distinguish a refused effect from a pad whose motors have failed.

Where this stops and a vendor utility starts

This is a read-only diagnostic. It will not calibrate a stick, remap a button, adjust a trigger response curve, update firmware or save a profile, and nothing it shows is written anywhere. Several genuinely useful controller features are also simply outside the standard mapping the browser hands over: motion sensors, touchpads, adaptive trigger resistance and battery level are not part of the snapshot, so their absence here says nothing about your hardware.

For the rest of an input checkup, the keyboard tester covers stuck keys and rollover, the mouse tester covers buttons, scroll direction and double-click behaviour, and the click speed test turns clicking into a score. If a game feels wrong and the pad checks out clean here, the next suspect is usually the display rather than the input, which is what the refresh rate test measures. The rest of the live hardware checks sit together under testers.

See it in action

Screenshot of the Gamepad Tester tool with a controller diagnostic waiting for a device, with an adjustable 0.15 deadzone and instructions to plug in or pair an Xbox, PlayStation or generic USB/Bluetooth gamepad and press any button
Gamepad Tester mid-process: a controller diagnostic waiting for a device, with an adjustable 0.15 deadzone and instructions to plug in or pair an Xbox, PlayStation or generic USB/Bluetooth gamepad and press any button.
Diagram: where the work happens on a SysFenix page that has no file input at all: the tool arrives as ordinary JavaScript inside the page, works the answer out on your own device and renders it in place, so the upload, queue and server-side record a typical online tool needs never happen
Where the work happens on a SysFenix page that has no file input at all: the tool arrives as ordinary JavaScript inside the page, works the answer out on your own device and renders it in place, so the upload, queue and server-side record a typical online tool needs never happen.

Frequently asked questions

My controller is plugged in and the page still says "No controller detected".

Press a button on the pad itself. Chrome and Edge hold a connected gamepad back from the page until you physically interact with it, so a controller sitting idle is invisible here even though your operating system already lists it. If a button press changes nothing, the other possibility is that this browser does not implement the Gamepad API at all, in which case the polling loop never starts and the counter can never change.

What exactly does the number on the Deadzone slider mean?

It is a radius, not a per-axis limit. Each stick reading is turned into one number, the straight-line distance from centre, and that number is compared against the slider. The slider runs from 0.05 to 0.30 in hundredths and opens at 0.15, which is deliberately smaller than the deadzones Microsoft's own controller API applies internally, around 0.24 on the left stick and 0.26 on the right. That gap is the point, since a pad can drift under a game's larger internal deadzone and still feel perfectly fine to play.

My stick says "active" instead of flagging drift when I push it. Is that broken?

No, that is the guard working. Anything past the deadzone but no further than a magnitude of 0.50 is reported as past-deadzone, which is the band real resting drift lives in. Anything beyond 0.50 is a clear deliberate push and is reported as active instead, so the tester never accuses you of drift while you are holding the stick. Take your hands off the pad completely before you read the status line.

Why do only two of the button tiles show a number and a filling bar?

Because those are the only two analog buttons in the layout. On a pad reported with the standard mapping, indices 6 and 7 are the left and right triggers, and only those tiles print the pressure value to two decimals and draw a fill bar. Every other button is treated as on or off, so its tile just lights up while it is held.

My pad shows raw axis numbers and "Button 0, Button 1" instead of proper names.

Your browser has flagged that controller as non-standard mapping, which means it cannot promise which physical control sits at which index. Rather than print names that might be wrong, the panel falls back to raw indices, drops the two stick boxes, and lists every axis value to three decimals under a Raw axes heading. Third-party arcade sticks, flight gear and older USB adapters land here often, and the raw numbers still tell you whether a control responds.

How strong is the rumble test and can I change it?

There is no strength control. The button fires a single dual-rumble effect lasting 500 milliseconds with both the weak and the strong motor requested at full magnitude, then stops. If the pad refuses the effect, the rejection is discarded quietly, so a controller that does nothing when you press the button is indistinguishable from one that ignored the request.

Related tools