Skip to content

Instantly share code, notes, and snippets.

@bryant988
Last active February 15, 2026 15:51
Show Gist options
  • Select an option

  • Save bryant988/9510cff838d86dcefa3b9ea3835b8552 to your computer and use it in GitHub Desktop.

Select an option

Save bryant988/9510cff838d86dcefa3b9ea3835b8552 to your computer and use it in GitHub Desktop.
Zillow Image Downloader
/**
* NOTE: this specifically works if the house is for sale since it renders differently.
* This will download the highest resolution available per image.
*/
/**
* STEP 1: Make sure to *SCROLL* through all images so they appear on DOM.
* No need to click any images.
*/
/**
* STEP 2: Open Dev Tools Console.
* Copy and paste code below
*/
const script = document.createElement('script');
script.src = "https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js";
script.onload = () => {
$ = jQuery.noConflict();
const imageList = $('ul.media-stream li picture source[type="image/jpeg"]').map(function () {
const srcset = $(this).attr('srcset').split(' '); // get highest res urls for each image
return srcset[srcset.length - 2]
}).toArray();
const delay = ms => new Promise(res => setTimeout(res, ms)); // promise delay
// get all image blobs in parallel first before downloading for proper batching
Promise.all(imageList.map(i => fetch(i))
).then(responses =>
Promise.all(responses.map(res => res.blob()))
).then(async (blobs) => {
for (let i = 0; i < blobs.length; i++) {
if (i % 10 === 0) {
console.log('1 sec delay...');
await delay(1000);
}
var a = document.createElement('a');
a.style = "display: none";
console.log(i);
var url = window.URL.createObjectURL(blobs[i]);
a.href = url;
a.download = i + '';
document.body.appendChild(a);
a.click();
setTimeout(() => {
window.URL.revokeObjectURL(url);
}, 100);
}
});
};
document.getElementsByTagName('head')[0].appendChild(script);
@legendaryroots
Copy link

This is a little bit of a smaller script that works if you open all images and scroll to the bottom, then run the script.

Works in active listings and sold listings as long as it has a modal with all of the pictures.

// === Zillow Vertical Media Wall Downloader ===
(async () => {
    // Scroll the wall so every lazy-loaded photo appears
    const wall = document.querySelector('ul[aria-label="media wall images"]');
    if (!wall) {
        alert("Couldn’t find the photo wall. Open the full gallery and scroll through all images first.");
        return;
    }
    wall.scrollIntoView({ behavior: "smooth" });
    await new Promise(r => setTimeout(r, 1200));

    // Get every JPEG source and pick the highest-resolution URL
    const sources = wall.querySelectorAll('picture source[type="image/jpeg"]');
    const urls = Array.from(sources).map(source => {
        const srcset = source.getAttribute('srcset');
        const parts = srcset.split(',').map(p => p.trim());
        const highest = parts[parts.length - 1].split(' ')[0]; // last entry = biggest size
        return highest;
    }).filter(Boolean);

    if (urls.length === 0) {
        alert("No photos found. Make sure you scrolled through the entire gallery.");
        return;
    }

    console.log(`Found ${urls.length} photos. Starting download...`);

    // Fetch all images as blobs (parallel, but browser is fine with it)
    const blobs = await Promise.all(
        urls.map(url => fetch(url).then(r => r.blob()))
    );

    // Download one by one with a small delay to keep Chrome happy
    for (let i = 0; i < blobs.length; i++) {
        const filename = `zillow-photo-${String(i + 1).padStart(3, '0')}.jpg`;

        const blobUrl = URL.createObjectURL(blobs[i]);
        const a = document.createElement('a');
        a.href = blobUrl;
        a.download = filename;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(blobUrl);

        console.log(`✅ Downloaded ${filename}`);
        await new Promise(r => setTimeout(r, 350)); // gentle on the browser
    }

    console.log(`🎉 All ${urls.length} photos saved!`);
})();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment