ScreenshotNeo

BlogHTML to image & PDF

PDFShift PDF Is Missing CSS or Images: How to Fix It

Diagnose missing images and styles in PDFShift PDFs. Fix lazy loading, check asset access, and wait for page readiness without hanging conversions.

By the ScreenshotNeo team4 October 20268 min read

If a PDFShift PDF is missing images, first check whether the page loads them only after scrolling: PDFShift says conversion does not ordinarily scroll the page, so lazy-loaded images may never be requested. Trigger a scroll or wait for a page readiness function. If CSS is missing, check that the stylesheet URL is correct and reachable by the converter; PDFShift also accepts CSS rules or a URL through its css parameter. These are diagnostic branches, not a diagnosis of any one conversion: the source URL or HTML, request options, resource responses, and output are needed to identify a specific failure.

This guide follows PDFShift’s documented behavior and examples. Check the current API or SDK documentation for option names and behavior that may vary by integration.

1. Identify which assets are missing

Start by separating the failure into one of these cases:

  • Only images below the fold are missing: suspect lazy loading or a page that needs scrolling before images are requested.
  • Some or all image elements are missing: inspect their URLs and whether the conversion service can fetch them.
  • CSS rules are missing: inspect stylesheet URLs and responses; determine whether the expected stylesheet is part of the source page or must be supplied separately.
  • The entire PDF looks incomplete: check the source page status, JavaScript readiness, and whether the conversion began before the page finished rendering.

Compare the PDF with the original page. In the source HTML, distinguish <img> elements from CSS background images and external stylesheets. Record the exact resource URLs and inspect the conversion request. Absolute URLs are often easier to diagnose than relative paths because they show exactly what the converter must fetch.

Then check whether each URL responds successfully from a context the converter can reach. A URL that works in your browser may still be inaccessible to a conversion service because of authentication, network restrictions, or how the URL is resolved. These are practical diagnostic checks; the reviewed PDFShift material does not provide a complete checklist for every access-control or URL-resolution failure.

2. Fix images that load only after scrolling

PDFShift documents lazy loading as one cause of missing images: conversion does not ordinarily scroll the page, while some sites request images only when they approach the viewport. Its help article shows adding JavaScript to scroll to the bottom before capture:

{
  "javascript": "window.scrollTo(0, document.body.scrollHeight);"
}

Adapt this to the request format used by your integration. Scrolling can prompt lazy images to load, but it does not prove that every request succeeded. A page may need more time, more than one scroll, or a specific interaction before it loads all assets.

Wait for an explicit page condition

For more control, PDFShift’s help article illustrates a globally available isPDFShiftReady function and a wait_for option that names it. The function scrolls and checks image completion:

window.isPDFShiftReady = function () {
  window.scrollTo(0, document.body.scrollHeight);
  return Array.from(document.images).every(function (image) {
    return image.complete;
  });
};
{
  "wait_for": "isPDFShiftReady"
}

The API option reference describes wait_for as waiting for a globally available function to return a truthy value. Make sure the function is installed in the page context where PDFShift evaluates it, as supported by your API integration.

Important edge case: image.complete can remain false when an image request fails. PDFShift warns that this can leave the readiness function false and cause the conversion to block and ultimately fail. Do not make conversion depend indefinitely on every image succeeding. Define a bounded wait or an application-level timeout and decide what to do when an asset fails, such as logging the URL and continuing when that image is optional. The exact timeout and failure-handling mechanism depends on your integration.

Check the image-loading option carefully

PDFShift’s option reference lists lazy_load_images for loading images that would otherwise load only when visible. The reviewed reference is for an Elixir client, version 0.2.4. Confirm that the option exists and behaves as expected in your API version or SDK before relying on it.

3. Diagnose missing CSS

First verify that the stylesheet URL is the intended one and that it returns successfully from a context available to the converter. Check for stylesheets referenced by the HTML as well as stylesheets supplied in conversion options. Confirm that the request is converting the expected source and that the style rules you need apply to the PDF output.

PDFShift’s css parameter accepts either a CSS string or a URL. The vendor guide demonstrates supplying a remote stylesheet URL; the option reference describes the parameter as appending styles to the document. For required rules, you can use the parameter or include the rules with the HTML, when appropriate. This reduces reliance on a separate stylesheet request, but it is not a guaranteed fix for unrelated rendering or access failures.

{
  "css": "https://example.com/pdf-print.css"
}

Or supply rules directly as a string:

{
  "css": "body { color: #222; } @media print { .screen-only { display: none; } }"
}

Use the actual URL or rules for your document. The examples illustrate the parameter shape, not a claim that those stylesheets exist.

