Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.
Use WeasyPrint for static or server-rendered HTML/CSS, and Playwright when the page depends on JavaScript or browser behavior. WeasyPrint turns a URL, file, string, or file object into PDF with HTML.write_pdf(). Playwright launches Chromium, waits for the page to render, and calls page.pdf() with browser print controls. Use ReportLab instead when you are designing the PDF from data, tables, and drawing primitives rather than converting an existing HTML document.
This guide shows runnable Python code, print styling, pagination, JavaScript handling, security boundaries, troubleshooting, and an API option when you do not want to manage a browser.
Choose the renderer before writing code
| Situation | Best fit | Reason |
|---|---|---|
| Invoice, report, email, or template with HTML and CSS already available | WeasyPrint | Focused HTML/CSS rendering with print-oriented pagination and no browser process to manage. |
| React, Vue, charts, client-side data, or other JavaScript-generated content | Playwright | Runs a real browser and can wait for navigation, network activity, and application state before printing. |
| PDF authored from structured data, tables, charts, and drawing operations | ReportLab | Its layout engine is designed for PDF primitives, not as a drop-in HTML/CSS renderer. |
If you are unsure, start with WeasyPrint. Move to Playwright when the PDF is missing content that only appears after JavaScript executes, or when matching Chromium’s print output matters more than a lightweight renderer.
Convert HTML with WeasyPrint
Install and make a PDF from a string
Install the Python package in the environment that will run the conversion:
#1 Best Overall
- RCA Female to HDMI Video Converters Adapter : The cable is used to convert analog composite input to HDMI 1080p output, displayed on a 1080p HD TV/TV/monitor.
- Input ports: 1xRCA Female (Yellow, White, Red), Output ports: 1xHDMI 1.3 1080p. NOT support 3D and 4K, NOT support HDMI Converts to AV
- AV to HDMI Converter: Plug and Play, Easy to Install and Operate, Powered by External USB Cable. Note: Please hook up the USB power cable (included) to 5V 1Apower source during use (not included power supply ).
- Support PAL, NTSC3.58, NTSC4.43, SECAM, PAL/M, PAL/N standard TV formats input. For PS2,PS3,Xbox,N64,STB, VHS, VCR, DVD Players and other devices with standard composite AV input.
- You Will Get : 1x RCA Female TO HDMI Converter, 1xHDMI cable, 1xUSB cable, 1xUser Manual. ONE YEAR WARRANTY - if you are not satisfied for any reason whatsoever, do not hesitate to contact us .
python -m pip install weasyprint
Then pass an in-memory document directly to HTML and write a file:
from weasyprint import HTML
html = """
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Invoice</title>
</head>
<body>
<h1>Invoice</h1>
<p>Total: $42.00</p>
</body>
</html>
"""
HTML(string=html).write_pdf("invoice.pdf")
write_pdf() creates one PDF. If you omit the target, it returns PDF bytes, which is useful for an HTTP response or object storage:
from weasyprint import HTML
pdf_bytes = HTML(string=html).write_pdf()
with open("invoice.pdf", "wb") as output:
output.write(pdf_bytes)
Load a URL or an existing HTML file
WeasyPrint accepts a URL or filename as well as a string. These forms let it resolve relative images, stylesheets, and fonts against the source document:
from weasyprint import HTML
HTML(url="https://example.com").write_pdf("example.pdf")
HTML(filename="report.html").write_pdf("report.pdf")
For a web application, returning bytes avoids a temporary file:
from flask import Flask, Response
from weasyprint import HTML
app = Flask(__name__)
@app.get("/invoice.pdf")
def invoice_pdf():
html = render_invoice_html() # your template function
data = HTML(string=html, base_url="https://your-app.example/").write_pdf()
return Response(data, mimetype="application/pdf",
headers={"Content-Disposition": "inline; filename=invoice.pdf"})
Set base_url whenever the HTML contains relative URLs and you are supplying a string. Without a base URL, a reference such as images/logo.png has no reliable location from which to load the image.
Control paper size, margins, and page breaks with CSS
WeasyPrint follows print CSS. Use @page for the sheet and margins, then hide screen-only elements in a print media query:
@page {
size: A4 portrait;
margin: 2cm;
}
@media print {
.no-print {
display: none;
}
}
.invoice {
break-inside: avoid;
}
.page-break {
break-before: page;
}
The size value can be a named paper size and orientation, or a custom dimension. Keep headings with their following content and use break-before, break-after, and break-inside to prevent awkward splits. Test long tables and paragraphs; a browser viewport is not a page layout.
Rank #2
- RCA to HDMI Converter: Converts analog RCA composite (Yellow, White, Red) input to HDMI 720P/1080P (60HZ) output,displayed on HDTV/Monitor,which can bring back your childhood memories.
- Plug to Play: ABLEWE Mini RCA to HDMI converter no extra drivers need, just plug and play,easy to use.Please hook up the USB power cable (included) to 5V power source during use.
- Wide Compatibility: Support source formats of PAL, NTSC3.58, NTSC4.43, SECAM, PAL/M, PAL/N standard TV. Provide advanced signal processing with great precision, colors, resolutions, and details.
- Widely Used:Widely applied to PS2,PS3,Xbox,N64, WII, STB, VHS, VCR, DVD Players and other devices with standard composite AV input.
- Attention & Package:Please ensure to connect this rca to hdmi converter to power source to make it work.Package include:1*RCA to HDMI Converter,1*usb power cable(adapter not included),1*User Manual.
Fonts, PDF/A, PDF/UA, and form fields
For controlled font loading, create a FontConfiguration and pass it to both stylesheet and PDF generation:
from weasyprint import HTML, CSS
from weasyprint.text.fonts import FontConfiguration
font_config = FontConfiguration()
css = CSS(filename="print.css", font_config=font_config)
HTML(filename="report.html").write_pdf(
"report.pdf",
stylesheets=[css],
font_config=font_config,
)
WeasyPrint documents PDF/A and PDF/UA variants for archiving and accessibility workflows, and a pdf_forms option for real PDF form fields. Select those options only when your compliance or form-processing requirement calls for them, and validate the resulting file with the toolchain used by your organization.
Render JavaScript pages with Playwright
Install Chromium and print a page
Playwright is the browser route. Install the Python package and its browser runtime in your deployment image:
python -m pip install playwright
playwright install chromium
This synchronous example waits for network activity, enables background graphics, and writes an A4 PDF:
Free tools Windows power users keep installed
One-click scans. No signup required.
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="networkidle")
page.pdf(
path="page.pdf",
format="A4",
print_background=True,
margin={
"top": "1cm",
"right": "1cm",
"bottom": "1cm",
"left": "1cm",
},
)
browser.close()
page.pdf() uses print CSS media by default. If the site has a screen stylesheet that you need to preserve, switch media before printing:
page.emulate_media(media="screen")
page.pdf(path="screen-style.pdf", print_background=True)
Wait for the application, not just the first response
networkidle is useful for pages that finish loading, but analytics, polling, and open connections can prevent it from completing. A deterministic application signal is safer:
page.goto("https://app.example/dashboard", wait_until="domcontentloaded")
page.wait_for_selector("[data-report-ready]")
page.pdf(path="dashboard.pdf", format="A4")
You can also wait for a known response, a short bounded timeout after a data request, or a JavaScript condition. Avoid an unbounded sleep: it makes every conversion slow while still failing on a slower page.
Rank #3
- Composite to HDMI Converter: Converts analog AV composite (Yellow, White, Red) input to HDMI 720P/1080P (60HZ) output, displayed on smart TV, Projector or HD Display, which bring back your old and cherish memories.
- Plug to Play: This HDMI Converter no extra drivers need, just plug and play,easy to use. Please hook up the USB Power Cable (included) to 5V power source during use. Note: The Video Converters only support converts AV to HDMI, can't converts HDMI to AV.
- Widely Used: This composite to hdmi adapter is widely applied to PS1, PS2, PS3, Xbox, N64, Wii, STB, VHS, VCR, DVD Players and other devices with standard composite AV input. Note: It can only be used when PS2 is set to RGB output.
- Wide Compatibility: This Video Audio Converter Adapter supports source formats of PAL, NTSC3.58, NTSC4.43, SECAM, PAL/M, PAL/N standard TV. Provide advanced signal processing with great precision, colors, resolutions, and details. Important Note: This converter can't improve video quality!
- Attention & Package: Please ensure to connect this av hdmi converter to power source to make it work. Package include: 1*AV to HDMI Adaptor, 1*USB Power Cable(adapter not included), 1*User Manual.
Paper formats, dimensions, headers, and footers
Playwright supports named formats such as Letter, Legal, Tabloid, Ledger, and A0 through A6. You can instead provide explicit px, in, cm, or mm dimensions. Margins are supplied as a dictionary, and landscape=True changes orientation.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Header and footer templates require display_header_footer=True. Templates can include the built-in page-number and date placeholders, but scripts inside those templates are not evaluated. Keep template HTML and CSS self-contained so it renders consistently in the browser’s print context.
WeasyPrint or Playwright: a practical decision
| Decision axis | WeasyPrint | Playwright |
|---|---|---|
| JavaScript execution | HTML/CSS renderer; choose it for content that is already present in the source. | Runs Chromium, so client-side rendering and browser APIs can complete before printing. |
| CSS and pagination | Print-oriented CSS and @page controls are central to the workflow. |
Matches Chromium’s print behavior and can switch between print and screen media. |
| Operational footprint | Focused renderer and a smaller process lifecycle. | Requires a browser runtime, launch management, and isolation. |
| Document features | Documents PDF/A, PDF/UA, fonts, forms, and page rules. | Offers browser print settings, paper formats, dimensions, and header/footer templates. |
| Best source of truth | HTML templates and print styles. | A page whose final state exists only after browser execution. |
Use ReportLab when HTML is not the source
ReportLab is appropriate when Python data is the source of truth and you want to place paragraphs, tables, charts, and drawing primitives yourself. It gives you a PDF layout engine, not a faithful HTML/CSS conversion. Rebuilding an existing responsive website in ReportLab usually creates unnecessary work; use WeasyPrint or Playwright instead.
Or skip the browser setup
If your input is a public URL and you want a hosted capture service rather than a local Chromium installation, ScreenshotNeo can return a clean screenshot or PDF through one GET request. Before capture it accepts the cookie or consent banner like a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing state with X-Page-Verdict and X-Billed headers.
Python call (the endpoint can return PDF as well as PNG, JPEG, or WebP; choose the response format required by your workflow):
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 & 11Crashes, 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 minuteimport 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)
Equivalent cURL and Node.js requests are useful in build pipelines and scripts:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
See the parameter reference and PDF options in the ScreenshotNeo documentation. The service also provides an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients; it supports waits, custom CSS and JavaScript, selectors, device presets, cookies, headers, geolocation, caching, signed links, asynchronous webhooks, bulk capture, and more.
The Free plan includes 1,000 screenshots per month with no card. Paid plans start at $5 for 3,000 shots, and every feature is available on every plan. Create a free ScreenshotNeo account.
Rank #4
- Convert RCA to HDMI Instantly – BD&M RCA to HDMI Converter easily converts analog RCA/composite AV signals to HDMI output, allowing you to connect older devices to modern HDTVs, monitors, and projectors with clear video and audio quality.
- Wide Device Compatibility – Supports VHS players, VCRs, DVD players, camcorders, retro gaming consoles, and more including PS1, PS2, PS3, Xbox, N64, Wii, and older AV devices with standard RCA output.
- 1080P HDMI Output – Advanced signal processing delivers stable and sharp video output with support for 720P/1080P HDMI resolution, improving compatibility with modern TVs and displays.
- Plug & Play Setup – No drivers or software required. Simply connect the RCA cables, HDMI cable, and included USB power cable for quick and easy installation in minutes.
- Compact & Reliable Design – Lightweight mini converter design makes it perfect for home entertainment setups, retro gaming, travel, or converting old media collections while maintaining stable performance.
Security and production boundaries
Untrusted HTML and CSS
WeasyPrint’s documentation warns: “Using WeasyPrint with untrusted HTML or untrusted CSS may lead to various security problems.” Treat templates supplied by users as hostile. Sanitize markup, restrict filesystem and network access, and use a controlled URL fetcher when external resources are necessary. Do not run arbitrary HTML in a privileged process with broad credentials.
Recommended Free Tools
Remote resources and credentials
Images, stylesheets, fonts, and scripts can make a conversion depend on another server. Restrict outbound destinations, set timeouts, and avoid embedding secrets in URLs. For authenticated pages, provide credentials through the browser context or a controlled fetch layer rather than exposing them in generated HTML.
Browser isolation
Playwright launches a full browser. Run it in an isolated worker or container, limit navigation and downloads according to your threat model, and close contexts and browsers in a finally block when you add error handling. Reuse a controlled browser process for batches, but do not let unrelated tenants share cookies or local storage.
Troubleshooting common failures
The PDF is blank or missing images
- WeasyPrint: supply a correct
base_urlfor string input, verify that image and font URLs are reachable by the conversion process, and check that CSS is not hiding the content. - Playwright: wait for the selector that proves the page is ready, not merely
domcontentloaded; make sure the browser has permission to reach the asset host.
JavaScript content never appears
WeasyPrint does not provide a browser execution environment. Use Playwright and wait for the rendered element or data request. If the application polls indefinitely, wait for a specific ready marker instead of networkidle.
Styles look different from the website
PDF output is a print context. In Playwright, call emulate_media(media="screen") when screen CSS is intentional, or add dedicated print CSS. In WeasyPrint, define @page, print colors, and page-break rules explicitly.
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 glitchesPlaywright cannot launch
Install the matching Chromium runtime in the same image or virtual environment as the package. In containers, verify that the runtime user has permission to access the browser files and that the process has the required sandbox configuration for your deployment.
Pages split at awkward points
Use WeasyPrint’s break-inside: avoid for cards and table rows where appropriate, add deliberate page breaks between major sections, and test with realistic long text. In Playwright, remember that the browser is printing the layout it calculated; fixed-height elements and overflow rules can clip content.
Best Value
- Export or Convert Text, HTML, PNG, JPG, or Camera Pictures to PDFs
- Unlimited use
- No ads
- No personal data taken
- GDPR compliant
Conversion hangs
Set navigation and overall job timeouts, identify pages with long-lived connections, and replace broad network-idle waits with a bounded readiness condition. Log the URL, renderer, wait condition, and failure type without logging secrets.
Performance, reliability, and cost planning
- For many static documents, WeasyPrint avoids browser startup and is easier to run as a short-lived worker.
- For many browser jobs, keep a controlled Playwright browser alive and create isolated contexts per document; always close contexts after each job.
- Cache stable assets and templates where policy allows, but invalidate the cache when CSS, fonts, or data changes.
- Use deterministic fonts and embed or package them with the worker so line wrapping does not change between machines.
- Record conversion duration, page count, renderer, and error category. Do not treat a process exit of zero as proof that every remote asset loaded.
- When a hosted URL capture is sufficient, ScreenshotNeo’s cache and verdict headers let you distinguish cache hits and failed or non-clean pages from billable clean shots.
FAQ
Can I convert an HTML string without creating an intermediate file?
Yes. Pass the string to HTML(string=...) and call write_pdf(); with no target, the method returns PDF bytes.
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 →Which option should I use for an invoice generated by a server template?
Use WeasyPrint when the template contains the final text and styles before conversion. Add a base URL for relative assets and define the paper and margin rules in print CSS.
Can Playwright print a custom paper size?
Yes. Use a named format or explicit dimensions in pixels, inches, centimeters, or millimeters, along with margins and landscape orientation as needed.
Is ReportLab a replacement for CSS?
No. ReportLab is the better choice when you want to author the PDF layout from Python drawing and data primitives. It is not a drop-in renderer for an existing HTML design.
Frequently Asked Questions
Can I convert an HTML string without creating an intermediate file?
Yes. Pass the string to HTML(string=...) and call write_pdf(); with no target, the method returns PDF bytes.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Which option should I use for an invoice generated by a server template?
Use WeasyPrint when the template contains the final text and styles before conversion. Add a base URL for relative assets and define the paper and margin rules in print CSS.
Can Playwright print a custom paper size?
Yes. Use a named format or explicit dimensions in pixels, inches, centimeters, or millimeters, along with margins and landscape orientation as needed.
Is ReportLab a replacement for CSS?
No. ReportLab is the better choice when you want to author the PDF layout from Python drawing and data primitives. It is not a drop-in renderer for an existing HTML design.
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.

