redfin-api
Redfin API
Redfin exposes an unofficial JSON API at https://www.redfin.com/stingray/. All
requests are HTTP GET. Responses are prefixed with {}& (4 bytes) before valid
JSON — always strip this prefix before parsing.
Authentication & Headers
- User-Agent header is required (use a current Chrome UA string)
- Optional cookies for authenticated access:
RF_ACCESS_LEVEL,RF_AUTH,RF_W_AUTH,RF_SECURE_AUTH,RF_PARTY_ID
- Add rate-limiting delays between requests to avoid being blocked
Response Format
Every endpoint returns this wrapper:
{
"version": 1,
"errorMessage": "Success",
"resultCode": 0,
"payload": { ... }
}
resultCode == 0 and errorMessage == "Success" indicates success. The
payload structure varies by endpoint.
Core Workflows
1. Search for Listings by Zip Code / Location
Step 1: Location autocomplete to get a region ID.
GET /stingray/do/location-autocomplete?location={query}&v=2
Response payload:
{
"sections": [{ "rows": [{ "id": "2_12345", "type": "2", "name": "92708", ... }] }],
"exactMatch": { "id": "2_12345", ... }
}
The id field is {region_type}_{region_id}. Split on _ to extract both.
Step 2: GIS CSV download to get property listings for that region.
GET /stingray/api/gis-csv?region_id={id}®ion_type={type}&...
Returns CSV data (not JSON — no {}& prefix). The CSV has:
- Row 0: headers (look for
URLcolumn) - Row 1: MLS disclaimer text ("In accordance with local MLS rules...")
- Rows 2+: property data
Extract the URL column to get Redfin property URLs for further querying.
2. Get Property IDs from a URL
GET /stingray/api/home/details/initialInfo?path={redfin_path}
Where path is the URL path portion (e.g., /CA/Fountain-Valley/12345-Main-St-92708/home/12345678).
Payload:
{
"propertyId": 12345678,
"listingId": 234567890,
"latLong": { "latitude": 33.71, "longitude": -117.95 }
}
3. Get Property Details
Most detail endpoints live under /stingray/api/home/details/. Some require
just propertyId, others require both propertyId and listingId.
For property-only endpoints, add accessLevel=1 and optionally pageType=3.
Endpoint Reference
URL-based (pass path parameter)
| Endpoint | Path |
|---|---|
| Initial Info | api/home/details/initialInfo |
| Page Tags | api/home/details/v1/pagetagsinfo |
| Primary Region | api/home/details/primaryRegionInfo |
Search
| Endpoint | Path | Key Params |
|---|---|---|
| Location Autocomplete | do/location-autocomplete |
location, v=2 |
| GIS CSV | api/gis-csv |
region_id, region_type, filters (see below) |
Property ID Only (propertyId param)
| Endpoint | Path | Page Type |
|---|---|---|
| Below The Fold (MLS) | api/home/details/belowTheFold |
3 |
| Hood Photos | api/home/details/hood-photos |
— |
| More Resources | api/home/details/moreResourcesInfo |
— |
| Page Header | api/home/details/homeDetailsPageHeaderInfo |
— |
| Property Comments | api/v1/home/details/propertyCommentsInfo |
— |
| Building Details | api/building/details-page/v1 |
— |
| Owner Estimate | api/home/details/owner-estimate |
— |
| Claimed Seller Data | api/home/details/claimedHomeSellerData |
— |
| Cost of Ownership | do/api/costOfHomeOwnershipDetails |
— |
Listing ID Only (listingId param)
| Endpoint | Path |
|---|---|
| Floor Plans | api/home/details/listing/floorplans |
| Tour Date Picker | do/tourlist/getDatePickerData |
Table ID (tableId param)
| Endpoint | Path | Extra Params |
|---|---|---|
| Shared Region | api/region/shared-region-info |
regionTypeId=2, mapPageTypeId=1 |
Full Property Details (propertyId + listingId params)
| Endpoint | Path | Page Type |
|---|---|---|
| Similar Listings | api/home/details/similars/listings |
— |
| Similar Sold | api/home/details/similars/solds |
— |
| Nearby Homes | api/home/details/nearbyhomes |
— |
| Above The Fold | api/home/details/aboveTheFold |
— |
| Property Parcel | api/home/details/propertyParcelInfo |
3 |
| Activity/History | api/home/details/activityInfo |
— |
| Off-Market Info | api/home/details/customerConversionInfo/offMarket |
3 |
| Rental Estimate | api/home/details/rental-estimate |
— |
| AVM Historical | api/home/details/avmHistoricalData |
— |
| Info Panel | api/home/details/mainHouseInfoPanelInfo |
— |
| Description | api/home/details/descriptiveParagraph |
— |
| AVM Details | api/home/details/avm |
— |
| Tour Insights | api/home/details/tourInsights |
3 |
| Stats | api/home/details/stats |
also needs regionId |
GISCSV Default Parameters
These defaults return a broad set of listings for a given region. Override
region_id and region_type per search.
DEFAULT_GISCSV_PARAMS = {
"al": "3",
"num_homes": "350",
"ord": "redfin-recommended-asc",
"page_number": "1",
"region_id": "", # required — from location autocomplete
"region_type": "2", # 2 = zipcode
"sf": "1,2,5,6,7", # property sub-filters
"status": "9", # 9 = all statuses
"uipt": "1,2,3,4,5,6,7,8", # all property types
"v": "8",
# boolean filters (all false for broadest results)
"has_pool": "false",
"has_parking": "false",
"has_laundry_facility": "false",
"has_laundry_hookups": "false",
"has_dishwasher": "false",
"has_att_fiber": "false",
"has_deal": "false",
"has_short_term_lease": "false",
"include_pending_homes": "false",
"isRentals": "false",
"is_furnished": "false",
"is_income_restricted": "false",
"is_senior_living": "false",
"pool": "false",
"travel_with_traffic": "false",
"travel_within_region": "false",
"utilities_included": "false",
}
Filtering for Single-Family Homes Only
To restrict to single-family homes (relevant for this project):
- Set
uipt=1(single family only, instead of1,2,3,4,5,6,7,8) - Set
sf=1,2,5,6,7(keeps the default sub-filters)
Property Type Codes (uipt)
| Code | Type |
|---|---|
| 1 | Single Family |
| 2 | Condo |
| 3 | Townhouse |
| 4 | Multi-Family |
| 5 | Land |
| 6 | Mobile/Manufactured |
| 7 | Co-op |
| 8 | Other |
Parsing Response Payloads
Redfin payloads are deeply nested. Use JMESPath expressions (or equivalent dictionary traversal) to extract data.
From InitialInfo Payload
| Field | JMESPath |
|---|---|
| Property ID | propertyId |
| Listing ID | listingId |
| Latitude | latLong.latitude |
| Longitude | latLong.longitude |
From BelowTheFold (MLS) Payload
| Field | JMESPath |
|---|---|
| Zip Code | publicRecordsInfo.addressInfo.zip |
| City | publicRecordsInfo.addressInfo.city |
| State | publicRecordsInfo.addressInfo.state |
| Image URLs | propertyHistoryInfo.mediaBrowserInfoBySourceId.*.photos[].photoUrls.nonFullScreenPhotoUrlCompressed |
| Thumbnail URLs | propertyHistoryInfo.mediaBrowserInfoBySourceId.*.photos[].thumbnailData.thumbnailUrl |
| Realtor Attribution | propertyHistoryInfo.mediaBrowserInfoBySourceId.*.photoAttribution | [0] |
| Event Count | length(propertyHistoryInfo.events) |
| Event Price | propertyHistoryInfo.events[N].price |
| Event Description | propertyHistoryInfo.events[N].eventDescription |
| Event Source | propertyHistoryInfo.events[N].source |
| Event Source ID | propertyHistoryInfo.events[N].sourceId |
| Event Date | propertyHistoryInfo.events[N].eventDate (Unix ms) |
Realtor Name Parsing
The photoAttribution field looks like "Listed by Jane Smith • Acme Realty.".
Split on •, trim whitespace, strip "Listed by " prefix from part 0, strip
trailing . from part 1.
Event Date Handling
Event dates are Unix timestamps in milliseconds. Convert:
datetime.fromtimestamp(event_date / 1000) (Python) or
time.Unix(0, event_date * int64(time.Millisecond)) (Go).
Most Useful Endpoints for Home Buying
For property evaluation, these three give you the most value:
- InitialInfo — property/listing IDs, lat/long
- BelowTheFold — address, property history (price changes), images, realtor info
- AVMDetails — Redfin's automated valuation model estimate
Additional high-value endpoints:
- SimilarSold — recent comparable sales
- SimilarListings — competing listings
- CostOfHomeOwnership — estimated monthly costs breakdown
- Activity — showing activity, saves, views
- Stats — market statistics for the region
Implementation Notes
Response Prefix Stripping
Every response (except GISCSV which returns raw CSV) is prefixed with {}&
(exactly 4 bytes). Strip before JSON parsing:
// Go
jsonBytes := responseBytes[4:]
# Python
data = json.loads(response.text[4:])
Rate Limiting
Add delays between requests (the gredfin project uses a configurable interval, typically a few seconds). Redfin will block aggressive scraping.
Error Handling
Always check both the HTTP status code AND the resultCode/errorMessage
fields in the JSON response. A 200 HTTP status can still contain an error in the
Redfin response body.
Hash-Based Deduplication
When polling properties over time, hash the payload bytes (MD5) and skip re-processing if unchanged from the last scrape.
More from brojonat/llmsrules
ibis-data
Use Ibis for database-agnostic data access in Python. Use when writing data queries, connecting to databases (DuckDB, PostgreSQL, SQLite), or building portable data pipelines that should work across backends.
13go-service
Build Go microservices with stdlib HTTP handlers, sqlc, urfave/cli, and slog. Use when creating or modifying a Go HTTP server, adding routes, middleware, database queries, or CLI commands.
13temporal-go
Build Temporal workflow applications in Go. Use when creating or modifying Temporal workflows, activities, workers, clients, signals, queries, updates, retry policies, saga patterns, or writing Temporal tests.
13parquet-analysis
Analyze parquet files using Python and Ibis. Use when the user wants to explore, transform, or analyze parquet data files, perform aggregations, joins, or export results. Works with local parquet files and provides database-agnostic data operations.
12ducklake
Work with DuckLake, an open lakehouse format built on DuckDB. Use when creating or querying DuckLake tables, managing snapshots, time travel, schema evolution, partitioning, or lakehouse maintenance operations.
12temporal-python
Build Temporal applications in Python using the temporalio SDK. Use when creating workflows, activities, workers, clients, signals, queries, updates, child workflows, timers, retry policies, saga/compensation patterns, testing, or any durable execution pattern in Python.
12