INP en Core Web Vitals: qué es y cómo mejorarlo

Qué mide el INP, en qué se diferencia del FID y cuál de las tres fases corregir primero.

  • Bueno ≤ 200 ms
  • Necesita mejorar ≤ 500 ms
  • Malo > 500 ms
Arjen Karel
Actualizado el · 13 min de lectura
Compartir

¿Qué es Interaction to Next Paint (INP)?

Interaction to Next Paint (INP) es el Core Web Vital (CWV) de capacidad de respuesta: el tiempo transcurrido desde un clic, tap o pulsación de tecla hasta el siguiente fotograma en pantalla, medido en la interacción más lenta de una visita a la página. Un buen INP es de 200 milisegundos o menos en el percentil 75.

El visitante percibe un mal INP como un botón que no reacciona por un momento: toca el menú, no cambia nada y vuelve a tocar. El INP es uno de los tres Core Web Vitals, junto con el LCP y el CLS, y Google los utiliza como señal de posicionamiento.

En una página donde se hace mucho clic, el INP descarta un valor atípico por cada 50 interacciones. Una visita sin un solo clic, tap o pulsación de tecla no tiene INP.

INP vs. FID: ¿qué cambió en marzo de 2024?

El INP sustituyó a First Input Delay (FID) como Core Web Vital el 12 de marzo de 2024. El FID solo medía la espera antes de que el navegador empezara a procesar la primera interacción de una visita. El INP mide cada interacción, desde el input hasta el siguiente fotograma en pantalla.

Por tanto, el INP también contabiliza el trabajo que el FID nunca vio: los event handlers que se ejecutan tras la espera, y el cálculo de estilo, layout y paint antes de que la pantalla cambie. Un clic cuyo handler empieza tras 10 ms y luego se ejecuta durante 300 ms pasaba el FID y suspende el INP.

First Input Delay (FID)Interaction to Next Paint (INP)
InteraccionesLa primeraCada clic, tap y pulsación de tecla
Qué se mideInput delayInput delay, processing duration y presentation delay
Bueno100 ms o menos200 ms o menos
Valor por visita a la páginaEl retraso del primer inputLa interacción más lenta

¿Qué interacciones mide el INP?

El INP mide clics, taps y pulsaciones de tecla, incluidos los teclados en pantalla. Cada pulsación al escribir en el campo de un formulario es una interacción independiente. El scroll, el hover y el zoom no cuentan como interacciones.

Aun así, el código de scroll puede ralentizar un clic. Un clic en un enlace ancla que inicia una animación de scroll con JavaScript es una interacción, y el código de scroll se ejecuta dentro de ella. Un handler que se ejecuta en cada evento de scroll mantiene ocupado el main thread, por lo que un tap que entra mientras el visitante hace scroll tiene que esperar. scroll-behavior: smooth en CSS proporciona scroll suave sin ningún script.

Las tres fases de una interacción de INP (subpartes)

Cada interacción que mide el INP tiene tres subpartes sucesivas: input delay, processing duration y presentation delay. El INP de una interacción es la suma de las tres, y la subparte más larga marca por dónde empezar el fix. Chrome DevTools muestra las tres en el desglose de INP (INP breakdown) de una traza.

Chrome DevTools Performance panel, one tap on a test page: INP 379 ms, INP breakdown with input delay 1 ms, processing duration 369 ms and presentation delay 9 ms

