Zillow ligger oven på 160 millioner amerikanske ejendomsoptegnelser, og at få de data ud i stor skala er en af de mest efterspurgte — og mest frustrerende — opgaver inden for ejendomsdata. Hvis du nogensinde har prøvet at scrape Zillow og endt med at stirre på en CAPTCHA-side i stedet for boligannoncer, er du langt fra alene.
Jeg har brugt meget tid på at undersøge og teste forskellige måder at scrape Zillow på — både med Python og med no-code-værktøjer, som vi har bygget hos Thunderbit. Denne guide dækker begge spor. Uanset om du vil have den fulde Python-gennemgang med anti-bot-strategier, eller du bare har brug for 200 boliger i et regneark inden frokost, er der noget her til dig. Vi ser på, hvorfor Zillow-data er vigtige, hvordan siden er bygget under motorhjelmen, en trinvis Python-tutorial, de præcise grunde til at scrapers fejler, og hvordan du automatiserer gentagne scraping-opgaver til prisovervågning.
Hvorfor overhovedet scrape Zillow-data?
Zillow er den største samling af amerikanske data om boligejendomme. Sitet har 210 millioner besøg om måneden og rummer omkring 750.000+ aktive boligannoncer til salg samt 1,9 millioner lejeboliger. Platformen står for mere end 50% af al trafik til amerikanske ejendomsportaler — mere end dobbelt så meget som den nærmeste konkurrent.

