Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use a real browser engine when the page depends on JavaScript. The dependable API pattern is to navigate with Chromium, wait for the application and its assets to finish rendering, set print options explicitly, and return the generated PDF bytes. Playwright’s page.pdf(), Chrome DevTools Protocol’s Page.printToPDF, and Puppeteer all expose this workflow. For a managed option, ScreenshotNeo can render a URL to PDF without you operating a browser fleet.

Choose the right conversion approach

A static HTML-to-PDF library can work for simple markup, but it will not reliably reproduce a modern application that runs JavaScript, fetches data, loads web fonts, or changes the DOM after navigation. Browser rendering executes those steps before printing.

Approach Best fit Important control Main trade-off
Playwright page.pdf() Node.js or multi-language Playwright services Wait for application state, then configure print options You operate Chromium, concurrency, updates and isolation
Chrome DevTools Protocol Page.printToPDF Teams driving Chromium directly Protocol-level paper, margin, range and transfer settings More plumbing than a browser automation library
Puppeteer Existing Puppeteer-centered JavaScript systems Its PDF API over Chrome DevTools Protocol or WebDriver BiDi Still requires browser lifecycle and production operations
Managed browser/PDF API Teams that want an HTTP endpoint instead of browser infrastructure Provider-specific rendering and delivery options Less control over browser versions, residency and retention

Decide first whether you need a URL, an HTML payload, or both. Validate allowed destinations and request size before a worker opens a browser. If arbitrary URLs are accepted, outbound navigation, credentials, resource limits and logging require an explicit threat model.

Convert a URL with Playwright

The following Node.js service accepts a URL, waits for a meaningful readiness selector, prints the page and writes a PDF. Install Playwright with npm install playwright; install the supported Chromium browser in your deployment image.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Elebase USB to USB C Adapter for iPhone 18 Pro Max,USBC Car Charger Adapter
  • Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
  • Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
  • Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
  • Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
  • 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.
import { chromium } from 'playwright';

const target = process.argv[2] || 'https://example.com';
const browser = await chromium.launch();
try {
  const page = await browser.newPage({
    viewport: { width: 1440, height: 900 },
    deviceScaleFactor: 1
  });
  await page.goto(target, { waitUntil: 'domcontentloaded', timeout: 60000 });

  // Replace this with your application’s real ready signal.
  await page.waitForLoadState('networkidle', { timeout: 30000 }).catch(() => {});
  await page.locator('main').waitFor({ state: 'visible', timeout: 30000 }).catch(() => {});
  await page.evaluate(() => document.fonts.ready);

  await page.pdf({
    path: 'output.pdf',
    format: 'A4',
    printBackground: true,
    preferCSSPageSize: true,
    margin: { top: '16mm', right: '14mm', bottom: '16mm', left: '14mm' },
    tagged: true,
    outline: true
  });
} finally {
  await browser.close();
}

Playwright documents that page.pdf() generates a PDF with print CSS media and returns a PDF buffer. The example uses a file path for simplicity; in an API, omit path and send the returned buffer with Content-Type: application/pdf.

Wait for the page you actually need

domcontentloaded only means the initial document was parsed. A single arbitrary delay is fragile: it may be too short on a slow run and wasteful on a fast one. Prefer a selector that appears when the application is ready, an application-specific flag, and explicit readiness for fonts or critical images. For a dashboard, that might be [data-report-ready="true"]; for a server-rendered document, a visible main element may be sufficient.

Choose print or screen styling

Print media is Playwright’s default. If the site’s screen design is the document you need, call await page.emulateMedia({ media: 'screen' }) before printing. Treat this as a design decision: print CSS often removes navigation and changes colors, while screen CSS may contain fixed elements that repeat or overlap on paper.

Control paper, layout and accessibility

Size, orientation and CSS page rules

Use a named format such as A4 or Letter, or provide explicit width and height. Set landscape: true for wide tables. preferCSSPageSize: true lets the document’s @page rules determine the sheet size rather than forcing the API’s format.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
await page.pdf({
  format: 'Letter',
  landscape: false,
  preferCSSPageSize: true,
  scale: 1
});

Playwright’s scale default is 1 and its documented range is 0.1 to 2. Lower scale can fit more content but makes text smaller; use it only after correcting margins and page-break rules.

