DEV Community

Realtyapi
Realtyapi

Posted on

Tired of Zillow Blocking Scrapers — Here's What Actually Works in 2026

If you've ever tried scraping Zillow with BeautifulSoup or Selenium, you know the pain. CAPTCHAs, IP bans, constantly changing HTML selectors, headless browser detection — it's an arms race you're not going to win.

I spent way too long fighting anti-bot systems before switching to an API-based approach. This post walks through how to pull Zillow property data, search listings, get Zestimates, and export everything to CSV/Excel — all with plain Python and zero browser automation.


What You'll Need

  • Python 3.7+
  • The requests library (pip install requests)
  • A free API key from RealtyAPI

That's it. No Selenium. No Playwright. No proxy rotation.


Getting Started: Your First Property Lookup

Let's start simple — get full property details for a single address:

import requests

url = "https://zillow.realtyapi.io/pro/byaddress"

params = {
    "propertyaddress": "1875 AVONDALE Circle, Jacksonville, FL 32205"
}

headers = {
    "x-realtyapi-key": "YOUR_API_KEY"
}

response = requests.get(url, headers=headers, params=params)
data = response.json()

print(f"Price: ${data['price']:,}")
print(f"Bedrooms: {data['bedrooms']}")
print(f"Bathrooms: {data['bathrooms']}")
print(f"Sqft: {data['livingArea']:,}")
print(f"Zestimate: ${data['zestimate']:,}")
print(f"Year Built: {data['yearBuilt']}")
Enter fullscreen mode Exit fullscreen mode

Sample output:

Price: $349,900
Bedrooms: 4
Bathrooms: 2
Sqft: 2,150
Zestimate: $355,200
Year Built: 1926
Enter fullscreen mode Exit fullscreen mode

The response includes 100+ fields — tax history, lot size, HOA, days on market, description, agent info, and a lot more. This single call replaces what would take dozens of Selenium page loads and parsing logic.


Searching for Listings (For Sale, Rent, or Sold)

This is where it gets powerful. You can search any location with filters, just like Zillow's own search page:

import requests

url = "https://zillow.realtyapi.io/search/byaddress"

params = {
    "location": "Austin, TX",
    "listing_status": "For_Sale",
    "sort_order": "Newest",
    "bed_min": "3",
    "bathrooms": "TwoPlus",
    "list_price_range": "min:300000, max:600000",
    "home_type": "Houses,Townhomes",
    "page": 1
}

headers = {
    "x-realtyapi-key": "YOUR_API_KEY"
}

response = requests.get(url, headers=headers, params=params)
results = response.json()

print(f"Total results: {results['totalResultCount']}")
print(f"Returned: {len(results['searchResults'])} listings\n")

for listing in results["searchResults"][:5]:
    print(f"{listing['address']} — ${listing['price']:,} | {listing['bedrooms']}bd/{listing['bathrooms']}ba | {listing['livingArea']} sqft")
Enter fullscreen mode Exit fullscreen mode

Sample output:

Total results: 847
Returned: 200 listings

4512 Crestway Dr, Austin, TX 78731 — $579,000 | 4bd/3ba | 2,340 sqft
1208 Payton Falls Dr, Austin, TX 78748 — $425,000 | 3bd/2ba | 1,876 sqft
9305 Bradner Dr, Austin, TX 78749 — $549,900 | 3bd/2ba | 2,100 sqft
7201 Elm Creek Dr, Austin, TX 78744 — $310,000 | 3bd/2ba | 1,450 sqft
2814 S 5th St, Austin, TX 78704 — $599,000 | 3bd/3ba | 1,920 sqft
Enter fullscreen mode Exit fullscreen mode

Each page returns up to 200 listings, and you can paginate up to 5 pages (1,000 results total per search).

Search for rentals:

params = {
    "location": "Los Angeles, CA",
    "listing_status": "For_Rent",
    "sort_order": "Price_Low_to_High",
    "bed_min": "1",
    "home_type": "Apartments/Condos/Co-ops",
    "page": 1
}
Enter fullscreen mode Exit fullscreen mode

Search recently sold homes:

params = {
    "location": "Miami, FL",
    "listing_status": "Sold",
    "sold_in_last": "30_days",
    "sort_order": "Newest",
    "page": 1
}
Enter fullscreen mode Exit fullscreen mode

Getting Zestimate History (10 Years of Estimates)

Track how Zillow's estimated value has changed over time:

import requests

url = "https://zillow.realtyapi.io/graph_charts"

