TL;DR — Quick Summary
TBT measures the total time the main thread was blocked by long tasks (> 50ms each) between FCP and TTI. Good TBT is ≤ 200ms. It carries 30% of the Lighthouse score (highest weight) and is the best lab proxy for real-world responsiveness (INP).
What is Total Blocking Time (TBT)?
Total Blocking Time is calculated by summing the 'blocking time' of every long task that occurs between FCP and TTI:
- •A long task is any task on the main thread exceeding 50 milliseconds.
- •The blocking time of a long task is the portion exceeding 50ms. A 70ms task has 20ms of blocking time. A 200ms task has 150ms.
- •TBT = sum of all blocking times between FCP and TTI.
Example: If three long tasks occur during loading — 80ms, 120ms, and 300ms — the blocking times are 30ms, 70ms, and 250ms, giving a TBT of 350ms (poor).
TBT is a lab-only metric because it requires precise timing of the FCP-to-TTI window, which is only available in controlled environments. INP is the field equivalent — measuring real-user interaction responsiveness across the entire page visit.
TBT Thresholds
| Metric | Good | Needs Improvement | Poor |
|---|---|---|---|
| TBT | ≤ 200ms | 200ms – 600ms | > 600ms |
Google evaluates the 75th percentile (p75) of real-user field data over a rolling 28-day window.
History & Evolution
TBT was introduced as a Lighthouse metric to complement TTI by quantifying how blocked the main thread was during loading.
Key milestones:
- •2019 — TBT introduced in Lighthouse as a key performance metric.
- •2020 — TBT weight increased in Lighthouse performance scoring, reflecting its importance for responsiveness.
- •2024 — With INP replacing FID as a CWV, TBT became even more important as the primary lab proxy for INP. Lighthouse 11+ sets TBT weight at 30%.
- •2025–2026 — TBT remains the highest-weighted Lighthouse metric at 30%.
How TBT is Measured
TBT is calculated by Lighthouse during a simulated page load. It sums the blocking portion (> 50ms) of every long task between FCP and TTI.
Available in:
- •Lighthouse (Chrome DevTools, CLI, CI) — 30% of performance score
- •WebPageTest — Shown in test results
- •PSI lab section — Lighthouse simulation
Not available in field data. INP is the real-user equivalent.
Key rule: Field data (CrUX) determines Google rankings. Lab data (Lighthouse, WebPageTest) is for debugging and iteration.
Common Causes of Poor TBT Scores
- 1Large JavaScript bundles — A single 500KB JS file blocks the main thread for 1-2 seconds on mobile devices.
- 2Third-party scripts — Analytics, chat widgets, ad scripts, and A/B testing tools often create long tasks.
- 3Unoptimized framework code — React/Vue/Angular initial hydration can create 200ms+ long tasks.
- 4Unused JavaScript — Code that's downloaded and parsed but never executed still blocks the main thread.
- 5Polyfills — Legacy polyfills for modern browsers add unnecessary parsing and execution time.
- 6No code splitting — Loading all application JavaScript upfront instead of on-demand.
Frequently Asked Questions
No. TBT is a lab-only metric. INP is the corresponding field metric and Core Web Vital. However, TBT is the most important Lighthouse metric (30% weight) and the best lab proxy for INP.
200 milliseconds or less. Between 200ms and 600ms needs improvement. Above 600ms is poor.
TBT measures main-thread blocking during page load (lab). INP measures interaction responsiveness throughout the page visit (field). They correlate strongly — reducing TBT almost always improves INP — but they measure different things. A page can have low TBT but high INP if slow interactions occur after loading completes.
Because responsiveness is the most impactful aspect of user experience, and TBT is the best lab proxy for real-world responsiveness. Google's research shows TBT correlates with INP more strongly than any other lab metric.
TBT measures total blocking during loading (quantitative — how much blocking). TTI measures when blocking stops (qualitative — when is the page interactive). TBT is more useful because two pages with the same TTI can have very different TBT scores.
Three strategies: 1) Code-split so JavaScript loads on-demand rather than all upfront. 2) Break long tasks into smaller chunks using scheduler.yield(). 3) Defer non-critical scripts to load after user interaction.
For step-by-step optimization, platform-specific fixes, code examples, and case studies, read our full guide:
The Ultimate Guide to Core Web Vitals: How to Pass All Metrics & Boost Rankings in 2026Struggling with TBT?
Request a free speed audit and we'll identify exactly what's holding your scores back.