Un tap en el filtro «All» de una página de prueba montada como portal de alquiler vacacional, registrado en el panel Performance: 369 de los 379 ms corresponden a processing duration, en su mayor parte layout que el click handler fuerza una y otra vez. Sin la grabación, ese mismo tap tarda 320 ms: la propia traza ralentiza el tap.

  • Input delay: el input espera a que termine la tarea que ya se está ejecutando en el main thread. Normalmente esa tarea es un script que corre durante la carga: un tag manager, un widget de chat o un framework que todavía se está hidratando.
  • Processing duration (también llamado processing time): se ejecutan los event handlers de la interacción. Un handler es lento cuando hace demasiado a la vez: por ejemplo, un tag de analítica que se dispara con el clic, o un script que lee las dimensiones de los elementos tras cada cambio y fuerza el layout una y otra vez.
  • Presentation delay: tras los handlers, el navegador recalcula estilos y layout, y luego pinta el siguiente fotograma. Un DOM grande ralentiza esta fase, igual que un re-render que modifica gran parte de la página. Otras tareas que se ejecuten antes de ese fotograma también cuentan aquí.

Core Web Vitals Visualizer: INP 480 ms for a pointerdown while the page was loading, with the INP breakdown input delay 2 ms, processing time 0 ms and presentation delay 478 ms

Un tap mientras la página aún cargaba, en el Core Web Vitals Visualizer. El handler tardó 0 ms; el siguiente fotograma esperó 478 ms por el trabajo de carga de la página, y cualquier espera tras el handler cuenta como presentation delay.

¿Qué es una buena puntuación de INP?

Un buen INP es de 200 milisegundos o menos. Entre 200 y 500 milisegundos necesita mejorar, y más de 500 milisegundos es deficiente. Google toma el percentil 75 (p75) de las cargas de página, por separado para móviles y desktop.

INP performance bar: GOOD ≤200 ms, NEEDS IMPROVEMENT 200 to 500 ms, POOR >500 ms

En el p75, tres de cada cuatro cargas de página deben tener un INP de 200 ms o menos, incluidas las de móviles lentos. Los móviles fallan primero: un procesador más lento ejecuta el mismo JavaScript durante más tiempo, por lo que el main thread está ocupado con más frecuencia cuando el visitante hace tap.

En CoreDash, el INP en móviles fue aproximadamente el doble que en desktop. La tabla agrupa las cargas de página de 149 proyectos entre el 11 de octubre y el 7 de noviembre de 2026:

INP en p75MóvilesDesktop
Todas las interacciones170 ms89 ms
Durante la carga de la página285 ms125 ms
Después de la carga158 ms84 ms

En esos mismos datos, las pulsaciones de tecla en desktop fueron más lentas que los clics y taps: 121 frente a 85 ms.

Según el State of Web Vitals, el 91,8% de los sitios tiene un buen INP en móviles.

Cómo medir Interaction to Next Paint (INP)

El INP que utiliza Google procede de visitantes reales en Chrome: el Chrome UX Report (CrUX), que muestran PageSpeed Insights y Search Console. Una herramienta de real user monitoring (RUM) te indica qué clic y en qué página es lento, y Chrome DevTools muestra el porqué.

Search Console y PageSpeed Insights

El informe de Core Web Vitals en Search Console agrupa por problema las URL que suspenden el INP, con URL de ejemplo para cada grupo. "INP issue: longer than 200ms (mobile)" significa que las visitas desde móviles a ese grupo de URL similares tienen un INP superior a 200 ms en el percentil 75; "INP issue: longer than 500ms (mobile)" significa más de 500 ms. El sitio puede parecerte rápido aunque el informe diga que suspende: muchos visitantes usan móviles más lentos que el tuyo y también hacen tap mientras la página todavía está cargando. PageSpeed Insights muestra el INP en p75 durante los últimos 28 días para una URL concreta, o para todo el sitio cuando esa URL tiene muy pocas visitas en Chrome. Cualquier fix tarda en reflejarse en ambos: Search Console tarda hasta 28 días.

Google Search Console, Core Web Vitals report on mobile for acme-inp.com: INP issue: longer than 200ms (mobile), need improvement, 1,240 affected URLs, rising over three months

URL afectadas por día para un problema de INP en Search Console.

Real user monitoring

CrUX ofrece un único número por URL o grupo de URL. Un script de RUM en tu propio sitio mide cada visita. En CoreDash miro primero el INP en p75 para móviles, desglosado por el elemento clicado y por el estado de carga.