params = {
    "which": "zestimate_history",
    "byaddress": "1875 AVONDALE Circle, Jacksonville, FL 32205",
    "recent_first": "True"
}

headers = {
    "x-realtyapi-key": "YOUR_API_KEY"
}

response = requests.get(url, headers=headers, params=params)
history = response.json()

for point in history["data"][:6]:
    print(f"{point['date']}: ${point['value']:,}")
Enter fullscreen mode Exit fullscreen mode

Sample output:

2026-04-01: $355,200
2026-03-01: $352,800
2026-02-01: $351,000
2026-01-01: $348,500
2025-12-01: $345,100
2025-11-01: $342,700
Enter fullscreen mode Exit fullscreen mode

Great for building valuation charts or tracking market trends programmatically.


Finding Comparable Homes (Comps)

If you're doing investment analysis or appraisals, comps are essential:

import requests

url = "https://zillow.realtyapi.io/comparable_homes"

params = {
    "byaddress": "1875 AVONDALE Circle, Jacksonville, FL 32205"
}

headers = {
    "x-realtyapi-key": "YOUR_API_KEY"
}

response = requests.get(url, headers=headers, params=params)
comps = response.json()

for comp in comps["comparables"][:5]:
    print(f"{comp['address']} — ${comp['price']:,} | {comp['bedrooms']}bd | {comp['livingArea']} sqft")
Enter fullscreen mode Exit fullscreen mode

You can also look up by ZPID or Zillow URL instead of address — the API accepts all three.


Walk Score, Transit Score, and Bike Score

import requests

url = "https://zillow.realtyapi.io/walk_transit_bike"

params = {
    "byaddress": "350 5th Ave, New York, NY 10118"
}

headers = {
    "x-realtyapi-key": "YOUR_API_KEY"
}

response = requests.get(url, headers=headers, params=params)
scores = response.json()

print(f"Walk Score:    {scores['walkScore']}/100")
print(f"Transit Score: {scores['transitScore']}/100")
print(f"Bike Score:    {scores['bikeScore']}/100")
Enter fullscreen mode Exit fullscreen mode

Sample output:

Walk Score:    98/100
Transit Score: 100/100
Bike Score:    76/100
Enter fullscreen mode Exit fullscreen mode

Saving Results to CSV / Excel

Here's a practical pattern for bulk lookups saved to a spreadsheet:

import requests
import csv

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://zillow.realtyapi.io"
headers = {"x-realtyapi-key": API_KEY}

# List of addresses to look up
addresses = [
    "1875 AVONDALE Circle, Jacksonville, FL 32205",
    "350 5th Ave, New York, NY 10118",
    "1600 Pennsylvania Ave, Washington, DC 20500",
    "3828 Double Oak Ln, Irving, TX 75061",
    "742 Evergreen Terrace, Springfield, IL 62704"
]

results = []

for addr in addresses:
    print(f"Fetching: {addr}")
    resp = requests.get(
        f"{BASE_URL}/pro/byaddress",
        headers=headers,
        params={"propertyaddress": addr}
    )

    if resp.status_code == 200:
        d = resp.json()
        results.append({
            "address": addr,
            "price": d.get("price", ""),
            "zestimate": d.get("zestimate", ""),
            "bedrooms": d.get("bedrooms", ""),
            "bathrooms": d.get("bathrooms", ""),
            "sqft": d.get("livingArea", ""),
            "year_built": d.get("yearBuilt", ""),
            "lot_size": d.get("lotAreaValue", ""),
            "home_type": d.get("homeType", ""),
            "days_on_zillow": d.get("daysOnZillow", ""),
        })
    else:
        print(f"  Error {resp.status_code} for {addr}")

# Write to CSV (opens in Excel, Google Sheets, etc.)
with open("zillow_data.csv", "w", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=results[0].keys())
    writer.writeheader()
    writer.writerows(results)

print(f"\nDone! Saved {len(results)} properties to zillow_data.csv")
Enter fullscreen mode Exit fullscreen mode

Output CSV looks like:

address price zestimate bedrooms bathrooms sqft year_built home_type days_on_zillow
1875 AVONDALE Circle, Jacksonville, FL 349900 355200 4 2 2150 1926 SINGLE_FAMILY 12
350 5th Ave, New York, NY 2850000 2910000 3 2 1800 1931 CONDO 45
... ... ... ... ... ... ... ... ...

You can open this directly in Excel or Google Sheets.

Want pandas instead?

import pandas as pd

