INP (Interaction to Next Paint)

No Comments
Inp (interaction to next paint)

Interaction to Next Paint (INP) measures how long your page takes to visually respond when a user clicks, taps, or presses a key — specifically, the time from the interaction to the next frame the browser paints afterwards. It became the responsiveness metric of Core Web Vitals in March 2024, replacing First Input Delay.

Thresholds at the 75th percentile of visits: 200 ms or less is good, 200–500 ms needs improvement, over 500 ms is poor. Unlike a load metric, INP is recorded across the entire visit and reports (roughly) the worst interaction — so one janky "add to cart" button can fail a page that feels fine everywhere else. That is exactly the point: users remember the one tap that did nothing.

What happens inside those 200 milliseconds

Every interaction has three phases, and INP is the sum of all three:

  • Input delay — the tap happened, but the main thread was busy running some other task, so your event handler had to wait in line. This is the only part FID ever measured.
  • Processing duration — your event handlers actually run. Heavy state updates, synchronous fetch-and-render logic, analytics firing on click — all of it counts.
  • Presentation delay — handlers finished, but the browser still has to do style recalculation, layout, and paint before the user sees anything change. A giant DOM makes this phase expensive on every single interaction.

The enemy in all three phases is the same: long tasks on the main thread. JavaScript is single-threaded; any task over 50 ms means any tap landing during it waits. A 300 ms hydration chunk, a 200 ms analytics init, a synchronous JSON parse — each one is a window during which your page is deaf.

Which interactions go wrong, and why

InteractionCounts toward INP?Typical main-thread culpritWhat actually helps
Tap / click on buttons, links, togglesYesHeavy click handlers; framework re-rendering a huge component treeDo less synchronously; update state, paint, then compute
Typing in an input or search boxYes (each keystroke)Re-filtering a big list on every keypressDebounce the work, not the paint; keep the echo of the keystroke instant
Opening a menu / accordion / modalYesInjecting large DOM subtrees, forced synchronous layoutPre-render hidden, toggle visibility; read layout before writing
ScrollingNoScroll jank is real but a different metric's problem
Hovering, moving the mouseNoIgnored by INP entirely

The core fix: yield to the main thread

You usually can't delete the work, but you can split it so the browser paints a response before the heavy part runs. The pattern:

button.addEventListener('click', async () => {
  // 1. Cheap, visible feedback first
  button.classList.add('is-busy');

  // 2. Yield so the browser can paint that frame
  await scheduler.yield();          // Chrome 129+
  // fallback: await new Promise(r => setTimeout(r, 0));

  // 3. Now do the expensive part
  const results = computeExpensiveThing();
  render(results);
});

The user sees the button react within one frame; the 250 ms of computation happens after the paint instead of in front of it. Same total work, radically different INP. For work that never needs the DOM — analytics batching, data transforms — move it to a Web Worker and get it off the main thread permanently.

How to check INP on your own site

  1. PageSpeed Insights: the field data block shows your CrUX INP. Note the lab section below it has no INP — Lighthouse doesn't interact with the page, so it reports Total Blocking Time as a rough proxy.
  2. Search Console → Core Web Vitals: filter for INP issues to find which templates fail. Interactive templates — search, filters, configurators — are the usual suspects.
  3. Chrome DevTools Performance panel: start recording, actually use the page like an impatient human, stop. The Interactions track shows each interaction as a bar; anything wide is your target. Enable 4x CPU throttling — your dev machine is lying to you otherwise.
  4. web-vitals library with attribution: onINP(console.log, { reportAllChanges: true }) tells you which element and which phase (input delay vs processing vs presentation) is eating the time — in the field, on real devices.
  5. CrUX API for the origin-level INP distribution and history.

Common mistakes in INP work

  • Debugging on a fast machine without throttling. INP problems live on mid-range Android. If you don't throttle CPU, you will not reproduce your users' 600 ms interactions — and you'll close the ticket as "cannot reproduce."
  • Chasing load-time metrics to fix INP. A page can have a perfect LCP and a terrible INP; deferred scripts that pile onto the main thread after load hurt interactions, not loading. The fix is scheduling, not compression.
  • Debouncing the visual feedback along with the work. Debouncing a search filter is right; making the keystroke itself feel dead is wrong. Paint first, compute later.
  • Third-party tag sprawl. Tag managers happily stack five trackers onto every click. Audit what runs in click handlers — each one runs inside your processing duration.
  • Ignoring DOM size. Past roughly a few thousand nodes, every style recalc and layout gets slower, which inflates presentation delay on every interaction. No handler optimization saves you from a 40,000-node DOM.

Frequently asked questions

Is INP really the single worst interaction?

Almost. For visits with lots of interactions, Chrome ignores a few of the very worst outliers (one per 50 interactions) and reports the highest remaining one. In practice: think "worst tap of the visit."

Why can't Lighthouse measure INP?

Because INP requires real interactions and Lighthouse never clicks anything. It's a field-only metric. Use Total Blocking Time in the lab as a correlated stand-in, then verify against CrUX — the distinction matters, as explained in field vs lab data.

How is INP different from FID?

FID measured only the input delay of only the first interaction — most sites passed effortlessly. INP measures the full delay-to-paint duration of effectively the worst interaction across the whole visit. Sites that sailed through FID at 10 ms routinely fail INP. The history is covered in INP: the metric that replaced FID.

Does fixing INP move business numbers?

The published case studies say yes — redBus documented a 7% sales increase after improving INP (write-up here). Responsiveness sits directly on the conversion path in a way load metrics don't.

Where's the full optimization playbook?

The complete INP guide walks through attribution, long-task hunting, and framework-specific patterns.

Claude Vincent is a technical SEO consultant focused on crawlability, rendering, and AI-search visibility. He writes the field guides and case studies at SEO ProCheck, with a bias toward the durable, unglamorous work that decides whether search engines and AI answer engines can actually read and cite a site.

About SEO ProCheck

Technical SEO consulting and GEO strategy with 20 years of enterprise experience. Case studies, resources, and tools for search and AI visibility.

Work With Me

Technical SEO audits, GEO strategy, site migrations, and international SEO. Hourly consulting for teams who need hands-on support, not just reports.

Subscribe to our newsletter!

More from our blog