Total Blocking Time (TBT)

What TBT measures, the 50ms long-task math, why it's the lab proxy for INP (not a Core Web Vital), and how to fix a red score — from a technical SEO.

First published: Jun 26, 2026 · Last updated: Jul 19, 2026 · Advanced
demand #2 in Web Vitals#8 in Web Performance#53 in Technical SEO#76 on the site

Total Blocking Time (TBT) is the sum of the blocking portion — the time above 50 ms — of every long task between First Contentful Paint and Time to Interactive. It's a lab-only metric, the single largest weight (30%) in the Lighthouse Performance score, and the lab proxy for the Core Web Vital INP (it used to proxy FID). It is NOT a Core Web Vital and never shows up in Search Console or CrUX. Lighthouse mobile thresholds: good ≤200 ms, poor >600 ms. You fix it the same way you fix INP — break up long JS tasks, code-split, defer or remove unused JS, and cut third-party script cost. My honest take: do it for users and conversions, not for a ranking bump.

TL;DR — TBTTotal Blocking Time — the sum of the blocking portion (time above 50 ms) of every long task between First Contentful Paint and Time to Interactive. It's a lab-recommended metric and the lab proxy for INP, not a Core Web Vital. is the total amount of time, between First Contentful PaintFirst Contentful Paint — the time from when a page starts loading to when any part of its content (text, image, SVG, or non-white canvas) first renders. Good is ≤1.8 s at the 75th percentile. It's a diagnostic metric, not a Core Web Vital. and Time to InteractiveTime to Interactive — a retired Lighthouse lab metric marking the point a page's main sub-resources have loaded and it can reliably respond to input. It was removed from the Lighthouse Performance score in Lighthouse 10 (2023) for being too volatile, was never a Core Web Vital, and still defines the end of the Total Blocking Time measurement window., that the main thread was blocked long enough to prevent input responsiveness. It sums the blocking portion (duration − 50 ms) of every long taskAny main-thread task over 50 ms — the primary cause of INP regressions. (any main-thread task over 50 ms). It’s a lab metric — the single largest weight (30%) in the LighthouseLighthouse is Google's free, open-source tool that audits a page under simulated lab conditions and scores it 0–100 across Performance, Accessibility, Best Practices, and SEO. It's lab data — useful for debugging, not a ranking signal. 10 score and the lab proxy for INPInteraction to Next Paint — the input-to-paint latency at the 75th percentile of a page's interactions. ≤200 ms is good. — but it is not a Core Web Vital and never appears in CrUXChrome User Experience Report — Google's public dataset of real-world (field) performance data from eligible Chrome users. It's the official field-data source behind the Core Web Vitals program. or Search ConsoleA free Google service that reports how a site performs in Google Search and surfaces problems with how Google crawls, indexes, and serves it. It's first-party data straight from Google — but you don't need it to appear in results.. Mobile thresholds: good ≤200 ms, poor >600 ms. Fix it like you’d fix INPInteraction to Next Paint — the input-to-paint latency at the 75th percentile of a page's interactions. ≤200 ms is good.: break up long JS tasks, code-split, defer/remove unused JS, tame third-party scripts. My honest take: fix it for users, not for a ranking bump.

Evidence for this claim Lighthouse classifies mobile TBT at 200 milliseconds or less as good and above 600 milliseconds as poor. Scope: Lighthouse mobile TBT scoring guidance; desktop scoring differs. Confidence: high · Verified: Chrome Developers: Total Blocking Time

What TBT actually measures

