Interaction to Next Paint (INP)
Interaction to Next Paint measures the time between a tap, a click or a key press and the next frame the browser paints. A good INP is 200 milliseconds or less. Above 500 milliseconds is poor. Google grades the 75th percentile of your real visits, so three quarters of them have to clear the bar.
INP is a field metric. Chrome collects it from real people, across a whole visit. It became a Core Web Vital on 12 March 2024, and replaced First Input Delay. FID timed only the first interaction, and only the delay before the handler ran.
What are the three parts of an interaction?
INP is the sum of three phases, not one measurement:
- Input delay — the wait before your event handler starts. A busy Main-thread workTotal time the browser’s single UI thread spent parsing, compiling and running code. is the usual cause.
- Processing duration — the time all the handlers for that event take to run.
- Presentation delay — the time from the last handler to the next painted frame.
Only three kinds of input are observed: a click with a mouse, a tap on a touchscreen, and a key press. Scrolling and hovering don't count.
Does INP report my slowest interaction?
Almost. Chrome discounts one interaction for every 50 on the page, so a single unlucky click can't decide the score of a page people use heavily. Past 50 interactions that works out close to the 98th percentile.
Below 50 interactions there is nothing to discount. INP is then the worst interaction of the visit.
Can you measure INP in a lab?
You can get a number. It isn't your INP, and the gap is wider than the usual lab-versus-field caveat.
Lighthouse reports INP in timespan mode only — you start a recording, interact with the page, and stop. The Lighthouse panel in Chrome DevTools drives that mode. Our own fleet runs navigation mode, so it never produces one.
Here's what that number is. In Lighthouse 12.8.2, responsiveness.js sorts the
interaction events Chrome kept — at most the ten worst — by duration, longest
first, and then picks one:
const index = Math.min(9, Math.floor(responsivenessEvents.length / 50));
return responsivenessEvents[index];
That's the same discount rule as the field metric. Under 50 interactions the index is 0. Your lab INP is the single worst click you made.
So I ran it. The test page has four buttons, and each handler blocks the main thread for a fixed time. I ran it on a laptop under Lighthouse 12.8.2 and Chrome for Testing 145, in timespan mode at 4× CPU throttling. The handlers busy-wait on wall-clock time, so the throttle doesn't inflate the blocking durations. Three timespans per row, and each range covers all three:
| Clicks in the session | INP | TBT |
|---|---|---|
| 60, 150, 350 ms | 365–371 ms | 415–432 ms |
| 60, 150, 350, 900 ms | 916–924 ms | 1,267–1,268 ms |
| 900 ms alone | 918–923 ms | 852–853 ms |
One 900 ms click on its own reports the same INP as the session with all four clicks in it. The 60, 150 and 350 ms interactions add nothing. TBTHow long the main thread was busy and couldn’t respond to taps or clicks. moves by about 415 ms between those two sessions, because TBT counts the blocking time of every long task.
Reversing the click order changed nothing either: 60, 150, 350 and 350, 150, 60 both reported 365–371 ms.
So I'd read a lab INP as a measurement of the script, not of the page. It tells you what the interaction you chose to test costs, which is useful when you're fixing one known-slow button. It tells you nothing about the interaction your visitors actually make most.
What a normal Lighthouse run reports instead
A navigation run has no INP audit at all. Not notApplicable — absent. The audit
declares supportedModes: ['timespan'], and filterAuditsByGatherMode in
filters.js drops any audit that doesn't support the current mode.
I checked one of our own reports to be sure. A completed Lighthouse 12.8.2 run of
image-line.com/fl-studio/download from Frankfurt has no
interaction-to-next-paint key in lhr.audits, and no entry for it in the
performance category.
What fills the gap is Total Blocking Time, which carries the largest single weight in the performance score at 30 percent. TBT sums the part of each long task that runs past 50 milliseconds, between First Contentful Paint and Time to Interactive.
That window closes during the load. Interactions after the load fall outside it. So TBT speaks to input delay on a busy page, and says nothing about handlers that run later or about paint cost. A page can report 0 ms TBT and still respond slowly to every click.
How to reduce INP
Take the three phases one at a time. Each one has its own fix.
- Cut input delay first. Break up long tasks during load, and evaluate less script while the page loads.
- Shorten your event handlers. Do the visible update, then hand the rest back to
the browser with
setTimeout. When the update has to paint first, userequestAnimationFramefollowed bysetTimeout. - Don't read a layout property straight after you write one. That forces a synchronous layout inside the handler.
- Attack presentation delay last. A smaller DOM paints faster, and
content-visibilitylets the browser skip work that's off screen.
What we measure, and what we don't
We can't give you INP. Our worker loads your page with nobody in front of it, so
there's no interaction to time. Every result carries six lab metrics —
lcp_ms, cls, tbt_ms, fcp_ms, speed_index_ms and tti_ms. There's no
inp_ms field, because there'd be nothing to put in it.
What a lab run does give you is a fixed set of conditions. We pin the Lighthouse and Chromium version, and the result records the Lighthouse version that produced your number. You pick the regions with the checkboxes on the audit form, up to two per run. Through the API you can ask for up to 5 runs per region. We return the median run, so one slow load doesn't decide the answer. The raw Lighthouse JSON and HTML come back with every report.
For INP itself, go to the field: the Chrome UX Report, Search Console, or the
web-vitals library on your own pages. Use TBT here as the early warning, and
treat a green TBT as evidence about the load and nothing more.
what’s this
The small set of field metrics Google treats as a ranking input and reports in Search Console. We measure their lab equivalents here — real-user field data (CrUX) is a separate signal. TBT is the lab stand-in for INP, not a Core Web Vital itself.
Common questions
What is a good INP score?
200 milliseconds or less, measured at the 75th percentile of real visits. Between 200 and 500 milliseconds needs improvement. Above 500 milliseconds is poor.
Can Lighthouse measure INP?
Only in timespan mode, where a person or a script interacts with the page while Lighthouse records. A normal navigation run drops the INP audit entirely, because the audit declares support for timespan mode only.
Does INP report my slowest interaction?
Almost. Chrome discounts one interaction for every 50 on the page. Below 50 interactions there is nothing to discount, so INP is the single worst one.
Why does my page have no INP in Search Console?
INP comes from the Chrome UX Report, which needs enough real visits to form a stable sample. A URL with too few visits has no INP of its own. Search Console groups similar URLs, and when a group still has too little data it falls back to an origin-level group.