ScreenshotNeo

BlogHow-to

How to Scrape Homes.com Property Data: Listings, Prices, and Details

Homes.com terms require written permission before scraping. Learn approved feed routes, lawful pipeline design, data fields, and screenshot workflows.

By the ScreenshotNeo team29 September 20267 min read

How to Scrape Homes.com Property Data: Listings, Prices, and Details

Direct answer: Do not scrape Homes.com listings, prices, or property details unless Homes.com has given you express written permission. Its Terms of Use prohibit scraping, data mining, and automated or manual extraction, along with copying content into a database or product. A publicly visible page is not a reuse license.

The compliant path is to request an approved feed or license, confirm any MLS restrictions, and collect only the fields and volume your agreement allows. This guide explains that process, how to build a lawful ingestion pipeline after approval, what fields may appear in an authorized builder feed, and how to create permitted screenshots with ScreenshotNeo.

What Homes.com permits

Homes.com terms prohibit users from “modify, merge, scrape, disassemble or reverse engineer” the Product or using “any data mining, gathering or extraction tool, or any robot, spider or other automatic device or manual process” to monitor or copy the Product or data generated from it. The terms also prohibit copying or exporting Product content into a database or software program and using it to create a database or product without written permission.

This covers browser automation, HTML parsers, headless Chromium jobs, and manual copy-and-paste at scale. Slower requests, robots.txt compliance, or limiting collection to visible fields does not replace written authorization.

Where listing data comes from

Homes.com support says it “receives a direct listing feed from the MLS.” That describes the stated source; it does not grant you rights to reuse the feed. MLS agreements differ by organization. CoStar’s 2025 Form 10-K explains that MLS rules govern how listing data may be used and displayed and that noncompliance can restrict or terminate access.

Choose an authorized route

Route Who it fits Ask for in writing
Builder XML submission Builders submitting their own communities and inventory Schema version, validation, refresh cadence, field definitions, photo and tour rules
Direct Homes.com license Research, analytics, or products that need Homes.com data Purpose, geography, fields, rate limits, retention, redistribution, attribution, price, termination
MLS-approved feed Eligible participants with an MLS relationship Display, storage, caching, downstream-use, audit, and revocation rules

The reviewed public materials do not confirm a general public developer API. Ask Homes.com directly whether an offering exists for your use case and preserve the approval, contract, and MLS permissions with your project records.

An authorized feed separates permission, ingestion, validation, and storage.
An authorized feed separates permission, ingestion, validation, and storage.

Builder feed evidence

A March 2026 Homes.com XML guide documents a submission route for communities, floor plans, move-in-ready homes, amenities, features, and financial information. It mentions price and room-count ranges, planned and sold-home counts, HOA fees, schools, tax rates or special assessments, coordinates, photo captions, and 3D tours. It is a builder submission guide, not proof of an open scraping API or a universal list of consumer-page fields. Builder inquiries are directed to newconstructionfeed@homes.com.

Request permission before writing code

  1. Describe purpose: internal research, a customer-facing search product, valuation, monitoring, or builder syndication.
  2. Specify scope: locations, entities, fields, records per day, retention, and whether data leaves your organization.
  3. Explain display: attribution, photo hosting, links back, refresh frequency, and deletion handling.
  4. Ask about the source: confirm which MLS agreement applies and whether your organization is eligible.
  5. Get written approval: keep the signed agreement or written confirmation before production collection.

Keep your ingestion interface replaceable so an approved XML, JSON, or MLS feed can be swapped in without redesigning downstream analytics.

Build a compliant ingestion pipeline

After authorization, separate downloading, validation, normalization, storage, and deletion. The examples use placeholders deliberately; replace them only with an endpoint and fields identified by your agreement.

cURL: download an authorized XML feed

curl --fail --location \
  --header 'Authorization: Bearer YOUR_AUTH_TOKEN' \
  --output homes-authorized.xml \
  'YOUR_AUTHORIZED_FEED_URL'

Use TLS, keep tokens out of shell history where possible, and record the feed timestamp and agreement identifier. A 401 or 403 should stop the job; do not retry indefinitely.

Python: validate and normalize permitted records

from __future__ import annotations
import os
import xml.etree.ElementTree as ET
from decimal import Decimal

INPUT = os.environ.get('AUTHORIZED_FEED', 'homes-authorized.xml')

def text(node, path):
    value = node.findtext(path)
    return value.strip() if value else None

root = ET.parse(INPUT).getroot()
records = []
for home in root.findall('.//moveInReadyHome'):
    price = text(home, 'price')
    records.append({
        'id': text(home, 'id'),
        'community': text(home, 'communityName'),
        'address': text(home, 'address'),
        'city': text(home, 'city'),
        'state': text(home, 'state'),
        'postal_code': text(home, 'postalCode'),
        'beds': text(home, 'bedrooms'),
        'baths': text(home, 'bathrooms'),
        'price': str(Decimal(price)) if price else None,
        'latitude': text(home, 'latitude'),
        'longitude': text(home, 'longitude'),
    })

