How to Capture Many Web Pages at Once (Bulk URL List to PDF)
Capturing one web page is a solved problem — Chrome, Firefox and every browser extension do it. The job gets harder when the list is forty URLs: a competitor audit, every page in a client’s redesign, a batch of policy pages to show a reviewer. Opening each one, scrolling to the bottom, and saving it by hand is where an afternoon goes.
Four methods actually work for a list, each for a different kind of person. Here is each one, what the output looks like, and where it falls over.
Quick answer
| What you have | Use | Output | Needs code? |
|---|---|---|---|
| A handful of tabs already open | A browser extension (GoFullPage, FireShot) | One image or PDF per tab | No |
| Hundreds a day, same job every time | A screenshot API (ScreenshotOne, Urlbox, Browshot) | Per-URL files via HTTP | Yes |
| A one-off list, you already code | A short Puppeteer or Playwright script | Whatever you tell it to save | Yes |
| A list of URLs, no scripting | A bulk-list tool like Site2PDF | A ZIP of per-page files, or one combined PDF | No |
1. A browser extension (one tab at a time)
Extensions like GoFullPage and FireShot capture whatever is in the active tab, scrolling it to the bottom and saving a PNG, JPG or PDF. Both have free tiers; GoFullPage is free with a paid tier for annotation tools, and FireShot’s free tier watermarks captures.
For a list, they do not scale. You open each URL, press the button, confirm the save dialog, and go to the next tab. FireShot’s Pro tier adds “batch capture of multiple URLs” and “batch capture of entire websites” from a list — that is the one feature that turns an extension into a bulk tool, and it is behind a paid licence (sold as a yearly subscription or a one-time lifetime fee).
Where they break:
- JavaScript-heavy pages. An extension runs inside the browser you already opened, so what you see is what you get — but if the page is still loading when you press the button, half the content is missing.
- Pages that need a login. An extension sees the session you are logged into; an API or a script needs cookies passed through.
- Lists longer than your attention. Twenty by hand is bearable. Two hundred is a mistake waiting to happen.
Use an extension when the list is short, the pages are already open, and you want zero setup.
2. A screenshot or PDF API
Screenshot APIs — ScreenshotOne, Urlbox, ScreenshotAPI.net, Browshot, ApiFlash — render a URL on their servers in a real headless browser and return the file. Most of them expose a batch endpoint on paid tiers: Browshot has /api/v1/batch/create (thousands of URLs from a text file), ScreenshotAPI.net adds “bulk” to its Startup tier, Urlbox and ScreenshotOne charge per render on a monthly quota.
A tiny curl for one URL looks like this:
curl -o pricing.png \
"https://api.screenshotone.com/take?url=https://example.com/pricing&access_key=KEY&full_page=true"
Looping that over a list is twenty lines of Bash or Python.
Where it breaks:
- It is a developer product. The dashboard is for billing, not for “paste this list and get the files.” You write code, parse errors, retry failures.
- The output is per URL. You get
pricing.png,about.png,blog-post-1.png— one file per request. Combining them into a single PDF or a tidy ZIP named after the right domain is on you. - Legal/integrity features are rare. Only Urlbox (Business tier) returns a SHA-256 hash and a timestamp with the file; none of the others. For legal archiving, that matters.
Use an API when you are capturing the same kind of page every day and the cost per render matters more than the setup time.
3. A short Puppeteer or Playwright script
If you already write a bit of JavaScript, twenty lines of Puppeteer or Playwright do what an API does, for free, on your own machine:
const puppeteer = require('puppeteer');
const urls = require('./urls.json');
(async () => {
const browser = await puppeteer.launch();
for (const url of urls) {
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle0' });
const name = url.replace(/^https?:\/\//, '').replace(/[^a-z0-9]+/gi, '-');
await page.pdf({ path: `${name}.pdf`, format: 'A4', printBackground: true });
await page.close();
}
await browser.close();
})();
That gets you a PDF per URL. Add fullPage: true for a PNG, or use page.screenshot() for an image. For a whole JavaScript site saved as PDF, the same loop works — you just feed it the sitemap.
Where it breaks:
- You run it. When a URL throws a timeout at 3 a.m. nothing retries it.
- Fixed headers, cookie banners and lazy images. The browser captures what is on screen; cleaning up all three takes more code than people expect.
- No searchable text.
page.screenshot()is a picture.page.pdf()keeps text, but only if the page uses system fonts — anything else needs an embedded font.
Use a script when the list is a one-off and you would rather own the capture than send URLs to a vendor.
4. A paste-a-list tool
The non-code answer is a tool that takes a list of URLs and gives back the archive. Site2PDF‘s Bulk URLs tab does this:
- Open the tool and switch to Bulk URLs.
- Paste the list — one URL per line, or separated by commas or spaces. The URLs can be from different websites; a competitor audit and an internal content review are the same shape of job here.
- Press Continue. You see the pages, can untick ones you added by mistake, and can drag them into the order you want.
- Pick a format: PDF, PNG or JPG. For PDF, choose Single file (every page in one combined document) or Separate files · ZIP (one PDF per URL, zipped). PNG and JPG always come back as a ZIP because several images cannot be merged into one file.
- Press Generate and download the archive when it is ready.
What ends up inside, when the list spans multiple sites, is a ZIP whose files are named after the domain and the path: 001-example.com-pricing.pdf, 002-another-site.com-about-us.pdf. A single-domain list drops the domain and just numbers the pages, so a 40-page audit of one site reads cleanly: 001-home, 002-pricing, 003-features.
Where it breaks:
- Bulk needs a free account. The signup is for your archive history and the plan allowance — a single-page capture does not require it.
- The list is capped by your plan’s per-archive page limit — the Free plan takes a short list; paid plans go up from there (see pricing). A one-off pack covers a single big list without a subscription.
- A ZIP of separate PDFs is a paid-plan feature. PNG and JPG lists still come back as a ZIP on the free plan; what the free plan cannot do is choose to split a PDF list across files.
Use this when the list is big, mixed-domain, or you would rather paste URLs than write a script.
Which one should you use?
- A dozen pages already open in tabs → an extension. GoFullPage free, FireShot free (watermarked) or FireShot Pro for batch.
- A pipeline that runs every day → an API. Pick the one whose quota matches your volume; expect to write code around it.
- A one-off list and you already code → Puppeteer or Playwright. Twenty lines, zero cost.
- A one-off list and you don’t code, or you want one combined PDF of the lot, searchable, with URL footers → a bulk-list tool. Especially if the list spans different domains or needs a dated record for a client handoff.
Two of these often live in the same workflow. A SEO team might script monthly competitor captures with Puppeteer and use the paste-a-list tool for one-off audits. An agency uses the extension for live review and the bulk tool to bundle a project when it ships.
FAQ
Can I bulk-screenshot websites for free?
Yes, up to a point. A browser extension is free for one tab at a time. A short Puppeteer script is free, on your machine. Several screenshot APIs include a free tier of around 100 renders a month. A bulk paste-a-list tool like Site2PDF has a free tier that fits short lists; longer ones need a paid plan or a one-off pack.
How do I keep the pages in the order I pasted?
The order you paste is the order the archive uses. Site2PDF numbers each file by position (001-, 002-, 003-), and the review step lets you drag rows if you need to reorder them. An API or a script keeps the order of the input list — unless you parallelise, in which case you have to sort by index yourself.
Can I bulk-capture a site that needs a login?
Yes with a script (pass the session cookie to Puppeteer), yes with an extension (it uses the browser session you already have), partially with APIs (some accept cookies as a parameter; many do not). Bulk tools vary — Site2PDF’s Bulk URLs is for public pages.
What about full-page vs just the visible area?
For a list, you almost always want full-page: scrolled to the bottom, lazy images loaded, cookie banner removed. Every method above supports it; see how full-page screenshots actually work for the mechanics and the usual gotchas.
What is the difference between a bulk screenshot and a full-site archive?
A bulk screenshot takes a list you supplied. A full-site archive discovers the pages — from the sitemap or by following links — and captures them. Bulk is right when you already know which URLs matter; full-site is right when you want “everything the public can see.”
The takeaway
For a short, same-domain list, open each page and use an extension. For a daily pipeline, pay for an API. For a one-off list — mixed domains, forty URLs, something you want as one searchable PDF or a per-page ZIP — paste it into site2pdf.online, pick the format, and let it run.