Tutorial12 min read

How to Scrape Images From a Website

Short answer

To bulk download every image on a page, including the ones that load only as you scroll, use a tool that scrolls the page first. On one page, a browser extension with auto-scroll does it in a few clicks: Download All Images, a Chrome extension, has a Deep Scan mode that scrolls the page to load lazy images and downloads them as a ZIP. For a whole site or thousands of images, use the Playwright scroll script below. Tools that don't run JavaScript, such as HTTrack or wget, miss images a script adds on scroll. Underneath, every tool does the same thing: it collects the image URLs (src, srcset, data-src, CSS backgrounds, og:image) and downloads each file once. At scale, the image files, not the HTML, decide how much proxy traffic you use: ProxyField residential proxies cost from $1.95/GB, and you start with the Easy Trial, 1 GB for $2.95.

residential IPs
412M+
from, traffic never expires
$1.95/GB
Easy Trial
1 GB for $2.95
On this page 11 sections
  1. Which tool for which job
  2. What image scraping is
  3. Where images hide in a page
  4. Scrape images without code
  5. Scrape images with Python
  6. Images on JavaScript pages and infinite scroll
  7. Bulk downloads at scale
  8. How much proxy traffic image scraping uses
  9. How to scrape images without getting blocked
  10. Copyright: scraping an image is not a license to use it
  11. How to Scrape Images From a Website FAQ

Which tool for which job

ToolWhat it isLoads images that appear on scrollScaleCode
Download All ImagesChrome extensionYes: Deep Scan scrolls the page for youthe open pagenone
DownThemAll!download-manager browser extensionOnly what is loaded: scroll to the bottom firstthe open pagenone
gallery-dlcommand-line program for image galleriesGets the whole gallery without scrolling, on the sites in its supported-sites listwhole galleries and profilesone command
HTTrackwebsite copierNo: its FAQ lists JavaScript-heavy sites as "bogus/incomplete"a whole sitenone
wgetcommand-line downloaderNo: it does not run JavaScripta page or a siteone command
Playwright script (below)real browser driven by PythonYes: scrolls until no new images appearthousands of pages~20 lines
Python + BeautifulSoup script (below)HTML parser and downloaderNo: reads the HTML onlythousands of pages~50 lines
Shell
# gallery-dl: install, then download a supported gallery into ./gallery-dl/
python -m pip install -U gallery-dl
gallery-dl "https://<supported-site>/<gallery-url>"
# wget: every JPG, PNG, WebP and GIF the page links to, into the current folder (no JavaScript)
wget -r -l 1 -nd -A jpg,jpeg,png,webp,gif "https://example.com/gallery"
# images on another host (a CDN): add -H -D cdn.example.com

To see whether a page loads images on scroll, open DevTools, go to the Network panel, filter by Img and scroll: if the list keeps growing, you need a tool from a "Yes" row.

What image scraping is

Image scraping is collecting image files, or their URLs and details, from web pages automatically: product photos for a catalog, listing photos for price research, pictures for a training dataset, or every image on your own site for an audit. It has two jobs, and tools differ in how well they do each:

  1. Finding the image URLs

    In the HTML, the CSS and the data the page loads.

  2. Downloading the files

    Without duplicates, broken files or blocks.

An image downloader does the second job for URLs you give it; an image scraper does both, and usually also keeps the context: the page URL, the alt text, the product or listing the image belongs to.

Where images hide in a page

The <img src> attribute is only the first place to look. Modern pages spread the real image URL over several attributes and files.

WhereWhat it looks likeHow to read it
<img src><img src="/photos/a.jpg" alt="Red chair">The src attribute; join it to the page URL
srcset and <picture>srcset="a-480.jpg 480w, a-1200.jpg 1200w"Split on commas and pick the widest candidate
Lazy-load attributesdata-src, data-lazy-src, data-originalRead the attribute; src often holds a placeholder
CSS backgroundsstyle="background-image: url(/hero.jpg)" or a stylesheet ruleSearch inline styles and the CSS files for url(...)
Meta tags<meta property="og:image" content="...">One main image per page, usually large
JSON in the page or an APIA <script> with product data, or a JSON response in the Network panelParse the JSON; the full-size URL is often only here
Canvas or blob URLs<canvas> or blob: addressesNot a downloadable file; take the source request from the Network panel, or a screenshot