Las herramientas de RUM ahora también miden el INP en Safari y Firefox. CrUX, y con él Google, solo contabiliza Chrome, por lo que las cifras pueden diferir.

Tus propios clics en Chrome DevTools

Abre el panel Performance en Chrome DevTools. Sus métricas en directo muestran el INP de tu sesión a medida que haces clic, con un registro de cada interacción y sus tres subpartes. Aplica una ralentización de CPU de 4x para que el portátil se comporte más como un móvil, y haz clic también mientras la página todavía cargue. Para ver qué se ejecutó, graba una traza mientras haces clic: el track Interactions marca la interacción y el track Main muestra las tareas que tiene debajo. La extensión Core Web Vitals Visualizer muestra este mismo desglose directamente en la página.

La librería web-vitals registra en la consola cada interacción que eleva el INP, junto con el elemento y las subpartes:

<script type="module">
  import {onINP} from 'https://unpkg.com/web-vitals@6/dist/web-vitals.attribution.js?module';
  onINP(console.log, {reportAllChanges: true});
</script>

Lighthouse

Una ejecución normal de Lighthouse no tiene INP: carga la página y nunca hace clic. La métrica de lab data más cercana es el Total Blocking Time (TBT), el tiempo que el main thread estuvo bloqueado durante la carga. El INP suele ser mucho más bajo que el TBT, pero mejorar el TBT también mejorará el INP. Por qué Lighthouse y las field data muestran cifras distintas: Lighthouse frente a field data.

Cómo mejorar el INP

Las interacciones más lentas en móviles determinan el INP. Búscalas en tus field data (Search Console o una herramienta de RUM), revisa su subparte más larga y redúcela: menos JavaScript durante la carga para el input delay, menos trabajo en el event handler para la processing duration y menos que renderizar para el presentation delay. La guía paso a paso de INP va desde el informe de Search Console hasta la línea de código.

WordPress

En un sitio WordPress, empieza por los scripts de plugins que carga cada página, porque cada uno puede hacer esperar a un tap. El Script Manager de Perfmatters y Asset CleanUp descargan los scripts de un plugin en las páginas que no los usan, como los de un plugin de formularios en las páginas de producto. Para lo que siga siendo lento después de eso, pide a un desarrollador una traza: una grabación del tap lento con la CPU ralentizada a 4x y el nombre del script que se ejecuta en él.

Los ajustes para retrasar JavaScript (Delay JavaScript execution en WP Rocket, Delay JavaScript en Perfmatters, Load JS Deferred configurado como Delayed en LiteSpeed Cache) retienen los scripts hasta la primera interacción y luego los ejecutan todos de golpe. Esto mejora la puntuación en Lighthouse porque Lighthouse nunca interactúa con la página. Un visitante real toca el menú y espera mientras el navegador descarga y ejecuta todo, y el INP registra el tap más lento de la visita. Deja esos ajustes desactivados para el INP.

WP Core Web Vitals, el plugin de corewebvitals.io, difiere los scripts en su orden original y ejecuta analítica, píxeles y widgets de chat tras la carga de la página, sin esperar a un tap.

Shopify

Cada app de Shopify suma tiempo a cada clic: la instalas por una sola funcionalidad y su script se carga en páginas y clics que no tienen nada que ver con ella. En el editor del tema, dentro de App embeds, desactiva las apps una a una y vuelve a medir el tap lento tras cada una. Los app blocks colocados en una sección siguen activos aunque desactives el embed de la app: elimínalos en esa sección. Una app eliminada puede dejar código en los snippets del tema, así que busca su nombre en el tema.

Los ajustes de las apps rara vez cambian lo que se ejecuta durante un clic. Eso lo decide el código del tema: qué hace el botón de añadir al carrito, cuándo se renderiza el drawer del carrito y qué scripts de apps se cargan. Esa parte es trabajo para un desarrollador: el handler de añadir al carrito actualiza primero la pantalla y hace el resto después, y el drawer del carrito solo renderiza lo que ha cambiado.

