TL;DR
Interaction to Next Paint (INP) measures how long a page takes to show a visual response after a click, tap or key press, and reports one of the slowest interactions of the visit. Good is 200 ms or less and poor is over 500 ms. Most slow INP comes from long JavaScript tasks, heavy third-party scripts, large DOMs and hydration, and the fix is to break up long tasks, yield to the main thread and load less JavaScript.
Key takeaways
- INP is the time from an interaction to the next frame painted, split into input delay, processing duration and presentation delay.
- Good INP is 200 ms or less at the 75th percentile of real users; poor is over 500 ms.
- INP needs real interactions, so it comes from field data; Total Blocking Time is the closest lab signal.
- Long tasks over 50 ms are the main cause, whether from your code, third-party scripts or hydration.
- Show visual feedback first, then yield to the main thread before doing heavy work.
- Defer third-party tags and shrink the DOM to cut both input delay and presentation delay.
Interaction to Next Paint (INP) measures how long a page takes to show a visual response after someone clicks, taps or presses a key, and reports one of the slowest interactions of the visit. A good INP is 200 ms or less. Most slow interactions come from long JavaScript tasks, and the fix is to do less work on the main thread, or to split it up so the browser can paint in between.
What INP measures
INP times every click, tap and key press during a visit, from the moment of input until the browser paints the next frame. Scrolling and hovering are not counted. At the end of the visit, INP reports the slowest interaction, or close to it on pages with many interactions, where a few extreme outliers are ignored.
Each interaction has three parts:
- Input delay. The time between the input and the moment the event handler starts. It is long when the main thread is busy with something else, such as a script still running from page load.
- Processing duration. The time the event handlers themselves take to run.
- Presentation delay. The time from the handlers finishing until the next frame is painted, including style calculation, layout and paint.
Knowing which part is large tells you where to look. A long input delay points at other work on the main thread. Long processing points at your handler. Long presentation delay points at a large DOM or expensive rendering.
The thresholds
INP became a Core Web Vital in March 2024, replacing First Input Delay. Like the other vitals, it is assessed on real users at the 75th percentile over a rolling 28 days.
| Rating | INP (75th percentile) |
|---|---|
| Good | 200 ms or less |
| Needs improvement | 200 ms to 500 ms |
| Poor | Over 500 ms |
The 75th percentile matters. A page that responds quickly on a fast laptop can still fail if a quarter of visits come from mid-range phones where the same JavaScript runs several times slower.
INP is field-only, so use TBT and long tasks in the lab
INP needs real interactions, so it comes from field data such as the Chrome UX Report. A standard Lighthouse run loads the page without touching it, so it cannot report INP.
The closest lab signal is Total Blocking Time. A long task is any main-thread task that runs for more than 50 ms. TBT adds up the part of each long task beyond 50 ms during page load. A page with high TBT has a busy main thread, and a click that lands during that time waits. TBT is also the largest single weight in the Lighthouse performance score, at 30%, as covered in how the Lighthouse performance score is calculated.
TBT and INP are related but not the same:
- TBT only covers page load. INP covers the whole visit, including a filter click two minutes later.
- TBT measures blocking in general. INP measures the specific interactions people actually use.
- A page can have low TBT and poor INP if one particular handler is slow, such as a search box that re-renders a large list on every key press.
Use TBT to catch heavy pages across the site, and field INP to confirm what users feel. Lab data vs field data goes deeper into why the two sources differ.
How to find slow interactions
Work from the field data down to the code.
- Find the pages. PageSpeed Insights shows field INP for a URL or origin when Chrome has enough data. Search Console’s Core Web Vitals report groups similar URLs with INP issues.
- Reproduce in DevTools. Open the page, set CPU throttling to 4x or 6x slowdown to approximate a phone, and use the Performance panel. It shows INP live as you interact, and a recording shows the long tasks behind each slow interaction.
- Try the likely interactions. Menus, filters, add-to-cart buttons, accordions, tabs, form fields and search boxes are the usual suspects. Also click during load, since that is when input delay is worst.
- Collect real-user detail. The attribution build of Google’s
web-vitalslibrary reports the element interacted with and the input delay, processing and presentation split for slow interactions, so you can see which control is slow for real visitors.
Common causes of slow interactions
- Heavy JavaScript during load. Large bundles parse and execute in long tasks. Any interaction that arrives during that time gets a long input delay.
- Third-party scripts. Tag managers, analytics, A/B testing, chat widgets, ad scripts and session recording all run on the same main thread as your code, and they often attach their own handlers to clicks.
- Hydration. Server-rendered pages built with a JavaScript framework can look ready before they are. Until hydration finishes, clicks either do nothing or wait behind a long task.
- Expensive event handlers. A handler that filters thousands of items, recalculates layout or sends synchronous analytics before updating the screen makes processing duration long.
- Large DOM. Every update to a page with tens of thousands of elements costs more style, layout and paint time, which shows up as presentation delay.
- Layout thrashing. Reading layout values such as
offsetHeightright after changing styles, in a loop, forces the browser to recalculate layout repeatedly.
How to fix INP
Break up long tasks and yield to the main thread
The most effective change is to stop running work in one long block. Do the visible part first, then give the browser a chance to paint, then do the rest.
function yieldToMain() {
if (globalThis.scheduler?.yield) {
return scheduler.yield();
}
return new Promise((resolve) => setTimeout(resolve, 0));
}
filterButton.addEventListener('click', async () => {
showLoadingState(); // visible feedback first
await yieldToMain(); // let the browser paint
await applyFilters(); // heavy work afterwards
await yieldToMain();
sendAnalytics(); // non-urgent work last
});
scheduler.yield() is available in recent versions of Chrome; the setTimeout fallback works everywhere. Apply the same pattern inside long loops: process a batch, yield, continue.
Defer and trim third-party scripts
- Remove tags nobody uses. Old tracking pixels and test scripts tend to pile up in tag managers.
- Load non-essential scripts after the page is interactive, or only when needed, for example a chat widget that loads when someone clicks the chat button.
- Load scripts only on the pages that need them, rather than site-wide.
Reduce DOM size and rendering cost
- Paginate or virtualize long lists so only visible items are in the DOM.
- Use
content-visibility: autoon long, off-screen sections so the browser skips rendering them until they are needed. - Keep the part of the page that changes after an interaction small, so each update touches fewer elements.
Debounce and throttle frequent handlers
For search-as-you-type, wait until typing pauses, often 150 to 300 ms, before filtering or fetching. Throttle handlers for resize and pointer movement. Update the input itself immediately so typing feels instant, and defer the expensive part.
Make hydration cheaper
Ship less JavaScript to the page. Hydrate interactive parts only, rather than the whole page, and delay hydration of components below the fold. Code-split routes so a blog post does not load the checkout bundle.
Cause and fix by phase
| Phase | Typical cause | First fix to try |
|---|---|---|
| Input delay | Long tasks from load, hydration or third parties | Split and defer scripts, load third parties later |
| Processing duration | Heavy work in the event handler | Show feedback, yield, then run the rest |
| Presentation delay | Large DOM, big re-renders, forced layout | Shrink the DOM, content-visibility, avoid layout thrashing |
How to check this across your whole site
Manually, start with field INP in PageSpeed Insights or Search Console to find poor pages, then test their main interactions in DevTools with CPU throttling on. For a wider net, run Lighthouse on a sample of pages from each template and sort by TBT, since a heavy main thread on one product page usually means the same on all of them. Lighthouse only tests one page explains why sampling just the homepage hides these problems.
AiroPages runs Lighthouse on every page on mobile and desktop, groups long-task and JavaScript issues by template, and shows Chrome UX Report field data next to the lab scores where Google has it, so you can see TBT and real-user INP side by side.
Responsiveness is a main-thread budget
INP comes down to one question: is the main thread free when someone interacts? Load less JavaScript, split up the work you keep, give feedback before doing heavy tasks, and keep the DOM small. Then check field INP again after 28 days, because that is the window Google uses to judge the result.
Frequently asked questions
What is a good INP score?
An INP of 200 milliseconds or less is good, between 200 and 500 milliseconds needs improvement, and over 500 milliseconds is poor. Google assesses it at the 75th percentile of real page visits over a rolling 28 days, so most of your visitors need a fast response for the page to pass.
Why does Lighthouse not show INP?
A standard Lighthouse test loads the page without clicking, tapping or typing, so there is no interaction to measure. Lighthouse reports Total Blocking Time instead, which measures how much long tasks block the main thread during load and is the closest lab signal for INP. Real INP comes from field data such as the Chrome UX Report.
What replaced First Input Delay?
Interaction to Next Paint replaced First Input Delay as a Core Web Vital in March 2024. FID only measured the input delay of the first interaction, while INP covers the full time to the next paint for interactions throughout the visit.
What causes a poor INP?
Poor INP is usually caused by long JavaScript tasks that keep the main thread busy, either when the user interacts or in the event handler itself. Common sources are large framework bundles and hydration, third-party scripts such as tag managers and chat widgets, very large DOMs that are slow to re-render, and handlers that do expensive work before updating the screen.
How do I find which interaction is slow?
Start with field data in PageSpeed Insights or Search Console to see which pages have poor INP. Then open the page in Chrome DevTools, set CPU throttling to mimic a phone, and use the Performance panel to record yourself using the page's main controls. For real-user detail, the attribution build of the web-vitals library reports the element and the timing breakdown of slow interactions.
Published