Responsive images matter most for quality: srcset lists the same picture at several widths, and the browser picks one for your screen. An image scraper that keeps src alone often saves the smallest version. Per the HTML standard on srcset, each candidate is a URL followed by a width (480w) or a pixel density (2x).

Easy Trial: 1 GB for $2.95.
Try for the price of 1 GB, no subscription, traffic never expires.

Scrape images without code

With an auto-scroll extension (Download All Images in Chrome):

  1. Install the extension from the Chrome Web Store and open the page with the images.
  2. Run Deep Scan. The extension scrolls the page to the end, so lazy-loaded images and infinite-scroll galleries load, and lists every image it found.
  3. Filter out icons and thumbnails: set a minimum width and height, pick the types you want (JPG, PNG, GIF, WebP, SVG) or the orientation, and exclude URLs that contain words such as logo or sprite.
  4. Select the images and download them as single files or as one ZIP, with a filename pattern if you need one.

Expect to get what your browser rendered, at the size the page loaded. An extension without a scroll step (or "Save page as") saves only the images loaded at that moment, so on lazy-loading pages scroll to the bottom by hand first, or the downloads stop at the first screen.

With DevTools: open the Network panel, filter by Img, reload and scroll. Every image the page loads is listed with its URL, size and type; right-click to copy the URLs.

Extensions use your browser's proxy setting; see the Chrome proxy guide to change the IP. None of these scale past a few pages, and none keep the link between an image and the product or listing it belongs to.

Scrape images with Python

The script below fetches a page, collects image URLs from src, srcset, lazy-load attributes and inline CSS, and downloads each one once. It needs pip install requests beautifulsoup4. Replace the start URL with a page you are allowed to scrape.

Python
import hashlib, pathlib, re
from urllib.parse import urljoin, urlparse
import requests
from bs4 import BeautifulSoup

PAGE = "https://example.com/gallery"
OUT = pathlib.Path("images"); OUT.mkdir(exist_ok=True)
s = requests.Session()
s.headers["User-Agent"] = "Mozilla/5.0 (compatible; image-audit/1.0)"

def widest(srcset):
    best, best_w = None, -1
    for part in srcset.split(","):
        bits = part.strip().split()
        if not bits:
            continue
        w = int(bits[1][:-1]) if len(bits) > 1 and bits[1].endswith("w") else 0
        if w > best_w:
            best, best_w = bits[0], w
    return best

def image_urls(html, base):
    soup = BeautifulSoup(html, "html.parser")
    urls = set()
    for img in soup.select("img, source"):
        for attr in ("data-src", "data-lazy-src", "data-original", "src"):
            if img.get(attr) and not img[attr].startswith("data:"):
                urls.add(urljoin(base, img[attr])); break
        if img.get("srcset") and widest(img["srcset"]):
            urls.add(urljoin(base, widest(img["srcset"])))
    for tag in soup.select("[style*=url]"):
        for u in re.findall(r"url\(['\"]?([^'\")]+)", tag["style"]):
            urls.add(urljoin(base, u))
    og = soup.select_one('meta[property="og:image"]')
    if og and og.get("content"):
        urls.add(urljoin(base, og["content"]))
    return urls

seen = set()
for url in image_urls(s.get(PAGE, timeout=30).text, PAGE):
    r = s.get(url, timeout=30, headers={"Referer": PAGE})
    if r.status_code != 200 or not r.headers.get("Content-Type", "").startswith("image/"):
        continue                                   # skip error pages saved as .jpg
    digest = hashlib.sha256(r.content).hexdigest()
    if digest in seen:
        continue                                   # same file under another URL
    seen.add(digest)
    ext = r.headers["Content-Type"].split("/")[1].split(";")[0].replace("jpeg", "jpg")
    name = pathlib.Path(urlparse(url).path).stem or digest[:12]
    (OUT / f"{name}-{digest[:8]}.{ext}").write_bytes(r.content)

Three details do most of the work:

  • The Content-Type check. A blocked or missing image often comes back as an HTML error page with a 200 or 403 status. Saving it as photo.jpg gives you a broken file; checking for image/ skips it.
  • The hash. The same picture often sits under several URLs (sizes, CDN parameters). Hashing the bytes keeps one copy.
  • The Referer header. Some sites refuse image requests that do not come from their own pages (hotlink protection). Sending the page URL as Referer is what a browser does.

