Hoe Zillow Vastgoedgegevens te Scrapen: Zoek JSON, Zestimate, PerimeterX
Zillow levert zijn lijstgegevens als JSON verborgen op de pagina — je hoeft nooit een enkele div te parseren. Hier is hoe je de kaartgrenzen-zoek-API aanstuurt, de pagineringlimiet omzeilt en PerimeterX overleeft.
Zillow bezit meer dan 110 miljoen eigendommen en trekt ongeveer 245 miljoen maandelijkse bezoekers, wat het de standaardbron maakt voor Amerikaanse vastgoedgegevens — prijzen, adressen, slaapkamers, badkamers, zestimate en huurinschattingen. Het zit ook achter PerimeterX en rendert client-side, dus naïeve scrapers krijgen een 403 en een lege pagina. Het goede nieuws: Zillow geeft je zijn gegevens als JSON als je weet waar je moet kijken, en de zoekfunctie wordt aangedreven door kaartcoördinaten die je direct kunt aanroepen. Hier is de hele aanpak.
Parse geen HTML — Zillow levert JSON
Er is geen noodzaak om te vechten met CSS-selectors op een Zillow-eigendommenpagina. Het volledige eigendomsrecord is ingebed als verborgen webgegevens in een script-tag. Twee locaties dekken bijna elke pagina: <script id="__NEXT_DATA__"> bevat de Next.js cache, en sommige pagina's gebruiken in plaats daarvan <script id="hdpApolloPreloadedData"> (de Apollo GraphQL cache). Pak een van beide, parseer het, en je hebt een schoon object met zpid, price, livingArea, bedrooms, bathrooms, latLong, homeStatus, rentZestimate en meer:
import json, re, requests
proxy = "http://USER:PASS@gate.quantumproxies.io:8000"
proxies = {"http": proxy, "https": proxy}
HEADERS = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36",
"accept-language": "en-US,en;q=0.9"}
def property_json(url):
r = requests.get(url, headers=HEADERS, proxies=proxies, timeout=20)
r.raise_for_status() # 403 => blocked, rotate IP
m = re.search(r'id="__NEXT_DATA__"[^>]*>(.*?)</script>', r.text, re.S)
if m:
data = json.loads(m.group(1))
cache = data["props"]["pageProps"]["componentProps"]["gdpClientCache"]
return next(iter(json.loads(cache).values()))["property"]
# fallback: Apollo cache
m = re.search(r'id="hdpApolloPreloadedData"[^>]*>(.*?)</script>', r.text, re.S)
cache = json.loads(json.loads(m.group(1))["apiCache"])
return next(v["property"] for k, v in cache.items() if "ForSale" in k)
Het ingebedde record is veel rijker dan de zichtbare pagina. Naast prijs en adres krijg je zestimate en rentZestimate — Zillow's eigen verkoop- en huurwaarderingen — plus homeStatus (te koop, verkocht, te huur), daysOnZillow, perceel- en woonoppervlak, en precieze breedte- en lengtegraad. Dat is alles wat een vergelijkingsmodel, een lead-scoring pipeline of een marktdashboard nodig heeft, geleverd als één schoon JSON-object per eigendom in plaats van een dozijn kwetsbare CSS-selectors die breken bij de volgende herontwerp.
De zoek-API werkt op kaartcoördinaten
Zillow's zoekfunctie is niet keyword-first — het is map-first. Onder de motorkap vuurt het indienen van een zoekopdracht een verzoek af naar zillow.com/async-create-search-page-state met een searchQueryState object waarvan het kernveld mapBounds is: vier getallen (noord, zuid, oost, west) die een rechthoek op de kaart tekenen. Geef het een begrenzingsvak en het retourneert elke lijst erin, als gestructureerde JSON:
def search_area(bounds, page=1):
url = "https://www.zillow.com/async-create-search-page-state"
body = {
"searchQueryState": {
"pagination": {"currentPage": page},
"mapBounds": bounds, # {'north':..,'south':..,'east':..,'west':..}
"filterState": {"sortSelection": {"value": "days"}},
},
"wants": {"cat1": ["listResults", "mapResults"], "cat2": ["total"]},
"requestId": 2,
}
r = requests.put(url, json=body, headers=HEADERS, proxies=proxies, timeout=20)
return r.json()["cat1"]["searchResults"]["listResults"]
# New Haven, CT bounding box
listings = search_area({"north": 41.366, "south": 41.230,
"east": -72.827, "west": -73.030})

