Feedback

Total Blocking Time (TBT)

By Christian Schreiber · Updated

Total Blocking Time, or TBT, measures how much time long tasks block the main thread while your page loads, the stretch during which a click or a tap would have to wait. It is a lab metric, and it carries more weight in the Lighthouse performance score than any other metric. A high TBT means the page looks ready but ignores input.

From PerfDelta's measurements: In the mobile lab test, 22% of 4,075 home pages have a good Total Blocking Time and 57% a poor one. The median is 771 ms, with the middle half between 245 ms and 1671 ms. More in the data section below.

What total blocking time measures: the blocking part of long tasks

The browser runs JavaScript, parses HTML and performs layout on a single main thread. While a task runs, nothing else can happen there, including the handling of a click. Any task longer than 50 milliseconds counts as a long task.

TBT does not add up the full length of those tasks. For each long task it counts only the portion above 50 ms, the blocking time, and sums these portions. A task of 70 ms contributes 20 ms. A task of 45 ms contributes nothing, because it stays under the threshold.

Take a page with four tasks on the main thread during load:

TaskDurationBlocking time
Parse and run the main bundle250 ms200 ms
Framework hydration120 ms70 ms
Analytics tag70 ms20 ms
Small event setup45 ms0 ms

The tasks take 485 ms in total, yet the TBT is 290 ms: the time input would have been stuck behind a task.

Lighthouse only counts tasks in a defined window: from First Contentful Paint, when content first appears, to Time to Interactive, the point after which the main thread stays quiet for five seconds with no long tasks and no more than two network requests in flight. Tasks before the first paint are ignored. For the start of that window, see First Contentful Paint.

Good TBT thresholds for mobile and desktop

Lighthouse scores TBT against separate thresholds for its mobile and desktop runs:

RatingMobileDesktop
Good200 ms or less150 ms or less
Needs improvement200 to 600 ms150 to 350 ms
Poormore than 600 msmore than 350 ms

The mobile run simulates a slower CPU, so the same JavaScript produces longer tasks. A page that passes on desktop can still be poor on mobile.

TBT weight in the Lighthouse score: 30 %, the largest single share

Since Lighthouse 10 the performance score is built from five lab metrics: TBT 30 %, Largest Contentful Paint 25 %, Cumulative Layout Shift 25 %, First Contentful Paint 10 % and Speed Index 10 %. A page with excellent loading metrics and heavy JavaScript can still end up with a mediocre score, and cutting TBT is often the fastest route to a better number in PageSpeed Insights.

TBT vs INP: the lab proxy for responsiveness

TBT is not a Core Web Vital. The Core Web Vital for responsiveness is Interaction to Next Paint, which measures real interactions from real users in the field. A lab test has no user clicking, so it cannot measure INP. TBT fills that gap, because a blocked main thread is the most common reason interactions feel slow.

TBT only looks at the loading phase, while INP covers every interaction over the whole visit. A low TBT with a poor field INP usually points to slow event handlers or heavy re-renders after load. A high TBT is a strong warning for field INP, and the fixes overlap almost completely.

What causes high total blocking time

How to find long tasks in DevTools and Lighthouse

In the Lighthouse report, open the diagnostics Avoid long main-thread tasks, which lists the longest tasks with their start time and duration, and Reduce JavaScript execution time, which shows how much CPU time each script uses for evaluation and parsing. Reduce the impact of third-party code shows which external providers block the main thread.

For detail, record a page load in the Chrome DevTools Performance panel with CPU throttling enabled. Long tasks appear in the main track with a red marker in the corner. Click one to see the responsible script and function. In the browser you can log long tasks with an observer:

new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log('Long task:', Math.round(entry.duration), 'ms');
  }
}).observe({ type: 'longtask', buffered: true });

How to reduce total blocking time

1. Split long tasks and yield to the main thread

Break large units of work into chunks and hand control back to the browser between them. scheduler.yield() is the modern API, with setTimeout as a fallback:

function yieldToMain() {
  if (globalThis.scheduler?.yield) {
    return scheduler.yield();
  }
  return new Promise((resolve) => setTimeout(resolve, 0));
}