Images on JavaScript pages and infinite scroll

If the image URLs are not in the page source, a script adds them after the page loads, often as you scroll. Two ways to get them:

  1. Find the data request

    In the Network panel, filter by Fetch/XHR and scroll: a gallery or product grid usually loads a JSON list with the image URLs, often in full size. Call that URL directly.

  2. Render and scroll

    Playwright opens the page in a real browser, scrolls until no new images appear, and reads every img after the scripts ran.

Python
from playwright.sync_api import sync_playwright

with sync_playwright() as p:
    browser = p.chromium.launch(proxy={"server": "http://gate.proxyfield.io:7000",
                                       "username": "<login>-country-us-city-new_york", "password": "<password>"})
    page = browser.new_page()
    page.goto("https://example.com/gallery", wait_until="networkidle")
    last = 0
    while True:
        page.mouse.wheel(0, 4000)
        page.wait_for_timeout(1500)
        count = page.locator("img").count()
        if count == last:
            break
        last = count
    urls = page.eval_on_selector_all("img", "els => els.map(e => e.currentSrc || e.src)")
    browser.close()
print(len(urls), "images")

currentSrc returns the candidate the browser actually chose from srcset. Download the URLs with the Requests loop above (with its Content-Type and hash checks): a plain HTTP download is faster than saving files through the browser. More patterns for script-built pages: how to scrape dynamic web pages.

Bulk downloads at scale

Thousands of images from many pages need a pipeline, not a loop:

  • Separate finding from downloading. Write the image URLs, with their page URL and alt text, to a file or table first; download from that list. A crash then costs you nothing already done.
  • Download in parallel, politely. Start low (about 5 parallel downloads per site) and raise the number while responses stay clean; image CDNs often accept more than the HTML server does. Back off on 429 responses. The patterns are in how to make web scraping faster.
  • Resume. Skip URLs whose file already exists, and keep a list of failures to retry later.
  • Store by hash. Name files by their hash (or keep the hash in your table) so duplicates never take space twice.
  • Keep the context. An image without its product, listing or page is hard to use later.

How much proxy traffic image scraping uses

Images are the heavy part of a page, so estimate traffic from the files, not the page count. A worked example: 10,000 images at an average of 200 KB each come to about 2 GB; with ProxyField residential proxies at the 1-9 GB rate of $2.95/GB, that is about $6 before blockchain network fees, and the HTML pages add a little more. Ways to cut it:

  • Download each image once (the hash check above) and never re-download files you already have.
  • Pick the size you need from srcset instead of always the widest.
  • When you render pages only to find URLs, block image downloads in the browser and fetch the files afterwards from your list.

Full pricing by volume: residential and mobile proxy pricing. The traffic never expires, so a large one-off download can use the same balance as next month's run.

How to scrape images without getting blocked

