Skip to content

First Input Delay is published by General Action, the company that makes Emdash. When we recommend Emdash, we are recommending our own product. About this site

Long tasks and Total Blocking Time

A long task is any task that runs on the browser’s main thread for more than 50 milliseconds. Total Blocking Time (TBT) is the sum, across all long tasks during page load, of the time each one ran beyond 50 ms. Both describe the same thing that First Input Delay measured from the visitor’s side: a main thread too busy to respond.

The browser’s main thread runs one task at a time. Web.dev defines a long task as “a task that runs on the main thread for more than 50 milliseconds”, and the blocking time of that task as “its duration in excess of 50 milliseconds”.

The 50 ms figure comes from the RAIL model. The goal there is to respond to an input within 100 ms so that it feels instant. If the page does its work in chunks of at most 50 ms, an input “can be queued for up to 50 ms” behind a chunk in progress, which leaves the remaining 50 ms to handle it.

The Long Tasks API reports them through a PerformanceObserver:

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

Two limits apply. MDN’s compatibility data lists PerformanceLongTaskTiming from Chrome 58 and Edge, with no support in Firefox or Safari. And the entries say little about the cause. Attribution identifies the frame or container a task ran in, not the script or function.

TBT turns a list of long tasks into one number. Web.dev’s definition: TBT “measures the total amount of time after First Contentful Paint (FCP) where the main thread was blocked for long enough to prevent input responsiveness.”

A worked example, with five tasks during a page load:

Task Duration Blocking time (duration minus 50 ms)
A 270 ms 220 ms
B 60 ms 10 ms
C 40 ms 0 ms
D 120 ms 70 ms
E 50 ms 0 ms
Total 540 ms 300 ms

The main thread was busy for 540 ms, and the TBT is 300 ms. Tasks C and E add nothing because they did not exceed 50 ms.

This is why splitting work helps even when the total stays the same. Break task A into six 45 ms tasks and its contribution falls from 220 ms to zero, because an input arriving at any point waits at most 45 ms.

  • Window. TBT starts at First Contentful Paint. By default Lighthouse stops counting at Time to Interactive. Other tools may use the whole trace.
  • Target. Web.dev recommends “a Total Blocking Time of less than 200 milliseconds when tested on average mobile hardware”.
  • Lighthouse scoring. The Lighthouse TBT audit rates mobile results as follows:
TBT on mobile Lighthouse rating
0 to 200 ms Fast (green)
200 to 600 ms Moderate (orange)
Over 600 ms Slow (red)

TBT carries 30% of the Lighthouse 10 performance score, the largest single weight.

TBT is a lab metric. It depends on the test device and CPU throttling, so compare runs made under the same conditions and do not compare your number with someone else’s.

The Long Animation Frames API (LoAF) was designed to fix the gaps in the Long Tasks API. Chrome’s documentation defines a long animation frame as “when a rendering update is delayed beyond 50 milliseconds”. It looks at the whole frame, so several short tasks that together delay a paint are caught, and so is rendering work.

It shipped in Chrome 123. MDN’s compatibility data, checked on November 13, 2026, shows no support in Firefox or Safari, so treat it as a Chromium-only diagnostic.

if (PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')) {
const observer = new PerformanceObserver((list) => {
for (const frame of list.getEntries()) {
console.log('Frame:', frame.duration, 'ms, blocking', frame.blockingDuration, 'ms');
for (const script of frame.scripts) {
console.log(' ', script.invoker, script.sourceURL, script.duration, 'ms');
}
}
});
observer.observe({ type: 'long-animation-frame', buffered: true });
}

The useful fields:

  • duration is the length of the frame. It matters for smoothness.
  • blockingDuration is the frame’s equivalent of blocking time: the parts of its tasks beyond 50 ms, added up. It matters for responsiveness.
  • scripts lists the scripts that ran for more than 5 ms, each with its invoker, sourceURL, sourceFunctionName and forcedStyleAndLayoutDuration. This is the attribution the Long Tasks API never had.
  • firstUIEventTimestamp tells you whether an interaction was handled during the frame.

Chrome’s documentation suggests a simple field filter: report frames where blockingDuration is over 100 and firstUIEventTimestamp is greater than 0. Those are the frames that held up a real interaction.

Measure Where it is collected What it tells you
Long tasks Lab and field (Chromium) Which stretches of main-thread work exceeded 50 ms
Total Blocking Time Lab How much blocking a page load contained. A risk estimate that needs no visitor
Long animation frames Field (Chromium) Which frames were slow, and which scripts ran in them
First Input Delay Field How long the first real input waited. Deprecated since 2024
Interaction to Next Paint Field How long the slowest real interaction took from input to paint

The chain of cause runs from the top of that table to the bottom. A long task that is running when a visitor taps produces input delay. That delay was the whole of FID, and it is the first phase of an INP interaction.

The link is statistical. TBT can flag blocking that no visitor ever runs into, and it can miss slow interactions that happen after load. Web.dev says TBT is “a reasonable proxy metric for INP for the lab” and “not a substitute for INP”. The web-vitals library connects the two ends in the field: its attribution build attaches the long animation frames that overlapped an INP interaction to the report.

For the practical side, see How to improve First Input Delay for ways to shorten long tasks, and How to measure First Input Delay for collecting field data.

Frequently asked questions

What is a long task?

A long task is a task that runs on the browser's main thread for more than 50 milliseconds. While it runs, the browser cannot respond to input, so a click or key press that arrives during a long task has to wait for it to finish.

Why is the long task threshold 50 milliseconds?

It comes from the RAIL performance model, which aims to respond to input within 100 milliseconds. If work is done in chunks of at most 50 milliseconds, an input can be queued behind a chunk for up to 50 milliseconds, which leaves the other 50 milliseconds to handle it.

How is Total Blocking Time calculated?

For every long task after First Contentful Paint, take the part of its duration beyond 50 milliseconds. Total Blocking Time is the sum of those parts. A 70 millisecond task adds 20 milliseconds, and a 40 millisecond task adds nothing.

What is a good Total Blocking Time?

Web.dev recommends a Total Blocking Time of less than 200 milliseconds when tested on average mobile hardware. Lighthouse scores 0 to 200 milliseconds as fast on mobile, 200 to 600 as moderate and over 600 as slow.

What is the difference between the Long Tasks API and the Long Animation Frames API?

The Long Tasks API reports individual tasks over 50 milliseconds with little detail about their cause. The Long Animation Frames API reports whole frames that took over 50 milliseconds to render, including the scripts that ran in them, their source URLs and the time spent on style and layout.

Can I measure Total Blocking Time for real users?

It is possible but not recommended. Web.dev says Total Blocking Time should be measured in the lab, because real interactions add a lot of variance, and suggests the Long Animation Frames API for field diagnostics instead.