Dashboard PDF export is one of the most-requested features in analytics tools, and also one of the hardest to get right. Puppeteer works locally but breaks in production (Lambda size limits, Docker complexity, cold starts). A hosted API keeps your infrastructure clean: you pass a URL, the API renders it with a full browser, and you get PDF bytes back.
URL-to-PDF with wait_until
Pass the dashboard URL. Use wait_until: networkidle0 to ensure JS-rendered charts finish before capture:
curl -X POST https://platform.htmltopdfapi.co/api/v1/pdf/generate \
-H "Authorization: Bearer $HTMLTOPDF_API_KEY" \
-H "Content-Type: application/json" \
-H "Accept: application/pdf" \
-d '{
"url": "https://your-app.com/reports/monthly",
"paper_size": "a4",
"orientation": "landscape",
"wait_until": "networkidle0"
}' \
--output dashboard.pdfwait_until Options
"load": fires when the HTML is loaded (fastest, may miss lazy-loaded charts)
"networkidle0": waits until no pending network requests for 500ms (most reliable for data-heavy dashboards)
"networkidle2": same as networkidle0 but allows up to 2 concurrent requests (for streaming endpoints)
For most dashboards, networkidle0 is the right default.
Export Button in React
async function exportDashboardPdf() {
const res = await fetch('/api/export-pdf', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url: window.location.href }),
})
if (!res.ok) throw new Error('Export failed')
const blob = await res.blob()
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = 'dashboard.pdf'
link.click()
URL.revokeObjectURL(link.href)
}Private Dashboards
If your dashboard is behind authentication, render the HTML server-side: fetch the data, build the HTML string, and POST that to the API instead of a URL. This avoids credential exposure entirely and is more reliable than generating time-limited preview URLs. See the dashboard export use case for a complete server-side HTML rendering implementation.