DEV Community

CyberMax
CyberMax

Posted on Originally published at cybermaxtools.com

Download every image from a list of web pages at full size (Python, JS and n8n)

If you have ever saved a product page and ended up with a folder of 300 px thumbnails, this is for you. Below: where the full-size files actually live in the HTML, and copy-paste code to pull them from a whole list of pages into one ZIP.

Short answer

For one page, a browser extension or "Save page as" saves the images the browser has loaded, which are often thumbnails. For full-size originals from many pages, send the page URLs to a bulk image downloader: Picpail on Apify reads img, srcset, lazy-loaded, CSS-background and og:image files, swaps CDN thumbnails for the originals, removes duplicates and returns one ZIP plus a row per image, at $0.0008 per image delivered.

Step by step

  1. List the pages you want: product pages, category pages, a gallery, a blog archive (one URL per line). Direct image URLs can go in the same list.
  2. Set a minimum size (for example 300 x 300 px) so icons, avatars and tracking pixels are skipped.
  3. Run the list through a bulk downloader and choose one ZIP (a folder per page) or one ZIP per page.
  4. Open the per-image table (format, width, height, bytes, alt text) to spot missing alt text or heavy files.
  5. Check the licence before you reuse any image you did not create.

Python (pip install apify-client): a list of pages in, one ZIP link out

import os
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("cybermax/bulk-image-downloader").call(run_input={
    "urls": ["https://books.toscrape.com/", "https://wordpress.org/news/"],
    "minWidth": 300, "minHeight": 300,   # skip icons and thumbnails
    "output": "zip",                      # or zipPerPage, files, list
})
out = client.key_value_store(run["defaultKeyValueStoreId"]).get_record("OUTPUT")["value"]
print("ZIP:", out["zips"][0]["url"])
for img in client.dataset(run["defaultDatasetId"]).iterate_items():
    if img.get("type") == "image":
        print(img["width"], img["height"], img["format"], img.get("alt") or "(no alt)", img["imageUrl"])
Enter fullscreen mode Exit fullscreen mode

JavaScript / Node (npm i apify-client)

import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('cybermax/bulk-image-downloader').call({
  urls: ['https://books.toscrape.com/'],
  minWidth: 300,
  formats: ['jpeg', 'png', 'webp'],
});
const { value } = await client.keyValueStore(run.defaultKeyValueStoreId).getRecord('OUTPUT');
console.log('ZIP:', value.zips[0].url);
Enter fullscreen mode Exit fullscreen mode

No code: n8n, Make or Zapier

n8n: HTTP Request node (or the Apify node, action "Run an Actor and get dataset")
Method:  POST
URL:     https://api.apify.com/v2/acts/cybermax~bulk-image-downloader/run-sync-get-dataset-items
Auth:    Header Auth  ->  Authorization: Bearer <your Apify token>
Body:    JSON  {"urls": ["https://example.com/gallery"], "minWidth": 300, "output": "zip"}
Output:  one n8n item per result row, ready for Google Sheets / Airtable / a Slack message

Make:    Apify app -> "Run an Actor" (Actor: cybermax/bulk-image-downloader, wait for finish = yes)
         -> Apify "Get Dataset Items" (dataset = the run's defaultDatasetId) -> Google Sheets "Add a Row"
Zapier:  Apify app -> action "Run Actor" (cybermax/bulk-image-downloader, input JSON as above)
         -> trigger "Finished Actor Run" -> "Fetch Dataset Items" -> your app
Runs longer than 5 minutes: start with POST /v2/acts/cybermax~bulk-image-downloader/runs and read the dataset when the run finishes.
Enter fullscreen mode Exit fullscreen mode

From an AI agent (MCP)

# Any MCP client (Claude Desktop, Claude Code, Cursor, VS Code): Apify's hosted MCP server
{
  "mcpServers": {
    "bulk-image-downloader": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://mcp.apify.com/?tools=cybermax/bulk-image-downloader",
               "--header", "Authorization: Bearer ${APIFY_TOKEN}"],
      "env": { "APIFY_TOKEN": "<your Apify token>" }
    }
  }
}
# The agent sees one tool, cybermax--bulk-image-downloader, with the Actor's input schema.
Enter fullscreen mode Exit fullscreen mode

One real dataset row (wordpress.org/news/, 24 Sep 2026)

Field Value
source srcset (the largest size, not the page's copy)
format jpeg
width x height 1920 x 1200
bytes 1,408,399
alt Sunita Rai at WordCamp Asia
fileName 002-wordpress.org_news/0002-sunita-rai-featured-img.jpg

Source: Picpail (Apify Actor cybermax/bulk-image-downloader) README, real run on 24 Sep 2026

Why "Save page as" misses the full-size images

Most sites send a small image first and list larger ones in srcset, load images only when you scroll (lazy loading), or put photos in CSS backgrounds. A browser save keeps what was rendered, so you get 300 px product thumbnails instead of the 2000 px originals.

A bulk downloader reads the page source instead: every srcset candidate, data-src and data-lazy attributes, CSS url() backgrounds and og:image, then asks the CDN (Shopify, WordPress, Wikimedia and similar) for the original file.

Download images from a list of URLs or a whole site section

Put every page in the urls list: category pages, product pages or the pages of a sitemap. Set sameDomainOnly to skip ads and third-party trackers, urlPattern to keep only paths such as /products/, and excludeUrlPattern to drop logo|icon|sprite files.

Run it on a schedule to get only new images

Turn on monitor mode and add an Apify Schedule (daily or weekly): each run returns only images that were not delivered before, such as new products in a category or a changed homepage banner. Images you already have are skipped and not charged.

Good to know

  • Price on Apify: $0.0008 per image delivered ($0.80 per 1,000), plus $0.0001 per MB for the part of a very large file above 2 MB. Duplicates, filtered images and failed downloads are free. Apify's free plan includes $5 of usage each month.
  • Pages that build everything with JavaScript after load may return a page-error row with the reason; those rows are free.

FAQ

Is it legal to download images from a website?
Saving publicly visible images is what a browser does, but reusing them needs the owner's permission or a licence. This is not legal advice.

How do I get the full-size image instead of the thumbnail?
Use a tool that reads srcset and asks the CDN for the original. Picpail does this by default (upgradeToOriginals).

Can I download images from many pages at once?
Yes: list the pages (hundreds are fine) and you get one ZIP with a folder per page, or one ZIP per page.

Can an AI agent use it?
Yes. Apify's MCP server exposes it as the tool cybermax--bulk-image-downloader, so Claude, Cursor or any MCP client can call it with your Apify token.

Why not a free browser extension?
For one page, an extension is fine. Extensions save what the browser shows (often thumbnails), one tab at a time; a bulk downloader works through a list, fetches originals and returns sizes and alt text.

Try it on your own list: Picpail on Apify (Apify's free plan includes $5 of usage a month).


Published automatically by CyberMax. Every number above comes from the linked public data; nothing is estimated.

Top comments (0)