Nothing to install

Gamepad tester that lights up every input

Plug in a controller, press any button, and the diagram below wakes up. Every one of the 17 canonical buttons and 4 axes is shown live, with analog triggers as continuous bars, both sticks as plotted coordinates, a dead-zone explorer, a drift meter and a rumble check. It runs entirely in your browser.

No controller yet

Press any button on your controller

A connected pad stays invisible to this page until you use it. That is the specification working as designed, not a fault — see the note below the tool.

Device report

id
waiting for input
mapping
—
index
—
buttons
—
axes
—
vibrationActuator
—

Vibration

Buttons

  • [0] Face button, bottom—
  • [1] Face button, right—
  • [2] Face button, left—
  • [3] Face button, top—
  • [4] Left shoulder (digital)—
  • [5] Right shoulder (digital)—
  • [6] Left trigger (analog on most pads)—
  • [7] Right trigger (analog on most pads)—
  • [8] Select-side centre button—
  • [9] Start-side centre button—
  • [10] Left stick click—
  • [11] Right stick click—
  • [12] D-pad up—
  • [13] D-pad down—
  • [14] D-pad left—
  • [15] D-pad right—
  • [16] Vendor / guide button—

Axes

  • [0] left stick horizontal0.000
  • [1] left stick vertical0.000
  • [2] right stick horizontal0.000
  • [3] right stick vertical0.000

Why the page looks empty until you press something

Almost every support thread about web gamepad testers starts the same way: it says no controller detected, but it is right here. Nothing is wrong. Browsers deliberately refuse to list a connected pad until you use it. The Gamepad specification carries a note to exactly that effect — that getGamepads() returns an empty list before a gamepad user gesture has been seen, and that the reason is fingerprinting. The set of controllers on your desk, complete with their id strings, is a startlingly good identifier; making a page earn it with a deliberate press is cheap protection.

The specification is careful about what counts as that gesture: a button only qualifies if it has a neutral resting state and has been seen released at least once, and axis movement only qualifies past a threshold the browser chooses — one the specification says should be large enough that random jitter does not count. The flip side is the part worth acting on. A controller that fills this page in while sitting untouched on your desk has produced movement past that bar on its own. Take that seriously and run the stick drift test.

Positions, not letters: how the index map really works

The single most useful thing to understand about the Gamepad API is that it numbers places on a controller, not the letters printed on the buttons. The specification defines one canonical layout, the Standard Gamepad, and describes each index purely geometrically: index 0 is the "Bottom button in right cluster", index 12 is the "Top button in left cluster", and so on around the pad. No vendor name appears anywhere in that table.

The Standard Gamepad button map. The Position column is the specification's own wording, quoted; the controller columns record which physical button occupies that position on each product. Cells that differ from the Xbox column are highlighted.
Index Position, in the specification's own words XboxDualSense (PS5)Switch Pro
buttons[0] Bottom button in right cluster ACross ✕B
buttons[1] Right button in right cluster BCircle ○A
buttons[2] Left button in right cluster XSquare □Y
buttons[3] Top button in right cluster YTriangle △X
buttons[4] Top left front button LBL1L
buttons[5] Top right front button RBR1R
buttons[6] Bottom left front button LTL2ZL
buttons[7] Bottom right front button RTR2ZR
buttons[8] Left button in center cluster ViewCreateMinus −
buttons[9] Right button in center cluster MenuOptionsPlus +
buttons[10] Left stick pressed button LS (left stick click)L3Left stick click
buttons[11] Right stick pressed button RS (right stick click)R3Right stick click
buttons[12] Top button in left cluster D-pad ↑D-pad ↑D-pad ↑
buttons[13] Bottom button in left cluster D-pad ↓D-pad ↓D-pad ↓
buttons[14] Left button in left cluster D-pad ←D-pad ←D-pad ←
buttons[15] Right button in left cluster D-pad →D-pad →D-pad →
buttons[16] Center button in center cluster Xbox buttonPS buttonHOME
The four canonical axes. Both sticks report a pair; the vertical axes are positive downward, which catches out nearly everyone the first time.
Index Position, in the specification's own words −1 means +1 means
axes[0] Horizontal axis for left stick (negative left/positive right) left right
axes[1] Vertical axis for left stick (negative up/positive down) up down
axes[2] Horizontal axis for right stick (negative left/positive right) left right
axes[3] Vertical axis for right stick (negative up/positive down) up down

