Quick answer
DOMContentLoaded is a browser event fired when the initial HTML document has been fully parsed and deferred scripts have executed, without waiting for images, iframes and other subresources, which complete at the later load event.
What is DOMContentLoaded?
DOMContentLoaded is a browser event that fires when the HTML document has been completely parsed and the DOM tree is built, and all deferred scripts have run. It does not wait for images, stylesheets that are not blocking a script, iframes or other subresources to finish loading. That later point is the load event.
In performance tools you often see it as DCL, a marker on the network waterfall, or as "DOMContentLoaded time" in navigation timing.
DOMContentLoaded vs load vs user-centric metrics
| Milestone | Fires when | What it tells you |
|---|---|---|
| Time to first byte | First byte of HTML arrives | Server and network speed |
| First contentful paint | First text or image painted | When the user first sees something |
| DOMContentLoaded | HTML parsed, deferred scripts executed | When code can safely work with the DOM |
| Largest contentful paint | Largest visible element painted | When the main content appears |
| load | All subresources (images, iframes) loaded | When the page is fully loaded |
DOMContentLoaded is a technical milestone for developers, not a measure of what users experience. A page can fire DCL early while the hero image is still loading, or late because a heavy script runs during parsing even though content was visible.
Reading it from navigation timing
Sample values for one page load, from performance.getEntriesByType("navigation")[0]:
| Field | Value (ms from navigation start) |
|---|---|
| responseStart (TTFB) | 180 |
| responseEnd | 260 |
| domInteractive | 820 |
| domContentLoadedEventStart | 1,140 |
| domContentLoadedEventEnd | 1,165 |
| domComplete | 2,480 |
| loadEventEnd | 2,500 |
The gap between domInteractive (820 ms, parsing done) and domContentLoadedEventStart (1,140 ms) is 320 ms spent running deferred scripts. The gap to domComplete (2,480 ms) is mostly images and other resources. Long DCL handler time (End − Start, 25 ms here) means code attached to the event is doing a lot of work.
What delays DOMContentLoaded
- Parser-blocking scripts. A plain
<script src>in the head stops parsing until it downloads and runs. - Stylesheets before scripts. A script after a stylesheet waits for that CSS, because the script might read styles.
- Deferred scripts.
deferscripts run before DCL fires, so large deferred bundles push it back. - Large HTML. Huge documents or deeply nested DOMs take longer to parse.
- Slow server response, which delays everything after it.
async scripts do not block parsing and may run before or after DCL; type="module" scripts are deferred by default.
Using the event in code
function init() {
// safe to query and modify the DOM here
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init);
} else {
init(); // DOM already parsed
}
Checking readyState first matters: if your script loads after the event has fired, a listener alone would never run. Analytics scripts commonly use this pattern to send the first pageview as soon as the DOM is ready.
How to improve it
- Add
deferorasyncto scripts that do not need to run during parsing. - Split and shrink JavaScript bundles; move non-critical work after load.
- Inline the critical CSS and load the rest without blocking.
- Reduce DOM size and avoid large inline scripts.
- Speed up the server response and use a CDN.
In TapCub
TapCub's performance report measures real visits and splits each load into backend (time to first byte), network transfer and frontend render (from the end of the response until the document is complete), alongside Core Web Vitals at P75 and P95. It does not report DOMContentLoaded as a separate metric; frontend render covers the same parsing and script work plus subresources. The TapCub script itself waits for DOMContentLoaded only if the page is still loading, then records the pageview. See good page load time and Core Web Vitals.
Sources
- MDN Web Docs. Document: DOMContentLoaded event.
- WHATWG. HTML Living Standard: the end (parsing).
- Harry Roberts (2023). In defence of DOMContentLoaded.
Was this explanation clear?
We use your answers to fix and expand this page.
Couldn’t send. Please try again in a minute.
Thanks for the feedback. We’ll use it to improve this page.You’ve already sent feedback on this page. Thanks.

Technical Engineer
Focuses on tracking code, SDKs, and API integrations, with practical guidance on implementation checks and troubleshooting.