Omzeil de 820-resultatenlimiet
Zillow pagineert slechts 20 pagina's van ongeveer 41 items, dus een enkele zoekopdracht heeft een limiet van ongeveer 820 resultaten, ongeacht hoeveel huizen er in het gebied zijn. Dichte markten verbergen duizenden meer. De oplossing is recursieve kwadrantensplitsing: als een begrenzingsvak het maximale aantal pagina's retourneert, splits het dan in vier kleinere vakken en zoek elk; blijf onderverdelen totdat elk vak minder dan de limiet retourneert. Deze inzoomstrategie kan honderden duizenden lijsten uit één metro naar boven halen die de platte zoekopdracht nooit zou tonen — en het onderverdeelt alleen waar de dichtheid het rechtvaardigt, zodat je geen verzoeken verspilt aan lege platteland.
Er is een kost verbonden aan die grondigheid: elke onderverdeling vermenigvuldigt verzoeken, dus een dichte metro kan één zoekopdracht in tientallen veranderen. Budgetteer ervoor — beperk de recursiediepte en zoom alleen in waar het aantal resultaten het rechtvaardigt, wat het algoritme voor je doet door alleen te onderverdelen wanneer een vak nog steeds het maximale aantal pagina's bereikt. Voor een nachtelijke vernieuwing van een hele stad landen de meeste verzoeken dan op de handvol dichte binnenstadsvakken terwijl de buitenwijken in één keer worden opgelost, zodat je precies daar diepte besteedt waar de inventaris is en nergens anders.
PerimeterX is waarom naïeve scrapers falen
Zillow's blokkering is niet primair op basis van snelheid; het is PerimeterX (nu HUMAN) die het verzoek profileert. Datacenter-IP's, ontbrekende browserheaders en onmenselijke timing veroorzaken allemaal een 403 of een uitdaging — dat is wat een assert status == 200 echt controleert. De oplossing is een coherent, vertrouwd verzoek: US residentiële proxies zodat het exit-IP eruitziet als een huizenkoper, realistische browserheaders, en exponentiële backoff die naar een nieuw IP roteert bij elke 403 in plaats van de verbrande te herproberen. Onze uiteenzetting van hoe PerimeterX automatisering detecteert behandelt de signalen in detail; dezelfde houding geldt voor Walmart, dat dezelfde leverancier gebruikt.
Wanneer PerimeterX aanscherpt of je liever geen browservloot onderhoudt, rendert een Scraper API de pagina, roteert residentiële IP's en wist de uitdaging voor je, en retourneert dezelfde verborgen JSON zonder de operationele overhead.
Scrape Zillow achter PerimeterX met residentiële IP's

Wanneer gebruik je in plaats daarvan county records
Zillow is uitstekend voor lijsten, foto's en schattingen, maar het is een secundaire bron. Voor gezaghebbend eigendom, verkoopgeschiedenis en geschatte waarden publiceren county assessor en recorder kantoren openbare records — vaak via hun eigen portalen of bulkgegevensuitvoer. Als je gebruiksdoel eigendomstitels, vergelijkingen of belastinggegevens zijn in plaats van live lijsten, zijn county-niveau records schoner, permissiever om te verzamelen, en volledig vrij van PerimeterX. Gebruik Zillow voor het marktsignaal en county records voor de feitelijke gegevens.
Is het legaal om Zillow te scrapen?
Dit is algemene informatie, geen juridisch advies. Publiek beschikbare lijstgegevens — prijzen, adressen, eigenschapskenmerken — worden over het algemeen als eerlijk beschouwd om te verzamelen tegen respectvolle snelheden. Zillow-resultaten kunnen echter persoonlijke gegevens bevatten: agentnamen, telefoonnummers en makelaarsdetails. Die zijn beschermd onder GDPR en vergelijkbare wetten, dus vermijd het verzamelen en opslaan ervan zonder een wettelijke basis. Verzamel de eigenschapsfeiten, niet de mensen.
Veelgestelde vragen
Kan ik Zillow-gegevens scrapen?
Ja — publiek zichtbare lijstgegevens kunnen worden verzameld. Zillow embedt elk eigendomsrecord als JSON in een script-tag (__NEXT_DATA__ of de Apollo-cache), en de zoekfunctie werkt op een kaartgrenzen-API die je direct kunt aanroepen. Het obstakel is niet de toegang maar PerimeterX, dus je hebt residentiële IP's en coherente headers nodig om 403's te vermijden.
Heeft Zillow een API?
Zillow biedt ongeveer 20 officiële API's, waaronder Eigendomsdetails en Buurtgegevens, maar ze vereisen sleutels, hebben gebruikslimieten en dekken niet elk veld of bulkgebruiksscenario. Veel teams scrapen in plaats daarvan de openbare pagina's juist omdat de verborgen JSON al de prijs, slaapkamers, badkamers, oppervlakte, zestimate en huurinschatting bevat die ze nodig hebben.
Waarom krijgt mijn Zillow-scraper een 403?
Een 403 op Zillow is bijna altijd PerimeterX, niet een snelheidslimiet. Datacenter-IP's, ontbrekende of inconsistente browserheaders en robotachtige verzoektiming veroorzaken het allemaal. Schakel over naar US residentiële proxies, stuur realistische headers, voeg menselijke tussenpozen toe, en roteer naar een nieuw IP bij elke 403 met exponentiële backoff in plaats van de geblokkeerde te blijven hameren.
Hoe scrape ik meer dan 820 Zillow-lijsten uit één gebied?
Een enkele zoekopdracht heeft een limiet van ongeveer 820 resultaten (20 pagina's van 41). Om dieper te gaan, splits je het kaartbegrenzingsvak in vier kwadranten en zoek je elk; onderverdeel recursief elk kwadrant dat nog steeds de limiet bereikt. Deze inzoombenadering onderverdeelt alleen dichte gebieden, zodat het de volledige inventaris van een metro vastlegt zonder verzoeken te verspillen aan dunbevolkte regio's.
Sla de HTML over en lees de ingesloten JSON, stuur de zoekopdracht aan met kaartgrenzen, splits kwadranten om de limiet te omzeilen, en routeer alles via schone residentiële IP's om PerimeterX voor te blijven. Doe dat en Zillow wordt een gestructureerde vastgoedfeed in plaats van een muur van 403's.