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 50 ms long-task definition
Section titled “The 50 ms long-task definition”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.
Observing long tasks
Section titled “Observing long tasks”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.
Total Blocking Time
Section titled “Total Blocking Time”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.
The measurement window and thresholds
Section titled “The measurement window and thresholds”- 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
Section titled “The Long Animation Frames API”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:
durationis the length of the frame. It matters for smoothness.blockingDurationis the frame’s equivalent of blocking time: the parts of its tasks beyond 50 ms, added up. It matters for responsiveness.scriptslists the scripts that ran for more than 5 ms, each with itsinvoker,sourceURL,sourceFunctionNameandforcedStyleAndLayoutDuration. This is the attribution the Long Tasks API never had.firstUIEventTimestamptells 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.
How they relate to FID and INP
Section titled “How they relate to FID and INP”| 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.