df = pd.DataFrame(results)
df.to_excel("zillow_data.xlsx", index=False)  # requires openpyxl
df.to_csv("zillow_data.csv", index=False)
Enter fullscreen mode Exit fullscreen mode

Saving Search Results to CSV

Same idea works for search results — pull hundreds of listings and dump to a spreadsheet:

import requests
import csv

API_KEY = "YOUR_API_KEY"
headers = {"x-realtyapi-key": API_KEY}

all_listings = []

# Paginate through up to 5 pages
for page in range(1, 6):
    print(f"Fetching page {page}...")
    resp = requests.get(
        "https://zillow.realtyapi.io/search/byaddress",
        headers=headers,
        params={
            "location": "Denver, CO",
            "listing_status": "For_Sale",
            "bed_min": "2",
            "list_price_range": "min:200000, max:500000",
            "page": page
        }
    )

    data = resp.json()
    listings = data.get("searchResults", [])
    if not listings:
        break

    for l in listings:
        all_listings.append({
            "address": l.get("address", ""),
            "price": l.get("price", ""),
            "bedrooms": l.get("bedrooms", ""),
            "bathrooms": l.get("bathrooms", ""),
            "sqft": l.get("livingArea", ""),
            "zpid": l.get("zpid", ""),
            "url": l.get("detailUrl", ""),
        })

with open("denver_listings.csv", "w", newline="") as f:
    writer = csv.DictWriter(f, fieldnames=all_listings[0].keys())
    writer.writeheader()
    writer.writerows(all_listings)

print(f"Saved {len(all_listings)} listings to denver_listings.csv")
Enter fullscreen mode Exit fullscreen mode

Searching by Coordinates (Radius Search)

Useful if you're building a map-based tool or have lat/lng data:

import requests

url = "https://zillow.realtyapi.io/search/bycoordinates"

params = {
    "latitude": "40.599283",
    "longitude": "-74.129194",
    "radius": "0.5",
    "listing_status": "For_Sale"
}

headers = {
    "x-realtyapi-key": "YOUR_API_KEY"
}

response = requests.get(url, headers=headers, params=params)
data = response.json()

print(f"Found {data['totalResultCount']} listings within 0.5 miles")
Enter fullscreen mode Exit fullscreen mode

More Endpoints Worth Knowing

Beyond what's shown above, here are some other useful endpoints:

Endpoint Route What It Returns
Property Images /propimages All listing photos for a property
Price History /pricehistory Full price change + tax history
Similar Properties /similar_properties Properties Zillow considers "similar"
Nearby Properties /nearby_properties Properties in the immediate area
Climate Risk /climate Flood, fire, heat, wind risk scores
Tax History /taxinfo_history Tax assessments over time
Owner/Agent Info /owner-agent Listing agent and owner details
Housing Market Data /housing_market Zillow Home Value Index (ZHVI) for any city
Agent Search /agent/search Find agents by location, specialty, language
Agent Reviews /agent/reviews Agent ratings and review text
Skip Trace /skip/byaddress Find property owner contact info
MLS Search /search/bymls Look up a listing by MLS number
Autocomplete /autocomplete Search suggestions (like Zillow's search bar)

All endpoints use the same authentication header and base URL. Just swap the route and params.


There's Also a Ready-Made Python Scraper

If you don't want to write the API calls yourself, there's an open-source CLI tool that wraps all of this with interactive prompts, bulk processing from JSON files, progress bars, and CSV/JSON export built in:

github.com/realtyapi/Zillow-Scraper-API-Python

Clone it, add your API key, and run python scraper.py — it gives you a menu to test any endpoint or run bulk jobs from a JSON file.


Other Real Estate APIs on the Same Platform

RealtyAPI also has endpoints for other platforms if you need data beyond Zillow:

  • Redfin API — Redfin listings, agent data, search by address/coordinates
  • Airbnb API — Short-term rental data, pricing, availability, reviews
  • StreetEasy API — NYC-specific listings and building data
  • Bayut API — UAE/Dubai property listings and agent data

All use the same API key and the same x-realtyapi-key header pattern.


Quick Reference

Base URL:    https://zillow.realtyapi.io
Auth Header: x-realtyapi-key: YOUR_API_KEY
Method:      GET (all endpoints)
Format:      JSON responses
Get API Key: https://www.realtyapi.io
Enter fullscreen mode Exit fullscreen mode

Hope this saves you the headaches I went through. If you have questions, drop a comment — happy to help.

Top comments (1)

Collapse
 
realtyapi profile image
Realtyapi

This is my first port. Please leave a like if you found the post helpful.

Thanks for reading till the end.