Interaction to Next Paint (INP) replaced First Input Delay (FID) as Google's Core Web Vitals responsiveness metric in March 2024 and remains the standard interactivity signal in Search Console and the Chrome User Experience Report (CrUX). While legacy FID measured only the input delay of the very first tap or click on a page, INP observes every discrete click, tap, and keyboard interaction across the entire lifespan of a page visit and reports the full duration from when the user initiates the input until the browser paints the next visual frame on screen.
Official INP thresholds and what counts as an interaction#
Google evaluates INP at the 75th percentile of real-user page loads recorded in field data, segmented across mobile and desktop devices:
| Rating | 75th Percentile INP Threshold | User Experience |
|---|---|---|
| Good | <= 200 milliseconds | The interface feels immediately responsive to taps, clicks, and typing. |
| Needs Improvement | 201 ms – 500 milliseconds | Noticeable lag between clicking a control and seeing visual feedback. |
| Poor | > 500 milliseconds | The page feels frozen or unresponsive; users frequently rage-click. |
Per the W3C Event Timing API and Google's INP specification, only three user actions are counted for INP:
- Clicking with a mouse.
- Tapping on a touchscreen.
- Pressing a key on a physical or onscreen keyboard.
Hovering (mouseover), scrolling, and pinch-zooming do not count directly as
INP interactions (though heavy scroll event listeners can block the main thread
and delay a simultaneous click or tap). Because a single tap or keypress often
fires multiple DOM events (pointerdown, mousedown, pointerup, click, or
keydown and keyup), INP groups those related events into one logical
interaction and uses the longest single component duration. For pages with fewer
than 50 total interactions during a visit, INP reports the single slowest
interaction; for long-lived single-page applications or editors with 50 or more
interactions, INP ignores the highest outlier per 50 interactions (approximating
the 98th percentile).
The three phases of every INP interaction#
Every INP measurement is the sum of three consecutive phases on the browser's main thread. As detailed in Optimize Interaction to Next Paint on web.dev, identifying which of the three phases is widest tells you exactly where to focus engineering effort:
[ User Input ] ---> (1. Input Delay) ---> (2. Processing Duration) ---> (3. Presentation Delay) ---> [ Next Paint ]
1. Input Delay#
The time between the operating system registering the user's hardware click/tap and the browser starting to execute your event handler callbacks.
- Root cause: The main thread was already busy doing something else when the
user clicked—most commonly framework hydration on initial load, a large
third-party tag manager script evaluating, or a recurring
setIntervaltimer.
2. Processing Duration#
The time spent executing all JavaScript event callbacks attached to that
interaction (pointerdown, click, React/Next.js synthetic event handlers,
analytics trackers).
Get SEO Insights Delivered
Join thousands of marketers receiving weekly SEO tips and strategies.
No spam, unsubscribe anytime. We respect your privacy.
- Root cause: Synchronous CPU-heavy work inside the click handler—such as
filtering a 10,000-row array, synchronously re-rendering an entire component
tree, firing five third-party tracking pixels synchronously before updating UI
state, or triggering forced synchronous layouts (layout thrashing) where
event-handler code mutates DOM styles and immediately reads layout geometry
(
offsetWidth,getBoundingClientRect()) in a loop while JavaScript is still executing.
3. Presentation Delay#
The time from when your JavaScript event callbacks finish until the browser completes style calculation, layout (reflow), paint, and compositing to push the updated pixels to the display.
- Root cause: Excessive DOM size (thousands of DOM nodes), expensive frame-level style and layout recalculations after large DOM mutations, complex CSS selectors, or heavy paint and compositing work before the next frame can be presented.
How to diagnose slow interactions in the field and lab#
Because INP requires real user clicks and taps, a standard automated Lighthouse page-load run does not report INP directly (Lighthouse uses Total Blocking Time, or TBT, as a load-time lab proxy, unless you script a Lighthouse User Flow timespan). To find the exact DOM element and script causing poor INP in production:
- Collect Real User Monitoring (RUM) attribution with
web-vitals: The officialonINPfunction in theweb-vitals/attributionlibrary exposes the CSS selector of the clicked element (interactionTarget), the interaction type, the breakdown acrossinputDelay,processingDuration, andpresentationDelay, and entries from the Long Animation Frames (LoAF) API (PerformanceLongAnimationFrameTiming), which identifies the exact script URLs and function names that blocked the frame. - Reproduce in Chrome DevTools Performance panel: Open Chrome DevTools, enable 4x or 6x CPU throttling and mobile viewport emulation (since low- and mid-tier Android devices dominate mobile CrUX field data), record a trace while clicking menus, accordions, search bars, and filters, and inspect the Interactions lane. Hovering over any interaction bar displays the exact millisecond split across Input Delay, Processing Time, and Presentation Delay.
For a full overview of how INP fits alongside LCP and CLS, read our Core Web Vitals optimization guide and our technical SEO audit guide.
Code patterns that fix high INP#
1. Yield to the main thread with scheduler.yield()#
When a click handler needs to perform both an immediate UI update (such as
opening a dropdown or toggling a button state) and non-visual background work
(such as logging analytics, saving to localStorage, or pre-computing a secondary
table), yield back to the browser right after updating the UI so the browser can
paint the next frame immediately:
async function yieldToMain() {
if ('scheduler' in window && 'yield' in scheduler) {
return scheduler.yield();
}
return new Promise((resolve) => setTimeout(resolve, 0));
}
button.addEventListener('click', async () => {
// 1. Critical visual state update first
toggleMenuOpenState();
// 2. Yield so the browser paints the open menu immediately!
await yieldToMain();
// 3. Run non-visual analytics and heavy state sync in a subsequent task
sendInteractionAnalytics();
recomputeSecondaryRecommendations();
});
Unlike setTimeout(fn, 0), which places the continuation at the very back of
the task queue behind unrelated third-party scripts, scheduler.yield() gives
your continuation priority after the browser's rendering opportunity completes.
2. Debounce text inputs and use React startTransition#
Typing into a live search box or filter input fires a keydown/input
interaction on every keystroke. If each keystroke synchronously re-renders 500
product cards, processingDuration and presentationDelay will regularly exceed
300ms on mobile devices.
- Wrap non-urgent result-list state updates in React's
startTransition()(oruseDeferredValue) so the input box updates its character immediately while the heavy list render stays interruptible. - Debounce expensive search or network callbacks so they fire after a 150ms–250ms pause in typing rather than on every character.
3. Reduce DOM size and use content-visibility: auto#
When a page contains more than 1,500 to 3,000 DOM nodes, even a small class
toggle on <body> or a parent container can trigger a 100ms+ style and layout
recalculation during Presentation Delay. Apply content-visibility: auto (paired
with contain-intrinsic-size) to offscreen article sections, long comment
threads, or below-the-fold tables so the browser skips layout and paint work for
offscreen subtrees during user interactions.
4. Defer non-essential third-party scripts and break up hydration#
If users tap your navigation menu within two seconds of page load and hit a 400ms Input Delay, inspect what is running during initial boot. Defer chat widgets, heatmaps, and non-critical tag manager triggers until after page load or first interaction, and avoid hydrating offscreen interactive islands all in one synchronous main-thread block.
Frequently asked questions#
Why did Google replace First Input Delay (FID) with INP?#
FID measured only the input delay (phase 1) of the very first interaction on a page and ignored the time spent running event handlers (phase 2) and painting the next frame (phase 3), as well as all interactions after the first click. Over 93% of mobile sites passed FID, even when their menus, filters, and forms felt sluggish. INP captures the full end-to-end latency of all interactions throughout the visit.
Why does Search Console show no INP data for some of my pages?#
Search Console and CrUX only report INP when a URL group has enough real-user Chrome visits that include a qualifying click, tap, or keypress. Read-only articles where visitors only scroll and read without clicking or tapping may report LCP and CLS in CrUX without having sufficient interaction samples to publish an INP score.
Does a fast server Time to First Byte (TTFB) improve INP?#
TTFB directly impacts Largest Contentful Paint (LCP), not INP. However, if a
page's click handler makes a synchronous or blocking network wait before updating
the UI without showing an immediate loading state, the user perceives lag. Always
paint immediate visual feedback (aria-busy="true" or a skeleton/spinner state)
within the first frame of the click rather than waiting for a network fetch to
resolve before painting.
Sources#
Related SEO Paths
About the Author
The Perfect SEO Tools team consists of experienced SEO professionals, digital marketers, and technical experts dedicated to helping businesses improve their search engine visibility and organic traffic.