ScreenshotNeo

BlogHTML to image & PDF

PDFCrowd CSS Not Loading: How to Fix Missing Styles in Converted PDFs

Find out why PDFCrowd cannot load CSS and fix it by checking conversion logs, asset URLs, access rules, timing, and separate header or footer templates.

By the ScreenshotNeo team4 October 20269 min read

If CSS is missing from a PDFCrowd conversion, start with the debug log and identify which stylesheet request failed. Then match the fix to how you sent the page: a URL, an HTML string, or a local file. Relative URLs commonly fail when the converter receives a standalone string or file; URL conversions can fail when the page or assets are private, local, or blocked. If the log shows the resources loaded successfully, investigate late-loading content or styles in a separately rendered header or footer.

PDFCrowd’s official FAQ recommends enabling debug logging with setDebugLog() to diagnose missing stylesheets and related resources. The log can include resource-loading details, timeouts, and browser console messages. PDFCrowd FAQ: stylesheets, images, and JavaScript · PDFCrowd PHP API guide: debugging and common problems.

1. Read the conversion log before changing settings

Turn on debug logging for the affected conversion, run it again, and look for the first failed CSS, font, image, or script URL. Note whether it failed to resolve, was denied, timed out, or was unavailable. A failed request points to a URL or access problem; a successful request with incomplete output points toward timing, visitor state, or a different rendering context.

In PDFCrowd’s PHP client, enable the log and retrieve its URL even if conversion raises an error:

<?php
require 'vendor/autoload.php';

$client = new \\Pdfcrowd\\HtmlToPdfClient('YOUR_USERNAME', 'YOUR_API_KEY');
$client->setDebugLog(true);

try {
    $client->convertUrlToFile('https://example.com/report', 'report.pdf');
} catch (\\Pdfcrowd\\Error $error) {
    error_log('PDFCrowd error: ' . $error);
    error_log('Status: ' . $error->getStatusCode());
    error_log('Reason: ' . $error->getReasonCode());
    throw $error;
} finally {
    $logUrl = $client->getDebugLogUrl();
    if ($logUrl) {
        error_log('PDFCrowd debug log: ' . $logUrl);
    }
}
?>

Use your actual PDFCrowd credentials. The PHP guide also notes that a local or connection failure can happen before a conversion log is available. If you use another client or the HTTP API, enable its equivalent debug logging and inspect the returned log link or conversion history. See the HTTP API documentation.

2. Match the asset fix to the conversion input

Input sent to PDFCrowd Why CSS may be missing What to do
URL conversion The converter cannot access the page or an asset, or the URL points to localhost/intranet. Check the failed URL from outside your browser session; make the resource reachable or configure the required authentication.
HTML string Relative links have no reliable document URL as their base. Use absolute public asset URLs or add a correct <base href> before the stylesheet links.
HTML file Relative links may resolve differently from the original site, and local paths are not accessible to the remote converter. Use absolute URLs, a base URL, or package the HTML and assets together in a ZIP while preserving paths.

For an HTML string: add a base URL or use absolute paths

A link such as <link rel="stylesheet" href="/static/report.css"> needs a known origin. If the stylesheet is public, the simplest option is an absolute URL. Alternatively, place a base element in the document head before relative links:

<!doctype html>
<html>
<head>
  <base href="https://www.example.com/">
  <link rel="stylesheet" href="static/report.css">
</head>
<body>
  <main>Report content</main>
</body>
</html>

Here the stylesheet resolves to https://www.example.com/static/report.css. Confirm the base points to the directory expected by your relative paths; a trailing slash can affect URL resolution. Do not use a base URL that points at localhost or an internal hostname the converter cannot reach.

For local HTML and assets: preserve the directory structure

When converting a file, placing the HTML and its CSS in the same ZIP can let relative paths resolve within the archive. Keep the referenced folder names and paths intact, and use the appropriate PDFCrowd file-conversion method. For example, if the HTML refers to assets/report.css, include that exact path in the archive. The official FAQ describes passing a ZIP of external assets to a convertFile... method. See PDFCrowd’s asset troubleshooting FAQ.

For rendered application HTML: inspect the final markup

Check the HTML that the application actually sends to PDFCrowd, rather than only the source template. Verify the rendered href, path casing, deployment prefix, and any asset-host configuration. In Django, PDFCrowd documents using complete asset URLs or adding a correctly configured <base> before stylesheet links. Its guide also notes that URL conversion makes a separate GET request and does not inherit the visitor’s Django session. PDFCrowd’s Django guide.

3. Check whether PDFCrowd can access the stylesheet

Take a failed URL from the log and request it independently. Confirm that it returns the stylesheet itself rather than a login page, redirect loop, error document, or HTML challenge. Then check:

  • Is the URL publicly reachable from outside your browser session?
  • Does the asset require a cookie, session, HTTP authentication, or signed URL?
  • Do a firewall, CDN, Cloudflare rule, hotlink protection, referrer restriction, or security plugin block automated requests?
  • Does the URL point to localhost, 127.0.0.1, a private IP, or an intranet hostname?
  • Does the page load its CSS from a separate host with its own access policy?

A URL that works on your machine may still be inaccessible from PDFCrowd’s servers. For protected pages, configure the appropriate cookies or authentication if supported by your integration, or send already-rendered HTML with assets made available to the converter. Never assume the browser’s logged-in session accompanies a URL conversion. PDFCrowd’s WordPress missing-content guide recommends opening a failed resource URL directly and checking access controls.

4. Separate missing resources from late-loading content

