How can I capture fully rendered HTML after dynamic scripts finish loading (Puppeteer)?

I require fully rendered HTML after all scripts run using Puppeteer. My current approach returns only static markup. How can I capture dynamic content? See alternative code example below:

const puppeteerModule = require('puppeteer');

(async () => {
  const browserInstance = await puppeteerModule.launch();
  const pageInstance = await browserInstance.newPage();
  await pageInstance.goto('http://example.com', { waitUntil: 'networkidle0' });
  const renderedHTML = await pageInstance.evaluate(() => document.documentElement.outerHTML);
  console.log(renderedHTML);
  await browserInstance.close();
})();

From my experience, the network idle setting in Puppeteer doesn’t always guarantee that every dynamic change in the DOM has completed. I’ve solved this by waiting for key elements that indicate complete rendering, using page.waitForSelector to ensure your specific dynamic content is present before capturing the HTML. Another useful tactic is to add a deliberate wait period with page.waitForTimeout to accommodate slow-loading scripts or delayed rendering. This approach helped me capture a fully-formed DOM where static checks fell short, making it a more robust solution in dynamic settings.

It is helpful to use a custom condition to ensure dynamic elements are fully loaded. In my practice, I frequently use page.waitForFunction to check if specific parts of the page have finished rendering. This can be more reliable than relying solely on network idle events since it directly tests the state of the DOM. Additionally, verifying through selectors that the intended dynamic content is present has worked well for me. This extra check prevents premature captures and ensures the HTML is truly fully rendered before extraction.

hey, i found that wrapping everything in a page.evaluate promise that waits for a custom event works well. add a slight timeout as backup if needed. it helps catch those late-loading dynamic parts that standard waits might miss

In my experience, overcoming incomplete HTML capture with Puppeteer required a more advanced waiting strategy. I faced similar challenges where network idle conditions weren’t sufficient because some scripts continue updating the DOM even after initial loads. I ended up using page.waitForFunction to check for a specific global flag or a stable element state that signals rendering completion. Additionally, I sometimes include a final small wait time to ensure any intermittent asynchronous updates are finished before retrieving the HTML. This method has greatly increased the reliability of my captures.