ScreenshotNeo

BlogHTML to image & PDF

How to Convert a List of Web Pages to PDF Files in Bulk with Chrome

Convert a URL list to separate or merged PDFs with a Chrome extension or headless Chrome, then automate the workflow with a script.

By the ScreenshotNeo team4 October 20269 min read

If you have a list of URLs, Chrome’s built-in Print flow handles one open page at a time. To convert many pages, use a bulk PDF extension or automate Chrome’s headless --print-to-pdf command. The extension route is easier for a one-off batch; headless Chrome gives you a repeatable workflow and control over filenames and error handling.

Choose the right bulk workflow

Workflow Best for Output What you need to know
Chrome Print A single page or occasional pages One PDF per page Open each page and print it individually.
Bulk WebPages & Links to PDF extension A pasted URL list or text file Separate PDFs or a merged PDF The extension listing advertises URL import, link ordering, and both output styles.
Microlink: Website to PDF extension A modest batch packaged for download Individual PDFs in a ZIP Its listing advertises batches of up to 100 unique URLs.
Headless Chrome Repeatable or scripted conversion A PDF for each invocation Chrome documents printing a target URL; iterating over a list is your own automation.

Extension features and privacy statements above are publisher descriptions, not independent test results. Before installing one, review its current permissions and privacy terms. The cited Chrome help describes printing an open page, not a native bulk URL-list converter. Google Chrome Help: Print from Chrome; Chrome Headless documentation; Chrome Web Store.

Method 1: Save a single page with Chrome Print

  1. Open the page in Chrome.
  2. Open Print with Ctrl+P on Windows or Linux, or Command+P on Mac.
  3. Choose Save as PDF or another PDF destination, if offered.
  4. Review the page preview and print settings, then save the file.

This is a straightforward method for one page. For a list, it requires repeating the process for each URL, so use an extension or a script for bulk work.

Method 2: Convert a URL list with a Chrome extension

A bulk extension can manage the URL list and PDF export inside its interface. The Bulk WebPages & Links to PDF listing says you can paste URLs or import a text file, select and reorder links, and export individual PDFs or one merged file. Its listing also describes preparing lazy-loaded content and fonts and processing locally; treat those as claims from the publisher.

  1. Find the extension in the Chrome Web Store and review its current publisher, permissions, and privacy disclosures.
  2. Prepare a plain-text list with one full URL per line, or copy the URLs you want to convert.
  3. Open the extension, import or paste the URLs, and remove entries you do not want.
  4. Arrange the order if the extension supports it.
  5. Choose separate PDFs or a merged document, set available page options, and start the export.
  6. Open a few resulting files and check that the page content, page breaks, and order meet your needs.

The Microlink: Website to PDF listing advertises up to 100 unique links and a ZIP download containing page PDFs. Check the current listing for limits and settings before relying on those features. Neither listing establishes independently verified speed, fidelity, or privacy.

Separate PDFs or one merged PDF?

  • Choose separate files when each page needs its own filename, can be reviewed or sent independently, or may need to be replaced later.
  • Choose a merged file when you need one reading or archive document and the order matters. Check the resulting page order and page breaks.
  • Choose a ZIP of separate files when you want one download but still need each page kept distinct.

Method 3: Automate a list with headless Chrome

Chrome’s headless command-line interface can print a URL to PDF. A script can call it once per URL, making the batch part your responsibility: the script supplies URLs, output names, waiting time, and error reporting. The following examples use a shell loop and require Chrome or Chromium to be installed.

Before you start

  • Find the executable name on your system: it may be google-chrome, google-chrome-stable, chromium, or chromium-browser.
  • Use fully qualified URLs including https://.
  • Choose an output directory with enough disk space and write permission.
  • Use a dedicated user-data directory for automation if you need a separate browser profile. Do not run concurrent Chrome jobs against the same profile directory.

Linux or macOS shell script

Save URLs in urls.txt, one per line. Set CHROME to your installed executable if the default command is different. This script skips blank lines and comments, assigns numbered filenames, and records URLs that fail.

#!/usr/bin/env bash
set -u

