---
name: cdp_press_key
kind: function
lang: py
domain: browser
version: "1.0.0"
purity: impure
signature: "def cdp_press_key(key: str, *, port: int = 9222, target_url_substr: str = '', modifiers: int = 0, timeout_s: float = 10.0) -> dict"
description: "Pulsa una tecla nombrada (Enter, Escape, Backspace, Tab, ArrowDown, Delete, ...) sobre el elemento enfocado de una pestana de un Chrome con remote debugging, via CDP Input.dispatchKeyEvent (rawKeyDown + keyUp). Primitiva de input CDP reutilizable: enviar mensajes (Enter en el composer de WhatsApp), cerrar overlays (Escape), navegar resultados (ArrowDown), borrar (Backspace) o combos con modificadores (Ctrl+A)."
tags: [cdp, browser, automation, python, navegator]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: "error_go_core"
imports: ["json", "urllib.request", "websocket"]
params_schema:
  params:
    - name: key
      desc: "Nombre canonico de la tecla a pulsar. Soportadas: Enter, Escape, Backspace, Tab, Delete, ArrowDown, ArrowUp, ArrowLeft, ArrowRight, Home, End. Una tecla no soportada devuelve ok=False sin tocar la red."
    - name: port
      desc: "Puerto de remote debugging de Chrome. Default 9222."
    - name: target_url_substr
      desc: "Substring que debe contener la URL del target (pestana). Si vacio, usa el primer target de tipo 'page'."
    - name: modifiers
      desc: "Bitmask de modificadores CDP combinables con OR: Alt=1, Ctrl=2, Meta/Cmd=4, Shift=8. Ej. Ctrl+Shift = 2|8 = 10. Default 0."
    - name: timeout_s
      desc: "Timeout en segundos para la conexion WebSocket. Default 10.0."
  output: "dict {ok: bool, error: str}. ok=True si los eventos rawKeyDown+keyUp se emitieron sin error. Nunca lanza: errores de red/conexion/transport y teclas no soportadas se devuelven en 'error' con ok=False."
tested: true
tests: ["test_golden_enter_emite_rawkeydown_y_keyup_vk13", "test_edge_tecla_no_soportada_ok_false_sin_abrir_ws", "test_error_create_connection_lanza_ok_false"]
test_file_path: "python/functions/browser/cdp_press_key_test.py"
file_path: "python/functions/browser/cdp_press_key.py"
---

## Ejemplo

```python
import sys, os
sys.path.insert(0, os.path.join("python", "functions"))
from browser.cdp_press_key import cdp_press_key

# Requiere un Chrome lanzado con --remote-debugging-port=9222
# y una pestana de WhatsApp Web abierta con el composer enfocado y texto escrito.
res = cdp_press_key("Enter", target_url_substr="whatsapp")  # envia el mensaje
print(res["ok"], res["error"])

# Combo con modificadores (Ctrl+A para seleccionar todo): Ctrl=2.
cdp_press_key("Home", target_url_substr="whatsapp", modifiers=2)
```

O directo por CLI: `python3 python/functions/browser/cdp_press_key.py "Enter" "whatsapp"`.

## Cuando usarla

Cuando necesites enviar una pulsacion de tecla sobre la pestana **ya abierta** del
navegador diario sin abrir ventana nueva ni darle foco al sistema: **Enter** para
enviar (composer de WhatsApp), **Escape** para cerrar overlays/dialogos,
**ArrowDown/ArrowUp** para navegar resultados de busqueda, **Backspace/Delete** para
borrar, o combos con `modifiers` (Ctrl/Shift/Alt/Meta). Tipicamente **despues** de
escribir con `cdp_type_chars_py_browser` para confirmar la accion. Es la primitiva de
input sobre la que se construyen funciones `whatsapp_*_py_browser` y cualquier script
que opere una pestana existente via CDP.

## Gotchas

- Actua sobre el elemento **enfocado** de la pagina: CDP `Input.dispatchKeyEvent` no
  apunta a un selector, va al foco actual. Asegura el foco (clic o `el.focus()` via
  `cdp_eval_py_browser`) antes de pulsar.
- **Enter en WhatsApp Web envia el mensaje** (no inserta salto de linea). Para newline
  dentro del composer usa Shift+Enter (`modifiers=8`) o no uses esta funcion para eso.
- `modifiers` es el bitmask de CDP, no un string: Alt=1, Ctrl=2, Meta/Cmd=4, Shift=8;
  combina con OR (ej. Ctrl+Shift = 10).
- No se emite evento `char` aparte: el par `rawKeyDown`+`keyUp` con el
  `windowsVirtualKeyCode` correcto (Enter=13) basta para disparar el envio en WhatsApp
  (validado via `press_key` del MCP del navegador).
- Requiere un Chrome lanzado con `--remote-debugging-port=9222` (o el puerto que pases).
  Sin remote debugging, `GET /json` falla y devuelve `ok=False`.
- Nunca lanza: errores de red, conexion WS, transport o tecla no soportada se reportan
  en el campo `error` con `ok=False`.
