Controller Latency Test
This controller latency test measures sample age: how old the newest gamepad reading is when the page draws it. It also notes the age at the moment a button goes down. That is the browser’s share of input lag. It is not your monitor, and it is not the full delay inside a game.
- Sample age from the gamepad timestamp
- Press-to-frame timing when a button changes
- Honest about what is left unmeasured
{"waiting":"Press any button on the controller. Browsers hide gamepads until you press a button on this tab.","noApi":"This browser does not expose the Gamepad API, so the live tester cannot read inputs. The written checks on this page still apply.","insecure":"This page is not a secure context, so the browser will not share gamepads. Open the site over HTTPS.","privacy":"Inputs stay in this browser. Nothing is uploaded.","checkAgain":"Check again","layout":"Button labels","layoutAuto":"Match the connected pad","layoutPs":"PlayStation","layoutXbox":"Xbox","layoutNintendo":"Nintendo","layoutGeneric":"Numbers","player":"Controller","buttons":"Buttons","face":"Face","dpad":"D-pad","shoulders":"Shoulders and triggers","center":"Center and sticks clicks","extra":"Other buttons","sticks":"Sticks","leftStick":"Left stick","rightStick":"Right stick","up":"Up","down":"Down","left":"Left","right":"Right","stickHint":"Up on the plot is up on the stick. The numbers keep the browser’s sign: positive Y is usually down.","offset":"Offset","deadzone":"Inner deadzone","radial":"Radial","axial":"Axial","shape":"Deadzone shape","afterDeadzone":"After deadzone","inside":"Inside deadzone","measureDrift":"Measure drift (3s)","release":"Release both sticks and hold them still.","measuring":"Measuring resting offset…","trace":"Trace circularity","tracing":"Push the stick around the outer gate.","stopTrace":"Stop trace","vibration":"Vibration","strong":"Strong motor","weak":"Weak motor","duration":"Duration","play":"Play vibration","pulse":"Pulse three times","triggerRumble":"Try trigger rumble","rumbleMissing":"This browser did not offer a vibration actuator for the selected controller. Chrome and Edge usually do; Firefox and Safari often do not.","rumbleSent":"Vibration command sent.","rumbleFailed":"The browser rejected the vibration command.","triggerUnsupported":"Trigger rumble is not available on this actuator. Dual rumble still ran if the browser accepted it.","rate":"Browser-observed rate","sampleAge":"Sample age","moveStick":"Move a stick to measure the update rate.","rateNote":"This is how often the browser hands us a new sample. It is not the controller’s USB poll rate.","ageNote":"How old the newest sample is when the page draws it. This is not display lag and not in-game lag.","ageUnavailable":"This browser’s gamepad timestamp cannot be compared with the page clock.","gyro":"Motion","requestHid":"Request DualSense access","hidIntro":"Gyro, accelerometer, touch position, and battery are not part of the standard Gamepad reading. Chrome and Edge on desktop can request a DualSense or DualShock 4 over WebHID.","hidMissing":"WebHID is not available here. Use Chrome or Edge on a desktop computer, connect the pad by USB, and try again. Buttons and sticks above still work through the Gamepad API.","hidEmpty":"No device was selected.","hidOk":"The browser allowed access to {name}. This version confirms the device and does not stream gyro values yet, so it cannot show a wrong motion number. Buttons and sticks above stay on the Gamepad API.","hidDenied":"The browser blocked or cancelled device access. Gamepad readings are unaffected.","raw":"Raw data","rawEmpty":"Raw values appear here after a controller connects.","checkup":"Full checkup","startCheckup":"Start full checkup","resetMarks":"Reset marks","stepButtons":"Buttons","stepSticks":"Sticks","stepTriggers":"Triggers","stepRumble":"Rumble","stepDone":"Review","checkupIdle":"A short pass over buttons, both sticks, both triggers, and vibration.","checkupButtons":"Press every face button, the D-pad, bumpers, menu buttons, and both stick clicks.","checkupSticks":"Rotate each stick out to the gate.","checkupTriggers":"Pull both triggers fully.","checkupRumble":"Play vibration, then say whether you felt it.","feltYes":"I felt it","feltNo":"I felt nothing","checkupSkipRumble":"This pad has no vibration actuator in this browser, so that step is skipped.","announcePress":"{label} pressed","modelLink":"This looks like {name}.","openModel":"Open the model page","presetNote":"Labels are locked to this page’s layout. Change “Button labels” if they do not match the pad in your hands.","mappingStandard":"standard mapping","mappingOther":"non-standard mapping","healthy":"Healthy","borderline":"Borderline","drift":"Drift","couldNotMeasure":"Could not get a still sample. Rest the controller on a table and try again.","suggested":"Suggested inner deadzone","coverageLow":"Keep tracing the outer edge. Too few sectors were filled to score the gate.","noPadSelected":"No controller is selected.","slotsLabel":"Connected controllers","noneConnected":"None connected yet","focusDrift":"This page focuses on stick drift. Every other check is still here.","focusDeadzone":"This page focuses on deadzone and calibration. Every other check is still here.","focusVibration":"This page focuses on vibration. Every other check is still here.","focusPolling":"This page focuses on the browser-observed update rate. Every other check is still here.","focusLatency":"This page focuses on sample age and input timing. Every other check is still here.","focusGyro":"This page focuses on motion. Buttons and sticks still use the Gamepad API.","focusButtons":"This page focuses on buttons. Sticks, triggers, and vibration are still here.","names":{"edge":"DualSense Edge","dualsense":"DualSense","ds4":"DualShock 4","joycon":"Joy-Con","switchpro":"Switch Pro Controller","bitdo":"8BitDo pad","deck":"Steam Deck or Steam Input device","series":"Xbox Series controller","xone":"Xbox One controller","xbox":"Xbox controller","nintendo":"Nintendo controller","generic":"generic PC gamepad"}}This page focuses on sample age and input timing. Every other check is still here.
Inputs stay in this browser. Nothing is uploaded.
Press any button on the controller. Browsers hide gamepads until you press a button on this tab.
This is how often the browser hands us a new sample. It is not the controller’s USB poll rate. How old the newest sample is when the page draws it. This is not display lag and not in-game lag.
Buttons
Face
D-pad
Shoulders and triggers
Center and sticks clicks
Sticks
Up on the plot is up on the stick. The numbers keep the browser’s sign: positive Y is usually down.
Vibration
Motion
Gyro, accelerometer, touch position, and battery are not part of the standard Gamepad reading. Chrome and Edge on desktop can request a DualSense or DualShock 4 over WebHID.
Full checkup
- Buttons
- Sticks
- Triggers
- Rumble
- Review
A short pass over buttons, both sticks, both triggers, and vibration.
Raw data
Raw values appear here after a controller connects.
How to measure input lag in the browser
- Wake the pad. Press a button so the browser starts delivering samples.
- Watch sample age. The chip is the median age of fresh timestamps. Lower is a fresher report.
- Tap a face button. The press reading is the sample age at the frame we first saw it down.
- Change the link. Repeat on USB and on Bluetooth before you blame the pad.
Gamepad timestamps and `performance.now()` share a time origin in browsers that implement the spec cleanly. Subtracting them gives the age of the sample at the moment we read it. If a browser’s timestamp is not comparable, the chip says so instead of showing a nonsense millisecond value. The polling rate test is the companion measurement.
Sample age vs end-to-end lag
End-to-end lag is everything from your finger to the photons: the pad, the radio or the cable, the OS, the game, the GPU, and the display. Sample age is one slice, the slice this website can see. A 4 ms wired age and a 20 ms Bluetooth age is a meaningful difference in that slice. A 2 ms difference is noise. A 60 Hz television can add a frame on its own, which this page will never show.
How to read your result
- Single-digit milliseconds on USB in Chromium is a healthy browser path.
- A jump when you switch to Bluetooth is the radio and the stack, which is what you wanted to see.
- A number that changes wildly while the pad sits still means the timestamp source is noisy. Compare presses instead of one frame.
- “Timestamp cannot be compared” means this browser is the wrong tool for a millisecond claim. Buttons and drift still work.
Ways to lower controller latency
Prefer USB when the milliseconds matter. Close remappers you do not need. Keep the test tab focused. In a game, use a wired pad, a high-refresh display, and the game’s low-latency mode if it has one. Those last two do not move the number on this page, and they do move what you feel. The practical list is How do you reduce controller input lag?.
Frequently asked questions
Is this the same as input lag?
It is the browser-visible part of input lag, also called sample age and press-to-frame timing here. Full input lag includes the game and the display.
What is a good sample age?
On desktop Chromium over USB, a small single-digit figure that stays stable is a good browser path. Do not chase 0. Bluetooth is often higher and can still be fine for most games.
Why does the number differ from a YouTube latency video?
Those tests usually photograph a screen and include the display. This page stops at the browser. Both can be correct and still disagree.