Interaction to Next Paint (INP): What It Is, How to Measure and Improve It
The complete guide to understanding, measuring, and optimizing Interaction to Next Paint, the Core Web Vital that measures page responsiveness

Interaction to Next Paint (INP) is a Core Web Vital that measures how quickly a webpage responds to user interactions such as clicks, taps, and key presses. INP captures the full latency from user input through JavaScript processing to the final visual update on screen. A good INP score is 200 milliseconds or less at the 75th percentile. INP replaced First Input Delay (FID) as a Core Web Vital in March 2024.
Table of Contents!
- What is Interaction to Next Paint (INP)?
- INP vs FID: What Changed and Why
- Which Interactions Does INP Measure?
- The Three Phases of an INP Interaction
- What Are Good and Bad INP Scores?
- How to Measure Interaction to Next Paint (INP)
- How to Improve Interaction to Next Paint
- Debugging INP with the Long Animation Frames (LoAF) API
- Case Studies: INP Improvements in Production
- What Real-World Data Shows About INP
- Frequently Asked Questions
- Related Deep Dives
What is Interaction to Next Paint (INP)?
Interaction to Next Paint (INP) is a Core Web Vital metric that measures the responsiveness of a webpage throughout a user's entire visit. Unlike its predecessor First Input Delay (FID), which only measured the delay before the first interaction's event handler began, INP evaluates every interaction a user makes with the page and reports a single value that represents the page's overall responsiveness.
Every time a user clicks a button, taps a link, presses a key on the keyboard, or interacts with a custom control, the browser measures the total time from the moment of input to when the next frame is painted on screen. INP selects one of the slowest of these interactions as the page's responsiveness score. For pages with fewer than 50 total interactions, INP reports the single worst interaction. For pages with many interactions, INP typically uses the 98th percentile to filter out occasional outliers.
A low INP means the page reliably responds to user input in a timely manner. A high INP means the page feels sluggish, unresponsive, or "janky" because the browser cannot process interactions and update the screen quickly enough.
INP vs FID: What Changed and Why
INP officially replaced First Input Delay (FID) as a Core Web Vital in March 2024. Google retired FID because it had two fundamental limitations that made it an incomplete measure of page responsiveness.
First, FID only measured the first interaction on a page. If a user's first click was fast but subsequent interactions were slow, FID would report a passing score despite the poor experience. INP measures all interactions throughout the session, providing a far more accurate picture of real responsiveness.
Second, FID only measured the input delay phase, meaning it captured the time the browser spent waiting before starting to process the event. It completely ignored the time spent executing event handler code (processing time) and the time needed to paint the visual result on screen (presentation delay). INP captures all three phases, giving developers a complete view of interaction latency.
| Aspect | First Input Delay (FID) | Interaction to Next Paint (INP) |
|---|---|---|
| Status | Retired (March 2024) | Active Core Web Vital |
| Interactions measured | First interaction only | All interactions throughout the session |
| Phases captured | Input delay only | Input delay + processing time + presentation delay |
| "Good" threshold | 100ms | 200ms |
| Reporting method | Single worst value | 98th percentile (or worst if fewer than 50 interactions) |
The transition from FID to INP caused a roughly 5 percentage point drop in mobile Core Web Vitals pass rates, according to the HTTP Archive Web Almanac 2024. This happened because many sites that appeared responsive under FID had slow later interactions that INP now captures.
Which Interactions Does INP Measure?
INP only measures interactions that involve discrete user input that the browser can observe through event handlers. Understanding which interactions count is essential for accurate debugging and optimization.
Interactions that count toward INP
- Mouse clicks (including clicks on buttons, links, checkboxes, and custom controls)
- Taps on touchscreens (equivalent to clicks on mobile devices)
- Key presses on a physical or on-screen keyboard (including typing in form fields, pressing Enter, using keyboard shortcuts)
Interactions that do NOT count toward INP
- Scrolling does not count because it is handled by the browser's compositor thread and does not typically block the main thread
- Hovering (mouseover) does not count because hovering is a continuous pointer state, not a discrete user interaction
- Drag gestures do not count, although the initial pointerdown that begins a drag can trigger an INP entry
- CSS transitions and animations that occur without user input are not interactions
A common misconception is that scrolling affects INP. It does not. However, if your page uses JavaScript-based scrolling instead of native browser scrolling, those JavaScript scroll handlers can trigger event callbacks that the browser measures as interactions. This is one reason why native CSS scrolling consistently outperforms JavaScript scrolling for responsiveness.
The Three Phases of an INP Interaction
Every interaction measured by INP consists of three sequential phases. The total INP value is the sum of all three. Understanding each phase is critical because the optimization strategy differs for each one.

