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);
@ak47us
Copy link

ak47us commented Sep 21, 2025

@SabinVI this worked on Edge. Thank you!

@tjsoco
Copy link

tjsoco commented Sep 29, 2025

@SabinVI this worked on Chrome for a "for Sale" house. Thank you!

@reworkednyc
Copy link

reworkednyc commented Oct 14, 2025

It is mid-October 2025 and I'm running Firefox current version (143.0.4 64-bit for ARM64). I was happily surprised to find that the script works perfectly. I used the version @SabinVI posted three weeks ago. Below is the exact procedure I followed:

  1. Navigated to the listing page for the house, whose status is 'under contract' (note I was on the main listing page, not the lightbox)
  2. Scrolled to the very bottom of the page without jumping, so as to load every picture that is available
  3. In Firefox, select the 'Tools' menu => 'Browser Tools' => 'Web Developer Tools'
  4. Within the Dev Tools popup that opens there are several tabs across the top. Select the 'Console' tab. Hit the Trash icon to clear the workspace (this won't harm anything)
  5. Type 'allow pasting' into the dialog
  6. Paste the @SabinVI code into the dialog and hit 'return'
  7. Wait a second while the magic happens. You may see some error lines and 'Found Image URLs'.
  8. After about 5 seconds, Firefox presented me with the 'save file' option. The resulting download was a .zip containing all of the pictures from the listing in high-resolution (~225kb avg in my case).

I was happy to find the script made it easy to archive the images - thanks to everyone who took the time to advance and refine this helpful bit of code. I hope my pedantic write-up is of use to fellow Firefox users who may be equally unfamiliar with using .js in console.

@fstlaneukraine
Copy link

Confirming that @SabinVI 's script and @reworkednyc worked perfectly on Brave v1.85.120 on 1/9/2026. Thanks, folks!

@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