Google’s definition is the place to start. TBT is “the total amount of time after First Contentful Paint (FCPFirst Contentful Paint — the time from when a page starts loading to when any part of its content (text, image, SVG, or non-white canvas) first renders. Good is ≤1.8 s at the 75th percentile. It's a diagnostic metric, not a Core Web Vital.) where the main thread was blocked for long enough to prevent input responsiveness.” The browser’s main thread processes one task at a time; while it’s busy with a long chunk of work, it can’t react to a click, a tap, or a keypress. TBT quantifies how much of your page-load window is spent in that blocked state.

Two definitions do all the work here:

  • A long task is “a task that runs on the main thread for more than 50 milliseconds.”
  • The blocking portion of a task is its duration minus 50 ms. Tasks at or under 50 ms contribute exactly 0 ms.

TBT is the sum of those blocking portions between FCP and Time to Interactive (TTI). So First Contentful Paint is the start line: nothing before the first paint counts, because there’s nothing on screen to interact with yet.

Evidence for this claim TBT sums the portion above 50 milliseconds of long main-thread tasks between FCP and Time to Interactive. Scope: Lighthouse lab metric definition; not a field Core Web Vital. Confidence: high · Verified: Chrome Developers: Total Blocking Time

The worked example

Google’s own table is the clearest illustration. Imagine five tasks run on the main thread between FCP and TTI:

Task durationBlocking time (duration − 50 ms)
Task one: 250 ms200 ms
Task two: 90 ms40 ms
Task three: 35 ms0 ms
Task four: 30 ms0 ms
Task five: 155 ms105 ms
Total Blocking Time345 ms

Tasks three and four are under the 50 ms line, so they contribute nothing. Task one blocks for 250 − 50 = 200 ms, task five for 155 − 50 = 105 ms. Add the blocking portions — 200 + 40 + 0 + 0 + 105 — and you get 345 ms of TBT. That’s a “needs improvement” score, driven almost entirely by two heavy tasks.

This is the counter-intuitive part worth internalizing: “A small number of tasks on the main thread doesn’t necessarily mean low blocking time. Conversely, a large number of tasks doesn’t necessarily lead to tons of blocking time.” (That framing is NitroPack’s, relayed here — reverified against the live source 2026-07-18.) What matters is whether individual tasks cross 50 ms, not how many tasks there are.

The measurement window: FCP to TTI

The window ends at Time to Interactive“the time from when the page starts loading to when its main sub-resources have loaded and it is capable of reliably responding to user input quickly.” In LighthouseLighthouse is Google's free, open-source tool that audits a page under simulated lab conditions and scores it 0–100 across Performance, Accessibility, Best Practices, and SEO. It's lab data — useful for debugging, not a ranking signal., TTI is foundA 302 (\"Found\") is a temporary redirect: it forwards users to a new URL while telling search engines the original URL should stay in the index. It's a weak canonicalization signal, not the zero-equity dead end of SEO folklore. by searching forward for a five-second “quiet window” with no long tasks and no more than two in-flight network requests.

Worth noting: TTI itself was removed from Lighthouse 10 because it proved overly sensitive to outlier network requests and long tasks, producing high variability. TBT survived and became the primary interactivity metric. As Philip Walton put it, “Newer, alternative, metrics like Largest Contentful PaintLargest Contentful Paint — render time of the largest visible image or text block, relative to when the page started loading. ≤2.5 s (at the 75th percentile) is good. (LCPLargest Contentful Paint — render time of the largest visible image or text block, relative to when the page started loading. ≤2.5 s (at the 75th percentile) is good.), Total Blocking Time (TBT), and Interaction to Next Paint (INP) are usually better metrics to use in place of TTI.” TBT didn’t replace TTI as the window’s endpoint — it’s a better single number for the same underlying problem. And TTI’s disappearance from the Lighthouse report UI isn’t the same claim as TTI no longer bounding Lighthouse’s default navigation window — the window itself is still measured that way under the hood.

One more scoping note: “FCP to TTI” describes Lighthouse’s default navigation audit specifically. Other tools, or Lighthouse itself running a timespan trace instead of a full page-load navigation, can total a different measured window — the 50 ms long-task math doesn’t change, but the start and end points of what gets summed are tool- and trace-mode-specific, not a universal law of the metric.

Is TBT a Core Web Vital? No.

This is the most common misconception, so let’s be blunt about it. The three Core Web VitalsWeb Vitals is Google's initiative (launched May 2020) for unified page-experience quality signals. Core Web Vitals — LCP, INP, and CLS — are the subset used in ranking; the rest (TTFB, FCP, TBT, Speed Index) are diagnostic, not ranking factors. are LCP, INP, and CLSCumulative Layout Shift — a unitless score for unexpected visual movement, taken from the largest burst (session window) of layout shifts, not the lifetime sum. ≤0.1 is good.. TBT is not one of them. Google’s own wording: “Total Blocking Time (TBT) is a lab metrics is vital in catching and diagnosing potential interactivity issues that can impact INP. However, it is not part of the Core Web VitalsGoogle's three real-user UX metrics — LCP (loading), INP (responsiveness), and CLS (visual stability) — used by Google's ranking systems, with no official weight attached, measured on field data. set because they are not field-measurable, nor do they reflect a user-centric outcome.” (The grammar in that sentence is theirs, not mine.)

So where does TBT show up, and where doesn’t it?

  • Where you see it: Lighthouse, PageSpeed Insights’ lab tab, and Chrome DevTools — all simulated/lab environments.
  • Where you don’t: Google Search ConsoleA free Google service that reports how a site performs in Google Search and surfaces problems with how Google crawls, indexes, and serves it. It's first-party data straight from Google — but you don't need it to appear in results.’s Core Web Vitals reportThe Google Search Console report (under Experience) that shows how your indexed URLs perform on the Core Web Vitals — LCP, INP, and CLS — using real-user field data from CrUX, grouped by device, status, and clusters of similar-performing URLs., CrUXChrome User Experience Report — Google's public dataset of real-world (field) performance data from eligible Chrome users. It's the official field-data source behind the Core Web Vitals program., or any field dataPerformance metrics captured from real users, not lab tests.. Those only carry LCP, INP, and CLS.

If someone tells you they’re “watching TBT in Search ConsoleGoogle's free tool for monitoring crawling, indexing, and search performance.,” they’re mistaken — GSC reports field data, and TBT isn’t a field metric.

One correction worth being precise about: TBT being lab-recommended isn’t the same as TBT being field-impossible. You can technically compute a TBT-style total in the field with the Long Tasks API — Google says so directly: “It is possible to measure TBT in the field, but we don’t recommend this as user interaction can affect your page’s TBT in ways that lead to lots of variance in your reports.” That’s a recommendation against it, not a technical wall. What’s actually true without exception is narrower: CrUX and Search Console’s Core Web Vitals report never carry TBT, full stop — those pipelines only ever collect LCP, INP, and CLS.

TBT is the lab proxy for INP

Here’s why TBT exists at all. Lab tools load a page in a simulated environment with no real user, so they can’t measure Interaction to Next Paint — INP needs actual clicks and taps. TBT fills that gap: “the Total Blocking Time (TBT) metric is lab-measurable and is a proxy for INP.”

The two are mechanically related: “Although INP and TBT are calculated differently, they are both reflections of a blocked main thread during the bootstrap process. When the main thread is blocked, the browser is delayed in responding to user interactions.” And empirically, “A low TBT often correlates with a low Interaction to Next Paint (INP).”

But “proxy” is not “substitute.” Google is explicit: “Total Blocking Time (TBT) may be a reasonable proxy metric for INP, but it’s not a substitute for INP in and of itself.” They diverge in real ways:

  • High TBT, fine INP. TBT measures blocking during load. If your users don’t actually try to interact during that blocked window — they wait for the page to look finished first — their INP can be fine even with an ugly TBT.
  • Fine TBT, poor INP. INP also covers slow event handlers and renderingTurning HTML, CSS, and JavaScript into the final visual page and DOM. work that fire after load, plus things like the browser’s 300 ms tap delay on non-mobile-optimized pages — none of which TBT sees.

When the lab and field disagree, trust the field. INP (the real-user number) takes priority over TBT (the lab estimate).

One historical note that trips people up: TBT used to be the lab proxy for First Input Delay (FID). INP replaced FID as a Core Web Vital on March 12, 2024, so TBT is now INP’s proxy. The underlying mechanism never changed — it’s always been about a blocked main thread during load — but any older article calling TBT “FID’s proxy” predates that switch.

Why TBT dominates the Lighthouse score

TBT carries the largest single weight in the Lighthouse Performance score — 30%, a weighting introduced in Lighthouse 10 and, verified live against Chrome’s scoring docs on 2026-07-18, still unchanged through the current Lighthouse 13:

MetricWeight
First Contentful Paint10%
Speed IndexSpeed Index measures how quickly content is visually displayed during page load — the average time at which visible parts of the page appear, scored in seconds (lower is better). It's a lab-only Lighthouse metric, not a Core Web Vital and not a ranking factor.10%
Largest Contentful Paint25%
Total Blocking Time30%
Cumulative Layout Shift25%

Treat that table as version-and-date-scoped, not a permanent constant — Lighthouse has changed its weights before and can again. Re-verify against Lighthouse performance scoring before quoting it in an audit deck.

This is the practical reason TBT matters for SEO audits even though it isn’t a ranking signal: a poor TBT has an outsized effect on that big Lighthouse number everyone screenshots. Addy Osmani’s worked example makes it concrete — removing one Intersection Observer polyfill cut TBT from 400 ms to 300 ms and lifted the Lighthouse Performance score from 63 to 70. One fix, seven points, because of the 30% weight.

One more nuance: the “Good ≤200 ms” category threshold and the Lighthouse score are different scales. To score 90+ on the TBT subscore you need roughly ≤300 ms on mobile, and to hit 100 you need ≤100 ms. (Those subscore figures are DebugBear’s documentation of the scoring curve, reverified against the live source 2026-07-18.) “Good” and “100” are not the same bar.

Does TBT affect SEO rankings?

Not directly — and I’ll be straighter about this than most.

TBT is not a ranking signal. Google’s interactivity ranking input is INP, a field metric. TBT is a diagnostic that helps you find and fix the long tasks that hurt INP. Improving TBT may improve INP, which might marginally help the Page Experience side of rankings — but that’s two links of “may” away from your positions.

And here’s my actual position on the whole Core Web Vitals question, which I’ve written before in my page speed guide: I don’t think Core Web Vitals have much impact on SEO, and unless you’re extremely slow I generally won’t prioritize them. Do them for users and conversions, not for a ranking bump. That applies doubly to TBT, which is a lab proxy for a field metric for a small ranking input. Fix it because a frozen page loses you customers — not because you’re chasing a position.

What causes high TBT

It’s almost always JavaScript:

  • Unnecessary JavaScript loading, parsing, or execution — the Lighthouse audit’s own words. Shipping a big bundle the page doesn’t need at load is the classic cause.
  • Inefficient JavaScript statements — heavy synchronous work that monopolizes the main thread.
  • Third-party scripts — tag managers, chat widgets, analytics, ad scripts. Often the single biggest contributor, and the one you control least.
  • Heavy framework bootstrap — React hydrationActivating server-rendered HTML in the browser by attaching JavaScript handlers. and similar can run long tasks during startup.
  • Style/layout recalculation and garbage collection — forced synchronous layout, large style recalcs, and GC pauses show up as main-thread tasks too; don’t assume every long task in the trace is JavaScript execution.

Don’t assume bundle transfer size is the whole story, either. Trace attribution has real gaps: cross-origin frames and worker threads have privacy and security limits on what a long-task observer can report about them (see Troubleshooting), so an unattributed task in your trace isn’t proof no third party is involved — it may just mean the attribution API isn’t allowed to tell you.

How to fix high TBT

The fixes are the same family as the INP fixes — both come down to a blocked main thread.

  1. Find the long tasks. Open the Chrome DevTools Performance panelThe Performance panel is Chrome DevTools' built-in, local profiler for recording and analyzing how a page loads and runs — CPU, main-thread work, rendering, network, and live Core Web Vitals. The recorded trace is local, lab data from your own browser — not what Googlebot sees — though the panel can optionally show real-user CrUX field data alongside it. and look for tasks over 50 ms (they’re flagged with red corners), or run the Lighthouse “Avoid long main-thread tasks” audit.
  2. Audit third-party scripts first. They’re usually the easiest wins. Use the DevTools Coverage and Network tabs to see what each script costs, and lazy-load heavy embeds (YouTube, maps, chat) behind a facade.
  3. Break up the long tasks. Yield to the main thread so the browser can handle input between chunks — “when tasks are broken up, the browser can respond to higher-priority work much sooner—including user interactions.” The modern API is scheduler.yield(), with a setTimeout(resolve, 0) fallback (see the Cheat Sheets tab for the pattern). Note that Google no longer recommends isInputPending() — yield regardless of whether input is pending.
  4. Reduce the JavaScript. Code-split large bundles so less parses and evaluates at load, remove unused JS (DevTools Coverage tab shows you what), and defer non-critical scripts.
  5. Move heavy computation off the main thread. Web Workers run CPU-heavy work on a separate thread, leaving the main thread free to respond.

A useful side effect: long tasks that block the main thread can also delay Largest Contentful Paint rendering, so fixing TBT sometimes improves LCP too — especially when render-blocking JS is involved.

Where to go next

TBT lives in the Core Web Vitals family alongside its field counterpart Interaction to Next Paint, the loading metrics Largest Contentful Paint and First Contentful Paint, and the lab tools Lighthouse, PageSpeed Insights, and Speed Index that report them. If you only remember one thing: TBT is the lab warning light for field responsiveness — chase the long tasks, not the number.

Add an expert note

Pin an expert quote

New person? Create their unclaimed profile at /admin/experts/ → Pin a quote first.