TL;DR

Downloading a single page as PDF is trivial — Chrome does it with Cmd+P. Downloading an entire site is a different problem: you have to enumerate the URLs first (that is crawling), render each one to PDF, then either keep them as separate files or merge into one. For 10 pages a sitemap plus a batch print extension is fine. For 100 pages you want wget or HTTrack driving a headless renderer. For 10,000 pages you need a real scraper. The workflow that covers all three sizes without leaving Chrome is ScrapeMaster to enumerate URLs plus a web-to-PDF converter on the output list.

TL;DR: single page vs whole site

People ask "how do I download a website as PDF" and mean two very different things.

One page: you are on an article, a docs page, a knowledge base entry. You want that specific URL saved. Open it, hit Cmd+P (Ctrl+P on Windows), pick "Save as PDF," done. If the layout comes out ugly, a reader-mode extension or a dedicated web-to-PDF extension fixes it. This is a solved problem — see our guide on how to save a webpage as a PDF if the print dialog is misbehaving.

Every page on the site: you want the full documentation, the whole blog, the entire product catalog, the complete help center — all pages, all URLs, in PDF form. This is a two-step job:

  1. Enumerate — figure out every URL that exists on the site. This is crawling.
  2. Render — visit each URL, wait for it to finish loading, save the result as PDF.