Input delay: menos JavaScript durante la carga

Un tap durante la carga espera al script que se esté ejecutando en ese momento. El panel Coverage de DevTools muestra qué código se ha ejecutado hasta el momento: un script que sigue prácticamente sin usarse tras hacer clics por la página puede eliminarse, y gran parte de lo que queda puede esperar a que la página haya cargado. ¿De verdad necesitas un widget de chat durante los primeros 500 ms de la carga? Inícialo tras el evento load, cuando el navegador esté inactivo:

window.addEventListener('load', () => {
  const whenIdle = window.requestIdleCallback || ((cb) => setTimeout(cb, 1));
  whenIdle(() => {
    const script = document.createElement('script');
    script.src = '/js/chat-widget.js';
    document.head.appendChild(script);
  });
});

async y defer evitan que un script bloquee el parser de HTML, pero el script sigue ejecutándose durante la carga, por lo que ayudan más al LCP que al INP. Encontrarás otras formas de ejecutar scripts más tarde en 16 métodos para diferir o programar JavaScript.

El navegador espera por los listeners de touchstart o wheel que no sean pasivos antes de hacer scroll en la página. Añadir { passive: true } elimina esa espera, pero como el INP no mide el scroll, no reducirá el INP.

Divide tus propios long tasks (cualquier tarea de más de 50 ms en el main thread) para que el navegador pueda atender un tap en espera entre medias. Devuelve el control al main thread (yield) tras unos 50 ms de trabajo, sin importar cuánto tarde un elemento individual:

function yieldToMain() {
  if (globalThis.scheduler?.yield) {
    return scheduler.yield();
  }
  return new Promise((resolve) => setTimeout(resolve, 0));
}

async function processItems(items) {
  let lastYield = performance.now();
  for (const item of items) {
    processItem(item);
    if (performance.now() - lastYield > 50) {
      await yieldToMain();
      lastYield = performance.now();
    }
  }
}

scheduler.yield() funciona en Chrome y Firefox; Safari se queda con el fallback de setTimeout. Más información en yield al main thread.

Processing duration: actualiza la pantalla primero

A fast event handler does what the visitor sees first and leaves everything else until after the next paint. A tag in the click handler runs before the screen can change. Moved after the update, the visitor sees the result first and the tag still runs:

button.addEventListener('click', () => {
  showConfirmation(); // lo que ve el visitante
  requestAnimationFrame(() => {
    setTimeout(() => {
      // se ejecuta tras pintar el siguiente fotograma
      dataLayer.push({ event: 'cta_click' });
    }, 0);
  });
});

Un requestIdleCallback() en este punto falla en todos los iPhone: Safari no lo admite, por lo que el handler lanza un error después de ejecutar showConfirmation(); el clic parece haber funcionado, pero el evento se pierde. La versión para Tag Manager está en programación de eventos en dataLayer; en el sitio de un cliente, mover dataLayer.push() para después del paint redujo el INP en 100 ms.

En un formulario o un botón de añadir al carrito que espera al servidor, muestra de inmediato en pantalla que el tap funcionó («Añadiendo al carrito...») y deja que la petición termine después.

El clic lento que veo más a menudo es el filtro de productos: el handler actualiza la lista, lee su nueva altura, cambia algo en función de esa altura y vuelve a leerla. Cada lectura tras un cambio obliga al navegador a recalcular el layout dentro del handler. En una página de prueba montada como portal de alquiler vacacional en WordPress, un tap en el filtro «All» tardó 320 ms; 298 ms correspondieron a layout forzado por el script del tema. Haciendo que el script lea todas las alturas primero, o dejando que CSS haga el trabajo del script, ese mismo tap tardó 16 ms, un solo fotograma. Ambos se midieron en Chrome con ancho de móvil y CPU ralentizada a 4x. En Forced reflow tienes el fix para temas, plugins, apps y tu propio código.

