TapCub is live — analytics, insights and live chat, free on one platform
Glossary

DOMContentLoaded: what it is, vs load, and what delays it

DOMContentLoaded fires when the HTML is parsed and deferred scripts have run, before images finish loading. How it compares with load, LCP and FCP, a navigation timing example, what delays it and how to use it in code.

Chen Yu Reviewed by Xu An Also called DCL Last updated Nov 5, 2026 Glossary

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

MilestoneFires whenWhat it tells you
Time to first byteFirst byte of HTML arrivesServer and network speed
First contentful paintFirst text or image paintedWhen the user first sees something
DOMContentLoadedHTML parsed, deferred scripts executedWhen code can safely work with the DOM
Largest contentful paintLargest visible element paintedWhen the main content appears
loadAll subresources (images, iframes) loadedWhen 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]:

FieldValue (ms from navigation start)
responseStart (TTFB)180
responseEnd260
domInteractive820
domContentLoadedEventStart1,140
domContentLoadedEventEnd1,165
domComplete2,480
loadEventEnd2,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. defer scripts 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

  1. Add defer or async to scripts that do not need to run during parsing.
  2. Split and shrink JavaScript bundles; move non-critical work after load.
  3. Inline the critical CSS and load the rest without blocking.
  4. Reduce DOM size and avoid large inline scripts.
  5. 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

Was this explanation clear?

We use your answers to fix and expand this page.

Chen Yu

Technical Engineer

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

FAQ

Questions people ask

Short answers to the follow-up questions that come up most.

Still have a question?

Chat with the team behind TapCub — we usually reply within a few hours on business days.

What is the difference between DOMContentLoaded and load?

DOMContentLoaded fires when the HTML is parsed and deferred scripts have run; load waits for all subresources such as images and iframes.

Is DOMContentLoaded a Core Web Vital?

No. It is a technical milestone. Core Web Vitals are LCP, INP and CLS.

Do async scripts delay DOMContentLoaded?

No, async scripts do not block parsing, though they may run before or after it. Deferred and parser-blocking scripts do delay it.

How do I run code when the DOM is ready?

Check document.readyState; if it is still "loading", listen for DOMContentLoaded, otherwise run immediately.

See this number on your own site

Add one script tag for web and apps, and the first reports fill in within minutes.

See your data clearly. Find your growth.

Every click, backed by data. Install one line of code and see your first numbers in a minute.

No credit card · Free plans for analytics and chat · Cookieless analytics