Escalado DPI y coordenadas de pantalla: por qué tus clics aterrizan en el lugar equivocado
Ajustes de tu pantalla — detectados automáticamente:
Escribiste un script que hace clic en (960, 540) — funcionaba perfectamente en tu viejo monitor de 1080p. Luego te pasaste a 4K, Windows configuró el escalado al 150 % y, de repente, el mismo clic aterriza 480 píxeles fuera de objetivo. Tu código no cambió. El sistema de coordenadas que hay debajo, sí.
El escalado DPI es la razón más común por la que las coordenadas de pantalla se "rompen" tras actualizar el monitor, estrenar portátil o arrastrar una ventana entre pantallas con escalados diferentes. A continuación explicamos qué ocurre realmente al 100 %, 125 %, 150 % y 200 % — y cómo solucionarlo en tus scripts.
Abrir herramienta gratuita de coordenadas de pantallaTu escalado DPI actual — en vivo
Tu navegador reporta lo siguiente sobre tu pantalla ahora mismo:
Si el Device Pixel Ratio muestra 1,0, estás al 100 % de escalado — los píxeles lógicos y físicos son los mismos. Si muestra 1,5, estás al 150 % y hay una transformación de coordenadas oculta en marcha. Usa nuestra herramienta de coordenadas de pantalla para ver cómo difieren tus posiciones lógicas y físicas en tiempo real.
Qué es el escalado DPI (y por qué existe)
Un monitor 4K de 27 pulgadas concentra 3840×2160 píxeles en aproximadamente el mismo espacio físico que una pantalla de 1080p. Sin escalado, el texto y los iconos se ven diminutos — unos 140 PPI frente a los ~92 PPI de un monitor de 24 pulgadas a 1080p. Utilizable, pero carga la vista.
Por eso Windows aplica el escalado DPI. Lo configuras al 150 % en ese monitor 4K y Windows finge que la pantalla solo tiene 2560×1440. Dibuja todo a ese tamaño menor y luego lo estira para rellenar los 3840×2160 completos. El resultado: la interfaz queda a un tamaño cómodo, pero se renderiza con más nitidez porque cada píxel "lógico" se mapea a 1,5 × 1,5 = 2,25 píxeles físicos.
El problema: La mayoría del software (y la mayoría de herramientas de automatización) solo ven el espacio de coordenadas lógicas. Creen que la pantalla tiene 2560×1440 cuando en realidad tiene 3840×2160. Esto genera un desajuste entre donde crees que estás haciendo clic y donde el clic se registra realmente.
Para una explicación más detallada de qué son realmente los píxeles "físicos" y "lógicos" y cómo se relacionan con los píxeles CSS, píxeles de dispositivo y píxeles independientes del dispositivo, consulta nuestra guía de píxeles físicos vs lógicos.
Resolución lógica vs física en cada factor de escalado
Tabla de consulta — encuentra tu resolución física a la izquierda y lee hacia la derecha para ver qué Windows realmente dice a las aplicaciones en cada factor de escalado:
| Resolución física | 100 % (Lógica) | 125 % (Lógica) | 150 % (Lógica) | 200 % (Lógica) |
|---|---|---|---|---|
| 1920×1080 | 1920×1080 | 1536×864 | 1280×720 | 960×540 |
| 2560×1440 | 2560×1440 | 2048×1152 | 1707×960 | 1280×720 |
| 3440×1440 | 3440×1440 | 2752×1152 | 2293×960 | 1720×720 |
| 3840×2160 | 3840×2160 | 3072×1728 | 2560×1440 | 1920×1080 |
Cómo leer esta tabla: Si tienes un monitor 4K (3840×2160) al 150 % de escalado, las aplicaciones no conscientes del DPI ven una pantalla de 2560×1440. Cuando una de estas aplicaciones pregunta "¿cuál es la anchura de la pantalla?", obtiene 2560 — no 3840. Cuando hace clic en la coordenada (1280, 720), Windows traduce eso al píxel físico (1920, 1080) antes de enviarlo a la pantalla.
Por eso tus scripts de comparativa de resoluciones pueden reportar valores inesperados — están viendo la resolución lógica, no la física.
El problema del offset de coordenadas: dónde aterriza tu clic realmente
Veámoslo con un ejemplo concreto. Quieres hacer clic en el centro de tu pantalla 4K — eso es el píxel físico (1920, 1080). Pero tu herramienta de automatización no sabe nada del escalado DPI. Calcula el centro de lo que ve — el espacio lógico de 2560×1440 — y hace clic en (1280, 720). Windows entonces escala ese clic:
Clic físico = clic lógico × factor de escalado
Clic físico = (1280, 720) × 1.5
Clic físico = (1920, 1080) ← correcto por casualidad!
En este caso funciona — y no es pura suerte. La virtualización DPI de Windows escala las coordenadas de forma uniforme, así que cualquier posición calculada como proporción de la pantalla (centro = 50 %, esquinas = 0 % o 100 %) se mapea correctamente independientemente del escalado. El desastre llega cuando apuntas a una posición absoluta — un botón, un icono, un píxel concreto — que no es una proporción sencilla del tamaño de pantalla:
| Quieres hacer clic (Físico) | Tu script envía (Lógico @ 150 %) | El SO escala a (Físico) | Resultado |
|---|---|---|---|
| (500, 300) | (500, 300) | (750, 450) | ❌ 250px de error |
| (960, 540) | (960, 540) | (1440, 810) | ❌ 480px de error |
| (1920, 1080) | (1280, 720) | (1920, 1080) | ✅ Correcto |
El problema está claro: si tu script usa coordenadas de un sistema pero la aplicación de destino usa otro, cada clic está desplazado por el factor de escalado. El offset empeora cuanto más te alejas de (0, 0).
Caso real: Usas PyAutoGUI para hacer clic en un botón en la posición lógica (500, 300) de una pantalla al 150 %. Tu script no es consciente del DPI, así que pyautogui.position() devuelve (500, 300). Pero el botón está realmente en la posición física (750, 450). Tu clic aterriza en (750, 450) — lo cual es incorrecto si el botón pertenece a una aplicación consciente del DPI como Chrome que se posiciona usando coordenadas físicas.
La solución: SetProcessDPIAware y la conciencia DPI
La solución es una sola llamada a la API — dile a Windows que tu aplicación entiende el alto DPI y quiere píxeles físicos:
// C / C++ (Windows API)
SetProcessDPIAware();
// C# (.NET)
[DllImport("user32.dll")]
static extern bool SetProcessDPIAware();
SetProcessDPIAware();
// Python (ctypes)
import ctypes
ctypes.windll.user32.SetProcessDPIAware()
// Python (recomendado para Windows más recientes)
import ctypes
ctypes.windll.shcore.SetProcessDpiAwareness(2) // PROCESS_PER_MONITOR_DPI_AWARE
// Python (recomendado para Windows 10 1703+ y Windows 11)
import ctypes
DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 = ctypes.c_void_p(-4)
ctypes.windll.user32.SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2)
Tras hacer esta llamada, las funciones de coordenadas devuelven valores de píxeles físicos en lugar de lógicos. pyautogui.size() devolverá 3840×2160 en lugar de 2560×1440. pyautogui.position() devolverá posiciones reales de píxeles. Y tus clics aterrizarán exactamente donde quieres.
¿Qué llamada debes usar?
| API | Comportamiento | Mejor para |
|---|---|---|
SetProcessDPIAware() | Conciencia DPI a nivel de sistema. Obtiene la resolución física del monitor principal. | Configuraciones de un solo monitor con un único factor de escalado. |
SetProcessDpiAwareness(2) | Conciencia DPI por monitor. Obtiene la resolución física real de cada monitor. | Configuraciones multimonitor con DPI mixto (Windows 8.1+). |
SetProcessDpiAwarenessContext(-4) | Conciencia DPI por monitor V2. Igual que la anterior, además corrige bugs de escalado de la barra de título y áreas no cliente en configuraciones con DPI mixto. | Recomendado para Windows 10 1703+ y Windows 11. Consulta nuestra guía de coordenadas multimonitor. |
Manifiesto de aplicación (sin necesidad de código)
Si estás construyendo una aplicación de Windows, puedes declarar la conciencia DPI en tu archivo de manifiesto en lugar de llamar a la API:
<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<asmv3:application>
<asmv3:windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true/pm</dpiAware>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
Para la solución completa específica de PyAutoGUI con soporte multimonitor y offsets de región de captura, consulta nuestra guía de coordenadas con PyAutoGUI.
Multimonitor con DPI mixto: cuando las cosas se complican de verdad
Dos monitores, factores de escalado distintos — pongamos un portátil 4K al 150 % y un monitor externo de 1080p al 100 %. La transformación de coordenadas cambia según mueves el cursor entre pantallas:
- En el monitor de 1080p (100 %): lógica = física. Sin offset.
- En la pantalla del portátil 4K (150 %): las coordenadas lógicas se dividen entre 1,5. Un clic físico en (2880, 1620) se reporta como (1920, 1080) a las aplicaciones no conscientes del DPI.
- Cuando arrastras una ventana de un monitor al otro, Windows reescala dinámicamente el espacio de coordenadas. Las aplicaciones no conscientes del DPI pueden renderizarse borrosas o con el tamaño incorrecto.
Esta configuración es un dolor para la automatización. Pero la solución es siempre la misma: llama a SetProcessDpiAwareness(2) para obtener conciencia DPI por monitor, y obtendrás las coordenadas físicas reales del monitor en el que esté tu cursor. Los cálculos completos de coordenadas para configuraciones con DPI mixto están en nuestra guía de coordenadas multimonitor.
Preguntas frecuentes
¿macOS tiene el mismo problema de escalado DPI?
En cierta medida, pero macOS lo gestiona de forma más elegante. Las pantallas Retina tienen un factor de escalado base de 2×, y las aplicaciones reciben coordenadas en "puntos" (píxeles lógicos). Sin embargo, los usuarios pueden elegir modos de pantalla como "Más espacio" o "Texto más grande" en Configuración del Sistema, lo que resulta en factores de escalado efectivos como 1,5× o 2,4× — tu devicePixelRatio del navegador reflejará esto. La mayoría de herramientas de automatización de Mac — AppleScript, Hammerspoon — gestionan la conversión automáticamente, así que te encuentras el problema del offset mucho menos a menudo en macOS.
¿Y en Linux?
Los servidores gráficos de Linux (X11 y Wayland) gestionan el escalado DPI de forma diferente según el compositor y el entorno de escritorio. En X11, el escalado se gestiona a menudo por aplicación usando Xft.dpi o variables de entorno. En Wayland, el compositor gestiona el escalado. El comportamiento de las coordenadas varía enormemente — no existe un equivalente universal a SetProcessDPIAware(). Prueba tus scripts en tu configuración específica de Linux.
¿Por qué PyAutoGUI devuelve un tamaño de pantalla incorrecto?
pyautogui.size() devuelve la resolución lógica por defecto en Windows. En una pantalla 4K al 150 % de escalado, devuelve 2560×1440 en lugar de 3840×2160. Llama a ctypes.windll.user32.SetProcessDPIAware() antes de importar PyAutoGUI y devolverá la resolución física real. Consulta nuestra guía de coordenadas con PyAutoGUI para la configuración completa.
¿Cómo compruebo mi factor de escalado actual de Windows?
Haz clic derecho en el escritorio → Configuración de pantalla → busca Escala y diseño. El porcentaje que aparece (100 %, 125 %, 150 %, 200 %) es tu factor de escalado. Divídelo entre 100 para obtener el multiplicador. O usa nuestra herramienta de arriba — detecta tu DPR automáticamente.
¿Puedo simplemente poner el escalado al 100 % y evitar todo esto?
Claro, pero en un monitor 4K todo se verá diminuto. Una pantalla 4K de 27 pulgadas al 100 % te da unos 140 PPI — legible pero poco agradable para uso prolongado. Arreglas un problema (las coordenadas) y creas otro (fatiga visual). Hacer que tus scripts sean conscientes del DPI es la mejor opción.
Relacionado: Quieres verificar tus coordenadas entre plataformas? Nuestro tutorial de coordenadas muestra como el escalado DPI afecta cada metodo.