CHROME="${CHROME:-google-chrome}"
OUT_DIR="pdfs"
PROFILE_DIR="$(mktemp -d)"
mkdir -p "$OUT_DIR"
index=0
failed=0

while IFS= read -r url || [ -n "$url" ]; do
  case "$url" in
    ''|'#'*) continue ;;
  esac
  index=$((index + 1))
  output="$OUT_DIR/$(printf '%04d' "$index").pdf"
  if "$CHROME" --headless --disable-gpu \
      --user-data-dir="$PROFILE_DIR" \
      --no-pdf-header-footer \
      --timeout=30000 \
      --print-to-pdf="$output" "$url"; then
    printf 'Saved %s\n' "$output"
  else
    printf 'Failed (%s): %s\n' "$output" "$url" >&2
    failed=$((failed + 1))
  fi
done < urls.txt

rm -rf "$PROFILE_DIR"
printf 'Processed %s URL(s); failures: %s\n' "$index" "$failed"
[ "$failed" -eq 0 ]

Run it with bash batch-to-pdf.sh. Numbered names preserve input order and avoid collisions when different URLs have the same page title. The temporary profile is removed at the end; if you need to inspect browser state after an error, temporarily keep that directory instead.

Windows PowerShell example

Set the executable path to the Chrome or Chromium installation on your machine. Put one URL per line in urls.txt.

$Chrome = "$env:ProgramFiles\Google\Chrome\Application\chrome.exe"
$OutDir = Join-Path (Get-Location) "pdfs"
New-Item -ItemType Directory -Force -Path $OutDir | Out-Null
$Index = 0
$Failures = 0

foreach ($Line in Get-Content "urls.txt") {
  $Url = $Line.Trim()
  if ([string]::IsNullOrWhiteSpace($Url) -or $Url.StartsWith("#")) { continue }
  $Index++
  $Output = Join-Path $OutDir ("{0:D4}.pdf" -f $Index)
  & $Chrome --headless --disable-gpu --no-pdf-header-footer --timeout=30000 "--print-to-pdf=$Output" $Url
  if ($LASTEXITCODE -ne 0) {
    Write-Error "Chrome failed for $Url"
    $Failures++
  }
}
"Processed $Index URL(s); failures: $Failures"
if ($Failures -gt 0) { exit 1 }

Change $Chrome if Chrome is installed elsewhere. The command-line flags shown are documented by Chrome; the looping, filenames, and failure counter are orchestration around its per-URL print command. Chrome Headless documentation.

Useful headless Chrome options

Option Purpose When to use it
--headless Run Chrome without a visible browser window. Batch jobs and server-side scripts.
--print-to-pdf=FILE Write the target page as a PDF. Set a unique output path for every URL.
--no-pdf-header-footer Omit Chrome’s default print header and footer. When you want cleaner page output.
--timeout=MS Set a maximum wait before capture. Allow more time for slower pages; a timeout does not guarantee all dynamic content has finished.

Chrome’s documented example demonstrates a single target URL. The scripts above add iteration; they do not add a guarantee that every site will render identically to its interactive browser experience.

How to prepare the URL list and name files

  • Use one absolute URL per line. Remove leading and trailing spaces.
  • Keep query parameters intact; they may identify the specific page or state you need.
  • Use stable numbered filenames when preserving source order matters. Titles can be missing, duplicated, or contain characters invalid in filenames.
  • For a larger archive, keep a separate mapping file of sequence number, source URL, output filename, and status. That makes retries and audits easier.
  • Decide how to handle redirects and duplicate URLs before the batch. A redirect can land on a different page, and duplicate inputs can produce duplicate files unless you remove them.

PDF output is a print rendering, so it can differ from the on-screen page. If a tool exposes print settings, check paper size, orientation, margins, scale, and background graphics. The available controls vary by workflow. The research for this guide does not establish a common set of extension settings, so inspect the actual interface and preview rather than assuming a setting exists.

