How to Save a Webpage as a PDF from the Command Line
Save a webpage as a PDF with Chrome Headless, or automate print layout, timing, and output with Playwright. Includes runnable commands, troubleshooting, and a ScreenshotNeo option.
For a one-off PDF, run Chrome in headless mode:
chrome --headless --print-to-pdf https://example.com/
Chrome saves output.pdf in the current working directory. To remove the printed date, URL, and page-number header and footer, add --no-pdf-header-footer:
chrome --headless --print-to-pdf --no-pdf-header-footer https://example.com/
For recurring jobs or precise print settings, use Playwright. It lets a script wait for page content and set paper size, margins, orientation, page ranges, and background printing. The sections below show both approaches and explain when another converter may fit.
1. Choose a command-line approach
| Approach | Use it when | Trade-off |
|---|---|---|
| Chrome Headless | You need a quick URL-to-PDF command or a small shell job. | Convenient, but layout control and page-specific waiting are limited from a single command. |
| Playwright | You need repeatable automation, explicit print options, or a site-specific wait condition. | Requires a Node.js project and browser installation. |
| wkhtmltopdf | You need its standalone command-line conversion workflow. | It uses Qt WebKit; check the resulting layout against your target page instead of assuming it matches current Chrome. |
There is no apples-to-apples performance comparison in the referenced documentation. Choose based on setup, rendering behavior, and how much control your job needs. Chrome’s headless command-line options are documented in the Chrome Headless command-line reference; Playwright’s print options are in its Page API; the wkhtmltopdf project describes its converter and rendering engine.
2. Save a URL with Chrome Headless
First make sure Chrome is installed and its executable is available to your shell. Depending on your operating system and installation, the command may be named chrome, google-chrome, or chromium. Use the name and path for the browser installed on the machine.
chrome --headless --print-to-pdf --no-pdf-header-footer 'https://example.com/'
The output is output.pdf in the current directory. Chrome documents --print-to-pdf as saving the target page under that filename. To select a different destination, provide the output path as the flag value:
chrome --headless --print-to-pdf='/tmp/example.pdf' --no-pdf-header-footer 'https://example.com/'
Quote URLs that contain shell-special characters, especially query strings with &. If you need to pass several Chrome flags, keep them before the URL.
Control when Chrome prints
For a page that populates shortly after navigation, Chrome provides a maximum wait timeout:
chrome --headless --timeout=5000 --print-to-pdf='page.pdf' 'https://example.com/'
--timeout=5000 means Chrome waits up to five seconds before printing in the documented example. It is a cap, not proof that every request or lazy-loaded item has finished. Chrome also documents a virtual-time budget for time-dependent scripts:
chrome --headless --virtual-time-budget=42000 --print-to-pdf='page.pdf' 'https://example.com/'
This advances time-dependent page behavior as if 42 seconds had elapsed. Treat it as a capture control, not a guarantee that the site has completed its work. For reliable automation, wait for a page-specific signal with Playwright.
3. Automate PDF output with Playwright and Node.js
Install Playwright in a new or existing Node.js project, then install its Chromium browser:
npm install playwright
npx playwright install chromium
Save the following as save-pdf.mjs. It navigates to a URL, waits for the page to reach a network-idle state, and writes a PDF with explicit print options.
import { chromium } from 'playwright';
const url = process.argv[2] ?? 'https://example.com/';
const output = process.argv[3] ?? 'page.pdf';
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle', timeout: 60_000 });
await page.pdf({
path: output,
format: 'A4',
printBackground: true,
displayHeaderFooter: false,
margin: { top: '12mm', right: '12mm', bottom: '12mm', left: '12mm' },
preferCSSPageSize: true,
});
console.log(`Saved ${output}`);
} finally {
await browser.close();
}
node save-pdf.mjs 'https://example.com/' 'example.pdf'
networkidle is not suitable for every site: analytics, polling, or long-lived connections can keep a page active. If that happens, wait for a specific selector that marks the content you need, or use domcontentloaded and add a page-specific wait:
await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60_000 });
await page.locator('main article').waitFor({ state: 'visible', timeout: 15_000 });
Choose a selector that exists only when the content to print is ready. A generic selector such as body may appear before client-rendered content.
Playwright print settings
| Option | What it controls |
|---|---|
path |
Output file path. Ensure its parent directory exists. |
format |
Paper format, such as A4 or Letter. |
width, height |
Custom page dimensions when you do not use a standard format. |
margin |
Top, right, bottom, and left margins. Values can use CSS units such as mm or in. |
landscape |
Print in landscape orientation when set to true. |
printBackground |
Include background graphics and colors when set to true. |
displayHeaderFooter |
Show or suppress the browser-generated header and footer. |
pageRanges |
Restrict output to selected pages, for example '1-3, 5'. |
preferCSSPageSize |
Prefer page dimensions declared in CSS over scaling content to the selected paper size. |
Playwright’s page.pdf() uses print CSS by default and modifies colors for printing. If you want screen styles, call await page.emulateMedia({ media: 'screen' }) before page.pdf(). For exact colors in print styles, CSS can use -webkit-print-color-adjust: exact. Refer to the current PDF API documentation for option details.
4. Understand print layout and browser differences
A PDF is a rendered print document, not necessarily a pixel-identical copy of the browser viewport. Print styles can hide navigation, change column widths, move page breaks, or replace screen-only layouts. Background printing is a separate setting, and the browser may adjust colors for print unless the page’s CSS requests exact color adjustment.
Playwright distinguishes its bundled Chromium/headless shell from branded Chrome or Edge. Headless behavior can differ, so identify which browser channel runs your job and inspect the output in that same environment. Browser version, fonts, installed libraries, and page CSS can all affect the result.
5. Troubleshooting missing or incorrect PDFs
| Symptom | Likely cause | Fix |
|---|---|---|
chrome: command not found |
The executable is not on PATH, or the installed browser has a different binary name. |
Locate the installed Chrome or Chromium executable and invoke it by its full path or actual command name. |
| No PDF appears | The command wrote output.pdf to a different current directory, or the output directory does not exist. |
Check the shell’s working directory; pass an explicit output path and create its parent directory first. |
| URL is cut off or arguments behave oddly | A query parameter containing & or another shell character was not quoted. |
Wrap the complete URL in single quotes, or use a script that passes the URL as a value. |
| Content is blank or incomplete | Printing began before client-rendered content or images were ready; a fixed timeout was too short. | Increase the wait cautiously or use Playwright to wait for a page-specific selector. Verify that the page does not require login or interaction. |
| Navigation times out in Playwright | The site keeps network connections open, or navigation exceeds the configured timeout. | Try domcontentloaded plus an explicit content selector instead of networkidle; set a timeout appropriate for the job. |
| Colors or backgrounds are missing | Print styles alter colors or background graphics are disabled. | Set printBackground: true; use print CSS and -webkit-print-color-adjust: exact where exact print colors are needed. |
| Unexpected page size or clipping | CSS page rules and the selected paper format conflict, or margins leave too little printable area. | Choose either CSS page sizing with preferCSSPageSize or an explicit format and margins; inspect page breaks and adjust the source print stylesheet. |
| Playwright cannot launch Chromium | The browser was not installed for the project or required runtime libraries are unavailable. | Run npx playwright install chromium and follow Playwright’s browser setup guidance for the operating system. |
| Authenticated content is absent | The command opened a fresh browser context without the required login state. | Use an authorized browser context with the required authentication state, and protect any stored credentials or session data. |
6. Performance, reliability, and cost
These approaches run a browser or conversion utility on your machine or server. Their practical cost includes the compute and storage you provide, plus the time needed to maintain browser binaries and fonts. The reviewed sources do not provide comparable speed or memory benchmarks, so measure the pages and environment that matter to your workflow.
- For occasional pages: Chrome’s one-line command has little setup once Chrome is installed.
- For repeatable jobs: Pin the runtime and browser version, set navigation and selector timeouts, and record failures so a timed-out page is not silently treated as a good PDF.
- For reliability: Check the output file exists and has nonzero size, and review representative PDFs after changing browser versions or page styles.
- For throughput: Reuse browser processes in a managed automation worker rather than starting a new browser for every URL, while limiting concurrent pages to the resources available.
- For dynamic pages: Prefer a meaningful readiness condition over ever-larger fixed delays.
7. Or skip the browser setup
If you want a hosted screenshot or PDF capture API instead of managing a browser, ScreenshotNeo accepts a URL in one GET request. For a webpage PDF, add the documented PDF output option and any paper or margin settings you need; the API supports PDF capture, paper size, margins, landscape, and page ranges. See the ScreenshotNeo API documentation for the current request parameters.
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com \
-d format=pdf \
-o page.pdf
ScreenshotNeo removes known cookie and consent banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. Its MCP server gives AI agents tools for screenshots, page information, and PDF capture. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Every feature is on every plan.
Create a free ScreenshotNeo account to get 1,000 screenshots a month with no card.
8. Frequently asked questions
Can Chrome print a local HTML file?
Yes. Pass a local file URL, such as file:///absolute/path/page.html, if the page and its linked resources are accessible to that browser process.
Can I save only selected pages from the document?
With Playwright, use the pageRanges PDF option. Chrome’s basic command shown above does not provide that same script-level PDF settings interface.
Will this work for every webpage?
No single command can guarantee that. Pages may require authentication, interaction, scripts, or resources unavailable to the browser. Check the generated PDF and add site-specific setup or waits when needed.
Does a webpage PDF preserve the screen exactly?
No. PDF generation uses print layout rules by default in Playwright, so the result may differ from the screen view. Use screen media emulation when appropriate, then inspect page breaks and styling.