If the log shows CSS loaded, but the page still looks incomplete, check when the page adds its content and styles. Some pages need JavaScript to finish rendering; some content appears only after a form submission, filter, or scroll. Use a reliable wait-for-element marker where possible, or a suitable JavaScript delay if there is no stable marker. For lazy-loaded content, increase the content viewport height so the content can be triggered. PDFCrowd documents these approaches in its missing-content guidance and API documentation.

Do not disable JavaScript as a general CSS fix. It can prevent the missing content from loading. If the PDF should reflect visitor-generated state—such as entered values or selected filters—use the conversion mode that captures that state where your integration supports it. A plain URL request may render the page’s default state instead.

5. Check headers, footers, and print styles separately

If the main document is styled but a header or footer is not, treat that region as its own template. PDFCrowd renders header and footer templates separately from the main page, so include the CSS each template needs and ensure its external assets can be reached from the converter. PDFCrowd’s API guide.

If the stylesheet loads but the PDF uses screen styling instead of print styling, check whether the source provides print-specific CSS and enable PDFCrowd’s print-media option for your client. Alternatively, apply the necessary custom CSS. These settings address which styles are applied; they will not make an inaccessible stylesheet URL load.

6. Make one targeted change at a time

  1. Save the debug log and identify the first relevant failed or delayed resource.
  2. Record whether the input is a URL, HTML string, or file.
  3. Change the matching issue: asset URL/base, archive paths, access/authentication, wait condition, or template CSS.
  4. Run the same conversion again and compare the log and PDF.
  5. Keep the working change and investigate the next issue only if styles are still missing.

This controlled sequence makes it easier to tell whether the problem was URL resolution, access, timing, or a separate template context.

Runnable Python example: enable PDFCrowd debug logging

Install the client with pip install pdfcrowd. This example converts a URL and prints the debug-log URL when available. Replace the credential placeholders and target URL.

import os
import sys
import pdfcrowd

client = pdfcrowd.HtmlToPdfClient(
    os.environ["PDFCROWD_USERNAME"],
    os.environ["PDFCROWD_API_KEY"],
)
client.setDebugLog(True)

try:
    pdf_bytes = client.convertUrl("https://example.com/report")
    with open("report.pdf", "wb") as output:
        output.write(pdf_bytes)
except pdfcrowd.Error as error:
    print(f"PDFCrowd error: {error}", file=sys.stderr)
    print(f"Status: {error.getStatusCode()}; reason: {error.getReasonCode()}", file=sys.stderr)
    raise
finally:
    log_url = client.getDebugLogUrl()
    if log_url:
        print(f"Debug log: {log_url}", file=sys.stderr)

For string conversion, use convertString(html) and make sure the string includes absolute asset URLs or a suitable base element. For a local document, use the relevant file conversion method and bundle local assets as documented by PDFCrowd.

Common errors and fixes

Symptom Likely cause Fix
Stylesheet URL fails in the debug log Wrong path, missing base URL, or inaccessible host. Correct the rendered URL; use an absolute public URL or a base element before relative references.
CSS works in a browser but not in a conversion The browser has a session or network access that the converter lacks. Check the URL without your logged-in session; configure supported authentication or expose the required asset safely.
URL conversion produces a login page The converter’s request does not carry the visitor’s session automatically. Configure the required cookies/authentication, or send rendered HTML using a suitable approach.
Local file conversion has unstyled output Relative resources are not packaged or resolve from a different location. Use absolute URLs, a correct base URL, or a ZIP archive that preserves referenced paths.
Only the header or footer is unstyled Its template does not include the necessary CSS or cannot load its assets. Add styles to that template and verify its external resource URLs.
Content appears after a delay or scroll JavaScript rendering or lazy loading finishes after capture begins. Wait for a stable element, use an appropriate delay, or increase content viewport height for lazy content.
The client times out without a useful log The request or connection failed before PDFCrowd completed conversion. Check client and application timeouts and connectivity; a local or connection failure may occur before a conversion log is available.

Performance, reliability, and cost considerations

Debug logging adds useful diagnostic output, so enable it while investigating and retain the log URL with the conversion record. A longer fixed delay increases conversion time and may still miss content that loads unpredictably; a reliable element wait is usually a more targeted choice. Making assets publicly reachable can simplify fetching, but do not expose protected documents or private stylesheets casually—use the authentication method supported by your workflow.

For reliability, keep asset URLs stable, test the exact conversion input that production sends, and distinguish an application-side timeout from a failed resource request. Do not infer that CSS is the cause from appearance alone: a login page, blank response, or visitor-state difference can make the output look unstyled. The dossier does not establish a PDFCrowd-specific cost figure for these fixes; check your current plan and conversion terms in your account.

Or skip the browser setup

If your goal is to inspect a page visually or produce a page capture, ScreenshotNeo is a website screenshot API and MCP server from ScreenshotNeo. It can return a screenshot or PDF from one GET request. It is an alternative capture workflow; it does not change the way PDFCrowd resolves CSS in your existing conversion.

One-call screenshot examples and the ScreenshotNeo documentation:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
  • Cookie banners, popups, and chat widgets are removed before the shot.
  • Bot checks, blank pages, and failed loads are never billed.
  • An MCP server lets AI agents take screenshots.
  • 1,000 screenshots a month are free with no card; paid plans start at $5 for 3,000.

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

FAQ

Will adding a base element fix every missing stylesheet?

No. It resolves relative URLs when they point to assets the converter can reach. It does not grant access to private assets or make localhost reachable.

Should I switch to URL conversion to fix CSS?

Only if the page and its assets are reachable to PDFCrowd and the page can render in the state you need. URL conversion has its own access and session requirements.

Does this mean my CSS is unsupported?

Not by itself. First verify that the stylesheet was requested and loaded. A failed request is different from a loaded stylesheet whose rules do not produce the expected print layout.