Rank #2
Anker USB-C Hub, 5-in-1 USB Hub for Laptops, 4K HDMI Multiport Adapter
  • 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
  • 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
  • Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
  • 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
  • What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.

Margins, backgrounds and color

Margins are part of the printable geometry, not decoration. Reserve space for headers and footers, and test long headings and tables at the chosen size. Background graphics are disabled by default in Playwright, so set printBackground: true when the design depends on them. If exact colors matter, add -webkit-print-color-adjust: exact in print CSS, while recognizing that browser behavior and user settings can still affect output.

Page breaks and fixed elements

Use print styles to keep related content together and prevent rows from splitting where practical:

@media print {
  .no-print { display: none !important; }
  h1, h2 { break-after: avoid; }
  .invoice-row { break-inside: avoid; }
}
@page { size: A4; margin: 16mm 14mm; }

Inspect multi-page tables, sticky navigation, fixed chat controls, images and very long unbroken strings. A layout that looks correct in a viewport can clip when the print engine paginates it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Headers, footers, ranges and document structure

Playwright supports header and footer templates, page ranges, outlines and tagged output. Templates have limitations: scripts inside them are not evaluated, and page styles are not visible inside the template. Keep template markup self-contained and verify it on several pages. Use pageRanges for partial exports, outlines for navigable sections, and tagged output when downstream accessibility tooling needs document structure.

await page.pdf({
  format: 'A4',
  displayHeaderFooter: true,
  headerTemplate: '<div style="font-size:9px;width:100%;text-align:center">Quarterly report</div>',
  footerTemplate: '<div style="font-size:9px;width:100%;text-align:center">Page <span class="pageNumber"></span> of <span class="totalPages"></span></div>',
  pageRanges: '1-4',
  tagged: true,
  outline: true
});

Build an HTTP HTML-to-PDF endpoint

A production endpoint should separate request validation, browser work and response delivery. Accept either a URL or bounded HTML; reject requests that contain both unless your contract defines precedence. Allow-list destinations when possible, cap navigation and output time, and prevent access to internal network ranges. Do not put cookies, authorization headers or document bodies in ordinary logs.

  1. Validate input: parse the URL, enforce schemes and host policy, and cap HTML/request bytes.
  2. Acquire a browser context: reuse a controlled browser process, but isolate cookies, storage and permissions per job.
  3. Navigate and wait: apply a navigation timeout, then wait for the application’s readiness signal and required assets.
  4. Print: set media, paper, margins, backgrounds, ranges and accessibility options deliberately.
  5. Deliver: return bytes directly for small files or stream/store large files in object storage.
  6. Clean up: close the page and context in a finally block, record structured diagnostics, and recycle unhealthy browsers.

For throughput, bound concurrent pages rather than starting an unlimited browser per request. Measure cold starts separately from warm conversions, and add retries only for transient navigation or browser failures. Retrying a deterministic layout error simply creates duplicate work.

Rank #3
Sale
Anker USB C Hub, 7in1 Multi-Port USB Adapter, 4K@60Hz USBC to HDMI Splitter
  • Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
  • Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
  • Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
  • Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
  • What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.

Use Chrome DevTools Protocol directly

Chromium exposes PDF generation through Page.printToPDF. The command accepts paper orientation and dimensions, margins, headers and footers, background printing, scale, CSS page-size preference, page ranges, outlines and tagged output. Results can be returned as base64 or through a stream, which is useful when files are large.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The surrounding sequence remains the same: create an isolated target, navigate, wait for application readiness, call Page.printToPDF, decode or stream the result, and close the target. CDP is appropriate when your platform already manages Chromium connections; otherwise Playwright usually removes protocol and lifecycle boilerplate.

Where Puppeteer fits

Puppeteer is a JavaScript library for automating Chrome and Firefox through Chrome DevTools Protocol and WebDriver BiDi, including PDF generation. Choose it when the rest of your system already uses Puppeteer APIs and fixtures. The engineering requirements do not disappear: wait for real readiness, control browser versions and fonts, constrain concurrency, and handle cleanup and retries.

Managed conversion: ScreenshotNeo

ScreenshotNeo is a managed website screenshot API and MCP server that also returns PDFs. It is the first service to try when you want browser rendering without operating Chromium: it produces clean shots by accepting cookie/consent banners like a visitor and removing more than 60 known consent platforms, newsletter popups and chat widgets. You can turn each cleanup step off.

