Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

The best way to collect real-estate data in 2026 is to start with an authorized source, not a scraper. For listing-level records, use a documented API or an MLS-approved RESO Web API feed. For neighborhood statistics, use the U.S. Census API. Use Python’s requests for ordinary HTTP/JSON endpoints and Playwright only when a provider explicitly permits browser-rendered access. A public webpage, a permissive robots.txt file, or a successful test request does not by itself grant permission to automate, store, display, or redistribute the data.

Decide what “real-estate data” means first

“Real estate data” can describe several different products. Define the output before choosing a library or endpoint:

Need Typical records Usually appropriate source
Current listings Address, list price, status, beds, baths, coordinates, photos MLS-authorized feed or licensed vendor API
Property or transaction attributes Parcel identifiers, sale history, assessed value, year built Recorder, assessor, open-data portal, or licensed provider
Market and neighborhood context Population, income, housing tenure, vacancy, permits U.S. Census datasets and other official statistical APIs

These categories have different permissions, coverage and update schedules. Write down the geography, fields, refresh interval, retention period, intended audience and whether you will redistribute the records. Ask the provider to confirm every item rather than assuming that two sources use the same field definitions.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Check permission before writing automation

Zillow and other consumer portals

Zillow’s general Terms of Use prohibit automated queries against its Services. The prohibited-use language includes “conduct automated queries (including screen and database scraping, spiders, robots, crawlers, bypassing ‘captcha’ or similar precautions, or any other automated activity with the purpose of obtaining information from the Services).” That clause applies to automated collection from the consumer service; it is not changed by the fact that a page is visible in a browser.

Zillow also describes a separate API route for preapproved licensees. An approved API agreement is not permission to scrape the consumer site, and API terms can restrict fields, display, storage, attribution and redistribution. Recheck the current consumer and API terms before each project because they can change.

MLS and RESO Web API

RESO Web API is a transport standard, not a universal license to MLS data. RESO states: “After agreeing to an MLS’s data use and licensing policies, data recipients work directly with that MLS’s software provider or technical staff to receive credentials and instructions on how to access that MLS’s data.” In practice, contact the relevant MLS or its authorized data provider, complete its licensing process and obtain credentials through that channel. Zillow says its listings are published through MLS IDX feeds, which illustrates why portal pages and the underlying MLS feed are separate access routes.

Before receiving data, get written answers about eligible users, allowed display, commercial or research use, refresh frequency, archival limits, required attribution, derivative works and redistribution. An MLS license in one market does not establish access or rights in another market.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Public pages, robots.txt and legal uncertainty

Do not treat browser visibility, an HTTP 200 response or robots.txt as a license. The sources establish provider terms and technical practices, not a universal legal rule for every country or state. Check the contract, applicable privacy and database laws, and your organization’s counsel when the use is commercial, large-scale or involves personal information.

Use a documented HTTP/JSON API with Python Requests

For an endpoint that you are authorized to call, Requests is usually simpler and more reliable than browser automation. The Requests documentation currently identifies version 2.34.2 and Python 3.10+ support. Install it in an isolated environment:

Rank #2
Sale
The Millionaire Real Estate Investor
  • Business & Economics
  • Real Estate
python -m venv .venv
# macOS/Linux
source .venv/bin/activate
# Windows PowerShell: .venvScriptsActivate.ps1
python -m pip install requests

The following client demonstrates explicit timeouts, an API key supplied through an environment variable, HTTP error handling, JSON validation and a minimal field projection. Replace the URL and parameter names with those documented by your licensed provider.

import json
import os
from datetime import datetime, timezone

import requests

API_URL = "https://api.example-licensed-provider.test/v1/listings"
api_key = os.environ["REAL_ESTATE_API_KEY"]
params = {
    "market": "example-market",
    "status": "active",
    "fields": "listing_id,address,price,beds,baths,latitude,longitude,updated_at",
    "limit": 100,
}

try:
    response = requests.get(
        API_URL,
        params=params,
        headers={"Authorization": f"Bearer {api_key}", "Accept": "application/json"},
        timeout=(10, 60),  # connect timeout, read timeout
    )
    response.raise_for_status()
except requests.Timeout as exc:
    raise RuntimeError("The provider did not respond within the timeout") from exc
except requests.HTTPError as exc:
    status = exc.response.status_code if exc.response is not None else "unknown"
    raise RuntimeError(f"Provider returned HTTP {status}") from exc

try:
    payload = response.json()
except ValueError as exc:
    raise RuntimeError("The endpoint returned non-JSON data") from exc

records = payload.get("listings")
if not isinstance(records, list):
    raise RuntimeError("Expected a listings array in the documented response")

retrieved_at = datetime.now(timezone.utc).isoformat()
with open("listings.json", "w", encoding="utf-8") as output:
    json.dump(
        {"retrieved_at": retrieved_at, "source": API_URL, "records": records},
        output,
        ensure_ascii=False,
        indent=2,
    )
print(f"Saved {len(records)} records at {retrieved_at}")

Keep secrets outside source control (environment variables or a secrets manager). Request only fields you need, honor the provider’s rate and pagination rules, and record the retrieval timestamp, market, source identifier and license constraints with every batch. For pagination, follow the provider’s documented cursor or page token; do not guess undocumented parameters.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Validate and preserve the dataset

Normalize without destroying source values

  • Keep the provider’s original address and identifiers alongside normalized forms.
  • Store the provider’s status vocabulary and map it to your own categories in a separate field.
  • Record the source timezone and the timestamp used for each update.
  • Check that numeric fields have documented units and that coordinates use the stated datum.
  • Deduplicate by the provider’s stable listing or parcel identifier, not by a formatted address alone.