async function initWidgets(widgets) {
  for (const widget of widgets) {
    widget.init();
    await yieldToMain(); // each init becomes its own short task
  }
}

A 300 ms initialisation split into six chunks of 50 ms each drops from 250 ms of blocking time to almost none, even though the total work stays the same.

2. Defer or remove third-party scripts

Remove tags nobody uses. Load the rest with defer or async, or after the page has loaded. Replace heavy embeds such as chat widgets and video players with a lightweight facade that loads the real script on click.

3. Ship less JavaScript with code splitting

Load only the code the current page needs and fetch the rest on demand with dynamic imports:

button.addEventListener('click', async () => {
  const { openGallery } = await import('./gallery.js');
  openGallery();
});

Removing dead code has the same effect. See reduce unused JavaScript for how to find it.

4. Move computation to a Web Worker

Work that does not touch the DOM, such as parsing large JSON responses or filtering data, can run in a Web Worker on a separate thread.

5. Reduce hydration cost

Hydrate only the interactive parts of the page. Islands architectures, partial hydration and server components keep static content out of the client bundle.

Reducing TBT in WordPress, Shopify and Next.js

WordPress: High TBT usually comes from plugins that load scripts on every page and from page builders. Deactivate unneeded plugins and use the delay JavaScript option of your caching plugin. Test forms and menus afterwards, because delayed scripts can break them.

Shopify: Apps inject their own scripts, and removed apps sometimes leave code in the theme. Uninstall unused apps and check the theme for leftover snippets.

React and Next.js: Use next/dynamic or React.lazy for components below the fold or behind interactions. In the App Router, keep components as server components unless they need state or event handlers, and load third-party scripts through next/script with a strategy such as lazyOnload.

Common mistakes when optimizing TBT

How to verify your TBT improvements

Run Lighthouse or PageSpeed Insights several times and compare the median, since TBT varies more between runs than most metrics. Check the mobile result and confirm in the Performance panel that the longest tasks have become shorter. Then watch field INP in the Chrome UX Report over its trailing 28-day window, because that is where the effect on real visitors shows up.

PerfDelta tests several pages of your site on mobile and desktop and shows lab and field data, so you can see whether a high TBT comes with a poor INP. Each Lighthouse opportunity in PerfDelta is listed with estimated savings and the affected files, and links to the matching guide.

Frequently asked questions

What is total blocking time?

Total Blocking Time is the sum of the blocking portions of all long tasks on the main thread between First Contentful Paint and Time to Interactive. For each task longer than 50 ms, only the part above 50 ms counts, so a 70 ms task adds 20 ms.

What is a good TBT score?

In Lighthouse, 200 ms or less is good on mobile and more than 600 ms is poor. On desktop, 150 ms or less is good and more than 350 ms is poor.

Is TBT a Core Web Vital?

No. TBT is a lab metric. The Core Web Vital for responsiveness is Interaction to Next Paint, measured in the field. TBT serves as its lab proxy.

How much does TBT affect the Lighthouse score?

TBT accounts for 30 % of the Lighthouse performance score, the largest single weight.

How do I reduce total blocking time?

Split long tasks and yield to the main thread, defer or remove third-party scripts, use code splitting, move computation to Web Workers and reduce hydration work.

Why does my TBT change between test runs?

Small timing differences on the test machine can push a task above or below the 50 ms threshold. Compare the median of several runs.

What PerfDelta's measurements show

In the mobile lab test, 22% of 4,075 home pages have a good Total Blocking Time and 57% a poor one. The median is 771 ms, with the middle half between 245 ms and 1671 ms.

By industry, the median ranges from 195 ms in Professional services to 1143 ms in Travel and hospitality.

Data as of October 16, 2026, recalculated daily. Source: PerfDelta's own measurements (Chrome UX Report and Lighthouse); details in the website speed statistics and the methodology.

Thresholds and sources

Lab test (Lighthouse):

Sources:

All sources retrieved on October 9, 2026. Thresholds and documentation change; the linked page is authoritative.

Test your site

Run a free scan to see whether this applies to your pages, on mobile and desktop, with lab and field data side by side.

Run a free test

A free account saves your tests and shows how your values change from one test to the next. Daily monitoring with field data and alerts starts with the Solo plan.

Related audits