Mouse Position Detector: Live X/Y Coordinate Tracker
This detector does something most coordinate tools skip: it shows all four coordinate systems side by side -- screen, client, page, and offset -- so you can see exactly how they differ in real time. Move your mouse over the gridded area below, and click to log coordinates for later. If you have ever wondered why e.clientX and e.screenX give you different numbers, the answer is right there on screen.
Why Four Coordinate Systems Exist
If you are building anything interactive on the web -- a drag-and-drop interface, a canvas drawing app, a game -- you will encounter at least four different coordinate pairs for the same mouse position. They are not redundant; each one answers a different question.
| Property | Measures From | Changes on Scroll? | Changes on Window Move? |
|---|---|---|---|
screenX / screenY | Top-left of the physical monitor | No | Yes (if window moves) |
clientX / clientY | Top-left of the browser viewport | No | No |
pageX / pageY | Top-left of the entire document | Yes | No |
offsetX / offsetY | Top-left of the element under the cursor | Depends | No |
Most online tools show you only screenX/screenY or clientX/clientY. That is enough for a quick reading, but it hides the information you actually need when debugging layout issues or writing drag-and-drop code. This detector shows all four simultaneously so you can see the differences in real time.
Try this: Move the detector to the top of the page and note the page and client values. Then scroll down half a page. The client values stay the same; the page values increase by the scroll distance. That gap is the scroll offset.
Screen vs Client: The Big Confusion
The most common question about mouse coordinates is: "Why do screenX and clientX give me different numbers for the same mouse position?" The answer is simple once you see it, but it trips up almost everyone the first time.
screenX measures from the top-left corner of your physical monitor. If your browser window is not in the top-left corner of the screen -- say it is 200 pixels from the left edge -- then screenX will always be about 200 higher than clientX for the same cursor position. Move your browser window, and screenX changes even though your mouse has not moved relative to the page.
clientX measures from the top-left corner of the browser viewport -- the area where the web page is displayed. It does not matter where your browser window sits on the monitor. The browser's chrome (tabs, address bar, bookmarks bar) is not included in the viewport.
Gotcha: The difference between screenX and clientX is not just the browser window position. On Windows with DPI scaling above 100%, there can be a scaling factor mismatch too. A 150% scaling factor means screenX might be 1.5x what you would expect from clientX alone. See our DPI scaling guide for the full explanation.
Page Coordinates and Scrolling
pageX and pageY are identical to clientX/clientY when the page is scrolled to the top. The moment you scroll down, they diverge: pageY increases by the number of pixels you have scrolled, while clientY stays the same.
This matters for one specific scenario: storing a mouse position to replay later. If you record a click position using clientX/clientY and the user scrolls before the replay happens, the position will be wrong. You need pageX/pageY instead, because they account for scroll position and will point to the same spot in the document regardless of where the viewport is.
There is one edge case: some browsers compute pageX/pageY slightly differently when CSS transforms are involved. A translated or rotated ancestor element can throw off the calculation. For most applications this does not matter, but if you are building a complex layout with transforms, test thoroughly.
Offset Coordinates for Element Interaction
offsetX and offsetY are the odd ones out. They measure from the top-left corner of the specific element your mouse is hovering over, not from the page or the viewport. If your mouse is over a button that sits 300 pixels from the left edge of the page, and you move the cursor 10 pixels into that button, offsetX will be 10 -- not 310.
This is extremely useful for drag-and-drop within a container, canvas drawing, and any interaction where you care about position relative to a specific element rather than the whole page. But it has a quirk: offsetX/offsetY change when the mouse moves over a child element, because the "offset parent" changes. If your container has child elements, offsetX might jump suddenly when the cursor crosses a child boundary.
Fix: Use e.currentTarget.getBoundingClientRect() and compute e.clientX - rect.left manually. This gives you a stable offset relative to the container regardless of child elements. The demo tool at the top of this page uses exactly this approach for its crosshair positioning.
Using the Coordinate Log
The grid above has a feature that sets it apart from other coordinate tools: click-to-capture. Every click inside the grid records the current mouse position -- in all three coordinate systems -- to a log below. You can capture as many points as you want, then copy them all at once in a tab-separated format that pastes cleanly into Excel, Google Sheets, or a script.
Why does this matter? If you are writing a PyAutoGUI script and need to record a sequence of click targets, or building a QA test that checks elements at specific positions, capturing a batch of coordinates in one go is far faster than reading and typing numbers one at a time. The copy button formats the data as: index, screenX, screenY, clientX, clientY -- one point per line.
Workflow: 1) Click each target position in the grid. 2) Hit "Copy Log". 3) Paste into your script or spreadsheet. For PyAutoGUI users, the screenX/screenY columns are what you pass to pyautogui.click(x, y). See our PyAutoGUI guide for more.
How DPI Scaling Affects These Numbers
If you are on a laptop with a high-DPI display (common on Retina Macs and many Windows ultrabooks), you might notice that screenX values do not match what you see in native OS tools. This is because the browser reports coordinates in CSS pixels, not physical pixels, while native tools like PowerShell GetCursorPos report physical pixels.
On a display running at 150% scaling, one CSS pixel equals 1.5 physical pixels. So a coordinate of 1000 in the browser corresponds to 1500 in native coordinates. This is the single most common source of "my automation script clicks in the wrong place" bugs. Check window.devicePixelRatio in the console -- that is your scaling factor.
For a deep dive into this topic with worked examples for 125%, 150%, and 200% scaling, see our DPI scaling guide and our physical vs logical pixels guide.
Touch Devices and Mobile
On touchscreens, there is no mousemove event -- but there is touchmove. The detector above works on mobile: touch and drag inside the grid, and the coordinate readouts update just like they do with a mouse. The values come from touches[0].clientX and touches[0].clientY, which map to the same coordinate systems.
One difference: screenX/screenY on mobile often reports the same values as clientX/clientY, because mobile browsers typically treat the viewport as the full screen. And offsetX/offsetY are not always available on touch events -- you may need to compute them manually using getBoundingClientRect.
If you are building a game or interactive tool for mobile, our pixel coordinates guide includes a touch-specific section with code examples.
How This Compares to Other Tools
There are plenty of mouse coordinate tools online. Here is what most of them do, and where this one differs:
| Feature | Typical Online Tools | This Detector |
|---|---|---|
| Coordinate systems shown | 1-2 (usually screen or client only) | All 4 simultaneously |
| Click to capture points | Rare | Yes, with copy/export |
| Crosshair guide lines | Sometimes | Yes, on both axes |
| Touch/mobile support | Usually broken | Works via touchmove |
| Educational content | None or minimal | Full guide with real use cases |
| Ads / popups | Often heavy | None |
Frequently Asked Questions
Why does screenX change when I move my browser window?
screenX measures from the physical monitor's edge. When you drag your browser window to a new position on screen, every pixel on the page has a new distance from the monitor edge, so screenX changes for the same point on the page. clientX does not change, because it measures from the browser viewport, which moves with the window.
Which coordinate pair should I use for my automation script?
If you are using PyAutoGUI, AutoHotkey, or similar OS-level automation, use screenX/screenY. These tools operate in physical screen coordinates. If you are automating within a browser using Puppeteer or Playwright, clientX/clientY or pageX/pageY are more appropriate. The coordinate log above captures both, so you can choose based on your tool.
Can I get the pixel color at the cursor position?
Browser security prevents reading arbitrary screen pixels via JavaScript. The getImageData API only works on canvas elements. For full-screen color picking, you would need a native tool like Digital Color Meter on macOS or a browser extension with elevated permissions. We cover native color-picking methods in our pixel coordinates guide.
Why does offsetX jump when my mouse crosses a child element?
offsetX/offsetY are relative to whatever element is directly under the cursor. When the cursor moves from a parent container onto a child element, the reference point shifts to the child's top-left corner. To get a stable offset relative to a specific container regardless of children, compute e.clientX - container.getBoundingClientRect().left instead.
Does this work inside an iframe?
Yes, but screenX/screenY will report coordinates relative to the iframe's position within the parent page, which can be confusing. The detector on this page runs within the main document, so it shows the correct values for this page.