Inden du kaster dig ud i Python-kode, er det vigtigt at vide, at Python ikke er den eneste måde at scrape Zillow på, og at det forkerte valg kan koste dig timer. Python-værktøjer som httpx og BeautifulSoup kræver et mellemniveau, manuel håndtering af headers og proxies, kører i moderat tempo (1–3 sekunder pr. side) og kræver løbende vedligeholdelse, selvom de er gratis; Selenium eller Playwright forbedrer anti-bot-håndtering ved at rendere JavaScript, men er langsommere (5–15 sekunder pr. side) og stadig vedligeholdelsestunge; scraping-API’er som ScraperAPI eller ScrapFly er hurtigere med indbygget anti-bot-support og moderat drift, men koster $30–599 om måneden; Zillows officielle API via Bridge Interactive er hurtig og kræver lidt vedligeholdelse, men er begrænset og koster omkring $500 om måneden; og no-code-værktøjer som Thunderbit er begyndervenlige, hurtige, kræver ingen vedligeholdelse takket være AI-tilpasning og tilbyder typisk en freemium-model.
Tidsbesparelsen alene er markant. Manuel research på tværs af 50+ postnumre kan nemt æde 15–20 timer om ugen. Automatiseret scraping kan gøre det samme på få minutter — en reduktion i tidsforbruget på 99,7%.
Alle måder at scrape Zillow på: Python vs. API vs. no-code (sammenlignet)
Inden du hopper direkte til Python-kode, så husk at "scrape Zillow med Python" ikke er din eneste mulighed. Det forkerte valg kan koste dig timer. Her er en side-by-side sammenligning, så du hurtigt kan vælge selv:
| Metode | Færdighedsniveau | Anti-bot-håndtering | Hastighed | Vedligeholdelse | Pris |
|---|---|---|---|---|---|
| Python + httpx/BeautifulSoup | Mellem | Manuel (headers, proxies) | Moderat (1–3s/side) | Høj (selectors går i stykker) | Gratis |
| Python + Selenium/Playwright | Mellem | Bedre (renderer JS) | Langsom (5–15s/side) | Høj | Gratis |
| Scraping-API (ScraperAPI, ScrapFly) | Mellem | Indbygget | Hurtig | Mellem | $30–599/md. |
| Zillows officielle API (Bridge Interactive) | Begynder–Mellem | N/A | Hurtig | Lav | ~ $500/md., begrænset adgang |
| No-code-værktøj (Thunderbit) | Begynder | Indbygget (AI tilpasser sig) | Hurtig | Ingen (AI læser siden igen) | Freemium |
Hvis du har brug for data med det samme uden at skrive kode, så start med Thunderbit. Hvis du vil forstå teknikken eller har brug for fuld kontrol, så læs videre til Python-gennemgangen.
Den 2-minutters løsning: scrape Zillow med Thunderbit (ingen kode nødvendig)
Før vi dykker ned i Python, får du her en løsning til dig, der bare vil have Zillow-data hurtigt — uden Python-opsætning, uden proxy-konfiguration og uden vedligeholdelse af selectors. Vi byggede denne arbejdsgang i Thunderbit netop for at hente strukturerede ejendomsdata uden teknisk overhead.
Sværhedsgrad: Begynder
Tidsforbrug: ~2 minutter
Det skal du bruge: Chrome-browser, Thunderbit Chrome-udvidelse (gratis niveau virker)
Trin 1: Installer Thunderbit og åbn Zillow
Installer Thunderbit-udvidelsen fra Chrome Web Store. Gå til en Zillow-side med søgeresultater — for eksempel en søgning efter boliger i Houston, TX.
Trin 2: Klik på "AI Suggest Fields"
Åbn Thunderbit-sidepanelet, og klik på "AI Suggest Fields." AI’en læser siden og foreslår automatisk kolonner: pris, adresse, soveværelser, badeværelser, kvadratmeter, Zestimate, annonce-URL og meget mere. I mine tests identificerer den typisk 20+ felter helt uden manuel opsætning.
Trin 3: Klik på "Scrape"
Tryk på Scrape-knappen. Data fyldes ind i en struktureret tabel inde i udvidelsen. Thunderbit håndterer Zillows paginering automatisk — både klikbaseret og uendelig scroll.
Trin 4: Berig med scraping af undersider
Vil du have data fra detaljesider som skattehistorik, skolernes vurderinger eller prisudvikling? Brug "Scrape Subpages" til at berige din tabel. Thunderbit følger hver annonce-URL og henter de ekstra felter — helt uden ekstra kode.
Trin 5: Eksportér
Eksportér til Google Sheets, Excel, Airtable eller Notion. Eksporten er gratis.
Hvorfor Thunderbit fungerer godt til Zillow
Den store fordel her er robusthed. Thunderbits AI læser sidens struktur på ny, hver gang du scraper. Når Zillow ændrer layout (hvilket sker ofte), er der ingen skrøbelige CSS-selectors, der skal repareres. AI’en tilpasser sig automatisk. Det løser reelt den "iboende skrøbelighed" i kodede scrapers, som frustrerer så mange brugere.
Hvilke data kan du scrape fra Zillow? (20+ felter)
De fleste guides tager pris og adresse og stopper der. Zillow-annoncer rummer faktisk langt flere udtrækkelige data, end man skulle tro — her er en referenceoversigt:
| Felt | Hvor det findes | Sværhedsgrad |
|---|---|---|
| Udbudspris | Søgning + detalje | Let |
| Adresse / postnummer | Søgning + detalje | Let |
| Zestimate | Søgning + detalje | Let |
| Pris-historik (hver hændelse) | Detalje | Svær (indlejret JSON) |
| Skattehistorik | Detalje | Svær (indlejret JSON) |
| Soveværelser / badeværelser / m² | Søgning + detalje | Let |
| Byggeår | Detalje | Let |
| HOA-gebyr | Detalje | Mellem |
| Walk Score / Transit Score | Detalje (iframe) | Svær (kræver JS-rendering) |
| Skolevurderinger | Detalje | Mellem |
| Grundstørrelse | Detalje | Let |
| Dage på Zillow | Søgning | Let |
| Mægler / ejendomskontor | Søgning + detalje | Mellem |
| MLS # | Detalje | Let |
| Ejendomstype | Søgning + detalje | Let |
| Breddegrad / længdegrad | __NEXT_DATA__ JSON | Mellem |
| Beskrivelsestekst | Detalje | Let |
| Foto-URL’er | Søgning + detalje | Mellem |
| Rent Zestimate | Detalje | Mellem |
| Sammenlignelige salg i nærheden | Detalje | Svær |
De "svære" felter — pris-historik, skattehistorik, sammenlignelige salg — ligger i indlejret JSON på detaljesiderne. Python-afsnittet nedenfor viser præcis, hvordan du udtrækker dem. Og hvis du hellere vil springe koden over, kan Thunderbits AI Suggest Fields automatisk genkende de fleste af disse kolonner, mens Subpage Scraping henter detaljefelterne automatisk.
Sådan sætter du dit Python-miljø op til at scrape Zillow
Sværhedsgrad: Mellem
Tidsforbrug: ~5 minutter til opsætning, ~30 minutter til hele gennemgangen
Det skal du bruge: Python 3.8+, Chrome-browser (til at inspicere sider), en teksteditor eller IDE
Installer de nødvendige biblioteker:
pip install httpx beautifulsoup4 pandas lxml
Her er, hvad hvert bibliotek bruges til:
- httpx — HTTP-klient med bedre ydeevne end
requestsog støtte for async - beautifulsoup4 + lxml — HTML-parsing
- pandas — eksport til CSV/Excel
- Valgfrit: selenium eller playwright, hvis du skal rendere sider med meget JavaScript
Forstå Zillows sidstruktur, før du scraper