Pages may load images or content as you scroll, require a sign-in, or render content only after user interaction. An extension listing may claim to prepare lazy-loaded content, but this has not been independently verified. Headless Chrome’s timeout controls waiting duration; it does not itself prove that a site’s application has completed every asynchronous task. For important captures, inspect representative PDFs, including the longest and most interactive pages.

Or skip the browser setup

ScreenshotNeo is a website screenshot API and MCP server. Its API returns a PNG, JPEG, WebP, or PDF from one GET request. For a URL list, you still need to orchestrate one request per URL or use its bulk capture option, which accepts up to 100 URLs per call. See the ScreenshotNeo API documentation.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.pdf
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()
with open("shot.pdf", "wb") as output:
    output.write(r.content)
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(`ScreenshotNeo returned ${res.status}`);
await import('node:fs/promises').then(fs => fs.writeFile('shot.pdf', Buffer.from(await res.arrayBuffer())));

ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots. The free plan includes 1,000 screenshots a month with no card, and paid plans start at $5 for 3,000. The API supports PDF settings including paper size, margins, landscape, and page ranges. Sign up for 1,000 free screenshots a month, with no card required.

Troubleshooting

Problem Likely cause What to try
No PDF appears Chrome executable is not found, the output directory is not writable, or the command failed. Check the executable path, run Chrome for one URL directly, and confirm the output directory exists and is writable.
PDF is blank or missing content The page may still be loading, require authentication, or depend on interactive actions. Increase --timeout, check the URL in a normal browser, and inspect the page’s access requirements. A longer timeout cannot resolve every client-side interaction.
Images are missing Images may load lazily or fail due to network access or site restrictions. Check the source page and network availability. Inspect extension settings or publisher claims about lazy loading, and verify the resulting PDF.
Files overwrite each other The script reused an output filename. Use a counter or another unique naming scheme instead of a shared filename or title alone.
Some URLs fail in a batch A page may be unavailable, malformed, blocked, or slower than the configured wait. Log each URL and exit status, retry only failed entries, and check the URL individually before repeating the full batch.
Chrome reports that the profile is in use Another Chrome process is using the same user-data directory. Use a unique temporary profile per job and avoid parallel processes sharing one profile.
Unexpected headers, footers, or page breaks Print defaults or the page’s print CSS affect the PDF. Try --no-pdf-header-footer and review the page’s print preview or the extension’s available layout settings.

Performance, reliability, privacy, and cost

  • Performance: Conversion time depends on the sites, page size, and content they load. There is no verified speed benchmark for the extensions or headless workflow in the research used here. Start with a small batch to estimate the workload on your own pages.
  • Reliability: Process pages individually so one failed URL does not discard the whole batch. Keep a status log, review sample PDFs, and retry failures separately. Very short timeouts can miss slow pages; very long ones make a stuck page delay the run.
  • Privacy: A URL can expose private information through query parameters, and pages may require account access. Review extension permissions and privacy disclosures before sending a list to an extension. The extension listings’ local-processing claim is publisher-provided, not independently confirmed here.
  • Cost: Chrome’s print command is part of the browser workflow; extension pricing or limits can change, so check their current listings. Automated conversion also uses your machine’s time and storage. ScreenshotNeo offers 1,000 shots per month free and paid plans from $5 for 3,000; only clean shots are billed, and response headers identify the page verdict and billing status.

Frequently asked questions

Can Chrome save a whole bookmark folder as PDFs by itself?

The cited Chrome help describes printing an open page. It does not describe a built-in bulk URL-list or bookmark-folder-to-PDF workflow. Use an extension that accepts a list or script headless Chrome.

Can I create one PDF from all the URLs?

Some extension listings advertise merged output. Headless Chrome’s documented command produces a PDF for a target URL, so merging the resulting files requires an additional PDF tool or workflow.

Will these methods preserve interactive features?

A PDF is a static print output; do not expect page interactions to remain usable. Content that appears only after scripts or user actions may also be absent unless it has rendered before printing.

Which method should I choose for recurring jobs?

Use a script when you need repeatable filenames, logs, and retry behavior. Use an extension when you prefer to manage a batch through a browser interface and its current features fit your output needs.