Read the first four rows across and you have the reason half the internet's controller guides contradict each other. The physical bottom button of the right cluster is labelled A on an Xbox pad, Cross on a PlayStation pad — and B on a Switch Pro Controller, because Nintendo arranges its letters the other way round. A game that reads buttons[0] and prints "press A" is correct on Xbox and actively wrong on Switch. The controller button mapping page works through the consequences, including what browsers do about it.

What mapping tells you before you trust any of this

The table above only applies when your controller reports mapping === "standard". That property is an enumeration with exactly three legal values, and the device panel in the tool prints yours verbatim.

The three values of GamepadMappingType, from the specification's enum.
ValueWhat the specification saysWhat it means for you
"standard" The user agent has remapped the device onto the Standard Gamepad layout, so the index table on this page applies. Indices are portable. A game that reads buttons[0] gets the bottom face button on every pad reporting this value.
"" (empty string) The spec states plainly: “The empty string indicates that no mapping is in use for this gamepad.” Indices are whatever the device reports in its own HID order. The table on this page does not apply, and neither does anyone else’s. Read the labels from the tester, not from a chart.
"xr-standard" Reserved for WebXR input sources, and never for ordinary game controllers. getGamepads() must never report it — the specification says so outright. XR controllers reach a page through WebXR instead, not through this API.

An empty string is the case worth knowing about, because it is silent. Generic USB pads, arcade sticks, flight gear, older third-party controllers and anything reached through an adapter frequently land here. Nothing errors; the buttons simply arrive in whatever order the device's own HID descriptor lists them, which might put Start at index 9 or at index 6. When the tool shows an empty mapping it says so in an amber panel, and the correct response is to stop reading charts — including this one — and read your own labels off the live panel instead.

The right bumper that never flashes cyan

Suppose the right bumper feels unreliable. Open the live panel and press every button in order around the pad. 16 of them flash cyan; buttons[5] never does, and its value stays at 0.00. That is a clean negative result — the browser received nothing at all — which puts the fault in the switch, its solder joint, or the ribbon between the board and the shoulder assembly. Now the counter-case, which looks similar and means the opposite: buttons[5] does light, holds a value of 1.00 while you hold it, and your game still ignores it. The hardware is fine and the binding is not; no amount of further hardware testing will help.

There is a third case unique to triggers, and it is why they have their own page. On many pads the analog triggers register as moving long before they register as pressed, so a trigger can look dead in a simple pass/fail tester while the value bar is clearly climbing. The analog trigger test shows the continuous value and the pressed flag next to each other, with the exact threshold Chromium applies between them.

How fast can a web page actually see your controller?

Three rate limits sit in series between the switch under your thumb and this page: the controller's own report rate, the rate the browser samples it at, and the rate the page reads the browser's snapshot. Any measurement can only ever reveal the slowest of the three, and the middle one is usually it. Chromium runs a dedicated gamepad polling thread with its interval set to 4 ms — the constant is commented "~250 Hz" in the browser's own source — so a 1000 Hz controller cannot present as 1000 Hz to any web page in that browser, no matter how the page is written.

This is why the update-rate meter in the tool is labelled the way it is. It reports how often your browser handed this page a snapshot carrying a new timestamp, and it does not call that number your controller's polling rate, because it is not. Testers that print "your polling rate: 250 Hz" are usually printing the browser's sampling interval back at you with the controller's name attached.

Dead zones, drift, and the difference between them

A thumbstick almost never reports exactly zero at rest, and games hide that behind a dead zone: a region around the centre whose inputs are forced to zero. Drift is what happens when the resting offset grows until it escapes the dead zone and the camera starts moving on its own. The two are inseparable — a drift figure means nothing without knowing what dead zone it has to clear — which is why this site treats them as one subject split over two pages. The dead-zone test lets you drag a threshold across your own live stick input and watch what survives; the stick drift test samples your untouched sticks for a minute and reports the largest offset they produced.