4. Check source status and render timing

PDFShift’s client option reference lists raise_for_status, which stops conversion when the source status is not 2xx, and delay, which waits before capture. In that reference, the delay is limited to 10 seconds. These options can help investigate a failing source response or a page that is still rendering, but increasing a delay is not proof that a missing asset URL or stylesheet has been fixed.

Prefer a readiness check tied to a real page condition when one is available. If a page depends on client-side rendering, check that the relevant content exists before conversion and ensure the wait has a bounded failure path. Also inspect whether the same resource succeeds when loaded from the source page without the conversion service.

5. Reduce avoidable external dependencies

PDFShift recommends reducing network requests to improve conversion speed. Its help guidance suggests sending raw HTML rather than a URL where feasible, inlining CSS and JavaScript when practical, removing unnecessary scripts, using base64 image data where appropriate, and optimizing image dimensions.

These steps can make a document less dependent on external fetches and reduce work during conversion. Treat them as reliability and performance techniques, not proof of the root cause. A failed request still needs investigation, especially if the asset is required for a correct PDF.

6. Troubleshooting checklist

Symptom Likely area to inspect Next action
Images below the fold are absent Lazy loading; no scroll before conversion Trigger a scroll, then wait for the page’s image-loading condition.
Readiness wait never finishes A failed image may keep image.complete false Log failed image URLs and use a bounded wait with an explicit failure policy.
Styles are absent or incomplete Stylesheet URL, resource access, or CSS supplied to the conversion Check the stylesheet response; try required rules through css as a string or URL.
Output captures an earlier page state Rendering or asynchronous content was not ready Wait for a page-specific condition; use a delay only as a diagnostic or when a fixed wait is appropriate.
Conversion fails on a non-success source response Source status and raise_for_status behavior Check the source response and the option behavior for your client and API version.
Only background images are absent CSS rule or asset URL, rather than an <img> load Inspect the computed CSS and the background image request separately.

7. Performance, reliability, and cost considerations

Scrolling and waiting can add conversion time, particularly on long pages or pages with many lazy assets. Wait for the condition that matters instead of adding an unnecessarily long fixed delay. Avoid a readiness predicate that can remain false forever after an optional asset fails.

Inlining critical styles or embedding suitable assets can reduce external requests, but increases the size of the HTML payload. Optimizing image dimensions can reduce transfer and processing work. The right balance depends on the document and the limits of your integration.

No failure-rate or success-rate statistic is established by the reviewed sources. PDFShift’s guidance identifies possible causes and supported options; it does not establish the cause of a particular failed job. For a specific incident, preserve the request parameters, source response, relevant asset responses, and resulting PDF so the failure can be reproduced and narrowed down.

8. Use ScreenshotNeo when the deliverable can be an image

ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. It returns a PNG, JPEG, WebP, or PDF from one GET request. It is an alternative to try first when the job is capturing a web page and a screenshot or PDF fits the workflow; it is not a claim that ScreenshotNeo fixes a PDFShift conversion or replaces every PDF-generation requirement. See ScreenshotNeo and the API documentation.

For example, this cURL request captures a page as WebP:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', new Uint8Array(await res.arrayBuffer()));

With Node.js on a runtime without Bun.write, save the response bytes using the runtime’s filesystem API. The endpoint and parameters are documented at ScreenshotNeo docs.

Or skip the browser setup

ScreenshotNeo accepts cookie or consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before the shot; each step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing, and response headers report the page verdict and billing status. Its MCP server lets AI agents using Claude, Cursor, or another MCP client take screenshots. The free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000 screenshots.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Sign up free for 1,000 screenshots a month, with no card required.

9. Frequently asked questions

Does img.complete mean the image loaded successfully?

No. A failed image can also leave a readiness check waiting or failing, so handle errors and bound the wait.

Can PDFShift add CSS to the source page?

Its css parameter accepts CSS as a string or a URL. Check your integration’s current documentation for the exact request shape.

Will a longer delay fix every missing asset?

No. A delay can help when rendering is still in progress, but cannot by itself correct an inaccessible or incorrect resource URL.

Is ScreenshotNeo a PDFShift setting?

No. It is a separate screenshot API and MCP server. Use it when its screenshot or PDF output matches the task.

Sources

  • PDFShift documentation and its help article, “All my images are not loaded when I convert to PDF?”
  • PDFShift API option reference for wait_for, lazy_load_images, css, delay, and raise_for_status; the cited option reference is for Elixir client version 0.2.4, so confirm applicability to your integration.
  • PDFShift performance guidance on reducing external requests, inlining resources, and optimizing image dimensions.