The tools split along that line. Some are good at step 1 (wget, HTTrack, Screaming Frog, sitemap parsers, ScrapeMaster). Some are good at step 2 (Chrome's print dialog, headless Chrome, wkhtmltopdf, Playwright, Puppeteer, web-to-PDF extensions). Very few tools do both well, which is why most guides on this topic quietly assume you already have the URL list.

The scale of the site matters more than anything else. Ten pages you can click through by hand while sipping coffee. A hundred pages you need automation for. Ten thousand pages you need a proper scraper, a queue, and a plan for what happens when the target site rate-limits you at page 3,847.

The rest of this post walks through four approaches, ranked by the size of the site you can throw at each one, and closes with the legal side — because "download the whole site" is exactly the sentence that gets people into trouble.

Method 1: sitemap crawl + batch print

Almost every well-run website publishes a sitemap at /sitemap.xml. It is a list of every URL the site owner wants indexed. That is your enumeration step, handed to you for free.

The workflow:

  1. Visit https://example.com/sitemap.xml in your browser.
  2. If it is a sitemap index (a sitemap of sitemaps), open each child sitemap.
  3. Copy the URLs out. You can right-click, View Source, and grab the <loc> tags with a simple regex, or paste the sitemap into any text editor and pull the URLs.
  4. Feed the URL list into a batch web-to-PDF extension, or paste them into a browser tab-opener extension and print each one.

Where it works: documentation sites (Vercel, Stripe, Cloudflare docs all publish clean sitemaps), blogs on WordPress, most well-maintained marketing sites, help centers on Zendesk and Intercom.

Where it does not work:

  • Sites that do not publish a sitemap, or publish an incomplete one. Modern SPAs often skip URLs that require client-side routing.
  • Sites where the sitemap is behind a login.
  • Anything with more than about 200 URLs — clicking Print on each tab in sequence gets old fast, and Chrome starts complaining about memory around tab 40.

Realistic ceiling: 50–100 pages. Beyond that the manual overhead defeats the purpose.

The subtle trap: sitemaps list URLs, not necessarily the URLs a human would want in a PDF. You will get tag pages, archive pages, redirect stubs, and empty category shells alongside the actual content. Budget time to prune the list before you start printing, or you will end up with a 400-page PDF where 80% of the pages say "No posts found in this category."

Method 2: wget + wkhtmltopdf

The classic Unix pipeline. wget mirrors a site. wkhtmltopdf renders HTML to PDF. Chain them and you can archive a modest site in a few minutes with a shell one-liner.

The setup:

wget --mirror --convert-links --adjust-extension --page-requisites \
     --no-parent https://example.com/

# Then for each downloaded HTML file:
find example.com -name "*.html" -exec \
    wkhtmltopdf {} {}.pdf \;

# And optionally merge:
pdfunite example.com/**/*.pdf whole-site.pdf

That is the textbook version. The reality is messier.

What wget handles well: static HTML, older WordPress sites, documentation generated by Sphinx or MkDocs, most sites that were built before 2015. It respects robots.txt by default (which you should not disable — see the legal section). It rate-limits itself with --wait=1. It resumes on failure.

What wget fails at: anything JavaScript-heavy. React, Vue, Angular, Next.js apps hydrated on the client, infinite-scroll pages, content loaded from XHR after page load — wget sees a mostly-empty HTML shell and downloads that. Your PDFs will be blank or show loading spinners.

What wkhtmltopdf fails at: modern CSS (grid, flexbox edge cases, container queries), custom fonts, print stylesheets that only load in real Chrome. It is built on an old WebKit and has been unmaintained since 2023. The output often looks nothing like what you saw in the browser.

The upgrade: replace wkhtmltopdf with headless Chrome:

find example.com -name "*.html" -exec \
    google-chrome --headless --disable-gpu \
    --print-to-pdf={}.pdf --no-margins file://{} \;

Now the rendering matches what a user sees. You still have wget's JavaScript problem for the enumeration half, but for a static site this pipeline scales to a few thousand pages before you have to think about queues and retries.

Realistic ceiling: 1,000–5,000 static pages. Modern JS-heavy sites: not viable.

Method 3: HTTrack + PDF converter

HTTrack is the "wget for people who do not like the command line." It is a desktop app (Windows, macOS, Linux) that mirrors a site to your local disk with a GUI wizard, respects robots.txt, handles redirects, and gives you a browsable local copy.

The workflow:

  1. Install HTTrack (WinHTTrack on Windows, WebHTTrack on Linux, brew install httrack on macOS).
  2. Point it at the site, pick a depth limit, hit Start.
  3. Wait. HTTrack is slower than wget on purpose — it throttles itself to look like a human browser.
  4. When it finishes, you have a directory tree of HTML files.
  5. Convert the tree to PDF: either loop headless Chrome over the files (see Method 2), open each one in your browser and print, or feed the directory to a batch PDF converter.

Where HTTrack shines: it is by far the most forgiving tool for someone who has never opened a terminal. The wizard walks you through depth, file types, external-link handling, and bandwidth caps. It gracefully handles interruptions. It builds an index page so you can browse the mirror locally.

Where it stumbles: same place wget does. HTTrack does not execute JavaScript. A React SPA becomes a directory of near-identical shell files. Cookies and session state are hard to configure. Sites that gate content on User-Agent or refuse to serve their content to non-browser clients will return 403s or strippedown pages.

The rendering half is still your problem. HTTrack gives you a mirror. Turning the mirror into PDFs is a separate step, and the same tradeoff applies: wkhtmltopdf is fast and ugly, headless Chrome is slow and accurate. For a site of a few hundred pages, a batch web-to-PDF extension pointed at the local file:// URLs is usually the least painful path.

Realistic ceiling: 2,000–3,000 pages of mostly-static content. Beyond that, HTTrack's single-threaded default becomes a bottleneck and you are better off with a real scraper.

Method 4: ScrapeMaster + Convert: Web to PDF

For any site where the first three methods break — JavaScript-heavy pages, dynamic content, infinite scroll, login-gated docs you have legitimate access to, or scale beyond a few thousand URLs — the answer is a real browser-based scraper for enumeration plus a real browser-based renderer for output.

The workflow:

  1. Open the site in Chrome. You are logged in (if applicable) and everything renders correctly. This is the enumeration environment.
  2. Use ScrapeMaster to walk the site's navigation. Point-and-click a link in a listing, and ScrapeMaster infers the pattern and pulls every matching URL. Add pagination handling if the listing is paginated — see our guide on handling pagination and infinite scroll for the tricky cases.
  3. Export the URL list as CSV.
  4. Feed the URL list into Convert: Web to PDF in batch mode. It opens each URL in a real Chrome tab, waits for rendering, and produces a PDF that matches what you would print by hand.
  5. Merge the outputs with a merge tool if you want a single file, or keep them per-page for easier searching.

Why this works where wget and HTTrack do not: you are using an actual Chrome browser for both halves. JavaScript executes. Fonts load. Login sessions persist. Lazy-loaded images fill in. The output PDFs look like the site, not like a 2015 mockup of the site.

Why it works at scale: ScrapeMaster runs the enumeration in your browser as a background task, so you can queue thousands of URLs and let it grind through overnight. The PDF converter processes them at the rate Chrome can render them — realistically 30–60 pages per minute on a modern laptop, faster if you narrow the batch.

Where the seams still show: you are limited by whatever the target site tolerates. A site that rate-limits at 60 requests per minute will rate-limit you the same way whether you are using ScrapeMaster or curl. Batch overnight, throttle by hand if needed, and do not point this at a site that has told you not to.

Realistic ceiling: the target's rate limit, not your tooling. For a well-behaved site with a public sitemap this scales to 10,000+ pages.

"Download an entire website" is a request that sounds innocent and often is not. Two rules cover most of the exposure:

Respect robots.txt. Every crawler and scraper — wget, HTTrack, ScrapeMaster, your own scripts — should honor the site's robots.txt file. It is a request from the site owner about which paths they do not want crawled. It is not legally binding in most jurisdictions, but ignoring it is the fastest way to lose a case if you end up in one. wget and HTTrack respect it by default. Do not turn that off.

Read the Terms of Service. Many sites explicitly prohibit bulk downloading or mirroring in their ToS. Whether that is enforceable depends on how you accepted the terms (browsewrap vs clickwrap), what jurisdiction you are in, and what you do with the data. For a full breakdown see our guide to whether web scraping is legal. The short version: scraping public data is generally legal in the US and EU; scraping personal data triggers GDPR/CCPA; violating a ToS you explicitly agreed to creates civil liability.

The pattern that gets people in trouble: logging into a site you have access to, then mirroring the whole thing "just in case." That converts a permissible read into an authorized access dispute. If you paid for a subscription, download what you need for your own use, not the entire archive. If the site has an official export function, use it — courts view "I used the export button you gave me" much more favorably than "I wrote a scraper."

A practical checklist before you point a crawler at any site:

  • Read the robots.txt.
  • Read the Terms of Service, at least the sections on "automated access" or "crawling."
  • Check whether the site publishes an official API, data export, or bulk download. Use that if it exists.
  • Rate-limit yourself even if the site does not. One request per second is polite; ten per second is aggressive.
  • Do not download personal data about identifiable individuals without a lawful basis.
  • Do not republish copyrighted content. Archiving for personal reference is different from posting the mirror publicly.

If you are archiving your own site, your employer's site, or a site whose owner has explicitly told you it is fine, none of this matters. Otherwise it all does.

Comparison table by scale

Site sizeBest methodHandles JS?EffortRisk of breakage
1–10 pagesChrome print, one page at a timeYesLowNone
10–50 pagesSitemap + batch web-to-PDF extensionYesLowSitemap gaps
50–200 pagesSitemap + Convert: Web to PDF queueYesMediumSitemap gaps, rate limits
200–2,000 pages (static)wget + headless Chrome, or HTTrackNo (wget)/No (HTTrack)MediumBlank PDFs on JS sites
200–10,000 pages (dynamic)ScrapeMaster + Convert: Web to PDFYesMediumRate limits
10,000+ pagesCustom pipeline (Playwright + queue)YesHighRate limits, bans, ToS

The numbers are rough. A ten-thousand-page static docs site might mirror in an hour with wget. A five-hundred-page e-commerce catalog with lazy-loaded images might take three hours with ScrapeMaster because every product page needs to fully render. Test on 20 pages before you commit to 20,000.

Frequently asked questions

How do I download a whole website as one PDF?

Two steps: enumerate every URL, then render each one and merge. For enumeration, use the site's /sitemap.xml if it has one, or a crawler like wget, HTTrack, or ScrapeMaster. For rendering, feed the URL list into a batch web-to-PDF extension or use headless Chrome in a shell loop. For a single combined PDF, use pdfunite (Linux/macOS), a merge tool, or a converter that offers "combine into one file" as an output option. Expect the combined file to be large — 500 pages of typical web content can run 100–300MB.

It depends on the site and what you do with the download. Public non-personal data is generally legal to crawl in the US and EU (see the hiQ v. LinkedIn ruling covered in our scraping legal guide). Personal data is regulated by GDPR and CCPA. Terms of service violations create civil liability. Republishing copyrighted content is separate copyright infringement. The safest patterns: archive your own site, archive sites that publish official data exports, archive public documentation for personal offline use. The riskiest: mirror a competitor's login-gated portal, republish someone else's archived content, or scrape personal profile data at scale.

What's the best tool to archive a website as PDF?

There is no single best tool because the right choice depends on the site's scale and how much JavaScript it uses. For static sites under 2,000 pages, HTTrack plus headless Chrome is free and battle-tested. For modern JavaScript-heavy sites, a browser-based scraper like ScrapeMaster paired with a Chrome-based PDF converter produces output that actually matches the site. For massive archives (10,000+ pages), you are writing a custom Playwright pipeline. For one-off single pages, Chrome's built-in Save as PDF is unbeatable and always available.

How do I download 100 pages as PDF at once?

Get the URLs into a list first — from a sitemap, a scraper, or by pasting from a spreadsheet. Then use a batch web-to-PDF extension that accepts a URL list, or a shell loop calling headless Chrome. For 100 pages either approach finishes in 5–15 minutes on a modern laptop. If the pages are all on the same domain and follow a pattern (like /product/1, /product/2), a scraper can enumerate and export the list in seconds. See our related walkthrough on converting an entire website to PDF page by page for the click-by-click version.

Does wget work for downloading webpages as PDF?

Not directly — wget downloads HTML, images, and CSS. It does not render or produce PDFs on its own. The classic combo is wget --mirror to grab the site, then wkhtmltopdf or headless Chrome to convert each HTML file to PDF. The wget half only works on sites where the important content is in the initial HTML response. For React, Vue, or any client-rendered SPA, wget downloads a mostly-empty shell and your PDFs will show loading spinners instead of content. On those sites you need a browser-based scraper that executes JavaScript before capturing the page.

Bottom line

The size of the site decides the tool. One page: Chrome print dialog. A few dozen pages of well-structured docs: sitemap plus a batch PDF extension. A few thousand static pages: wget or HTTrack plus a rendering step. Anything JavaScript-heavy, login-gated, or scaled beyond a few thousand URLs: a real browser-based scraper plus a real browser-based renderer. Respect robots.txt, read the terms, throttle your requests, and do not scrape personal data without a lawful basis. For the dynamic-site case that covers most real work, pair ScrapeMaster for enumeration with a Chrome-based PDF converter on the output — everything runs locally, nothing gets uploaded, and the PDFs match what you see in the browser.