What is a good INP score? And how to fix a slow one
A good INP is 200ms or less for three out of four real visits. Here’s what Interaction to Next Paint measures, what makes clicks feel slow, and the fixes that actually help.
Nour8 min read · 
Why the click lags.
You tap “Add to cart” and nothing happens. Half a second later the button finally changes. Nothing crashed and the page loaded quickly, but it felt slow. That pause is what Interaction to Next Paint, or INP, measures.
INP has been one of Google’s three Core Web Vitals since March 2024, when it replaced First Input Delay. It’s also the one most sites struggle with, because a lab test can’t measure it. Here’s what a good score is, what makes it slow, and how to fix it.
The short answer
A good INP is 200 milliseconds or less. Between 200 and 500ms “needs improvement”, and over 500ms is poor. Google looks at the 75th percentile of real visits, so three out of four visits need to be at or under 200ms to pass.
Phones and desktops are judged separately. Phones are almost always slower, since a mid-range Android has a fraction of a laptop’s processing power. If you only test on your own machine, your phone visitors are probably having a worse time than you think.
What INP measures
Every time someone clicks, taps or presses a key, the browser has to run your code and then draw the result on screen. INP is the time from the moment of the input to the next frame the browser paints, so it covers the whole wait, not just the start of it.
The browser watches every interaction during a visit and reports one of the slowest. On pages with lots of interactions it skips the very worst one for every 50, so a single freak hiccup doesn’t decide the score. Scrolling and hovering don’t count. Typing, clicking and tapping do.
INP isn’t about how fast the page loads. It’s about how fast it answers.
That has a side effect worth knowing: INP only exists on visits where someone interacted. A visitor who reads and leaves without clicking anything doesn’t report one. So you’ll usually have fewer INP numbers than load numbers like LCP, and that’s expected.
The three parts of a slow click
Each interaction’s time is made of three pieces, and each has different fixes.
- 01Input delay. The browser can only do one thing at a time on the main thread. If it’s busy running some other script when the tap arrives, the tap waits in line. Long scripts during page load and timers firing in the background are the usual culprits.
- 02Processing time. Your event handlers run. A click handler that updates a big state object, re-renders half the page or sends tracking calls before doing anything useful makes this part long.
- 03Presentation delay. After your code finishes, the browser recalculates styles, works out the layout and paints. A huge page, or code that changes lots of elements at once, makes this slow too.
Knowing which part is slow tells you where to look. A long input delay means something else was hogging the browser. Long processing means your own handler. Long presentation means the update itself is too big.
What usually makes INP slow
- Too much JavaScript at once. Any task longer than 50ms blocks the browser, and a page can easily run tasks of several hundred milliseconds while it starts up.
- Clicks during hydration. On React, Vue and similar sites, the page is visible before it’s ready. A tap that lands while the framework is still attaching itself waits until it’s done.
- Third-party scripts. Chat widgets, A/B testing tools, tag managers and ads all run on the same main thread as your code, and some of them listen to every click.
- Heavy handlers. Filtering a long list, sorting a table or re-rendering a whole component tree on every keypress.
- A very large page. Thousands of elements make every style and layout update more expensive, so even a small change takes long to paint.
Finding the slow interaction
Lighthouse can’t help much here: it doesn’t click anything. Its Total Blocking Time is a rough stand-in for “the page is busy”, but a green Lighthouse score says little about INP. We covered that gap in Your Lighthouse score is green. Why are your Core Web Vitals failing?
Instead, start from real visits and work down:
- 01Find the page and device. Look at INP per page, split by phone and desktop. Search Console groups similar pages together, and a tool that collects real visits shows each page on its own.
- 02Reproduce it with a slow phone. In Chrome DevTools, open the Performance panel, slow the CPU down four or six times, and use the page like a visitor would. The live INP number updates as you click, and you can see which interaction was slowest.
- 03Record the slow interaction. Record a trace while you do it. The interaction shows up with its input delay, processing and presentation parts, and underneath it the scripts that ran. Long yellow blocks are JavaScript. Purple is style and layout.
- 04Check who owns the script. If the long task belongs to a third-party script, the fix may be loading it later or removing it, not touching your own code.
Real-visit data also helps here. Browsers that support the Long Animation Frames API can report which script caused a slow frame for actual visitors, which is often faster than trying to reproduce the slow click yourself.
Fixes that work
- 01Show the response first, work second. Update the button, open the menu or show the spinner right away, then do the slow part. The browser can paint the feedback before the heavy work starts, and INP stops when it paints.
- 02Break up long tasks. Split big jobs into chunks and let the browser breathe between them. In Chrome, await scheduler.yield() hands control back so a waiting tap can run. A setTimeout of zero does a similar job everywhere else.
- 03Mark updates that can wait. In React, wrap slow, non-urgent state updates in startTransition so a typing or click update isn’t blocked by them. Debounce search boxes and filters instead of running them on every key.
- 04Do less at startup. Split code so each page only loads what it needs, and delay analytics, chat widgets and other extras until after the page is usable. Fewer scripts competing early means shorter input delay.
- 05Make updates smaller. Change only the elements that need to change, keep the page’s element count down, and avoid reading layout (like an element’s height) right after changing styles, which forces the browser to recalculate in the middle of your code.
Start with the first one. Showing feedback straight away is often a small change, and it’s the difference between a click that feels instant and one that feels broken.
Keeping it fast
INP tends to creep up quietly. Nobody ships a release called “make clicks slower”. A new tracking script here, a bigger component there, one more dependency, and a few releases later the page that passed is in the yellow.
Because Google’s report covers the last 28 days, that creep shows up weeks after the release that caused it. The quicker way is to compare each release with the one before it, page by page, on phones and desktops separately. We explain how in Did my deploy slow down my site? How to know for sure.
That’s what CodeGecko does. It collects INP and the other Core Web Vitals from real visits, groups them by release, and tells you after each deploy whether INP got worse on any page and device, with the commits that shipped next to it. We only call a change real when it’s bigger than 5% of the old number or 20ms, whichever is larger. The methodology has every rule, and the demo shows what a regressed release looks like.
- Aim for 200ms or less at the 75th percentile, on phones as well as desktops.
- Measure real visits. Lab tests don’t click, so they can’t give you INP.
- Find the slowest page and interaction, then check which of the three parts is long.
- Show feedback first, break up long tasks and delay what can wait.
- Watch INP release by release, so a slow click is caught the day it ships.
NourBuilding CodeGecko
Get in early.
We’re letting teams in a few at a time. Join the waitlist and we’ll email you once, when your spot opens.