1. Input Delay
The input delay is the time between when the user interacts with the page and when the browser begins executing the associated event handlers. This delay occurs because the browser's main thread may be busy with other work, such as parsing JavaScript, running previously scheduled tasks, or processing other event callbacks.
Input delay is especially problematic during the page loading phase when many scripts are parsing and executing simultaneously. CoreDash data shows that interactions during the loading phase have a p75 INP of 132ms, compared to just 50ms for interactions after page load is complete. That is a 2.6x difference. Reducing main thread contention during page startup is one of the most effective ways to improve INP.
At the median, input delay is the smallest INP sub-part. But at the 90th percentile, input delay becomes the dominant contributor because long tasks on the main thread can delay event processing by hundreds of milliseconds. The HTTP Archive Web Almanac 2024 found that fewer than 25% of websites keep task duration below the recommended 50ms threshold.
2. Processing Time
The processing time is the total time the browser spends executing all event handler callbacks associated with the interaction. This includes any JavaScript that runs in response to the event, from form validation to state updates to analytics tracking calls.
Processing time accounts for a significant portion of total INP. If an event handler performs expensive DOM operations, makes synchronous API calls, or runs inefficient loops, the processing time will balloon. One common pattern that inflates processing time is running non-essential code (such as analytics events or third-party tag callbacks) inside the same event handler as the critical visual update.
3. Presentation Delay
The presentation delay is the time between when all event handlers have finished executing and when the browser presents the next frame containing the visual update. This phase includes style recalculation, layout computation, painting, and compositing.
At the median, presentation delay is the largest INP sub-part because every interaction requires at least one rendering pass. Pages with a large or deeply nested DOM take longer to recalculate styles and perform layout. Single Page Applications that re-render large component trees after state changes are particularly susceptible to high presentation delay.
What Are Good and Bad INP Scores?
To pass the Core Web Vitals assessment for the Interaction to Next Paint metric, the 75th percentile of all interactions recorded in the field must stay below 200 milliseconds:
- An INP below or at 200 milliseconds means that your page has good responsiveness.
- An INP between 200 and 500 milliseconds means that your page's responsiveness needs improvement.
- An INP above 500 milliseconds means that your page has poor responsiveness.

