What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
When JavaScript creates content that must appear in a PDF, use a browser renderer such as Playwright for Python. Navigate to the page—or load your own HTML, add the external script with page.add_script_tag(url=...), and wait for the content your document needs before calling page.pdf(). The navigation load event is a starting point, not proof that a single-page app has finished fetching and rendering its data. Playwright Page API · Playwright navigation guide
Choose the right way to load the JavaScript
There are two different tasks that are easy to confuse. If the target is already a web page, navigate to its URL with page.goto(); the page’s own HTML normally loads its script files. If you have an HTML document and want to attach an external script to it, create or load that document and call page.add_script_tag(url=...). In both cases, export only after the content to be printed is ready.
| Situation | Use | Important qualification |
|---|---|---|
| Capture a remote page that runs JavaScript | Playwright with Chromium and page.goto(url) |
Wait for application-rendered content if it arrives after navigation. |
| Render your own HTML and attach a script hosted elsewhere | page.set_content(html), then page.add_script_tag(url=script_url) |
The page must be able to retrieve the script; cross-origin restrictions or script errors can prevent rendering. |
| Convert static HTML and CSS with no JavaScript-generated content | WeasyPrint may fit | WeasyPrint does not execute JavaScript. First steps · Scope description |
For new work that depends on modern browser-side code, Playwright is the appropriate direction among these choices: it provides a browser page, script injection by URL, and PDF export. This is not a performance ranking; the cited sources do not provide a like-for-like benchmark for this workflow.
Install Playwright and its browser
In a virtual environment, install the Python package and its Chromium browser. The browser installation is a separate step; a Python import alone does not install the browser binary needed to launch.
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitches#1 Best Overall
python -m venv .venv- Activate the environment: on macOS or Linux,
source .venv/bin/activate; on Windows PowerShell,.venvScriptsActivate.ps1. python -m pip install playwrightpython -m playwright install chromium
For reproducible deployments, pin the Playwright package version in your dependency file and install its matching browser as part of the build or deployment process. Browser versions and rendering can change, so inspect representative PDFs after upgrades.
Convert an existing URL to PDF
This minimal synchronous example navigates to a public page, waits for the browser’s load event, and writes a PDF. Replace the URL with the page you are allowed to access.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://example.com", wait_until="load")
page.pdf(path="output.pdf")
browser.close()
The load event waits for dependent resources such as scripts, stylesheets, frames, and images. It does not guarantee that a modern app has completed later data requests or rendered its final interface. If the page fills in after navigation, use a selector or an application-specific readiness condition before printing.
Wait for a page-specific ready element
For example, if the page adds an element with the ID report-ready only after its report is rendered, wait for it explicitly:
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Rank #2
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("https://example.com/report", wait_until="load")
page.locator("#report-ready").wait_for(state="visible", timeout=30000)
page.pdf(path="report.pdf")
browser.close()
Choose a signal that corresponds to the content being printed, not merely a generic element that appears before data arrives. A selector timeout is useful: it fails the job rather than silently producing a PDF of a loading screen. For an app without a suitable element, expose or identify an app-specific state and wait for that state with Playwright’s page waiting APIs. Keep waits bounded so a broken page does not hang a conversion indefinitely.
Load your own HTML and add a script from a URL
When you control the HTML rather than navigating to a complete website, use page.set_content() to create the document and page.add_script_tag(url=...) to load the external JavaScript. The following runnable pattern assumes the script renders a #report-ready element after it has completed the work the PDF needs.
from playwright.sync_api import sync_playwright
html = """
Report
"""
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.set_content(html, wait_until="load")
page.add_script_tag(url="https://example.com/path/to/library.js")
# If the external script starts asynchronous work, wait for its result,
# not just for the script element to have loaded.
page.evaluate("window.renderReport()")
page.locator("#report-ready").wait_for(state="visible", timeout=30000)
page.pdf(path="output.pdf")
browser.close()
The example uses a placeholder script URL and an inline rendering function to make the readiness step concrete. In your page, replace them with the real script URL and the way that script is intended to initialize. A script can load successfully and still start asynchronous work; wait for that work’s finished state before export. Playwright documents the script URL option and PDF method in its Page API.
Set print behavior before exporting
page.pdf() uses print CSS media by default. That means rules inside @media print apply, and screen-only layouts may not be what the PDF shows. If you deliberately want screen media instead, set it before calling pdf():
page.emulate_media(media="screen")
page.pdf(path="output.pdf")
Printed colors are adjusted by default. If exact background and foreground colors are important, use the CSS property -webkit-print-color-adjust: exact on the relevant elements and verify the result in the generated PDF. Also check page breaks, margins, headers and footers, and whether content intentionally hidden for print should remain hidden. Avoid switching to screen media as a blanket fix: it changes which CSS rules govern the document.
Choose a renderer based on what the document needs
Playwright for pages whose content depends on JavaScript
Playwright opens a browser page, can navigate to a URL or add a script URL to a document, and can export that page as a PDF. It is the fit when the document must run client-side code, fetch data, or reflect browser rendering. Its flexibility brings browser installation and page-readiness decisions that a static renderer does not require. Page API · Navigation guidance
WeasyPrint for static HTML and CSS
WeasyPrint accepts URL input and fetches HTTP resources, but it does not execute JavaScript or perform live browser rendering. Use it for static markup or content already rendered into HTML, not as a way to run a URL-hosted script. Its default HTTP client does not handle cookies or authentication; the project documents custom URL fetching for some resource-loading needs. First steps · API reference, version 70.0
wkhtmltopdf for an existing legacy integration
wkhtmltopdf’s command-line documentation includes JavaScript controls such as enablement, delay, and a window-status option. Those documented switches do not establish compatibility with current JavaScript frameworks. Its upstream repository was archived on January 2, 2023, so evaluate it carefully before choosing it for new work. Usage documentation · Repository archive notice
The Tool Desk
Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Handle access, security, and deployment concerns
Authenticated pages and remote assets
A URL that works in your logged-in browser may not work in a clean automation browser. If the target requires a session, supply the needed authentication in the browser context or navigate through an authorized login flow before capture; do not assume a static renderer’s default fetcher will reuse browser credentials. WeasyPrint’s default HTTP client does not support cookies or authentication, though its documentation describes custom fetching. Confirm the actual page and asset access requirements before selecting a renderer.
Untrusted HTML and URLs
Rendering a user-supplied URL or HTML can expose a server-side renderer to network resources referenced by that content. WeasyPrint’s guidance specifically calls for constraining resource access and sanitizing untrusted HTML and CSS in server use cases. Apply equivalent caution to any server-side browser workflow: restrict which content can be submitted and what network destinations the rendering service can reach. Do not treat arbitrary external URLs as harmless input.
Version changes and output checks
Pin renderer dependencies where consistent output matters, and inspect representative PDFs whenever you upgrade. WeasyPrint notes that releases can change document rendering; the cited scope description is from its version 58.0 documentation and its API reference is version 70.0. That scope statement describes the project’s JavaScript limitation, not a newly introduced change. Browser updates can also alter rendered output, so test the actual layouts your users depend on.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Troubleshoot common PDF failures
| Symptom | Likely cause | What to do |
|---|---|---|
| Python reports that Chromium cannot launch or is missing | The Playwright package is installed but its browser binary is not. | Run python -m playwright install chromium in the same environment or build image used to execute the script. |
| The PDF contains a spinner, empty chart, or old data | Export happened at navigation load, before later app requests and rendering finished. |
Wait for the page’s actual ready selector or app-specific signal before calling page.pdf(). |
| Script injection fails or has no visible effect | The script URL may be inaccessible, blocked, invalid, or incompatible with the document; it may also load while its asynchronous work remains incomplete. | Check the URL and page errors, verify the script is allowed to load, and wait for the rendered result rather than only script insertion. |
| Colors or layout differ from the browser window | PDF output uses print media and adjusts printed colors by default. | Review print CSS; use page.emulate_media(media="screen") only when screen rules are desired, or apply -webkit-print-color-adjust: exact for colors that must be retained. |
| A remote resource is missing on an authenticated page | The renderer does not have the page’s session or authorization, or the chosen fetcher cannot supply it. | Provide authorized browser credentials for Playwright, or configure an appropriate custom fetcher where supported; verify resource access individually. |
| The conversion hangs on a page that never becomes ready | The wait condition has no effective timeout or depends on a signal that never appears. | Use a finite timeout and fail visibly when readiness is not reached; distinguish an app failure from a successful PDF job. |
Or skip the browser setup
If your goal is a screenshot or PDF of a website rather than a Python-controlled browser workflow, ScreenshotNeo is a website screenshot API and MCP server. A single GET request returns a PNG, JPEG, WebP, or PDF. For example, this saves a PDF of a public URL:
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallCrashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteBest Value
curl -G "https://api.screenshotneo.com/v1/shot"
-d access_key=YOUR_API_KEY
--data-urlencode url=https://stripe.com
-d format=pdf
-o shot.pdf
See the ScreenshotNeo API documentation for request options. Cookie and consent banners are accepted and removed before capture, along with supported newsletter popups and chat widgets; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for AI agents and MCP clients. The Free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. This is a hosted alternative, not a replacement for Playwright when you need custom Python browser logic or to add an arbitrary script to your own HTML before printing.
Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.
Frequently Asked Questions
Does Playwright wait for all JavaScript before making a PDF?
No universal event proves that every application task is finished. Wait for a page-specific selector or readiness state that corresponds to the content you need.
Can WeasyPrint run a JavaScript file loaded from a URL?
No. WeasyPrint can load HTML and remote resources but does not execute JavaScript; use a browser renderer for JavaScript-generated content.
Is there a benchmark showing which renderer is fastest for this task?
The cited official sources do not provide a comparable benchmark for URL-loaded JavaScript-to-PDF rendering, so no general speed ranking is established.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

