Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Scan for outdated or missing drivers - takes under a minute3Repair Windows errors before they cause bigger problemsSome links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
A Playwright PDF that is rejected by a reader and a PDF that opens to a blank page are different failures. Start by confirming which one you have, then generate the document with Playwright’s Chromium path, select print or screen CSS deliberately, wait for the application’s actual content, and review print-specific options. The following diagnostic flow covers missing text, absent images, clipped pages and generation exceptions without assuming that one setting fixes every case.
1. Identify what “invalid” means
First preserve the exact bytes returned by page.pdf() (or the file written with its path option) and record the exception, if any. There are two broad symptoms:
- The PDF reader rejects the file: PDF generation failed, the output was not saved completely, or another part of the program replaced the file. Capture the Playwright exception and verify the file you inspect is the one produced by the failing run.
- The file opens but is empty or incomplete: Chromium produced a valid PDF, but print CSS, readiness timing, missing assets or page-size settings prevented the expected content from appearing.
The Playwright Page API returns PDF bytes and can write directly to a path. Do not diagnose a rendering problem as byte-level corruption until you have checked both the exception and the saved file.
2. Use Chromium for page.pdf()
PDF generation through the Page API is a Chromium workflow. A July 2025 report describes Playwright 1.53.0 on Ubuntu 22.04 with Python 3.10 failing under WebKit with an error that PDF generation is supported only for headless Chromium. Use browser_type.chromium, and note your Playwright version, browser build, operating system and launch mode when behavior differs between machines. Playwright’s browser documentation distinguishes its Chromium builds, including headless implementations.
#1 Best Overall
- BEST FOR SMALL BUSINESSES – Engineered for extraordinary productivity, the Brother DCP-L2640DW Monochrome (Black & White) 3-in-1 combines laser printer, scanner, copier in one compact footprint and delivers high-quality black & white prints
- FAST PRINTER WITH EFFICIENT SCANNING – Produces documents quickly with print speeds up to 36 ppm(2) and scan speeds up to 23.6/7.9 ipm(3) (black/color). A 50-page auto document feeder(4) allows for convenient, time saving multi-page scanning and copying
- FLEXIBLE CONNECTION OPTIONS – Easily navigate the changing demands of your business with secure multi-device connectivity via built-in dual-band wireless (2.4GHz / 5GHz) and Ethernet. Or connect locally to a single computer via USB interface
- BROTHER MOBILE CONNECT APP – Print, scan, and manage your wireless printer anytime, from almost anywhere from your mobile device. Order Brother Genuine Supplies, track toner usage, and complete more work on-the-go(5)
- CHOOSE BROTHER GENUINE TONER – When it’s time to replace your toner, be sure to choose Brother Genuine TN830 or TN830XL replacement toner. And with Refresh EZ Print Subscription Service, you’ll never worry about running out of toner again and you’ll enjoy savings of up to 50%(6) on Brother Genuine Toner. Get started with Refresh today with a Free Trial(1)
from pathlib import Path
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page()
page.goto("https://example.com", wait_until="load")
pdf_bytes = page.pdf(path="out/report.pdf")
print(f"wrote {len(pdf_bytes)} bytes")
browser.close()
Install the browser that matches your Playwright package (for example, after installing Playwright, run its browser-install command) and test with a minimal page before adding your application. Navigating to an existing PDF is a separate operation from generating a PDF with page.pdf(); do not use the latter API to infer support for every PDF-navigation scenario.
3. Decide whether the PDF should use print or screen CSS
page.pdf() uses print media by default. A stylesheet can therefore hide navigation, change colors, collapse containers or otherwise produce a layout unlike the browser window. If the screen layout is the intended design, emulate screen media before printing:
page.emulate_media(media="screen")
pdf = page.pdf(
path="out/screen-layout.pdf",
print_background=True,
)
If print output is intended, leave the default media and inspect the page’s @media print rules. Look specifically for display: none, white text on a white print background, hidden overflow, zero-height wrappers and print-only page-break rules. These are properties of the page you are printing, not universal Playwright defects.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Print backgrounds and colors
Background graphics are disabled unless requested. Set print_background=True when colored panels, background images or shaded table rows are part of the document. Printing can also modify colors; the API documentation suggests the CSS declaration -webkit-print-color-adjust: exact when exact colors are required.
Rank #2
- BEST FOR HOMES & HOME OFFICES – Engineered for consistent, premium print quality, the Brother HL-L2405W Monochrome (Black & White) Laser Printer delivers sharp, crisp prints at an affordable price. Prints one-sided documents at speeds up to 30ppm(2)
- COMPACT, CONNECTED PRINTER – Flexible connection options make this an ideal printer for home use and at-home offices. Securely connect to multiple devices with built-in dual-band wireless (2.4GHz/5GHz) or locally to a single computer via USB interface
- BROTHER MOBILE CONNECT APP – Manage your printer remotely and print from your mobile device anytime, from almost anywhere. Order Brother Genuine Supplies, track toner usage, and complete more work on-the-go(3)
- VERSATILE PAPER HANDLING – Enjoy seamless, reliable everyday printing with the 250-sheet paper tray(4) and a manual feed slot that enables printing on envelopes and specialty pape
- BROTHER IS AT YOUR SIDE – Backed by Brother with a 1-year limited warranty and free online, call, or live chat support for the life of your printer
@media print {
.screen-only { display: none; }
.report { break-inside: avoid; }
}
.report {
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
4. Wait for the content that must be printed
page.goto() normally waits for the load event, which includes dependent stylesheets, scripts, iframes and images requested as part of navigation. Modern applications can still fetch data after that event, lazy-load images, hydrate components or render rows after an API response. Printing immediately can therefore produce a valid but empty document.
Wait for a page-specific readiness signal: a final heading, a report container with content, a known row count or an application-provided completion marker. Prefer a condition tied to the document over an arbitrary sleep.
from playwright.sync_api import expect
page.goto(report_url, wait_until="domcontentloaded")
page.locator("[data-report-ready='true']").wait_for(state="visible")
expect(page.locator("h1")).to_have_text("Monthly report")
# If the report has a measurable list:
expect(page.locator("table tbody tr")).to_have_count(25)
page.pdf(path="out/monthly.pdf", print_background=True)
The navigation guide cautions that networkidle is discouraged as a generic readiness test: analytics, WebSockets or polling can keep a page busy forever, while a page can become visually ready before all background requests stop. Use wait_for_timeout() only as a short diagnostic experiment, not as your production readiness strategy.
Recommended Free Tools
Images, fonts and lazy content
For image-heavy pages, wait for the relevant image elements and verify they have completed loading before printing. A lazy image may not request its source until it enters a viewport. Scroll the page or trigger the application’s own “load more” behavior, then wait for a selector that confirms completion. If your application controls the HTML, add an explicit readiness attribute after data, images and fonts needed by the report are ready.
Rank #3
- FAST PRINT SPEEDS: Print up to 19 pages per minute.
- COMPACT DESIGN: Space-saving, compact design fits anywhere in your home, school or small office.
- WIRELESS CONNECTIVITY: Print from almost anywhere in your workspace using your compatible mobile device.
- PAPER CAPACITY: Up to 150 sheets.
- SUSTAINABILITY: Uses less than 2 watts in Energy Saver mode.
5. Review PDF options that affect layout
Once media and readiness are correct, check the options documented by the Page API. A mismatch in page dimensions can make content appear clipped or off-page even though the PDF is valid.
| Option | Use it when | Typical failure it prevents |
|---|---|---|
print_background=True |
Background graphics or colored sections matter | White or visually incomplete pages |
format |
You want a standard paper size such as A4 or Letter | Unexpected scaling or page breaks |
width / height |
The document has a custom viewport-like size | Clipping caused by an assumed paper size |
prefer_css_page_size=True |
Your stylesheet defines @page dimensions |
Chromium overriding the CSS page size |
margin |
Headers, footers or edge-to-edge content need predictable space | Overlapping or clipped content |
page_ranges |
Only selected pages should be exported | Missing pages mistaken for blank output |
scale |
Content needs controlled enlargement or reduction | Overflow or tiny text; documented range is 0.1–2 |
Do not combine contradictory sizing strategies without testing. For example, a CSS @page size, a fixed format and a large scale can produce a layout that technically prints but no longer fits its intended paper.
A complete synchronous example
from pathlib import Path
from playwright.sync_api import sync_playwright, expect
URL = "https://example.com/report"
OUT = Path("out/report.pdf")
OUT.parent.mkdir(parents=True, exist_ok=True)
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page(viewport={"width": 1440, "height": 1000}, device_scale_factor=1)
page.goto(URL, wait_until="domcontentloaded")
page.locator("[data-report-ready='true']").wait_for(state="visible", timeout=30_000)
expect(page.locator("main")).to_be_visible()
# Omit this line when the report is intentionally print-styled.
page.emulate_media(media="screen")
page.pdf(
path=str(OUT),
format="A4",
print_background=True,
prefer_css_page_size=True,
margin={"top": "16mm", "right": "14mm", "bottom": "16mm", "left": "14mm"},
scale=1,
)
browser.close()
print(f"Created {OUT}")
Replace the readiness selector and URL with signals owned by your application. A selector that merely exists in the initial HTML is not enough if its contents are populated later.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →6. Why images can be missing
A May 2024 issue reported blank image areas in a Windows 10 environment using Python 3.11.8, Playwright 1.44.0 and Chromium 125.0.6422.26. The reproduction already used networkidle, screen-media emulation and print_background=True. A maintainer treated it as a related bug and closed the request while noting that PDF printing was not a project priority. This is historical, environment-specific evidence—not proof that current Playwright releases have the same defect.
Rank #4
- BEST FOR HOME OFFICES & SMALL TEAMS – Engineered for consistent, premium print quality, the Brother HL-L2460DW Monochrome (Black & White) Laser Printer produces documents that are clear, crisp, and easy to review and share, all at an affordable price
- COMPACT, CONNECTED, EXCEPTIONALLY EFFICIENT– Connect with built-in dual-band wireless (2.4GHz/5GHz), Ethernet, or to a single computer via USB interface. Prints at speeds up to 36ppm(2), plus automatic duplex printing saves time and reduces paper waste
- BROTHER MOBILE CONNECT APP – Manage your wireless printer remotely and print from your mobile device anytime, from almost anywhere. Order Brother Genuine Supplies, track toner usage, and complete more work on-the-go(3)
- VERSATILE PAPER HANDLING – Tackle high-volume black & white printing with the 250-sheet capacity paper tray.(4) The manual feed slot enables printing on envelopes and specialty paper
- BROTHER IS AT YOUR SIDE – Backed by Brother with a 1-year limited warranty and free online, call, or live chat support for the life of your printer
For a current incident, create a minimal page containing one local image and one remote image, then test it with a current Playwright and Chromium pair. Record whether the image loads in the page screenshot, whether it is present in the DOM, and whether it appears in the PDF. That isolates application timing and asset permissions from a browser regression. Check image URLs, authentication headers, CORS or signed URLs, lazy-loading behavior and the image’s computed print styles before attributing the result to the historical issue.
7. A practical troubleshooting sequence
- Save and inspect the exact output. Capture the exception, file path and byte length. Open the file in more than one PDF reader if it is rejected by only one reader.
- Reduce to Chromium. Re-run with
p.chromium.launch(headless=True)and record Playwright, Chromium, Python and operating-system versions. - Print a static page. If a minimal static HTML page works, the failure is likely in application readiness, assets or CSS rather than basic PDF generation.
- Check media. Compare default print media with
page.emulate_media(media="screen"); inspect@media printand@page. - Wait for an application signal. Replace immediate printing and generic sleeps with a selector, count or explicit ready state.
- Verify assets. Confirm images and fonts load in the page, trigger lazy content, and test authenticated resources with the same context and cookies.
- Review sizing. Check paper format, CSS page size, margins, ranges and scale for clipping or intentionally omitted pages.
- Reproduce minimally on current versions. Only then compare the symptoms with historical issue reports.
8. Reliability and performance practices
- Pin and regularly update a compatible Playwright package and Chromium build; log both versions with every generated document.
- Use a bounded timeout for readiness conditions and fail with a useful diagnostic rather than silently emitting an empty PDF.
- Keep a small fixture page in CI that exercises text, a background, a remote image and a multi-page section.
- Prefer deterministic readiness markers over fixed delays. A delay can waste time on fast runs and still be too short on slow ones.
- Capture a diagnostic screenshot immediately before PDF generation. It shows whether the page itself is empty before you investigate PDF rendering.
- Limit concurrency according to available CPU and memory; each Chromium context and page consumes resources, especially for large, image-heavy documents.
- Store the source URL, media choice, paper settings, browser versions and readiness duration alongside generated files so regressions are comparable.
Or skip the browser setup
If your requirement is simply a clean screenshot or PDF of a URL rather than a custom Playwright workflow, ScreenshotNeo provides a single request. It accepts consent banners like a visitor and removes more than 60 known consent platforms, newsletter popups and chat widgets before capture. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server exposes take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients.
For API parameters and all options, see the ScreenshotNeo documentation. This call captures Stripe as a WebP file:
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(`${res.status} ${res.statusText}`);
const fs = await import('node:fs/promises');
await fs.writeFile('shot.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo includes full-page capture with lazy images loaded, CSS-selector element capture, dark mode, device presets and custom viewports, retina scale, PDF paper and page controls, custom CSS and JavaScript, clicks, selector or network-idle waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, TTL caching, signed links, asynchronous webhooks, bulk capture for up to 100 URLs per call, usage reporting and an OpenAPI specification. Existing parameter names used by other screenshot APIs are accepted to ease migration.
The Free plan includes 1,000 shots each month with no card. Paid plans start at $5 for 3,000 shots; every feature is available on every plan, and yearly billing provides two months free. Create a free ScreenshotNeo account to try it.
Best Value
- FROM AMERICA'S MOST TRUSTED PRINTER BRAND – Perfect for small teams printing professional-quality black & white documents and reports. Perfect for 1-3 people
- WORLD'S SMALLEST LASER IN ITS CLASS – Precision laser printing that fits anywhere
- FAST PRINT SPEEDS – Up to 21 black-and-white pages per minute single-sided
- WIRELESS WITH SELF-RESET – Helps you stay connected
- PRINT FROM ANY DEVICE – Wireless printing from any mobile device, PC or tablet. Works with Microsoft, Mac, AirPrint, Android, Chromebook and more
FAQ
Can I generate a PDF with Playwright WebKit or Firefox?
The documented page.pdf() generation path is Chromium-based. Use Chromium for this workflow; test other engines separately for their own supported capabilities.
Should I always use networkidle before printing?
No. It is discouraged as a generic readiness test. Wait for an application-specific state that proves the content intended for the PDF is complete.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Outdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchDoes print_background=True force images to appear?
No. It enables background graphics. It does not repair missing image requests, lazy-loading timing, authentication failures or a browser-specific rendering defect.
Frequently Asked Questions
Can I generate a PDF with Playwright WebKit or Firefox?
The documented page.pdf() generation path is Chromium-based. Use Chromium for this workflow; test other engines separately for their own supported capabilities.
Should I always use networkidle before printing?
No. It is discouraged as a generic readiness test. Wait for an application-specific state that proves the content intended for the PDF is complete.
Does print_background=True force images to appear?
No. It enables background graphics. It does not repair missing image requests, lazy-loading timing, authentication failures or a browser-specific rendering defect.
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 →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.