It is important to understand that INP uses the 75th percentile, not the average. This means that 75% of your real users must experience interactions faster than 200ms. The 75th percentile methodology ensures that the metric reflects the experience of users on slower devices and connections, not just those with high-end hardware.
How to Measure Interaction to Next Paint (INP)
The Interaction to Next Paint can only be measured with field tools that capture real user interactions. Unlike lab metrics that simulate a single page load, INP requires actual visitors clicking, tapping, and typing on your pages. There is no way to get a meaningful INP score from a synthetic test because INP depends on real human behavior.
Get the Official INP Metrics
You can get the official INP metrics from PageSpeed Insights or the CrUX dashboard and Google BigQuery. PageSpeed Insights reports the 75th percentile score based on the last 28 days of Chrome user data. Google BigQuery provides more historical context and allows custom queries across the entire CrUX dataset.
Google Search Console also reports INP issues under the Core Web Vitals section, grouping affected URLs and flagging pages that need improvement or have poor responsiveness.
Track INP with Real User Monitoring
While the official CrUX dataset is the definitive source for Core Web Vitals scores, it is highly anonymized and does not support real-time monitoring or detailed filtering. That is why web performance professionals rely on Real User Monitoring (RUM) tools like CoreDash to get actionable, real-time INP data. RUM tools collect INP measurements from every page load, attribute them to specific elements, load states, and device types, and allow you to diagnose exactly which interactions are causing problems.
Measure INP for the Current Session
The simplest way to debug INP during development is through Chrome DevTools. Open the Performance panel and use "timespan" mode in Lighthouse to record interactions and see their latency. You can also use the Core Web Vitals Visualizer extension, which overlays INP scores on the page as you interact with it.
For hands-on debugging, use the Google Web Vitals JavaScript Library to log individual interactions to the console:
Log the INP to the console with the Web Vitals JavaScript library
<script type="module">
import {onINP}
from 'https://unpkg.com/web-vitals@4/dist/web-vitals.attribution.js?module';
onINP(console.log);
</script>
How to Improve Interaction to Next Paint
Improving the Interaction to Next Paint requires optimizing all three phases: input delay, processing time, and presentation delay. Your page might respond instantly to most interactions, but if even one interaction is slow, it can define the entire INP score. That is why a systematic approach is necessary.
PageSpeed TIP: most of the time the INP will be much worse when a user interacts with the page during the startup stage of page loading. That is why, when debugging the INP, it makes sense to log all interactions as well as the page loading state!
1. Minimize Input Delay: Prevent Long Tasks on the Main Thread
Usually any page is less responsive during the page startup phase, when most main thread work happens (parsing, decoding, rendering, and scripting). To keep the main thread as free as possible:
- Remove unused code. Use tree shaking to strip dead code and code splitting to break your bundle into smaller chunks that load on demand. Audit your code coverage using Chrome DevTools to identify scripts that load but never execute.
- Load non-essential code during browser idle time. Do you really need a chat widget during the first 500ms of page load? Schedule non-critical scripts with
requestIdleCallback()to run only when the browser is idle. - Identify and rewrite slow scripts that consume excessive CPU resources. Use the Chrome Performance panel to find scripts with long execution times and target them for optimization.
- Keep your page easy to render. Avoid large DOM sizes, excessive images, too many videos, and CPU-intensive CSS animations.
- Use async and defer on script tags to prevent JavaScript from blocking the HTML parser. Consider deferring non-critical JavaScript entirely until after the page has become interactive.
Break Up Long Tasks with scheduler.yield()
JavaScript runs on the browser's main thread using a "run to completion" model: once a task starts, it blocks the main thread until it finishes. Long tasks (over 50ms) prevent the browser from responding to user input. The scheduler.yield() API allows you to explicitly create yield points within long-running code, giving the browser an opportunity to process pending user interactions before continuing.
async function yieldToMain() {
if ('scheduler' in window && 'yield' in window.scheduler) {
return await window.scheduler.yield();
}
// Fallback for browsers without scheduler.yield()
return new Promise((resolve) => {
setTimeout(resolve, 0);
});
}
// Usage: break up a long task into smaller chunks
async function processLargeDataSet(items) {
for (let i = 0; i < items.length; i++) {
processItem(items[i]);
// Yield every 5 items to let the browser handle user input
if (i % 5 === 0) {
await yieldToMain();
}
}
} Defer Non-Critical Work with requestIdleCallback
Use requestIdleCallback() to schedule non-essential tasks (analytics, telemetry, prefetching) for when the browser is idle. This keeps the main thread clear for user interactions and directly reduces input delay.
// Instead of running analytics synchronously:
document.querySelector('.cta-button').addEventListener('click', (e) => {
// Critical: update the UI immediately
showConfirmation();
// Non-critical: send analytics during idle time
requestIdleCallback(() => {
sendAnalyticsEvent('cta_clicked', { page: location.pathname });
}, { timeout: 2000 });
}); Use Passive Event Listeners
For events that do not need to call preventDefault(), mark your event listeners as passive. This tells the browser it does not need to wait for your handler to decide whether to cancel the default behavior, allowing smoother scrolling and faster touch response.
// Passive listener: browser does not wait for preventDefault()
document.addEventListener('touchstart', handleTouch, { passive: true });
document.addEventListener('wheel', handleWheel, { passive: true }); 2. Minimize Processing Time: Provide Immediate Feedback
When a visitor performs an action like submitting a form or adding an item to a basket, do not wait for the server-side confirmation before updating the UI. Provide immediate visual feedback ("Submitting your form...", "Adding item to basket...") and then complete the operation in the background.
Also, yield to the main thread as soon as possible after the critical visual update. Because JavaScript follows a "run to completion" model, it blocks the main thread until all code in the callback has executed. You can manually create a yield point where the browser can update the layout and then continue running the remaining non-critical code.
const formfeedbackEl = document.getElementById("formfeedback");
const formEl = document.getElementById("form");
formEl.addEventListener("submit", (evt) => {
evt.preventDefault();
formfeedbackEl.innerText = "Submitting form ... please hold on";
let headers = new Headers({ Accept: "application/json" });
let formData = new FormData(formEl);
fetch("/form-endpoint", { method: "POST", headers, body: formData })
.then(function (response) {
return response.json();
})
.then(function (jsonData) {
formEl.reset();
formfeedbackEl.innerText = jsonData.message;
});
setTimeout(other_code_that_needs_to_run(), 0);
}); 3. Minimize Presentation Delay: Keep Things Simple
When the page needs to update after an interaction, the browser must recalculate styles, perform layout, paint the changed pixels, and composite the result. The complexity and size of your DOM directly determines how long this rendering work takes.
Some poorly optimized SPA environments re-render far too much content after each interaction. For example, when updating a counter, make sure you update only the counter element, not the entire component tree.
Follow these two golden rules for faster rendering:
- Keep the DOM small and simple. It is much easier for a browser to render a page with fewer DOM elements (HTML nodes) than a page with deeply nested, complicated DOM structures. Aim for fewer than 1,400 DOM elements total, and avoid nesting deeper than 32 levels.
- Use content-visibility to lazy-render off-screen content. The
content-visibility: autoCSS property speeds up initial rendering by deferring the rendering of off-screen content until the user scrolls near it.
/* Apply content-visibility to off-screen sections */
.below-the-fold {
content-visibility: auto;
contain-intrinsic-size: auto 500px;
} Debugging INP with the Long Animation Frames (LoAF) API
The Long Animation Frames (LoAF) API is a powerful tool for diagnosing INP issues. It provides detailed information about frames that take longer than 50ms to render, including script attribution data that tells you exactly which scripts are contributing to slow interactions.
Unlike the older Long Tasks API, LoAF captures rendering time as well as script execution time, making it particularly useful for diagnosing presentation delay issues. LoAF entries include the frame duration, the blocking duration, and an array of script entries that show the source URL, function name, and execution time of each script that ran during the frame.
// Observe Long Animation Frames to find INP bottlenecks
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// Only look at frames longer than 100ms
if (entry.duration > 100) {
console.log('Long frame:', entry.duration + 'ms');
// Log each script that contributed
for (const script of entry.scripts) {
console.log(
'Script:', script.sourceURL,
'Function:', script.sourceFunctionName,
'Duration:', script.duration + 'ms'
);
}
}
}
});
observer.observe({ type: 'long-animation-frame', buffered: true }); RUM tools like CoreDash integrate LoAF data automatically, correlating long animation frames with specific user interactions so you can identify exactly which script, on which page, for which type of interaction, is causing your worst INP scores.
INP and LCP: The Long Task Connection
Long tasks on the main thread affect both INP and Largest Contentful Paint (LCP). A JavaScript task that blocks the main thread for 200ms delays event processing (worsening INP) and also delays the browser from rendering the LCP element (worsening LCP). When you optimize your main thread by breaking up long tasks, deferring non-critical JavaScript, and reducing script execution time, you improve both metrics simultaneously.
Case Studies: INP Improvements in Production
redBus: 80 to 100% Mobile Conversion Improvement
redBus, one of the world's largest online bus ticketing platforms, invested in Core Web Vitals optimization across their global markets. Their focus on reducing JavaScript execution time and optimizing event handlers contributed to an 80 to 100% improvement in mobile conversion rates across their global markets. The improvements were driven by a combination of reducing main thread blocking time, optimizing third-party script loading, and implementing code splitting to reduce the amount of JavaScript parsed during page startup.
Preply: INP from 250ms to 185ms, $200K per Year in Estimated SEO Savings
Preply, an online language tutoring platform, improved their Home page INP from approximately 250ms to 185ms and their Search page INP from approximately 250ms to 175ms. The team achieved these gains by profiling their React application, identifying and eliminating unnecessary re-renders, and deferring non-critical event callbacks. The improved Core Web Vitals scores correlated with higher search rankings, translating to an estimated $200,000 per year in organic search value.
What Real-World Data Shows About INP
The Mobile-Desktop INP Gap
CoreDash data reveals that mobile INP (131ms at p75) is 2.8 times worse than desktop INP (48ms at p75). This is the largest device gap of any Core Web Vital metric. Mobile devices have slower processors, less memory, and higher network latency, all of which contribute to longer main thread blocking times and slower event processing. On desktop, 95.6% of interactions achieve a "good" INP score, while on mobile that figure drops to 88.0%. Mobile users also experience 5 times more "poor" INP events (9.6% vs 1.9%).
Keyboard vs Pointer Interactions
CoreDash data shows that keyboard interactions (75ms p75) are 56% slower than pointer interactions (49ms p75). Keyboard events also have significantly more poor experiences: 7.4% of keyboard interactions result in poor INP, compared to just 1.4% for pointer interactions. This gap is likely because keyboard events, especially in form fields, trigger more complex processing such as input validation, autocomplete suggestions, and state updates.
During-Load vs Post-Load Interactions
Interactions that occur during page load have dramatically higher INP than those after the page has fully loaded. CoreDash data shows that interactions during the "loading" phase have a p75 INP of 132ms, compared to just 50ms for post-load interactions. That is a 2.6 times difference. Even interactions during the "dom-content-loaded" phase (75ms) show elevated INP because async scripts and sub-resources are still being processed. This data strongly supports the recommendation to defer non-critical JavaScript to reduce main thread contention during page startup.
Global INP Pass Rates
According to the HTTP Archive Web Almanac 2024, 74% of all mobile pages achieve a "good" INP score (up from 55% in 2022). However, only 53% of the top 1,000 most-visited websites pass INP. High-traffic websites tend to have more complex JavaScript, more third-party scripts, and more intricate DOM structures, all of which contribute to worse responsiveness. On desktop, 97% of pages achieve good INP scores, highlighting the enormous mobile-desktop performance divide. The median Total Blocking Time in lab tests is 67ms on desktop but 1,209ms on mobile.
Frequently Asked Questions
What is a good INP score?
A good INP score is 200 milliseconds or less at the 75th percentile. This means that at least 75% of all user interactions on the page must complete in under 200ms. Scores between 200ms and 500ms need improvement, and scores above 500ms are considered poor. Google uses this threshold for the Core Web Vitals assessment that feeds into search ranking signals.
What replaced First Input Delay (FID)?
Interaction to Next Paint (INP) replaced First Input Delay (FID) as a Core Web Vital in March 2024. INP is a more complete metric because it measures all interactions throughout a page visit (not just the first one) and captures the full interaction lifecycle including input delay, processing time, and presentation delay (not just the input delay that FID measured).
Does scrolling affect INP?
No, scrolling does not affect INP. Scroll events are handled by the browser's compositor thread, which operates independently from the main thread. INP only measures discrete user interactions: clicks, taps, and key presses. However, if your page uses JavaScript-based scrolling (for example, custom smooth scroll libraries), those JavaScript handlers can trigger event callbacks that do count toward INP. Using native CSS scroll behavior avoids this problem entirely.
What interactions does INP measure?
INP measures three types of discrete user interactions: mouse clicks (including clicks on buttons, links, and custom controls), touchscreen taps (the mobile equivalent of clicks), and keyboard key presses (including typing in form fields and pressing navigation keys). INP does not measure scrolling, hovering, dragging, or CSS animations. For each interaction, INP captures the total time from user input through event handler processing to the next visual frame painted on screen.
Why is my INP worse on mobile?
Mobile devices have significantly slower processors, less available memory, and higher network latency compared to desktops. These hardware constraints mean that JavaScript takes longer to execute on mobile, the main thread is blocked more frequently, and rendering requires more time. CoreDash data shows that mobile INP (131ms at the 75th percentile) is 2.8 times worse than desktop INP (48ms). To improve mobile INP, focus on reducing JavaScript execution time, breaking up long tasks, and minimizing DOM complexity.
Related Deep Dives
This hub page covers the fundamentals of Interaction to Next Paint. For in-depth guidance on specific aspects of INP optimization, explore these dedicated articles:
- Find and Fix INP Issues: A step-by-step diagnostic methodology using Search Console, RUM data, and Chrome DevTools to identify exactly which interactions are causing your worst INP scores.
- INP Input Delay: Deep dive into the first phase of INP. Learn how long tasks on the main thread block event processing and how to minimize input delay with task scheduling, code splitting, and web workers.
- INP Processing Time: Deep dive into the second phase of INP. Learn how to optimize event handler callbacks, prioritize critical code, defer non-essential work, and use React concurrency features to reduce processing time.
- INP Presentation Delay: Deep dive into the third phase of INP. Learn how DOM size, layout thrashing, and client-side rendering contribute to slow visual updates and how to reduce presentation delay.
You may also find these PageSpeed optimization guides helpful for improving INP:
Performance is a Feature.
Treating speed as an afterthought fails. Build a performance culture with a dedicated 2-sprint optimization overhaul.
- 2-Sprint Overhaul
- Culture Building
- Sustainable Speed