Presentation delay: un DOM más pequeño, menos re-renders

Un DOM grande ralentiza cada fotograma posterior a los handlers. Lighthouse lo recoge en «Optimize DOM size»: cómo reducir el tamaño del DOM.

En páginas largas, content-visibility: auto permite al navegador omitir el renderizado de secciones fuera del viewport hasta que el visitante hace scroll cerca de ellas:

.product-reviews,
.site-footer {
  content-visibility: auto;
  contain-intrinsic-size: auto 600px;
}

Asigna a cada una de esas secciones un contain-intrinsic-size cercano a su altura real. Sin él, la sección omitida mide cero píxeles de alto y la barra de scroll pega saltos a medida que las secciones se renderizan.

Algunas single page applications vuelven a renderizar demasiado contenido tras cada interacción: un clic modifica un solo contador y se re-renderiza media página. En React DevTools, «Highlight updates when components render» muestra qué componentes renderiza un clic.

Cómo depurar el INP con la API Long Animation Frames (LoAF)

La API Long Animation Frames (LoAF) reporta cada fotograma que tardó más de 50 ms, junto con los scripts que se ejecutaron en él: el archivo, la función y cuánto tiempo corrió cada uno. Con ella, una interacción lenta en las field data pasa a tener el nombre del script. LoAF funciona en navegadores basados en Chromium (Chrome 123 y posteriores).

new PerformanceObserver((list) => {
  for (const frame of list.getEntries()) {
    if (frame.duration < 100) continue; // solo los fotogramas más lentos
    for (const script of frame.scripts) {
      console.log(script.sourceURL, script.sourceFunctionName,
        Math.round(script.duration) + ' ms');
    }
  }
}).observe({ type: 'long-animation-frame', buffered: true });

Una herramienta de RUM recopila estas entradas en cada visita. En CoreDash, abre INP, Breakdown y agrupa por LOAF: cada fila es un script, con el INP de las interacciones en las que se ejecutó, desglosado en sus tres subpartes. Empieza por el script cuya barra sea más larga en móviles. La guía de la API Long Animation Frames explica cada campo de una entrada.

CoreDash INP subparts by LOAF: p75 INP per script, each split into input delay, processing and presentation.

CoreDash, agrupado por LOAF (desktop): el verde es input delay, el morado processing duration y el azul presentation delay.

¿El tap lento proviene de un script que no has escrito tú, como una app, un tag o un banner de consentimiento, y no sabes cuál eliminar? En una Core Web Vitals power hour revisamos juntos tus field data y una traza de ese tap, y te llevas el fix por escrito.

About the author

Arjen Karel is a web performance consultant and the creator of CoreDash, a Real User Monitoring platform that tracks Core Web Vitals data across hundreds of sites. He also built the Core Web Vitals Visualizer Chrome extension. He has helped clients achieve passing Core Web Vitals scores on over 925,000 mobile URLs.

Arjen Karel

¿Necesitas una web más rápida?

Soy Arjen y llevo 17 años arreglando webs lentas. Si te encuentras con problemas que no puedes resolver por tu cuenta, envíame tu URL y hablamos.

Envíame tu URL
Arjen Karel
Arjen Karel, Consultor de rendimiento web desde 2009

¿Por qué no funciona nuestro fix?

A veces la CDN sigue sirviendo el HTML antiguo, o el fix se metió en la plantilla de desktop y el móvil usa otra. Envíame tu URL y el problema, y te respondo con varias opciones. Primero reviso tus field data, luego dedicamos una hora a tu web, y en menos de un día tienes mis notas por escrito. 350 € sin IVA.

Envíame tu URL

¿No tienes desarrollador para hacer el fix? Hago el trabajo yo mismo, en una copia de tu web.