for record in records:
    if not record['id']:
        raise ValueError('Authorized feed record is missing its required id')
print(f'Validated {len(records)} authorized records')

Element names vary by contract and schema version. Add schema validation, duplicate detection, currency rules, and a dead-letter file for rejected records.

Node.js: fetch JSON when your agreement supplies JSON

const res = await fetch(process.env.AUTHORIZED_FEED_URL, {
  headers: { Authorization: `Bearer ${process.env.AUTH_TOKEN}` },
});
if (!res.ok) throw new Error(`Feed request failed: ${res.status}`);
const payload = await res.json();
const homes = (payload.items || []).map((h) => ({
  id: h.id,
  address: h.address,
  price: h.price,
  beds: h.bedrooms,
  baths: h.bathrooms,
}));
console.log(`Validated ${homes.length} authorized records`);

Do not point these examples at consumer pages. They are for an endpoint your written authorization identifies as a feed.

Fields, freshness, and data quality

Agree on a field dictionary before ingestion. Define a stable listing identifier, status values, price semantics, address normalization, room-count types, coordinate precision, photo rights, and update timestamps. Builder documentation also discusses amenities, appliance and fixture brands, HOA fees, schools, tax rates, captions, and 3D tours. Ask whether each field is optional, who owns corrections, and how sold or withdrawn homes are represented.

Measure freshness from the feed publication timestamp, not your download time. Store source time, retrieval time, and transformation version. Reconcile counts by market and status. Alert on zero-record feeds, schema drift, duplicate IDs, unexpected price changes, or coordinates outside the declared geography.

Reliability, performance, and cost

  • Reliability: Use bounded retries for transient 5xx and network failures, exponential backoff, idempotent upserts, and a circuit breaker. Never retry 401, 403, or a revoked agreement.
  • Performance: Prefer a licensed bulk feed over page-by-page collection. Stream large XML files, batch database writes, and process only changed records when a delta field exists.
  • Cost: Budget for the licensed feed, storage, transfer, validation, and monitoring. A free page or inexpensive proxy does not make unauthorized collection acceptable.
  • Retention: Schedule deletion of expired listings, photos, and derived datasets according to the agreement.

Troubleshooting authorized integrations

Symptom Cause Fix
401 Unauthorized Expired or wrong token Rotate credentials through the approved channel and verify environment variables.
403 Forbidden Account, market, or use is not authorized Stop retries and contact Homes.com or the MLS administrator.
429 Too Many Requests Rate limit exceeded Honor Retry-After, reduce concurrency, and request a documented limit increase.
XML parse error Truncated download or schema change Verify length and checksum, redownload once, then validate against the agreed schema.
Prices become null Field moved or became optional Inspect the versioned schema and update the mapper with a migration test.
Duplicate homes Missing stable key or incorrect joins Use the provider identifier and enforce a unique database constraint.
Photos or tours fail Media rights differ from data rights Check the agreement and store only permitted URLs or media.

Or skip the browser setup

If you need to capture a page you are authorized to view, ScreenshotNeo provides one GET endpoint returning PNG, JPEG, WebP, or PDF. Cookie banners, newsletter popups, and chat widgets are removed before capture. Bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, and response headers identify the page verdict and billing status.

ScreenshotNeo removes common consent and overlay elements before an authorized capture.
ScreenshotNeo removes common consent and overlay elements before an authorized capture.

Its MCP server gives Claude, Cursor, and other MCP clients take_screenshot, get_page_info, and capture_pdf. Free usage includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000 shots.

cURL

curl -G 'https://api.screenshotneo.com/v1/shot' -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

Python

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)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

See the ScreenshotNeo API documentation for full-page or CSS-element capture, device presets, dark mode, custom CSS and JavaScript, waits, blocked resource types, headers and cookies, timezone and geolocation, PDF margins and page ranges, caching TTL, signed links, async webhooks, bulk capture, and usage reporting. These controls do not change Homes.com or MLS permissions.

Create a free ScreenshotNeo account with 1,000 screenshots a month and no card.

Production checklist

  • Written Homes.com or MLS permission names your purpose.
  • Fields, geography, refresh rate, retention, redistribution, and attribution are documented.
  • Credentials are secret-managed and 401/403 responses halt jobs.
  • Schema validation, idempotent writes, freshness metrics, and deletion jobs are live.
  • Media and screenshot use are covered separately where required.
  • Audits can show source, timestamp, transformation version, and authorization.

FAQ

Can I scrape Homes.com if listings are publicly visible?

Not under the published terms without express written permission. Public visibility does not change the prohibition on automated or manual extraction.

Does Homes.com have an API?

The reviewed public materials do not confirm a general public API. Ask Homes.com for an approved feed or license for your exact use.

Can I use the builder XML guide for any listing?

No. It documents a builder submission schema and is not evidence that every consumer listing exposes those fields.

Are MLS feeds interchangeable?

No. MLS rules and agreements vary. Confirm eligibility and display, storage, and redistribution terms for each MLS.

No. It captures an authorized page; it does not change Homes.com or MLS permissions.