Det her er det vigtigste at forstå, før du skriver kode. Zillow er en Next.js-applikation — bekræftet af ingeniørindlæg fra Zillow-medarbejdere. Det betyder, at det meste af dataen, du vil have, ikke ligger i de synlige HTML-elementer. Det er indlejret i en <script id="__NEXT_DATA__"> JSON-blok.
Åbn en hvilken som helst Zillow-boligside, tryk F12, gå til Elements, og søg efter __NEXT_DATA__. Du finder et massivt JSON-objekt med alle annonceoplysningerne — priser, koordinater, ejendomsdetaljer, pris-historik, skatteregistre, skolevurderinger og mere.
Hvorfor er det vigtigt? Zillows CSS-klassenavne er hash-baserede (genereret af styled-components) og ændrer sig ved hver deployment. En klasse som StyledPropertyCardHomeDetailsList-c11n-8-109-3__sc-1j0som5-0 vil have en helt anden hash næste uge. Enhver scraper, der bruger CSS-selectors, vil derfor ofte gå i stykker.
JSON-tilgangen via __NEXT_DATA__ er langt mere stabil, fordi den slet ikke afhænger af HTML-strukturen.
Vigtige JSON-stier for søgeresultater:
| Sti | Indhold |
|---|---|
props.pageProps.searchPageState.cat1.searchResults.listResults | Array med søgeresultater |
props.pageProps.searchPageState.cat1.searchResults.mapResults | Resultater i kortvisning |
props.pageProps.searchPageState.cat1.searchList.totalPages | Samlet antal tilgængelige sider |
På detaljesider bruger nogle __NEXT_DATA__, mens andre bruger en alternativ script-tag med hdpApolloPreloadedData. Koden nedenfor håndterer begge dele.
Trin for trin: Sådan scraper du Zillow med Python
Trin 1: Sæt HTTP-headers op for at undgå at blive blokeret med det samme
Sender du en ren httpx.get() til Zillow, får du en CAPTCHA-side i stedet for boligdata. Zillow bruger PerimeterX (HUMAN Security) sammen med Cloudflare — begge vurderet til 8/10 i sværhedsgrad af scraping-benchmarks. Systemet tjekker din TLS-fingeraftryk, HTTP-headers og IP-ry.
Her er de minimumsheaders, der virker i 2025:
import httpx
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,"
"image/avif,image/webp,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9",
"Accept-Encoding": "gzip, deflate, br",
"Sec-Ch-Ua": '"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"',
"Sec-Ch-Ua-Platform": '"Windows"',
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"Upgrade-Insecure-Requests": "1",
}
Sec-Ch-Ua-headers er afgørende. Mange tutorials udelader dem — og det er præcis derfor, deres kode ikke virker mod PerimeterX.
Trin 2: Scrape Zillow-søgeresultater
Zillows søge-URL’er følger et ret forudsigeligt mønster. For Houston, TX:
- Side 1:
https://www.zillow.com/houston-tx/ - Side 2:
https://www.zillow.com/houston-tx/2_p/ - Side 3:
https://www.zillow.com/houston-tx/3_p/
Hver side indeholder omkring 41 boliger. Zillow sætter en grænse ved 20 sider (~820 annoncer). For større datasæt skal du opdele geografisk (mere om det senere).
Her er koden til at scrape søgeresultater ved at hente data fra __NEXT_DATA__-JSON’en:
from bs4 import BeautifulSoup
import json
import time
import random
def scrape_zillow_search(url):
"""Scrape listing data from a Zillow search results page."""
response = httpx.get(url, headers=headers, timeout=15)
if response.status_code != 200:
print(f"Got status {response.status_code} for {url}")
return []
soup = BeautifulSoup(response.text, "lxml")
script_tag = soup.find("script", {"id": "__NEXT_DATA__"})
if not script_tag:
print("No __NEXT_DATA__ found — likely blocked by CAPTCHA")
return []
next_data = json.loads(script_tag.string)
try:
results = (
next_data["props"]["pageProps"]["searchPageState"]
["cat1"]["searchResults"]["listResults"]
)
except KeyError:
print("Unexpected JSON structure — Zillow may have changed its format")
return []
listings = []
for item in results:
listing = {
"zpid": item.get("zpid"),
"address": item.get("addressStreet"),
"city": item.get("addressCity"),
"state": item.get("addressState"),
"zipcode": item.get("addressZipcode"),
"price": item.get("unformattedPrice") or item.get("price"),
"beds": item.get("beds"),
"baths": item.get("baths"),
"sqft": item.get("area"),
"zestimate": item.get("zestimate"),
"days_on_zillow": item.get("daysOnZillow"),
"listing_url": item.get("detailUrl"),
"img_src": item.get("imgSrc"),
"property_type": item.get("hdpData", {}).get("homeInfo", {}).get("homeType"),
"latitude": item.get("latLong", {}).get("latitude"),
"longitude": item.get("latLong", {}).get("longitude"),
}
listings.append(listing)
return listings
For at scrape flere sider, skal du loop’e med pauser:
all_listings = []
base_url = "https://www.zillow.com/houston-tx/"
for page in range(1, 6): # Første 5 sider
url = base_url if page == 1 else f"{base_url}{page}_p/"
print(f"Scraper side {page}...")
page_listings = scrape_zillow_search(url)
all_listings.extend(page_listings)
# Tilfældig pause mellem 3-7 sekunder
delay = random.uniform(3, 7)
time.sleep(delay)
print(f"Samlet antal scrape-de boliger: {len(all_listings)}")
Du bør nu se strukturerede boligdata samle sig i all_listings. Hvis du får tomme resultater, så tjek afsnittet "Hvorfor scrapers går i stykker" nedenfor.
Trin 3: Scrape Zillows detaljesider
Søgeresultater giver dig det basale. Detaljesider indeholder de dybere data: pris-historik, skattehistorik, skolevurderinger, agentinfo og ejendomsbeskrivelser. Hver annonce-URL fra trin 2 peger på en detaljeside.
Zillows detaljesider bruger to mulige dataformater. Her er kode, der håndterer begge:
def scrape_zillow_detail(url):
"""Scrape detailed property data from a Zillow listing page."""
response = httpx.get(url, headers=headers, timeout=15)
if response.status_code != 200:
return None
soup = BeautifulSoup(response.text, "lxml")
# Prøv __NEXT_DATA__ først (mest almindeligt)
script_tag = soup.find("script", {"id": "__NEXT_DATA__"})
if script_tag:
next_data = json.loads(script_tag.string)
try:
cache_str = next_data["props"]["pageProps"]["componentProps"]["gdpClientCache"]
cache = json.loads(cache_str)
first_key = next(iter(cache))
prop = cache[first_key]["property"]
return extract_property_fields(prop)
except (KeyError, StopIteration):
pass
# Fallback: hdpApolloPreloadedData
apollo_tag = soup.find("script", {"id": "hdpApolloPreloadedData"})
if apollo_tag:
raw = json.loads(apollo_tag.string)
api_cache = json.loads(raw["apiCache"])
for key, value in api_cache.items():
if "ForSale" in key or "property" in str(value)[:100]:
prop = value.get("property", value)
return extract_property_fields(prop)
return None
def extract_property_fields(prop):
"""Extract structured fields from a Zillow property JSON object."""
return {
"zpid": prop.get("zpid"),
"zestimate": prop.get("zestimate"),
"rent_zestimate": prop.get("rentZestimate"),
"description": prop.get("description"),
"year_built": prop.get("yearBuilt"),
"lot_size": prop.get("lotSize"),
"hoa_fee": prop.get("monthlyHoaFee"),
"mls_id": prop.get("mlsid"),
"broker_name": prop.get("brokerName") or prop.get("attributionInfo", {}).get("brokerName"),
"price_history": [
{
"date": event.get("date"),
"event": event.get("event"),
"price": event.get("price"),
}
for event in prop.get("priceHistory", [])
],
"tax_history": [
{
"year": record.get("time"),
"tax_paid": record.get("taxPaid"),
"value": record.get("value"),
}
for record in prop.get("taxHistory", [])
],
"schools": [
{
"name": school.get("name"),
"rating": school.get("rating"),
"distance": school.get("distance"),
}
for school in prop.get("schools", [])
],
}
Loop gennem dine annonce-URLs med pauser:
detail_data = []
for listing in all_listings[:10]: # Start med 10 for at teste
detail_url = listing.get("listing_url")
if not detail_url:
continue
if not detail_url.startswith("http"):
detail_url = f"https://www.zillow.com{detail_url}"
print(f"Scraper detalje: {detail_url}")
detail = scrape_zillow_detail(detail_url)
if detail:
detail_data.append({**listing, **detail})
time.sleep(random.uniform(3, 8))
Efter dette trin bør du have en liste af dictionaries med både søge-niveau- og detaljeniveau-data for hver ejendom.
Trin 4: Håndter paginering for at scrape flere sider
For områder med mere end 820 annoncer (20-siders loftet) skal du opdele geografisk. Zillows interne API accepterer mapBounds-parametre. Strategien: del kortet op i kvadranter og scrape hver for sig.
def split_bounds(bounds):
"""Split map bounds into 4 quadrants."""
mid_lat = (bounds["north"] + bounds["south"]) / 2
mid_lng = (bounds["east"] + bounds["west"]) / 2
return [
{"north": bounds["north"], "south": mid_lat, "east": bounds["east"], "west": mid_lng},
{"north": bounds["north"], "south": mid_lat, "east": mid_lng, "west": bounds["west"]},
{"north": mid_lat, "south": bounds["south"], "east": bounds["east"], "west": mid_lng},
{"north": mid_lat, "south": bounds["south"], "east": mid_lng, "west": bounds["west"]},
]
For de fleste behov — overvågning af 50–200 boliger i et bestemt område — er den almindelige URL-paginering tilstrækkelig. Kvadrant-metoden er til by- eller statsdækkende scraping.
Trin 5: Eksportér dine scrape-de Zillow-data
Gem det hele som CSV med pandas:
import pandas as pd
df = pd.DataFrame(detail_data)
df.to_csv("zillow_houston_listings.csv", index=False)
print(f"Eksporterede {len(df)} boliger til zillow_houston_listings.csv")
Til JSON-eksport:
with open("zillow_houston_listings.json", "w") as f:
json.dump(detail_data, f, indent=2)
Hvis du vil springe eksporttrinnet helt over, eksporterer Thunderbit gratis til Google Sheets, Airtable og Notion — nyttigt, hvis du vil have data i et samarbejdsvenligt format med det samme.
Hvorfor Zillow-scrapers går i stykker (og hvordan du bygger robuste løsninger)
Det her er overlevelsesguiden.
Efter min erfaring går scrapers i stykker på Zillow af tre helt konkrete grunde — og hver har en praktisk løsning.
PerimeterX og CAPTCHA’er: Derfor returnerer dine requests tomme data
Zillows PerimeterX-integration tjekker flere signaler samtidigt: TLS-fingeraftryk, HTTP-headers, IP-ry og anmodningsmønstre. Når den opdager automation, viser den en "Press & Hold"-CAPTCHA-side i stedet for boligdata.
Det præcise fejlscenarie: Du sender en request med standard Python-headers. HTML-svaret indeholder PerimeterX challenge-scripts i stedet for ejendomsdata — og dit BeautifulSoup-parse finder ingen __NEXT_DATA__-tag.
Løsningen: Brug de fulde browser-lignende headers fra trin 1. Hvis du laver mere end et par dusin requests, har du også brug for proxy-rotation (beskrevet nedenfor). Til tung scraping bør du overveje et bibliotek som curl_cffi med impersonate="chrome" — det er den eneste Python HTTP-klient, der kan matche et rigtigt Chrome-TLS-fingeraftryk.
Dynamiske CSS-selectors: Derfor returnerer BeautifulSoup None
Hvis du bruger CSS-selectors som .list-card-price eller klassenavne med hashes, vil din scraper gå i stykker hver gang Zillow ruller ny kode ud.
Zillow bruger styled-components, som genererer klassenavne som StyledPropertyCardHomeDetailsList-c11n-8-109-3__sc-1j0som5-0. Hash-delen ændrer sig for hver build.
Løsningen: Brug slet ikke CSS-selectors. Hent data fra __NEXT_DATA__-JSON-blokken som vist i koden ovenfor. Den metode har været stabil i årevis, fordi JSON-strukturen ændrer sig langt sjældnere end HTML-markup.
Hvis du absolut skal bruge HTML-parsing, så kig efter data-test-attributter (fx data-test="property-card") eller brug delvise class-matches som [class*="PropertyCard"]. Men JSON-udtræk er den mere pålidelige vej.
Proxy-rotation og eksponentiel backoff: Kode der overlever IP-bans
Datacenter-IP’er bliver med det samme blacklisted af Zillow. Du har brug for residential proxies for stabil adgang. Sikker hastighed: 1 request hver 3–8 sekunder pr. IP, og hold dig under ca. 500 requests i timen.
Her er en retry-decorator med eksponentiel backoff og tilfældig jitter:
import random
import time
def backoff_with_jitter(attempt, base_delay=2, max_delay=60):
"""AWS-style full jitter exponential backoff."""
delay = min(max_delay, base_delay * (2 ** attempt))
return random.uniform(0, delay)
def fetch_with_retry(url, max_retries=5):
for attempt in range(max_retries):
try:
response = httpx.get(url, headers=headers, timeout=15)
if response.status_code == 200:
return response
if response.status_code in (403, 429):
delay = backoff_with_jitter(attempt, base_delay=5)
print(f"Blokeret ({response.status_code}). Prøver igen om {delay:.1f}s...")
time.sleep(delay)
continue
except Exception as e:
if attempt == max_retries - 1:
raise
time.sleep(backoff_with_jitter(attempt))
return None
Og en simpel proxy-rotationspool:
class ProxyPool:
def __init__(self, proxies):
self.proxies = proxies
self.index = 0
self.failures = {}
def get_next(self):
proxy = self.proxies[self.index % len(self.proxies)]
self.index += 1
return {"http://": proxy, "https://": proxy}
def report_failure(self, proxy):
self.failures[proxy] = self.failures.get(proxy, 0) + 1
if self.failures[proxy] > 3:
self.proxies.remove(proxy)
# Brug:
pool = ProxyPool(proxies=[
"http://user:pass@residential1.example.com:8080",
"http://user:pass@residential2.example.com:8080",
])
Hos proxy-udbydere tilbyder DataImpulse residential proxies til omkring $1/GB (den billigste løsning), mens IPRoyal og Smartproxy er solide mellemklassevalg til $4–7/GB.
Det vedligeholdelsesfri alternativ
Hvis du scraper Zillow regelmæssigt og er træt af at rette ødelagte selectors eller styre proxy-pools, læser Thunderbits AI sidens struktur helt forfra ved hver scraping. Ingen selectors at vedligeholde, ingen proxy-konfiguration. Det løser reelt den skrøbelighed, som gør kodede scrapers til en tilbagevendende hovedpine.
Automatisér Zillow-scraping: Planlægning og prisovervågning
Alle ejendomsinvestorer, jeg har talt med, vil have dette, og ingen andre Zillow-guides dækker det: gentagne automatiske scraping-kørsler til prisovervågning.
For Python-brugere: Cron-jobs og registrering af prisændringer
Sæt et cron-job op, der kører din scraper hver uge og markerer prisændringer:
import pandas as pd
from datetime import datetime
def detect_price_changes(new_data, historical_file, threshold=0.05):
"""Compare new scrape with historical data, flag changes > threshold."""
try:
old = pd.read_csv(historical_file)
except FileNotFoundError:
new_data.to_csv(historical_file, index=False)
print("Første kørsel — baseline-data gemt.")
return pd.DataFrame()
merged = new_data.merge(old, on="zpid", suffixes=("_new", "_old"))
merged["price_change_pct"] = (
(merged["price_new"] - merged["price_old"]) / merged["price_old"]
)
alerts = merged[merged["price_change_pct"].abs() > threshold]
# Tilføj nye data med tidsstempel
new_data["scraped_at"] = datetime.now().isoformat()
new_data.to_csv(historical_file, mode="a", header=False, index=False)
return alerts
Tilføj dette til din crontab for ugentlige kørsler om mandagen kl. 6:
0 6 * * 1 cd /path/to/scraper && python zillow_monitor.py
Et praktisk eksempel: overvåg 50 Austin, TX-annoncer hver uge. Hver mandag scraper scriptet de aktuelle priser, sammenligner dem med ugen før og outputter en CSV, der fremhæver alle prisfald på over 5%.
For ikke-kodere: Thunderbits Scheduled Scraper
Thunderbits Scheduled Scraper lader dig beskrive intervallet i almindeligt sprog ("hver mandag kl. 9"), indsætte dine Zillow-søge-URL’er og klikke på Schedule. Data eksporteres automatisk til Google Sheets ved hver kørsel. Ingen Python, ingen cron, ingen server at vedligeholde. Det er især nyttigt for ejendomsmæglere eller driftsteams, der har brug for stabil prisovervågning uden udviklerstøtte.
Tips til ansvarlig scraping af Zillow
Et par noter om at holde sig på den rigtige side af grænsen:
- Scrape kun offentligt tilgængelige data. Gå ikke ind på sider bag login eller autentificering.
- Brug fornuftige request-hastigheder. 3–8 sekunder mellem requests. Lad være med at overbelaste serveren.
- Scrape ikke personlige/private brugerdata. Agentnavne og mægleroplysninger på annoncer er offentlige; brugerkontodata er ikke.
- Gem og brug data etisk. Markedsresearch, investeringsanalyse og leadgenerering er legitime formål. Spam er ikke.
- Juridisk kontekst: hiQ v. LinkedIn-afgørelsen slog fast, at scraping af offentligt tilgængelige data ikke bryder CFAA. Meta v. Bright Data (2024) bekræftede lignende principper. Når det er sagt, begrænser Zillows ToS automatisk adgang, og de håndhæver det via IP-bans og CAPTCHA’er frem for retssager. Tjek altid den aktuelle vejledning, og respekter robots.txt.
Vælg den rigtige metode til at scrape Zillow med Python
Den bedste vej afhænger af din situation:
Har du brug for data hurtigt, uden kode? Thunderbit fører dig fra en Zillow-søgeside til et struktureret regneark på cirka 2 minutter. AI’en tilpasser sig layoutændringer, håndterer paginering og eksporterer gratis. Installer Chrome-udvidelsen og prøv den på en Zillow-søgeside.
Vil du have fuld kontrol? Brug Python-koden i denne guide. Hent fra __NEXT_DATA__-JSON (ikke CSS-selectors) for stabilitet. Sæt korrekte browser-lignende headers op. Brug residential proxies og eksponentiel backoff for pålidelighed.
Skal du skalere op? Scraping-API’er som ScrapFly (99% succesrate på Zillow) eller ScraperAPI håndterer proxy- og CAPTCHA-infrastrukturen for dig til $30–599/måned afhængigt af volumen.
Vil du følge priser over tid? Sæt et cron-job op med scriptet til registrering af prisændringer, eller brug Thunderbits Scheduled Scraper for en løsning uden vedligeholdelse.
Dataen er der. Det eneste spørgsmål er, hvor meget ingeniørtid du vil bruge på at få den ud. Hvis du vil have mere om at få webdata ind i regneark, så tjek vores guide til at scrape data fra websites til Excel eller vores opsamling af Zillow-statistikker for den nyeste platformdata. Du kan også se tutorials på Thunderbit YouTube-kanalen.
Prøv Thunderbit til Zillow-scraping Get Started Free
Ofte stillede spørgsmål
Kan man scrape Zillow med Python gratis?
Ja — httpx, BeautifulSoup og pandas er alle gratis og open source. Ulempen er tiden: du skal selv håndtere headers, proxy-rotation og vedligeholdelse af selectors. Forvent at bruge 4–8 timer på den første opsætning og 4–10 timer om måneden på vedligeholdelse, når Zillow ændrer sit site. Thunderbit har også et gratis niveau, hvis du vil slippe helt for kodningsarbejdet.
Har Zillow en officiel API?
Zillow afviklede sin gratis offentlige API i september 2021. Adgang går nu gennem Bridge Interactive, som kræver godkendelse, koster cirka $500/måned og er målrettet licenserede ejendomsprofessionelle. For de fleste brugere — investorer, forskere og mæglere, der laver markedsanalyse — er scraping det praktiske alternativ. Zillow udgiver stadig gratis researchdata som CSV-filer på zillow.com/research/data/, herunder Zillow Home Value Index og Zillow Observed Rent Index.
Hvordan undgår jeg at blive blokeret, når jeg scraper Zillow?
Tre ting: (1) brug realistiske browser-headers, inklusive Sec-Ch-Ua — det er den header, de fleste tutorials overser, og den PerimeterX tjekker først; (2) brug rotation af residential proxies — datacenter-IP’er bliver straks blacklisted; (3) hent data fra __NEXT_DATA__-JSON i stedet for HTML-selectors, så du undgår brud ved layoutændringer. Hold request-hastigheden på 1 hver 3–8 sekunder pr. IP. Eller brug et værktøj som Thunderbit, der håndterer anti-bot-beskyttelse automatisk.
Hvad er den bedste måde at scrape Zillow uden at kode?
Thunderbits AI Web Scraper er den hurtigste vej. Installer Chrome-udvidelsen, gå til en Zillow-søgeside, klik på "AI Suggest Fields" for automatisk at finde kolonnerne, og klik derefter på "Scrape." Eksportér til Google Sheets, Excel, Airtable eller Notion uden at skrive kode. AI’en læser siden helt forfra hver gang, så den går ikke i stykker, når Zillow opdaterer layoutet.
Hvor ofte ændrer Zillow sin struktur på sitet, og hvordan påvirker det scrapers?
Zillow udruller opdateringer ofte — nogle gange ugentligt. Fordi de bruger styled-components, ændrer CSS-klassenavne sig ved hver deployment, og scrapers, der bygger på CSS-selectors, går derfor ofte i stykker. Den mest robuste tilgang i Python er at hente data fra __NEXT_DATA__-JSON-blokken, som ændrer struktur langt sjældnere. Hvis du vil have en løsning uden vedligeholdelse, genlæser Thunderbits AI sidens struktur ved hver scraping og tilpasser sig automatisk til layoutændringer.
Læs mere


