How to Read the DevTools Network Waterfall Step by Step
Your page takes four seconds to show anything, Lighthouse gives you a score of 52, and you have no idea which of the 87 requests is to blame.

Your page takes four seconds to show anything, Lighthouse gives you a score of 52, and you have no idea which of the 87 requests is to blame. The DevTools network waterfall already holds the answer, laid out as coloured bars, but most developers open the Network panel only to check whether a request returned 200 and never learn to read the chart beside it.
I use the waterfall almost every week when a client reports a slow page, and it usually takes under ten minutes to find the real bottleneck. This walkthrough uses Chrome, but Firefox and Edge show the same information with slightly different colours.
Set Up the DevTools Network Waterfall Properly
A waterfall recorded with the wrong settings will mislead you. Before reloading, do the following:
- Open DevTools and switch to the Network panel.
- Tick Disable cache so you see what a first time visitor sees. Untick it later to test repeat visits.
- Set throttling to Fast 4G or Slow 4G. On a fibre connection everything looks fine and the problems hide.
- Right click the column headers and enable Priority and Protocol. Both become important later.
- Hard reload the page and wait until the request count stops climbing.
Make sure the timeline is visible on the right. If the panel is narrow, drag the DevTools edge wider; the bars need room to be readable.
What Each Colour in a Request Bar Means
Hover over any bar to see a breakdown. Each request passes through a series of phases:
| Phase | What is happening | When it is suspicious |
|---|---|---|
| Queueing / Stalled | The browser is waiting to start the request | Long stalls on many requests suggest too many connections to one origin or low priority assets |
| DNS lookup | Resolving the domain name | Over 50 ms for a third party domain on every page |
| Initial connection and SSL | TCP and TLS handshake | Repeated for many different domains |
| Waiting for server response (TTFB) | Server is building the response | Over 600 ms on HTML or API calls |
| Content download | Bytes travelling to the browser | Long bars on images or JS bundles |
The short version: a long green or teal "waiting" section points at the server, and a long blue "download" section points at file size.
Six Patterns to Look For
1. A slow first bar
The HTML document is the first request, and nothing else can start until it arrives. If its waiting time is 1.4 seconds, that delay pushes every later request right by the same amount. Fix the server first: database queries, missing caches or slow rendering. A classic cause on API driven pages is the pattern in our article on how N+1 queries slow an API.
2. A staircase
If bars start one after another in a diagonal staircase rather than in parallel, you have a dependency chain. HTML loads a CSS file, which imports a font CSS file, which loads the font. Each step waits for the one before. Preloading the final resource or inlining the first step collapses the chain.
3. A wide gap with nothing loading
White space in the waterfall usually means the main thread is busy parsing or executing JavaScript. The Network panel cannot explain it; switch to the Performance panel to see which script is running.
4. Many short bars from many domains
Analytics, tag managers, chat widgets and ad scripts each bring their own DNS lookup and TLS handshake. Ten third party domains can add 300 to 500 ms on a mobile connection before a single byte of their content arrives.
5. A late hero image
Find your largest image. If it starts after 40 other requests with a "Low" priority, the browser did not know it mattered. Adding fetchpriority="high" to that image often moves it to the front of the queue.
6. The same file downloaded twice
Filter the request list by file name and sort by Name. Two identical bundles with different query strings, or the same font loaded from your server and from a CDN, are surprisingly common after a migration. On one client site, a theme and a plugin each loaded their own copy of the same carousel library, adding 92 KB of compressed JavaScript for a slider that appeared on only one page. Use the Initiator column to see which file triggered each request, then remove the duplicate at its source rather than hiding it with a cache rule.
Why the Total Load Time Is the Wrong Number to Chase
The status bar at the bottom shows "Load" and "Finish" times, and teams often set goals around them. I think that is a mistake. The Finish time includes every analytics ping, lazy loaded widget and polling request that fires after the page is already usable. I have seen a site cut Finish from 9 seconds to 4 and feel no faster to users, because the content had always appeared around 2.5 seconds.
Look at the blue and red vertical lines instead, which mark DOMContentLoaded and Load, and especially at when your largest visible element arrives. The requests that end before the main content renders are the ones worth optimising. Everything to the right of that point matters far less.
Repeat visits are worth checking separately. Turn the cache back on and reload, and many requests should show "(memory cache)" or "(disk cache)". Navigating back and forth is a different story again, covered in our explainer on how the back-forward cache makes the back button feel instant.
Save and Compare Waterfalls
A single recording is a snapshot. To prove a fix worked, export the session as a HAR file before and after the change (right click in the request list and choose save all as HAR). Load both into DevTools later, side by side, under identical throttling. If a regression slips in weeks later and you cannot tell which commit caused it, combining saved waterfalls with git bisect to find the commit that broke your build narrows it down quickly.
One warning: HAR files contain cookies, headers and sometimes tokens. Scrub them before attaching one to a public issue tracker.
FAQ
What does stalled mean in the DevTools network waterfall?
Stalled means the request was ready but the browser had not started it yet. Common causes are connection limits per origin on HTTP/1.1, lower priority than other requests, or the browser waiting for a cache check.
What is a good TTFB in the Network panel?
For the main HTML document, under 200 ms is very good and under 600 ms is acceptable for most sites. Measure with throttling and a cold cache so the number reflects real visitors.
Why does the waterfall look different every time I reload?
Network conditions, server load, caching and script timing all vary slightly between loads. Record three or four runs and compare the typical pattern rather than trusting a single one.
Can I see the network waterfall on a mobile device?
Yes. Connect an Android phone by USB and use remote debugging in desktop Chrome, or connect an iPhone to a Mac and use the Safari Web Inspector to view the same timeline.
More in Dev Tools
Dev Tools
How Lockfiles Keep Builds Reproducible Across Machines
The build passed on your laptop at 4pm. At 4:20 the same commit fails in CI with an error from a package you have never heard...
Dev Tools
How to Set Up Prettier and ESLint So They Stop Fighting
You save a file, Prettier adds a trailing comma, ESLint underlines it in red, you run the ESLint fixer, it removes the comma,...
Dev Tools
How Git Bisect Finds the Commit That Broke Your Build
A bug appears, and you know it worked last week. Somewhere in the hundreds of commits since, one change broke it.