How to Wait for Web Fonts to Load Before PDFShift Captures a Page
Use PDFShift’s wait_for hook with document.fonts.ready so PDF generation waits for web fonts instead of relying on a fixed delay.
Use PDFShift’s wait_for option to make conversion wait until a named, globally available JavaScript function returns a truthy value. Have that function report when document.fonts.ready resolves. You can put the readiness code in the page or inject it with PDFShift’s javascript parameter if you cannot edit the page. PDFShift documents this readiness workflow.
1. Add a font readiness signal
document.fonts.ready is a promise that resolves when the document’s font loading and related layout work have settled. Set a flag when it resolves, then expose a global function that PDFShift can poll:
let allFontsAreLoaded = false;
document.fonts.ready.then(() => {
allFontsAreLoaded = true;
});
function areFontsReady() {
return allFontsAreLoaded;
}
The function must be available in the rendered page’s global context. PDFShift repeatedly calls the function named by wait_for and continues when it returns a truthy value. The function name in the request must match the global function exactly.
2. Configure PDFShift to wait
Set wait_for to areFontsReady. The following is a complete cURL request using the documented function-name approach. Replace the API key and target URL with your values:
curl -X POST https://api.pdfshift.io/v3/convert/pdf \
-H 'X-API-Key: YOUR_PDFSHIFT_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"source": "https://example.com/report",
"wait_for": "areFontsReady"
}' \
--output report.pdf
Confirm the endpoint, authentication, and request fields against the current PDFShift API documentation for your account and integration. The essential part for font readiness is the wait_for value: it points to a function name, not to a promise or JavaScript expression.
3. Put the signal in the page or inject it
When you control the source page
Include the readiness code in a script that runs in the page being converted. Make sure the global function is established before PDFShift begins polling. If your application loads fonts dynamically after its initial font set becomes ready, signal only after those additional font loads have also completed.
When you cannot edit the page
PDFShift documents using its javascript parameter to inject the readiness code. Supply the code through that parameter using the serialization format required by the current API documentation, and set wait_for to areFontsReady. The injected code still needs to create a function that is globally available in the page context.
Do not assume that an arbitrary inline function, a closure-local function, or the promise itself can be passed as wait_for. The documented mechanism polls a named global function and checks whether its return value is truthy.
4. Why this works better than a fixed delay
A fixed sleep guesses how long a font request will take. That guess can be too short on a slow or cold request and unnecessarily long when fonts are already cached. The readiness function expresses the condition the conversion actually needs: the browser’s font set has settled.
The same polling mechanism can wait for other page-specific asynchronous work, such as chart rendering, by returning true only after that work is ready. Keep the condition narrow: PDFShift’s total conversion timeout includes page loading, waiting, and conversion, so extra conditions use time that would otherwise be available for the PDF itself.
5. Font loading edge cases
- Remote font host is slow or blocked:
document.fonts.readycannot make an unreachable font server respond. Check the page’s network access and font URL. PDFShift suggests trying locally hosted or base64-encoded fonts when custom fonts load inconsistently. - Cross-origin font configuration is wrong: verify the font host’s access headers and the page’s font URL. A font request that fails may leave the page rendering with a fallback font.
- Fonts are added after the promise resolves: if application code introduces more fonts later, coordinate the readiness signal with that application work; the initial font readiness signal may be too early for a later change.
- Font is ready but layout still changes: if your page performs additional asynchronous layout work after fonts settle, include that work in the readiness condition too, such as waiting for the application’s chart or rendering state.
- Function is not global: module-scoped declarations may not be visible to the conversion poller. Define the named function in the page’s global scope as required by the integration.
6. Troubleshooting
| Symptom | Likely cause | What to check |
|---|---|---|
| Conversion proceeds before the font is ready | wait_for names the wrong function, or the function returns true too early. |
Match the option value to the global function name and return true only after document.fonts.ready resolves. |
| Conversion waits until it times out | The function is unavailable, keeps returning false, or the page never reaches the condition. | Check that JavaScript runs, the function is globally visible, the readiness flag changes, and required font requests can complete. |
| PDF uses a fallback font | The custom font failed to load or was unavailable to the rendering page. | Inspect the font URL and network access. Try hosting the font locally or embedding it as base64, as PDFShift’s guidance suggests. |
| Works locally but not in conversion | The conversion environment may not have the same access to the page or font resources. | Check that both the page and font assets are reachable from the conversion environment and that the readiness script is included in that page context. |
| Request rejects the option | Request shape or parameter serialization does not match the current API endpoint. | Verify the endpoint and exact field format in PDFShift’s current API documentation; retain the function-name value for wait_for. |
7. Timeout, reliability, and cost considerations
Waiting consumes the conversion’s total time budget; page loading, the readiness wait, and PDF conversion share it. PDFShift’s help article has stated account-specific limits of 30 seconds for free accounts and 100 seconds for premium accounts. These are vendor-published values and can change, so check your current account terms before relying on them.
Prefer the readiness condition to an arbitrary long delay, but make sure the page can reach it reliably. A failed font host or a function that never returns true turns a rendering issue into a timeout. For frequently generated PDFs, dependable font hosting and a readiness function that covers only necessary work help avoid wasted wait time and repeat conversions.
8. Or skip the browser setup
If you need a clean page screenshot rather than a PDF, ScreenshotNeo offers a website screenshot API: one GET request returns a PNG, JPEG, WebP, or PDF. It accepts cookie and consent banners like a visitor, then removes more than 60 known consent platforms as well as newsletter popups and chat widgets; each cleanup step can be turned off. Its response identifies the page verdict and billing status in headers. See the ScreenshotNeo API documentation.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://stripe.com \
-o shot.webp
For PDF output, request the PDF format and configure the available PDF options in the API. ScreenshotNeo also supports full-page capture with lazy images loaded, selector capture, viewport and device settings, custom CSS and JavaScript, wait conditions, request blocking, cookies and headers, caching, asynchronous jobs, and bulk capture. Check the docs for exact parameter names and supported values.
Cookie banners, popups, and chat widgets are removed before the shot. Bot checks, blank pages, and failed loads are never billed; cache hits also cost nothing. An MCP server lets AI agents use take_screenshot, get_page_info, and capture_pdf. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots.
Sign up for ScreenshotNeo’s free 1,000 screenshots a month, with no card required.
FAQ
Can PDFShift wait directly on document.fonts.ready?
Use a named function for wait_for. The function can return a flag set when document.fonts.ready resolves; the documented option polls the function name until it returns a truthy value.
Can I use a delay instead?
A delay can be a fallback, but it cannot tell whether fonts actually finished loading. A readiness function adapts to the page’s state.
Does the same approach work for non-font content?
Yes. The function can report readiness for other asynchronous page content, provided it is globally available and eventually returns true.
What if the font is still inconsistent after waiting?
Investigate whether the font resource is reachable and correctly configured. PDFShift suggests trying a locally hosted or base64-encoded font for more consistent loading.


