> ## Documentation Index
> Fetch the complete documentation index at: https://docs.scrapengine.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Mouse Move

> Move the cursor to coordinates or a CSS selector, dispatching interpolated mousemove events so hover-based UI fires correctly.

## Overview

Dispatches a series of `mousemove` events along a straight line from the cursor's previous position to the target, so the DOM sees a realistic `mouseenter` / `mousemove` / `mouseleave` cascade on every element the cursor passes over. The endpoint supports two modes:

* **Coordinates** — move to `(x, y)` in viewport CSS pixels.
* **Selector** — move to the center of the element matched by a CSS selector. Waits for visibility.

The two modes are mutually exclusive. Pass either `(x, y)` **or** `selector`, never both.

## Path Parameters

<ParamField path="id" type="string" required={true}>
  Browser session ID (UUID).
</ParamField>

## Body

<ParamField body="x" type="integer">
  X coordinate in viewport CSS pixels. Required together with `y` when `selector` is omitted.
</ParamField>

<ParamField body="y" type="integer">
  Y coordinate in viewport CSS pixels. Required together with `x` when `selector` is omitted.
</ParamField>

<ParamField body="selector" type="string">
  CSS selector of the element to hover. Mutually exclusive with `x`/`y`. Moves to the center of the element's bounding box.
</ParamField>

<ParamField body="timeout" type="integer" default="5000">
  How long to wait (ms) for the selector to become visible. Ignored when using coordinates.
</ParamField>

<ParamField body="index" type="integer" default="0">
  Which match to target when the selector resolves to multiple elements (0-based).
</ParamField>

<ParamField body="holdKeys" type="string[]">
  Modifier keys held for the duration of the move. Each value must be one of `Shift`, `Control`, `Alt`, `Meta`.
</ParamField>

<ParamField body="steps" type="integer" default="10">
  Number of intermediate mousemove events dispatched along the path. `1` teleports — useful for deterministic tests, but does not fire `mouseenter` / `mousemove` on elements in between. Capped at 100.
</ParamField>

<ParamField body="durationMs" type="integer" default="150">
  Total time (ms) to complete the move. Step delay is `durationMs / steps`.
</ParamField>

## Example Request

<CodeGroup>
  ```bash cURL (coordinates) theme={null}
  curl -X POST "https://api.scrapengine.io/api/v1/browser/sessions/0f2b1f6a-88ac-4d25-bc58-67a6f4b4a001/mouse/move" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{ "x": 400, "y": 300 }'
  ```

  ```bash cURL (selector — hover a menu) theme={null}
  curl -X POST "https://api.scrapengine.io/api/v1/browser/sessions/.../mouse/move" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{ "selector": "nav .dropdown-trigger" }'
  ```

  ```javascript JavaScript theme={null}
  await fetch(
    "https://api.scrapengine.io/api/v1/browser/sessions/.../mouse/move",
    {
      method: "POST",
      headers: {
        "Authorization": "Bearer YOUR_API_KEY",
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ selector: "nav .dropdown-trigger" }),
    },
  );
  ```

  ```python Python theme={null}
  import requests

  requests.post(
      "https://api.scrapengine.io/api/v1/browser/sessions/.../mouse/move",
      headers={"Authorization": "Bearer YOUR_API_KEY"},
      json={"selector": "nav .dropdown-trigger"},
  )
  ```
</CodeGroup>

## Response

### Success Response (200)

<ResponseField name="x" type="integer">
  X coordinate the cursor landed on (in viewport CSS pixels). For selector mode, this is the center of the resolved element.
</ResponseField>

<ResponseField name="y" type="integer">
  Y coordinate the cursor landed on (in viewport CSS pixels).
</ResponseField>

**Example Response:**

```json theme={null}
{
  "x": 400,
  "y": 300
}
```

### Error Responses

| Status | Description                                                                                        |
| ------ | -------------------------------------------------------------------------------------------------- |
| `400`  | Invalid body — both modes provided, neither provided, steps/durationMs out of range, bad modifier. |
| `401`  | Unauthorized — invalid or missing API key.                                                         |
| `404`  | Session not found, or selector did not become visible before timeout.                              |
| `503`  | The browser session is temporarily unreachable.                                                    |

## Notes

* **Cursor position is tracked per session.** The move starts from the last known cursor position (initially `(0, 0)`). A subsequent `mouse/click` at a different coord will also update the tracked position, so chained `move → click → move` flows look continuous.
* **Interpolation fires the full DOM cascade.** `mouseenter` and `mouseleave` fire on every element the cursor crosses, along with intermediate `mousemove` events — necessary for hover-activated menus, tooltips, and many `:hover` CSS effects.
* **For deterministic tests**, pass `steps: 1, durationMs: 0` to teleport. For scraping hover-triggered UI, stick with the defaults.
* **Modifier keys** are held for every intermediate event, not just the final position.
