Controller Tester
Check every button, stick and trigger on any gamepad — then run a 5-second stick drift test. Runs entirely in your browser; no input data ever leaves the page.
Browsers keep a gamepad hidden until it sends its first input, so nothing shows up here until you press something. A stick click counts. Connect by USB cable or Bluetooth first.
Positions follow the W3C standard mapping. Face-button letters follow the label set chosen below — the browser only guarantees the position, never the printing on the plastic.
Values are read once per animation frame straight from navigator.getGamepads(). Nothing is recorded, stored or uploaded — reload the page and every counter is gone.
Stick drift test
Put the controller down on a flat surface and take your thumbs off both sticks. The test reads both sticks once per animation frame for five seconds and reports how far each stick wanders from its centre while nothing is touching it.
- Max deviation—
- Mean resting X—
- Mean resting Y—
- Mean offset—
- Samples—
Resting cloud, zoomed 4×. Green ring 0.05, gold ring 0.12, outer ring 0.25 of full stick travel. The white cross is the mean; gold dots are readings that ran off the plot.
- Max deviation—
- Mean resting X—
- Mean resting Y—
- Mean offset—
- Samples—
Resting cloud, zoomed 4×. Green ring 0.05, gold ring 0.12, outer ring 0.25 of full stick travel. The white cross is the mean; gold dots are readings that ran off the plot.
Verdict thresholds are based on the maximum deviation from centre: under 0.05 clean, 0.05–0.12 minor, 0.12 and above significant. Samples are taken once per animation frame, so a 60 Hz display captures roughly 300 readings in five seconds and a 144 Hz display roughly 720.
Deadzone visualiser
Drag the slider to the deadzone you are considering. The shaded circle is the region a game would throw away. If a stick's drift ring pokes outside it, that stick will still move the camera on its own at that setting.
Run the drift test to see whether your resting noise fits inside this deadzone.
Rumble test
Fires the pad's motors through vibrationActuator.playEffect('dual-rumble'). The strong motor is the heavy low-frequency one, the weak motor is the small high-frequency one. Every burst is capped at 600 ms.
Connect a controller to test rumble.
How to use it
- Connect and wake the pad. Plug in the USB cable or pair over Bluetooth, then press any button. The Gamepad API deliberately reports nothing until the pad sends its first input, so the page stays on the prompt until you do. If it still does not appear, press Scan again.
- Walk every control once. Face buttons, both bumpers, both stick clicks, all four d-pad directions, Start and Back. Each control turns red while held and stays marked afterwards — anything still grey in the checklist after a full pass is not reaching the browser at all.
- Squeeze each trigger through its full travel. A healthy analogue trigger climbs smoothly from 0.000 to 1.000. One that jumps in steps, plateaus early or never reaches 1.000 has a worn sensor, and one that reads above 0.000 at rest needs the same treatment as a drifting stick.
- Roll both sticks around the rim. The dot should touch the edge of its circle in every direction and snap back to the middle. A dot that stops short in one direction is a stick that will feel slow on that side in-game, usually a worn gimbal rather than a dead sensor.
- Run the drift test properly. Set the controller down — do not hold it. The weight of a thumb resting on a stick is enough to bias the result by more than the drift you are trying to measure.
- Read the verdict against the number, not the word. Clean means the worst single reading stayed under 0.05 of full travel. Minor (0.05–0.12) is normally fixable with a slightly larger in-game deadzone. Significant (0.12+) will visibly move your character or camera on its own and needs a repair, not a setting.
What the numbers actually mean
Each stick axis is a floating-point number from -1.00 to +1.00, and in the standard mapping Y is inverted: pushing up gives you a negative number. That trips up more people writing their own input code than any other part of the API. The value you see here is whatever the browser was handed by the OS driver, which is not always the raw sensor reading — more on that below.
Why the sample rate is the display's, not the controller's
The Gamepad API has no event for stick movement. State only updates when you re-read navigator.getGamepads(), so this page polls inside requestAnimationFrame and therefore samples at your refresh rate: about 60 readings per second on a 60 Hz display, about 144 on a 144 Hz one. Your controller reports far faster than that — a wired XInput pad sends at 125–250 Hz, many Bluetooth pads at 66–125 Hz — so this tool sees a subset of the reports the pad produced, not all of them. That is fine for drift (a drifting stick is drifting continuously) but it means this page cannot measure your controller's polling rate, and any tool that claims to from JavaScript alone is guessing.
What drift actually is
Most analogue sticks are two potentiometers on a gimbal: a wiper drags across a resistive track and the voltage is digitised. The wiper wears a groove in the track and the carbon dust it grinds off collects where the wiper sits most — dead centre. Both effects move the "this is the middle" voltage, and once it moves past the game's deadzone the character walks off on its own. That is why drift almost always appears at the centre first and why it gets worse fastest on the stick you use for movement. Hall-effect and TMR sticks read a magnet instead of touching anything, which is why they do not develop this failure.
Reading the resting cloud
- A tight dot on the crosshair — healthy. Any wobble is a fraction of the plot.
- A tight dot offset from the crosshair — classic worn-centre drift. The stick is stable, it just no longer agrees where the middle is. A deadzone slightly larger than the offset hides it completely, at the cost of a numb centre.
- A fuzzy circle centred on the crosshair — electrical noise rather than mechanical wear: a cheap ADC, a bad ground on a long USB cable, or a failing battery. Try a different cable or port before blaming the stick.
- A line along one axis — one of the two potentiometers is failing while the other is fine. Common, and it is the pattern that produces drift in exactly one direction in-game.
- Occasional spikes far from the cluster — an intermittent connection, usually the stick module's ribbon cable or a cracked solder joint. This one is worth opening the pad for; a deadzone will not save you, because the spikes are far larger than any sane deadzone.
The 0.000 trap
Some controllers and drivers zero out small values before the browser gets them. A DualSense over Bluetooth, several third-party pads and most "XInput wrapper" drivers do exactly this. On those pads a drift test in any browser tool will report a perfect result even when the stick is visibly wandering in-game, because the wandering is being erased upstream. This page flags it explicitly when every sample comes back as exactly 0.000 rather than quietly awarding you a clean bill of health.
If the result is bad
In rough order of effort: recalibrate first (Windows: run joy.cpl, open Properties, then Settings → Calibrate), update the controller's firmware from the manufacturer's app, then try compressed air and a little isopropyl alcohol around the stick base — contamination is a genuinely common cause and costs nothing to rule out. If the drift survives all three it is mechanical, and the fix is a replacement stick module or a hall-effect drop-in. Raising the in-game deadzone is a workaround, not a repair: it works until the offset outgrows the deadzone you can tolerate.
Mapping, and why an unrecognised pad shows numbers
When the browser recognises a controller it sets mapping to standard and guarantees the layout: index 0 is the bottom face button, 6 and 7 are the triggers, 12–15 are the d-pad, axes 0–3 are the two sticks. Otherwise mapping is empty and the indices mean whatever the device felt like — some pads even report their d-pad as a ninth axis rather than as buttons. That is why this page hides the diagram for non-standard pads instead of drawing labels it cannot stand behind. Switching a third-party controller between XInput and DirectInput mode (usually a switch on the back or a button combo) changes which side of that line it lands on.
Privacy: this tool uses no microphone, camera or screen capture. Controller input is read in the page, drawn to the screen and discarded — there is no upload, no analytics event carrying your input, and nothing is written to storage. Reload the page and every counter and sample is gone.
FAQ
How do I test my controller in the browser?
Connect the controller by USB cable or Bluetooth and press any button on it. Browsers deliberately hide a gamepad until it sends its first input, so nothing appears until you press something. After that the diagram lights up live: face buttons, d-pad, bumpers, both sticks and the analogue triggers, plus a press counter for every control. Nothing is installed and no input data leaves your browser.
How do I test for stick drift?
Put the controller down on a flat surface, take your thumbs off both sticks, and run the 5-second drift test. It samples both sticks once per animation frame — roughly 300 readings on a 60 Hz display — and shows each stick's maximum deviation from centre, its mean resting position and a plot of the resting cloud. Under 0.05 is clean, 0.05 to 0.12 is minor drift you can usually hide with a deadzone, and 0.12 or more is significant drift that will move your character on its own.
The drift test says 0.000 on everything. Is my controller perfect?
Maybe, but check the plot before celebrating. Some pads and drivers apply their own deadzone before the browser ever sees a value, so a stick that is genuinely wandering gets snapped to exactly zero. If every single sample is exactly 0.000 the tool says so on screen. That means the reading is being cleaned up upstream and this test cannot see small drift on that controller.
Why does my controller not show up at all?
Three usual causes. You have not pressed a button yet, and the Gamepad API stays silent until the pad sends input. The page is not on a secure connection, and Chrome only exposes gamepads in a secure context. Or the controller is in a mode the browser does not understand: a PlayStation pad still in Bluetooth pairing mode, a Switch Pro controller in Nintendo mode, or a wireless Xbox pad whose dongle lost sync all report nothing. Try a USB cable first, then press Scan again.
What deadzone should I use in games?
Run the drift test, look at the maximum deviation, and set the in-game deadzone just above it. A clean controller usually needs 0.05 to 0.08. A worn one may need 0.15 or more, which is the point where aiming starts to feel numb around the centre. The deadzone visualiser here draws the circle at whatever radius you pick and tells you how many of your resting samples escape it.
Why are my buttons shown as numbers instead of A, B, X and Y?
It means the browser could not match your pad to the standard layout, so its mapping field reports something other than standard. The buttons still work and still register, but their physical positions are unknown, so drawing them on a diagram would be a guess. Use the numbered grid instead: press each control and watch which index lights up.