Both pages carry generated arithmetic; none of the numbers were borrowed. The dead-zone tables are computed from the geometry of the unit disc — how much travel each shape removes, how far a square dead zone reaches on the diagonals, what a scaled response returns at each input magnitude — and every published cell is checked against the same functions the tool uses when the site is built.

What this tester cannot tell you

  • It cannot see inputs the controller keeps to itself: pairing buttons, most profile switches, and on many pads the gyroscope and touchpad surface.
  • It cannot separate the controller from the cable, the adapter or the port. Swap one variable at a time; retest wired if you tested wireless.
  • It cannot read your device's true USB polling rate, for the reason above.
  • It cannot prove a stick is healthy from an all-zero drift run, because an upstream dead zone produces the identical result.
  • It cannot promise that a pad reporting an empty mapping matches any published index table, including this site's.

Common reasons people run this test

  • A second-hand purchase. Two minutes here covers every button, both sticks and both triggers before the return window closes — the Xbox, DualSense, DualShock 4 and Switch Pro pages open with the right labels already applied.
  • Suspected drift after a game started creeping — measure before buying replacement modules.
  • Warranty evidence. A screenshot showing a resting offset with the controller untouched is more persuasive than a description.
  • Building something. If you are writing a game or a web app, the index table and the mapping caveat are the two things worth getting right on day one.

Questions people actually ask

My controller is plugged in and the page says nothing is connected. Is it broken?

Almost certainly not — this is the single most common confusion about gamepads on the web, and the behaviour is deliberate. The Gamepad specification instructs browsers to hide connected pads until you actually use one, in a note that says plainly that getGamepads() returns an empty list before a gamepad user gesture has been seen, to mitigate fingerprinting. A page that could silently enumerate your controllers would learn a lot about you before you agreed to anything. Press any button, or push a stick well off centre, and the pad appears immediately.

Why do the buttons on the diagram not match the letters on my controller?

Because the specification numbers positions, not letters. Index 0 is defined as the "Bottom button in right cluster" — which is A on an Xbox pad, Cross on a PlayStation pad and B on a Switch Pro Controller, because Nintendo prints its letters in the opposite arrangement. Open the controller button mapping page for the full index table with all three label sets side by side.

Does this test prove my controller is fine for gaming?

It proves the chain from the controller through the driver, the OS and the browser delivers every input to an application. That is most of what people mean by "does it work". It does not test anything a game does past that point: in-game bindings, an overlay grabbing input first, or a title that reads raw HID or XInput directly rather than through the browser. If everything lights up here but a game ignores a button, the fault is on the game side of that line.

Can a browser test really detect stick drift?

It can measure what reaches the browser, which is the useful part, with one caveat that decides how to read the result. Drivers and controller firmware often apply their own dead zone before any application sees the axis, so a stick with mild drift can report a flat 0.000 here. That is why the drift meter reports the share of samples that were exactly zero alongside the offset: an all-zero run is reported as inconclusive rather than as a clean bill of health.

Is the vibration test safe to run repeatedly?

Yes. The effect this page requests is a fixed 600 ms dual-rumble, and the specification defines those parameters as a duration and two magnitudes that default to zero. Nothing is written to the controller's persistent storage and nothing continues after the duration elapses. If the button does nothing, your pad or browser exposes no vibrationActuator — the device panel tells you which.

Why does my 1000 Hz controller not read as 1000 Hz?

Because a web page never sees the device directly. Chromium samples gamepads on its own thread every 4 ms — around 250 Hz — so anything faster than that arrives already thinned out. The tool's Update rate tab is labelled for what it actually measures: the rate your browser handed states over at. It never calls that number the controller's own polling rate, because it is not one.

Does anything I do here get uploaded?

No. The page is static: the Gamepad API runs in your browser, the readings are rendered back to you, and there is no server component to receive them. Your controller's id string — often the only genuinely identifying thing a pad exposes — never leaves the tab. The privacy page sets out what the site does load and why, including the advertising script, which is the only third-party code on the page.

Link to this tester

Helping someone diagnose a controller on a forum or in a repair guide? Copy this:

<a href="https://padtest-78m.pages.dev/">PadTest — free online gamepad tester</a>

Keep testing

Test the rest of the desk