Track licensing metadata

A useful record envelope includes source, retrieved_at, geography, provider_record_id, last_updated_at, license_reference and retention_deadline. Build deletion and refresh jobs around the contract. Do not assume that a record you may display may also be exported to customers, used to train a model or retained after a listing expires.

When browser automation is genuinely required

Use a browser only if the authorized interface requires rendering, interaction or a documented session flow. Playwright exposes request and response lifecycle events, which can help you understand what an approved application is doing. It does not grant access rights and must not be used to evade CAPTCHAs, bot checks, authentication, rate controls or other restrictions.

import asyncio
from playwright.async_api import async_playwright

async def inspect_authorized_page(url: str):
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)
        page = await browser.new_page()

        page.on("response", lambda response: print(response.status, response.url))
        await page.goto(url, wait_until="networkidle", timeout=60_000)
        await page.screenshot(path="authorized-page.png", full_page=True)
        await browser.close()

asyncio.run(inspect_authorized_page("https://example-authorized-portal.test"))

Keep this pattern limited to pages and accounts for which you have written permission. If a response is a CAPTCHA, access-denied page or login failure, stop and contact the provider. Do not rotate identities, defeat challenges or probe alternate endpoints.

Use Census data for market context, not listings

The U.S. Census Data API provides official datasets and documents free API-key registration. Census data can describe an area’s population, tenure, income or vacancy, but it is not a substitute for individual property listings or parcel records. Join it to listing data only after matching geography definitions (for example, county, tract or place) and the relevant survey or estimate year.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Save the dataset name, table or variable identifiers, geography, estimate year and retrieval time. Avoid comparing figures from different years or survey products without labeling the difference.

Choose an access route by trade-off

Route Permission model Granularity Technical shape Main risks to verify
Licensed vendor API Vendor contract and API terms Often listing or property level Documented HTTP/JSON Quotas, fields, retention, redistribution
MLS RESO Web API MLS data-use and licensing policy MLS listing records Standardized feed after credentials Market eligibility, IDX display, attribution, refresh
Official public dataset Dataset-specific terms Usually statistical or governmental records HTTP API or downloads Geography, vintage, update schedule
Authorized browser workflow Explicit site or account permission What the approved application exposes Playwright-rendered pages Authentication, rate limits, session and UI changes

Performance, reliability and cost controls

  • Start small: test one market and a few records before scheduling a job.
  • Bound every request: use connect and read timeouts, provider-approved page sizes and a maximum retry count.
  • Retry selectively: transient network failures may be retried with backoff; do not repeatedly retry authentication, permission or validation errors.
  • Cache responsibly: cache only when the license permits it and attach an expiration policy to the cache.
  • Measure freshness: log request time, response status, record count and provider update timestamps.
  • Control spend: request only needed fields, avoid unnecessary browser sessions and confirm the provider’s quota or per-call pricing before scaling.

Troubleshooting common failures

401 or 403 responses

Usually the credential is missing, expired, scoped to another market or not entitled to the endpoint. Verify the account and contract with the provider. Do not work around the response.

429 rate limiting

Reduce concurrency, honor the documented retry-after value and ask for an approved quota. A longer timeout does not solve a rate-limit policy.

200 response but invalid JSON

The server may have returned HTML, a login page or an intermediary error. Log the content type and a short, non-sensitive prefix, then inspect the provider’s status and authentication guidance.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Missing or inconsistent fields

Check the schema, market coverage and field semantics. Preserve nulls rather than converting them to zero, and ask the provider whether a field is optional or delayed.

Browser page is blank or blocked

Stop the run and determine whether the provider requires a supported login, an approved integration or a different endpoint. Do not add CAPTCHA-solving, stealth plugins or proxy rotation.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your task is to capture an authorized webpage rather than collect structured listing records, ScreenshotNeo provides a one-call screenshot API and MCP server. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups and chat widgets; each step can be disabled. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing status. Its MCP tools—take_screenshot, get_page_info and capture_pdf—work with Claude, Cursor and other MCP clients.

Use the documented endpoint and options at ScreenshotNeo’s API documentation:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

ScreenshotNeo supports full-page captures with lazy images loaded, CSS-selector element shots, dark mode, 12 device presets and custom viewports, retina scale, PDF paper and page controls, HTML/CSS rendering, custom JavaScript and CSS, clicks, selector or network-idle waits, request and resource blocking, headers, cookies, user agents, Authorization, timezone, geolocation, transparent backgrounds, resizing, chosen-TTL caching, signed image links, asynchronous signed webhooks, bulk capture of up to 100 URLs per call, a usage API and an OpenAPI specification. Parameter names used by other screenshot APIs also work.

Plans include 1,000 screenshots per month free with no card; paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account to try it.

FAQ

Is scraping a public real-estate page automatically legal?

No single answer applies everywhere. Check the site’s terms, data license and applicable law; public visibility alone does not establish permission for automation or redistribution.

Does RESO Web API mean anyone can access MLS data?

No. RESO standardizes transport. You still need the relevant MLS agreement, credentials and permitted use.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Should I use Requests or Playwright?

Use Requests for a documented HTTP/JSON interface. Use Playwright only when an authorized workflow genuinely requires browser rendering or interaction.

Can Census API data identify a specific house?

Census datasets provide area-level statistical context. They are not individual listing or parcel feeds.

Frequently Asked Questions

What should I document for each real-estate dataset?

Record the source, license or contract reference, geography, fields, retrieval time, provider update timestamp, retention rule and redistribution permission.

How should I respond to a CAPTCHA or access-denied page?

Stop the automation, preserve the error for diagnosis and contact the provider about an approved API, feed or account. Do not bypass the control.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.