-
Star
(149)
You must be signed in to star a gist -
Fork
(18)
You must be signed in to fork a gist
-
-
Save bryant988/9510cff838d86dcefa3b9ea3835b8552 to your computer and use it in GitHub Desktop.
/** | |
* 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); |
Script below copied from @ncarson9 's post , and as of June 19, 2025, this works for me in mac Chrome. Load the photo window in Zillow, scroll to the bottom of the lightbox page in order to have the page load all of the photos, then open the Developer Tools window in Chrome, go to Console, and paste into Console and hit enter, and then a .zip file of images is saved to downloads by the browser 🙌🏼:
const TARGET_FORMAT = "jpeg"; // Options: `jpeg` or `webp` const TARGET_SIZE = "1536"; // Options: `1536`, `1344`, `1152`, `960`, `768`, `576`, `384`, `192` // Load JSZip library const script = document.createElement('script'); script.src = "https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js"; document.head.appendChild(script); script.onload = function() { // Function to download the zip file function downloadZip(zip) { zip.generateAsync({type: 'blob'}).then(function(content) { const link = document.createElement('a'); link.href = URL.createObjectURL(content); link.download = 'images.zip'; document.body.appendChild(link); link.click(); document.body.removeChild(link); }); } // Function to gather and zip image URLs from "media wall" function gatherAndZipImages() { // Gather the image URLs const mediaWall = document.querySelector('div[data-testid="hollywood-vertical-media-wall"]'); const sources = Array.from(mediaWall.querySelectorAll(`source[type="image/${TARGET_FORMAT}"]`)); // Try to pull the largest src URL from a source's srcset // srcset is in the format "<url> <size>, <url> <size>" so we split it and try to grab the last (hopefully largest) URL // It shouldn't really matter, though, since the regex will replace the target size with the largest possible anyway const imageUrls = sources.map(source => {return source.srcset.split(",").at(-1).split(" ")[1].replaceAll(/_\d+.(jpg|webp)/g, `_${TARGET_SIZE}.${TARGET_FORMAT}`)}); const zip = new JSZip(); const imgFolder = zip.folder("images"); if (imageUrls.length > 0) { console.log('Image URLs:', imageUrls); const downloadPromises = imageUrls.map((url, index) => { return fetch(url).then(response => response.blob()).then(blob => { imgFolder.file(`image_${index + 1}.${TARGET_FORMAT}`, blob); }); }); Promise.all(downloadPromises).then(() => { downloadZip(zip); }); } else { console.log(`No .${TARGET_FORMAT} images found.`); } } // Execute the function to gather and zip images gatherAndZipImages(); }Thanks!
Thank you so much for this. Unfortunately it seems to stop after the first 7 photos in Chrome.
Thanks again. It was my mistake, I loaded all the pictures, but was in the horizontal slideshow and not the vertical scroll lightbox. Works great! In chrome, on Zillow, and converted all 54 webp to jpg. 6-30-25
...and if I open an individual downloaded jpg in File Explorer, it even re-constitutes the slideshow to where I can just tab through the whole set. Thanks for you efforts!
Thanks again. It was my mistake, I loaded all the pictures, but was in the horizontal slideshow and not the vertical scroll lightbox. Works great! In chrome, on Zillow, and converted all 54 webp to jpg. 6-30-25
I am getting the same error:
Uncaught TypeError: Cannot read properties of null (reading 'querySelectorAll')
at gatherAndZipImages (:26:46)
at script.onload (:53:5)
I can't figure out how to the vertical scroll Lightbox. All I get is this one:
@VeniceNerd I see this issue as well. That particular listing looks to be using Zillow Showcase ShowingTime+, the ST+ in the lower right hand corner, some kind of feature they're promoting to realtors. Just for comparison, looking at nearby 27556 Antelope Dr, Santa Clarita, the listing looks normal, non-ShowingTime+.
. If I try again for 27555 Antelope Drive, but this time on Redfin, I notice the 'lightbox' structure may be accessible. I also see that its not Santa Clarita, but Canyon Country, but that's probably not important. You might try the script on Redfin, I have no clue if its particular to Zillow. If it doesn't work then you'd need to appeal to the programmers in this thread; I don't know anything about it. YMMV, Regards,
This is not working in Firefox, Chrome, or Edge as of April '25. Getting either "Cannot read properties of null (reading 'querySelectorAll')" error or "redeclaration of const TARGET_FORMAT" depending on browser.