Our marketing team's landing pages looked perfect in browsers but terrible as PDFs. Web fonts showed as system defaults, hero images were missing, and charts rendered as empty boxes.
The issue? IronPDF was capturing PDFs before asynchronous content loaded. The WaitFor class solved this. Here's how.
Why Do PDFs Render Incorrectly?
Modern web pages load content asynchronously:
- Web fonts from Google Fonts or Typekit
- Images via lazy loading
- Charts rendered by JavaScript
- Ajax-loaded data
When you convert HTML to PDF, the renderer might capture the page before these resources finish loading.
using IronPdf;
// Install via NuGet: Install-Package IronPdf
var renderer = new ChromePdfRenderer();
// Without WaitFor: PDF renders immediately, before fonts/images load
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("incomplete.pdf");
The PDF shows "Loading..." placeholders and fallback fonts because rendering happened too soon.
How Do I Wait for Fonts to Load?
Use WaitFor.AllFontsLoaded():
using IronPdf;
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.WaitFor.AllFontsLoaded();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("with-fonts.pdf");
IronPDF now waits until all @font-face declarations finish loading before rendering. Web fonts appear correctly in the PDF.
Can I Wait a Specific Amount of Time?
Yes. Use RenderDelay for a fixed wait:
using IronPdf;
var renderer = new ChromePdfRenderer();
// Wait 3 seconds before rendering
renderer.RenderingOptions.WaitFor.RenderDelay(3000);
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("delayed.pdf");
This gives JavaScript time to execute. I use 2-3 seconds for pages with moderate JS, 5+ seconds for heavy single-page applications.
How Do I Wait for Specific Elements?
Wait for an element to appear before rendering:
using IronPdf;
var renderer = new ChromePdfRenderer();
// Wait for element with ID "chart-loaded"
renderer.RenderingOptions.WaitFor.HtmlElementById("chart-loaded");
var pdf = renderer.RenderUrlAsPdf("https://example.com/dashboard");
pdf.SaveAs("with-chart.pdf");
Your JavaScript sets an element when rendering completes:
<div id="chart-container"></div>
<script>
renderChart().then(() => {
// Signal to IronPDF that chart is ready
document.body.insertAdjacentHTML('beforeend', '<div id="chart-loaded"></div>');
});
</script>
IronPDF waits until #chart-loaded exists before capturing the PDF.
Can I Wait for Multiple Elements?
Yes. Wait by tag name, class, or query selector:
using IronPdf;
var renderer = new ChromePdfRenderer();
// Wait for all images to have loaded attribute
renderer.RenderingOptions.WaitFor.HtmlElementByQuerySelector("img[loaded='true']");
var pdf = renderer.RenderUrlAsPdf("https://example.com/gallery");
pdf.SaveAs("with-images.pdf");
Your page sets attributes as images load:
document.querySelectorAll('img').forEach(img => {
img.onload = () => img.setAttribute('loaded', 'true');
});
How Do I Wait for Network Activity to Stop?
Use NetworkIdle:
using IronPdf;
var renderer = new ChromePdfRenderer();
// Wait until network is idle (no requests for 500ms)
renderer.RenderingOptions.WaitFor.NetworkIdle();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("network-idle.pdf");
This waits until all Ajax requests, image loads, and other network activity finishes. Useful for data-heavy dashboards.
Can I Customize the Network Idle Threshold?
Yes. Specify how many active requests are acceptable:
using IronPdf;
var renderer = new ChromePdfRenderer();
// Wait until 2 or fewer active requests
renderer.RenderingOptions.WaitFor.NetworkIdle(2);
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("mostly-loaded.pdf");
NetworkIdle(0) waits for zero active requests. NetworkIdle(2) allows up to 2 ongoing (e.g., long-polling connections).
How Do I Trigger Rendering from JavaScript?
Call a JavaScript function that signals when ready:
using IronPdf;
var renderer = new ChromePdfRenderer();
// Wait for window.ironPdfReady to be true
renderer.RenderingOptions.WaitFor.JavaScript("window.ironPdfReady === true");
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("js-triggered.pdf");
Your page sets the flag when rendering should begin:
<script>
async function loadData() {
await fetchDataFromAPI();
await renderCharts();
window.ironPdfReady = true; // Signal to IronPDF
}
loadData();
</script>
IronPDF polls the JavaScript expression. When it evaluates to true, rendering starts.
What's the Difference Between WaitFor Methods?
- PageLoad: Default. Renders immediately after HTML loads (no waiting)
- RenderDelay: Fixed time delay (e.g., 3000ms)
- AllFontsLoaded: Waits for @font-face fonts
- NetworkIdle: Waits for network requests to finish
- HtmlElement...: Waits for specific DOM elements
- JavaScript: Waits for custom JS expression to be true
Choose based on what your page needs to load.
Can I Combine Multiple WaitFor Conditions?
No. Only one WaitFor condition applies. Choose the most appropriate:
// This only uses JavaScript condition (last one set)
renderer.RenderingOptions.WaitFor.AllFontsLoaded();
renderer.RenderingOptions.WaitFor.JavaScript("window.ready");
// Only window.ready is checked
If you need multiple conditions, implement them in your JavaScript:
window.ready = async function() {
await document.fonts.ready; // Fonts loaded
await waitForNetworkIdle(); // Network idle
return true;
};
Then use JavaScript("window.ready()").
How Long Should I Wait?
Start with these guidelines:
- Static content: No wait needed (default PageLoad)
-
Web fonts only:
AllFontsLoaded() -
Light JavaScript:
RenderDelay(1000)- 1 second -
Ajax data:
NetworkIdle()or element-based wait -
Heavy SPAs (React/Vue/Angular):
RenderDelay(3000)or JavaScript trigger -
Complex dashboards:
NetworkIdle()+RenderDelay(5000)fallback
Monitor rendering times and adjust based on results.
What Happens if WaitFor Times Out?
IronPDF has a global timeout (default 60 seconds). If WaitFor doesn't complete, rendering fails with a timeout exception.
Increase the timeout for slow pages:
using IronPdf;
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.Timeout = 120; // 120 seconds
renderer.RenderingOptions.WaitFor.NetworkIdle();
var pdf = renderer.RenderUrlAsPdf("https://slow-site.com");
Can I Test WaitFor Locally?
Yes. Create test HTML with delays:
<!DOCTYPE html>
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
</head>
<body style="font-family: 'Roboto';">
<div id="content">Loading...</div>
<script>
setTimeout(() => {
document.getElementById('content').innerText = 'Content Loaded!';
document.body.insertAdjacentHTML('beforeend', '<div id="ready"></div>');
}, 2000);
</script>
</body>
</html>
Test different WaitFor strategies:
// Without WaitFor: PDF shows "Loading..."
var pdf1 = renderer.RenderHtmlFileAsPdf("test.html");
// With WaitFor: PDF shows "Content Loaded!"
renderer.RenderingOptions.WaitFor.HtmlElementById("ready");
var pdf2 = renderer.RenderHtmlFileAsPdf("test.html");
How Does WaitFor Affect Performance?
WaitFor adds latency proportional to wait time:
- AllFontsLoaded: +200-500ms (font load time)
- RenderDelay(3000): +3000ms fixed
- NetworkIdle: Variable (depends on network activity)
- Element-based: Variable (depends on when element appears)
For high-throughput systems, profile actual wait times and optimize:
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
renderer.RenderingOptions.WaitFor.AllFontsLoaded();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
stopwatch.Stop();
Console.WriteLine($"Rendering took {stopwatch.ElapsedMilliseconds}ms");
If avg wait time is 500ms but you're using RenderDelay(3000), you're wasting 2.5 seconds per PDF.
Can I Disable WaitFor?
Yes. Call PageLoad() (or don't set any WaitFor):
var renderer = new ChromePdfRenderer();
// No WaitFor set - renders immediately after page load
var pdf = renderer.RenderHtmlAsPdf("<h1>Static Content</h1>");
Static HTML renders fastest without waiting.
What About Legacy RenderDelay Property?
The old RenderingOptions.RenderDelay property still works but is deprecated:
// Old (deprecated)
renderer.RenderingOptions.RenderDelay = 3000;
// New (recommended)
renderer.RenderingOptions.WaitFor.RenderDelay(3000);
Use the new WaitFor.RenderDelay method for future compatibility.
Written by Jacob Mellor, CTO at Iron Software. Jacob created IronPDF and leads a team of 50+ engineers building .NET document processing libraries.
Top comments (0)