Last active
February 15, 2026 15:51
-
Star
(157)
You must be signed in to star a gist -
Fork
(19)
You must be signed in to fork a gist
-
-
Save bryant988/9510cff838d86dcefa3b9ea3835b8552 to your computer and use it in GitHub Desktop.
Zillow Image Downloader
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * 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); |
Confirming that @SabinVI 's script and @reworkednyc worked perfectly on Brave v1.85.120 on 1/9/2026. Thanks, folks!
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
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:
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.