Only clean shots are billed. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads and cache hits cost nothing, and the response identifies the result with X-Page-Verdict and X-Billed headers.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

One-call PDF example

Request a PDF by adding the PDF options documented at ScreenshotNeo’s API documentation. The basic request pattern is:

Rank #4
Sale
UGREEN USB to USB C Adapter Combo 4-Pack, 10Gbps USB C Converter Space Gray
  • Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
  • Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
  • Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
  • Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
  • Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft
curl -G "https://api.screenshotneo.com/v1/shot" 
  -d access_key=YOUR_API_KEY 
  --data-urlencode url=https://stripe.com 
  -d format=pdf 
  -o page.pdf

The API also supports full-page capture with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets or any viewport, retina scale, paper size, margins, landscape mode, page ranges, custom CSS and JavaScript, pre-capture clicks, selector hiding, selector/delay/network-idle waits, request and resource blocking, custom headers/cookies/user agents/Authorization, timezone and geolocation, transparent backgrounds, resizing, chosen-TTL caching, signed links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, usage reporting and an OpenAPI specification. Common parameter names used by other screenshot APIs work as well, easing migration.

Python

import requests

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

Node.js

const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://stripe.com',
  format: 'pdf'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
await Bun.write('page.pdf', res);

ScreenshotNeo also provides MCP tools named take_screenshot, get_page_info and capture_pdf for Claude, Cursor and other MCP clients. Pricing is Free for 1,000 shots per month with no card, then Starter $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000 and Business $249 for 1,000,000; yearly billing gives two months free, and every feature is on every plan.

Or skip the browser setup: 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; and 1,000 screenshots a month are free with no card, with paid plans starting at $5 for 3,000. Create a free ScreenshotNeo account.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshoot common PDF failures

Blank or incomplete output

The print call ran before client-side rendering or assets finished. Replace arbitrary sleeps with a readiness selector or application signal, wait for fonts, and verify that critical images have loaded. Check that the URL did not redirect to a login or bot-check page.

Wrong colors or layout

Print CSS is different from screen CSS. Compare both intentionally, choose emulateMedia('screen') only when appropriate, enable printBackground, and inspect print-specific rules and color-adjust behavior.

Clipped content and bad page breaks

Check @page dimensions, margins, scale, break rules, fixed-position elements and long tables. A smaller scale is a last adjustment, not a substitute for correcting geometry.

Best Value
Anker USB C Hub, 5-in-1 USBC to HDMI Splitter with 4K Display
  • 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
  • Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
  • Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
  • HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
  • What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.

Missing headers or footers

Confirm displayHeaderFooter, keep template styles inline, and do not rely on scripts or page styles inside the template. Verify page-number placeholders across a multi-page document.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Timeouts and intermittent failures

Set separate navigation and total-job timeouts, capture the final URL and console errors in diagnostics, and retry only transient browser or network failures. Bound concurrency and recycle browsers that accumulate memory or renderer errors.

Engine mismatch

The documented Playwright MCP PDF export path is Chromium-only. If your deployment uses another engine, select a Chromium worker for PDF jobs or use a service that supplies Chromium rendering.

Self-hosted or managed?

Question Self-hosted Playwright/CDP Managed API
Rendering control Pin browser, fonts, network policy and print CSS Provider controls browser and infrastructure
Operations You own cold starts, scaling, patches, retries and observability HTTP integration reduces browser operations
Data handling Choose residency, retention and credential boundaries Verify provider residency, retention and compliance terms
Cost model Infrastructure and engineering cost, plus browser capacity Per-document or plan charges and possible limits
Lock-in More portable browser code Convenient features may use provider-specific parameters

Choose self-hosting when browser version, private network access, residency or bespoke instrumentation is central. Choose a managed endpoint when reliable conversion matters more than running Chromium, and verify current limits, retention, compliance and pricing before committing.

Frequently Asked Questions

Can an API convert a page that requires login?

Yes, if the browser context can authenticate safely. Supply cookies or authorization only through an isolated context or a provider’s documented credential options, and never expose those values in URLs or logs.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should I wait for network idle on every page?

No. Analytics, WebSockets and polling can prevent network idle indefinitely. Use an application-specific readiness signal, optionally combined with a bounded network-idle wait.

What does a PDF buffer contain in Playwright?

Without a path, page.pdf() returns the generated PDF as a buffer, which you can send in an HTTP response or write to storage.

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.