Skip to content
SEO Optimizer is live, Audit on page SEO and AI-search readiness. Try it free
Entrar

How to Fix INP (Interaction to Next Paint)

Featured image for "How to Fix INP (Interaction to Next Paint)"

Interaction to Next Paint (INP) measures how long your page takes to visibly respond after someone clicks, taps or types. Google replaced First Input Delay with INP as a Core Web Vital in March 2024, and it is now the metric most sites fail. A good INP is 200 ms or less; above 500 ms is poor. This guide shows how to fix INP by finding the interaction that is slow and removing the work that blocks it.

Why INP Is Slow (and What You Need to Fix INP)

INP is the time from the user's input to the next frame the browser paints. That time has three parts, and to fix INP you need to know which one is large:

  • Input delay. The main thread is busy with something else (a long task, a third-party script, hydration) when the user clicks, so the event waits in a queue.
  • Processing time. Your event handlers themselves run too long: heavy state updates, synchronous loops, re-rendering a big component tree.
  • Presentation delay. After your code finishes, the browser still has to recalculate styles, lay out and paint. A huge DOM or layout thrashing makes this slow.

Almost every slow INP traces back to one root cause: too much JavaScript running on the main thread in long, unbroken chunks. Any task over 50 ms is a "long task", and while one runs, the page cannot respond to input.

How INP Relates to Total Blocking Time

INP is a field metric: it comes from real users interacting with real pages, so lab tools cannot measure it directly. Total Blocking Time (TBT) is the closest lab proxy. TBT adds up the part of every long task above 50 ms during page load. When you reduce total blocking time, you usually improve INP too, because both are driven by long tasks on the main thread. If your field INP is poor but you have no field data to debug with, work on TBT first.

How to Find the Interaction You Need to Fix

You cannot fix INP by guessing. Find the specific interaction first.

  1. Check field data first. Search Console's Core Web Vitals report and our Core Web Vitals test show whether real users see a poor INP, and on which URL groups.
  2. Reproduce it in DevTools. Open the Performance panel, enable CPU throttling (4x slowdown approximates a mid-range phone), start recording, then click the buttons, menus and form fields that matter. Long tasks show as red-flagged blocks on the Main track.
  3. Log interactions in production. The web-vitals library reports INP with attribution, telling you which element and which event type produced the worst interaction.
lib/reportInp.tsLog the slowest interaction with attribution
import { onINP } from "web-vitals/attribution";

onINP(({ value, attribution }) => {
  // Send to your analytics endpoint
  navigator.sendBeacon("/api/vitals", JSON.stringify({
    inp: Math.round(value),
    target: attribution.interactionTarget,
    type: attribution.interactionType,
    inputDelay: attribution.inputDelay,
    processing: attribution.processingDuration,
    presentation: attribution.presentationDelay,
  }));
});

The three numbers in that attribution map directly to the three parts above, so you know which fix to reach for.

How to Fix INP

1. Break up long tasks

The single most effective way to fix INP is to stop running long tasks. Split work into chunks and yield to the main thread between them so the browser can handle input. scheduler.yield() is built for this, with a setTimeout fallback for browsers that lack it.

lib/yieldToMain.tsYield between chunks of work
export function yieldToMain(): Promise<void> {
  if ("scheduler" in globalThis && "yield" in (globalThis as any).scheduler) {
    return (globalThis as any).scheduler.yield();
  }
  return new Promise((resolve) => setTimeout(resolve, 0));
}

export async function processItems(items: Item[]) {
  for (const item of items) {
    process(item);
    await yieldToMain(); // let pending clicks and taps run
  }
}

2. Do the visible update first, defer the rest

Many teams fix INP with this step alone.

Users judge responsiveness by the first visual change. Update the UI immediately (open the menu, show the spinner, mark the checkbox), then defer analytics calls, network requests and expensive recalculation until after the next paint. In React, startTransition marks non-urgent state updates so urgent ones render first.

components/Filters.tsxKeep the click fast, mark the heavy update as non-urgent
const [checked, setChecked] = useState(false);
const [results, setResults] = useState(all);

function onToggle() {
  setChecked((c) => !c);             // urgent: paints right away
  startTransition(() => {
    setResults(filterLargeList(all)); // non-urgent: can be interrupted
  });
}

3. Ship less JavaScript

Every kilobyte of script has to be parsed, compiled and executed on the main thread, often right when users start interacting. Remove unused code, split bundles by route, and lazy-load widgets that are below the fold or behind a click. Our guide to reducing unused JavaScript covers this in detail, and it is often the quickest way to reduce total blocking time and fix INP together.

4. Tame third-party scripts

Chat widgets, tag managers, A/B testing tools and ad scripts run long tasks you do not control. Load them with defer or after the page is interactive, remove the ones nobody uses, and move what you can off the main thread. See how third-party scripts affect performance for a triage approach.

5. Shrink the DOM and avoid layout thrashing

If attribution shows a large presentation delay, this is where you fix INP.

Presentation delay grows with DOM size. Pages with thousands of nodes make every style recalculation slow. Virtualize long lists, remove hidden markup you never show, and avoid reading layout properties (offsetHeight, getBoundingClientRect) right after writing styles in the same handler, which forces synchronous layout.

6. Debounce input handlers

Search-as-you-type and resize or scroll handlers that do heavy work on every event pile up long tasks. Debounce them so the work runs once the user pauses, and keep the keystroke itself cheap.

How to Check That You Fixed INP

Lab checks tell you quickly whether long tasks and TBT went down. Field INP takes longer: Google's data is a rolling 28-day window, so expect up to four weeks before a fix to INP shows fully in Search Console. Keep logging INP with attribution in production so you see the effect on real users first.

How Scanverra Helps You Fix INP

A Scanverra performance audit reports Total Blocking Time from a lab run and ties it to the causes behind slow interactions: main-thread work, script boot-up time, unused and legacy JavaScript, third-party code, long tasks and DOM size. When Google has enough real-user traffic for your URL, the Core Web Vitals test also shows field INP next to LCP and CLS. Where field data is missing, which is common for low-traffic pages, Scanverra can only show the lab proxy, so confirm INP with your own real-user monitoring. Once you fix INP, pair this guide with fixing LCP and fixing CLS to pass all three Core Web Vitals, and read the Core Web Vitals guide for how they fit together.

FAQ

Perguntas frequentes

200 milliseconds or less at the 75th percentile of page visits is good. Between 200 and 500 ms needs improvement, and above 500 ms is poor.

Find the slowest interaction with the web-vitals attribution build or the DevTools Performance panel, then break up the long task behind it by yielding to the main thread. Cutting unused and third-party JavaScript usually comes next.

Usually, yes. Total blocking time is a lab metric that sums long-task time during load, and INP is driven by the same long tasks. TBT is the best lab proxy when you cannot reproduce field INP directly.

Lab tests run on a fast machine and rarely click anything. Real users on mid-range phones interact with menus, filters and forms after the page loads, when third-party scripts and hydration are still running. Throttle the CPU and test real interactions to reproduce it.

Field data is a rolling 28-day window, so a fix can take up to four weeks to show fully in Search Console and other field-data reports.

Grátis - sem necessidade de cadastro

Check this on your own site

Run a free scan and see exactly where you stand - no sign-up required.

Executar auditoria grátis