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:
| Task | Duration | Blocking time |
|---|---|---|
| Parse and run the main bundle | 250 ms | 200 ms |
| Framework hydration | 120 ms | 70 ms |
| Analytics tag | 70 ms | 20 ms |
| Small event setup | 45 ms | 0 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:
| Rating | Mobile | Desktop |
|---|---|---|
| Good | 200 ms or less | 150 ms or less |
| Needs improvement | 200 to 600 ms | 150 to 350 ms |
| Poor | more than 600 ms | more 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
- Large JavaScript bundles. Every script has to be parsed, compiled and executed, even if most of the code is not needed on the current page.
- Third-party scripts. Analytics, advertising, chat widgets and consent banners run on your main thread, often during load.
- Hydration in JavaScript frameworks. Server-rendered React or Vue apps rebuild component state and attach handlers in the browser, often as one long task.
- Heavy main-thread work. Large DOM trees, expensive layout and synchronous loops over large data sets extend tasks.
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
- Testing only on desktop. The slower simulated CPU on mobile makes tasks longer.
- Moving work instead of splitting it. Deferring a 400 ms task to a later point in load still produces a 400 ms task inside the measured window.
- Assuming a tag manager makes tags cheap. Tags loaded through it still run on your main thread.
- Treating TBT as the goal. Check field INP as well, since that is the metric Google uses.
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):
TBT mobile: ≤ 200 ms good. > 600 ms poor
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 testA 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.