---
name: cdp_move_mouse_human
kind: function
lang: go
domain: browser
version: "1.0.0"
purity: impure
signature: "func CdpMoveMouseHuman(c *CDPConn, toX, toY float64, opts MouseHumanOpts) error"
description: "Mueve el ratón desde (opts.FromX, opts.FromY) hasta (toX, toY) siguiendo una curva de Bézier cúbica con easing ease-in-out, micro-jitter perpendicular y pausas variables entre puntos, imitando el movimiento humano para reducir la detección de automatización."
tags: [cdp, chrome, browser, mouse, human, navegator]
uses_functions:
  - cdp_evaluate_go_browser
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports:
  - math
  - math/rand
  - time
tested: true
tests:
  - "numero de puntos es steps+1"
  - "primer punto aproxima origen"
  - "ultimo punto aproxima destino"
  - "todos los puntos dentro de bounding box razonable"
  - "steps cero normaliza a 1 punto mas origen"
  - "smoothstep en extremos es 0 y 1"
  - "smoothstep monotono creciente"
  - "curva de un solo segmento vertical"
  - "defaults aplicados cuando opts es zero value"
  - "valores explicitos no se sobreescriben"
  - "puntos de control entre origen y destino (intervalo razonable)"
  - "distancia cero no produce NaN"
test_file_path: "functions/browser/cdp_move_mouse_human_test.go"
file_path: "functions/browser/cdp_move_mouse_human.go"
params:
  - name: c
    desc: "Conexión CDP activa obtenida con CdpConnect."
  - name: toX
    desc: "Coordenada X del destino en píxeles de viewport."
  - name: toY
    desc: "Coordenada Y del destino en píxeles de viewport."
  - name: opts
    desc: "MouseHumanOpts: Steps (puntos intermedios, default 25), DurationMs (duración total, default 350-800 ms aleatorio), JitterPx (desviación perpendicular máxima por punto, default 2.0), FromX/FromY (origen, default 0,0 si < 0)."
output: "error si la conexión es nula o falla algún Input.dispatchMouseEvent."
---

## Ejemplo

```go
conn, _ := CdpConnect(9222)
defer CdpClose(conn, 0)

// Mover desde (100, 200) hasta (640, 480) con parámetros por defecto
err := CdpMoveMouseHuman(conn, 640, 480, MouseHumanOpts{
    FromX: 100,
    FromY: 200,
})

// Personalizar curva: 40 pasos, 600 ms, jitter de 4px
err = CdpMoveMouseHuman(conn, 300, 200, MouseHumanOpts{
    Steps:      40,
    DurationMs: 600,
    JitterPx:   4.0,
    FromX:      640,
    FromY:      480,
})
```

## Cuando usarla

Antes de `CdpClick` o `CdpClickHuman` cuando necesitas que el movimiento del ratón parezca humano. Útil en scrapers o bots donde la trayectoria rectilínea instantánea dispara detección (Cloudflare, PerimeterX, DataDome). También útil para simular hover antes de un click para activar tooltips o menús desplegables.

## Gotchas

- Las coordenadas son relativas al viewport visible, no a la página completa. Si el elemento está fuera del scroll, las coordenadas serán incorrectas — hacer scroll primero con `CdpEvaluate` + `scrollIntoView`.
- `time.Sleep` es intencional: simula la duración física del movimiento. En tests headless sin Chrome real no hay efecto visible pero el sleep ocurre igualmente.
- No garantiza indetectabilidad total. Sistemas de detección sofisticados analizan más señales (aceleración del dispositivo, patrones de timing a lo largo de la sesión, huellas de Canvas/WebGL).
- `math/rand` usa la semilla por defecto (no criptográfica). Para movimientos más impredecibles, considera sembrar con `rand.New(rand.NewSource(time.Now().UnixNano()))`.
- El micro-jitter es perpendicular al segmento global origen-destino, no a la tangente local de la curva. Para trayectorias muy curvas, la dirección del jitter puede no ser óptima.
- `DurationMs` controla la pausa total pero no tiene en cuenta la latencia de red al Chrome. El movimiento real tarda `DurationMs + latencia_cdp * Steps`.