Image servers block for the same reasons page servers do: too many requests from one IP, requests that do not look like a browser, and missing headers.

  1. Send browser-like headers, including User-Agent, Accept: image/avif,image/webp,*/* and the Referer of the page the image is on.
  2. Pace per host. Keep a delay per domain, and honor Retry-After on 429 responses.
  3. Rotate IPs on large jobs. With a rotating gateway, each download can leave from a new IP; use a sticky session when the site ties images to the session that loaded the page.
  4. Respect the site's limits. If a site clearly refuses automated access, stop; the questions to ask first are in is web scraping legal.

ProxyField gives you the second half of that list: a new IP per request or sticky sessions from 30 seconds to 36 hours, country, region and city targeting, and unlimited concurrent threads, on residential proxies with 412M+ residential IPs in 195+ countries. The gateway is gate.proxyfield.io:7000; <login>-country-us-city-new_york asks for an IP in New York. Region, session and session time go in the same username: -region-<region>, -session-<id> and -ttl-<seconds> (30 to 129,600 seconds, 20 minutes by default), as in <login>-country-us-region-new_york-city-new_york-session-he9f2qga-ttl-600; every part after the login is optional.

How to Scrape Images From a Website FAQ

How do I scrape images from a website?

ProxyField residential proxies, from $1.95/GB, carry the downloads when you scrape images from a website at scale; the scrape itself is to collect the image URLs from src, srcset, lazy-load attributes, CSS backgrounds and the og:image tag, join them to the page URL, and download each file only if the response is really an image. For one page, a browser extension or the DevTools Network panel is enough; for thousands, a script with deduplication and rotating proxies does the job.

What's a good tool to bulk download all the images from a website, including the ones that only load as you scroll?

For one page, a Chrome extension with auto-scroll, such as Download All Images (its Deep Scan scrolls the page to load lazy images, then downloads them as a ZIP), is the quickest. For galleries on the sites it supports, gallery-dl downloads whole collections from the command line; for thousands of pages, a Playwright script scrolls each page and collects every image URL. HTTrack and wget do not run JavaScript, so they miss images loaded on scroll.

Why does my image downloader miss images that load as I scroll?

Lazy-loaded images are requested only when they come into view, and until then the src holds a placeholder or the real URL sits in data-src. A tool that does not scroll, or does not run JavaScript, never sees them: use one with an auto-scroll step, scroll to the bottom before you run it, or read data-src and srcset in a script.

Can HTTrack download all images from a website?

It copies a site with the images its HTML links to, but its FAQ lists JavaScript-heavy sites among the cases it cannot fully handle, so images added by scripts or on scroll are often missing. For those pages, use a browser-based tool or the Playwright script on this page.

What is image scraping?

Collecting images, or their URLs and details, from web pages automatically, for example product photos for a catalog or pictures for a dataset. A scraper finds the image URLs in the page and downloads the files, usually keeping the page URL and alt text with each one.

Can I scrape all images from a website automatically?

Yes, by combining a crawler with an image scraper: the crawler visits every page in scope, and the scraper collects the image URLs from each one into a list that a downloader works through. Deduplicate by file hash, because the same image often appears on many pages.

What's the difference between an image scraper and an image downloader?

An image downloader saves files from URLs you already have, or from the page open in your browser. An image scraper also finds the URLs across many pages, including srcset, lazy-load attributes and CSS, and keeps the context each image came from.

How do image scrapers handle responsive images and srcset?

They read the srcset attribute, which lists the same picture at several widths, and pick a candidate, usually the widest. A scraper that reads only src often saves the smallest version; in a browser, currentSrc tells you which candidate was actually loaded.

Can you scrape CSS background images?

Yes. Search inline style attributes and the page's stylesheets for url(...) values and join them to the page or stylesheet URL. Images set by scripts after load show up in the browser's Network panel under Img.

How do I scrape images from a JavaScript-rendered page?

First look for the JSON request the page makes for its gallery or product grid, which often holds full-size URLs. If there is none, open the page in Playwright, scroll until no new images appear, and read every img element's currentSrc.

Show 6 more questionsShow fewer questions

How do I scrape images without getting blocked?

Send browser-like headers with the page as Referer, keep a delay per host, back off on 429 responses and spread large jobs over rotating IPs. Stop if the site clearly refuses automated access.

How many images can I scrape safely?

There is no fixed number: it depends on the site's rate limits and terms. Start with one download every second or two per site, watch for 429 and 403 responses, and raise the pace slowly; spreading requests over many IPs helps with per-IP limits, not with a site that forbids scraping.

How do you stop duplicate image downloads?

Hash each file's bytes (SHA-256) and skip any hash you already have, because the same picture often sits under several URLs and sizes. Also skip URLs already in your download log, so a rerun does not fetch them again.

Can I scrape website images without writing code?

Yes, for a few pages: an image-downloader browser extension lists every image on the open page, and the DevTools Network panel filtered by Img shows each image URL. For many pages or regular runs, a script is easier to keep working.

Can a web crawler download pictures?

Yes. A crawler follows links from page to page, and an image step in each page's processing collects the picture URLs and downloads them. Keep the two apart in a list or queue, so that a failed download never stops the crawl.

How much proxy traffic does image scraping use?

Roughly the total size of the files: 10,000 images at about 200 KB each come to about 2 GB, plus the HTML pages. Downloading each file once and choosing smaller srcset sizes when you don't need full resolution cut that number.

Easy Trial: 1 GB for $2.95.

Try for the price of 1 GB, no subscription, traffic never expires.