Homesnap Scraper - US For-Sale Listings, Prices & Property Data
Pricing
from $0.40 / 1,000 listings
Homesnap Scraper - US For-Sale Listings, Prices & Property Data
Scrape Homesnap (Homes.com / CoStar) homes for sale: address, price, beds, baths, sqft, lot size, coordinates, MLS id, status, HOA, year built, and photos. Search by place, ZIP, URL, or bounding box; filter by price, beds, baths, size, and property type. HTTP-first, runs on proxies.
Pricing
from $0.40 / 1,000 listings
Rating
0.0
(0)
Developer
Ihor Bielievskiy
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Give it a place name, a ZIP, or a Homesnap city URL and get back clean, structured listings: address, price, beds, baths, square footage, lot size, coordinates, MLS id, listing status, HOA, year built, and photos. Filter by price, beds, baths, size, and property type. Export as JSON, CSV, or Excel.
Homesnap now serves Homes.com / CoStar data. This actor calls Homesnap's own JSON listing API directly instead of driving a headless browser, so it's fast.
Use a US residential proxy. The Homesnap listing API serves degraded (empty) results to non-US and datacenter IPs —
Countcomes back0even for big markets. From a US residential IP it returns the real inventory. The default proxy config is US residential for exactly this reason; leave it on unless you know what you're doing.
What it can scrape
Set listingType:
for_sale— active for-sale listings (the default)under_contract— listings under contract / pendingsold— recently sold homes
Tell it where to look in whichever way is easiest:
search— a list of place names or ZIPs, e.g."Austin, TX"or"10028".startUrls— Homesnap for-sale city URLs straight from the address bar.cities— a list of{ state, city }objects.boundingBox— a raw map viewport (north/south/east/west) for full manual control.
Each location is resolved to its Homesnap area and the listings inside its bounding box are returned (up to 500 per location — the API's own viewport cap).
Filtering and sorting
All filters run on the actor side after the fetch, so they compose cleanly:
| Filter | Meaning |
|---|---|
priceMin / priceMax | Price range in USD. |
bedsMin | Minimum bedrooms. |
bathsMin | Minimum bathrooms (half-baths count as 0.5). |
sqftMin / sqftMax | Interior size range. |
propertyTypes | Keep only these type codes: 1 single family, 2 condo, 3 townhouse, 4 co-op, 5 multi-family, 6 land, 7 manufactured, 8 commercial. |
sortBy | price_asc, price_desc, newest, beds_desc, or sqft_desc (applied per location). |
Input
| Field | Description |
|---|---|
search | List of place names or ZIPs to resolve and scrape. |
startUrls | Homesnap for-sale city URLs (/homes-for-sale/{City}/{State}). |
cities | List of { state, city } objects. |
boundingBox | Optional raw viewport { north, south, east, west } in decimal degrees. |
listingType | for_sale, under_contract, or sold. |
propertyTypes | Optional list of property-type codes (see table above). |
priceMin / priceMax | Price range filter. |
bedsMin / bathsMin | Minimum beds / baths filter. |
sqftMin / sqftMax | Size range filter. |
sortBy | Result ordering within each location. |
maxItems | Stop after this many results across all locations (0 = no limit). |
proxyConfiguration | Apify Proxy — see the coverage note at the top. |
impersonate | Browser TLS fingerprint (chrome by default). |
{"search": ["Austin, TX"],"listingType": "for_sale","priceMin": 300000,"priceMax": 900000,"bedsMin": 3,"propertyTypes": [1, 3],"sortBy": "price_asc","maxItems": 200}
Output fields
| Field | Type | Notes |
|---|---|---|
listing_id / property_id | int | Homesnap identifiers (used for dedupe). |
mls_id / mls_number | str / int | MLS source number and id. |
status | str | Human label: for_sale, under_contract, sold, off_market. |
listing_status_code / mls_status_code | int | Raw status codes. |
transaction_type / transaction_type_label | int / str | Code plus for_sale / for_rent when known. |
address, unit, city, state, zip_code | str | Address parts. |
price, original_price | float | USD. |
price_per_sqft | float | price / sqft, when both present. |
beds, baths, baths_full, baths_half | int / float | baths counts half-baths as 0.5. |
sqft, lot_size | int / float | Interior sqft and lot size. |
year_built, unit_count | int | |
property_type / property_type_label | int / str | Code plus label (single_family, condo, …) when known. |
property_subtype | int | Raw subtype code. |
days_on_market | int | |
list_date / list_date_iso | int / str | Epoch ms and ISO-8601 UTC. |
hoa_fee, hoa_frequency | float / str | |
lat, lng | float | Coordinates. |
url, building_name | str | |
photo_urls | list[str] | CoStar CDN URLs, sized to 1024x768. |
details | str | Listing remarks when present. |
Rows that fail to resolve or parse are emitted as typed error records (error, error_type, area_id, detail, source_url) instead — never silently dropped.
Example output
{"listing_id": 227047402,"property_id": 400029947475,"mls_id": "RLS20099639","status": "for_sale","transaction_type": 1,"transaction_type_label": "for_sale","address": "205 E 85th Street #THA","unit": "THA","city": "New York","state": "NY","zip_code": "10028","price": 7295000.0,"price_per_sqft": 2206.59,"beds": 3,"baths": 4.0,"sqft": 3306,"lot_size": 0.0,"year_built": 2009,"property_type": 2,"property_type_label": "condo","list_date": 1717200000000,"list_date_iso": "2024-06-01T00:00:00+00:00","hoa_fee": 4749.0,"hoa_frequency": "Monthly","lat": 40.777978,"lng": -73.953811,"building_name": "The Brompton","url": "https://www.homesnap.com/NY/New-York/205-E-85th-Street/property/400029947475","photo_urls": ["https://ahprd1cdn.csgpimgs.com/i2/.../1024x768/image.jpg"]}
How it works
Two calls per city:
POST /service/Misc/Searchresolves the city text to its Homesnap area (id + bounding box + state).POST /service/Listings/Searchreturns the for-sale listings inside that bounding box, capped atmaximumListings(max 500). The request carries theX-CoStar-Brandheader and the criteria envelope the site's map uses.
Photos come straight from the listing payload (CoStar CDN), so there's no extra request per home; the {size} slot is filled in for you.
A few things worth knowing
- US residential proxy. Covered at the top — without one, non-US / datacenter IPs get empty results. The default config handles this.
- 500 listings per location. That's the API's map-viewport cap, not the actor. For full coverage of a dense metro, scrape it by neighborhood / smaller cities, or pass tighter
boundingBoxviewports. - Nothing fails silently. If a city can't be resolved or a request is rejected (e.g. the API contract changes → HTTP 422), you get a typed error row for it (with the error class in
error_type). If every location comes back empty or failed while a proxy is configured — the signature of a non-US/datacenter soft-block — the whole run is marked failed with a clear message instead of finishing green with zero items. So an empty successful run means "nothing found", never a hidden block. - You're billed per valid listing delivered, so error rows and duplicates don't cost you anything.
Notes
Only public, unauthenticated Homesnap pages are scraped. The data comes from Homesnap's public site (Homes.com / CoStar); follow their Terms and the laws that apply to you, and use it responsibly. Removal requests are honored.
Who built this
I build scrapers for my own projects and publish the ones that turn out genuinely useful. If you need a custom scraper, a data pipeline, or a change to this actor, I'm available for freelance work.
GitHub: github.com/bujhmml · Site: bujhmml.fun