To get Redfin listing data into a pipeline, use Scavio's Redfin API. POST /api/v1/redfin/search with a ZIP code and "limit": 350 returns up to 350 listings per call with price, price per square foot, beds, baths, days on market, coordinates and the MLS number; page until a call returns fewer than 350 and you have every listing in the ZIP. Then /property adds each home's dated price history and tax history, and a sold search adds what closed. Every call costs 1 credit, about $0.002 on the Growth plan billed yearly.
Redfin publishes no listings API. Its Data Center offers free downloads, but each row is one region for one period, so they work for market trends and not for a table of homes. The steps below were run on October 27, 2026, and every response shown is a trimmed capture from that day.
Step 1: Pull every listing in a ZIP
curl -s https://api.scavio.dev/api/v1/redfin/search \
-H "Authorization: Bearer $SCAVIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"location": "78701", "listing_status": "for_sale", "limit": 350}'location takes a 5-digit ZIP or a redfin.com region URL (/city/, /neighborhood/, /county/ or /zipcode/); a city name such as "Austin, TX" is not accepted. For downtown Austin this returned all 231 listings in one call, and the response echoes the region it resolved: {"id": 34095, "type": 2, "url": "https://www.redfin.com/zipcode/78701", "service_area": "downtown-austin"}. One row, as captured (photos and description trimmed):
{
"position": 1,
"property_id": 34243271,
"listing_id": 224809554,
"mls_id": "3861292",
"mls_status": "Active",
"status": "active",
"url": "https://www.redfin.com/TX/Austin/904-West-Ave-78701/unit-214/home/34243271",
"price": 629000,
"price_per_sqft": 434,
"hoa_month": 883,
"beds": 3,
"baths": 2,
"sqft": 1450,
"year_built": 1966,
"property_type": "condo",
"address": {
"street": "904 West Ave #214",
"city": "Austin",
"state": "TX",
"postal_code": "78701",
"country": "US"
},
"neighborhood": "West Condo 904",
"location": { "latitude": 30.273701, "longitude": -97.749765 },
"days_on_market": 1,
"listed_at": "2026-10-26T20:07:28.313Z",
"badges": ["New"],
"photo_count": 24
}Key your table on property_id. A property keeps it across listings over the years, listing_id identifies this one listing, and mls_id is the key for joining against an MLS feed or another portal.
Step 2: Page to the end, then compute your own medians
Larger ZIPs need more than one call. Add page and stop when a page returns fewer listings than limit:
curl -s https://api.scavio.dev/api/v1/redfin/search \
-H "Authorization: Bearer $SCAVIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"location": "33131", "listing_status": "for_sale", "limit": 350, "page": 2}'Downtown Miami returned 350, 350 and 195 listings on pages 1 to 3, 895 in all with no duplicate property_id. Each response also carries a medians object, and it describes that page only:
{ "price": 699000, "sqft": 1105, "price_per_sqft": 710, "days_on_market": 40, "beds": 2, "baths": 2 }That was page 1. Page 2's median days on market was 161 and page 3's was 427, and across all 895 listings it was 131, because the first page leans towards new listings. Merge the pages before you compute any market statistic. Across six ZIPs, 2,177 listings took 9 calls; the best Redfin listing data APIs charts how long they had been for sale.
Step 3: Pick up new listings between full pulls
curl -s https://api.scavio.dev/api/v1/redfin/search \
-H "Authorization: Bearer $SCAVIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"location": "33131", "listing_status": "for_sale", "sort": "newest", "max_days_on_market": 7, "limit": 350}'This returned downtown Miami's 35 newest listings, none older than 8 days, in one call. max_days_on_market and min_days_on_market cannot be sent together, and numeric filters take whole numbers only, so "baths_min": 1.5 is rejected rather than rounded.
Step 4: Get the history for each new or changed listing
curl -s https://api.scavio.dev/api/v1/redfin/property \
-H "Authorization: Bearer $SCAVIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"property_id": "31166026"}'property_id also accepts the listing URL from a search row. For 1812 West Ave #404 in Austin, trimmed:
{
"property_id": 31166026,
"mls_source": "Unlock MLS",
"status": "Closed",
"price": 590000,
"redfin_estimate": 544396.4,
"rental_estimate": 3343,
"price_history": [
{ "date": "2026-10-16T07:00:00.000Z", "event": "Sold (MLS)", "mls_status": "Closed" },
{ "date": "2026-09-30T11:47:39.100Z", "event": "Contingent", "mls_status": "Active Under Contract" },
{ "date": "2026-09-19T13:58:09.777Z", "event": "Price Changed", "price": 590000 },
{ "date": "2026-09-09T07:00:00.000Z", "event": "Listed", "mls_status": "Active", "price": 595000 }
]
}The same response held 17 years of tax history, three schools with ratings, flood, fire and heat risk, zoning (MF-4), 6 comparable sales with sold dates and 18 similar listings. This is a Texas home, and Texas does not disclose sale prices, so its "Sold (MLS)" event carries no price. It returned in 1.9 s. Failed calls are not charged, so run property calls from a queue with a long timeout and a retry.
Step 5: Add what sold
curl -s https://api.scavio.dev/api/v1/redfin/search \
-H "Authorization: Bearer $SCAVIO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"location": "98103", "listing_status": "sold", "sold_within_days": 30, "limit": 350}'Seattle's 98103 returned 55 homes sold in the past 30 days, with a median price of $940,000 in the page's medians. 3915 Sunnyside Ave N came back at $1,726,100; its property call shows it listed at $1,690,000 on September 17 and sold on October 20. Sold rows carry no sold date, so take the date from the property call. sold_within_days is rejected unless listing_status is "sold".
Step 6: Schedule it
A daily job pulls each ZIP in full, upserts by property_id, and queues a property call for anything new or repriced. A minimal version in Python:
import requests
API = "https://api.scavio.dev/api/v1/redfin"
HEADERS = {"Authorization": "Bearer YOUR_SCAVIO_API_KEY"}
def pull_zip(zip_code):
rows, page = [], 1
while True:
r = requests.post(f"{API}/search", headers=HEADERS, timeout=300, json={
"location": zip_code, "listing_status": "for_sale",
"limit": 350, "page": page,
})
r.raise_for_status()
data = r.json()["data"]
rows += data["listings"]
if data["count"] < 350:
return rows
page += 1
def changed(today, yesterday):
"""yesterday maps property_id -> price from the last run."""
return [row["property_id"] for row in today
if yesterday.get(row["property_id"]) != row["price"]]Listings that were in yesterday's pull and are missing today went pending, sold or off the market, which a property call confirms. Add /api/v1/redfin/market with the same ZIP once a week for context: for 98103 it returned a median sale price of $950,000, a 100.4% median sale-to-list and 13 median days to pending.
All three endpoints
| Endpoint | What it returns | Credits |
|---|---|---|
/api/v1/redfin/search | Up to 350 listings a page, for sale, sold or for rent, with page medians | 1 |
/api/v1/redfin/property | One home: price and tax history, Redfin Estimate, rental estimate, schools, climate risk, comparables | 1 |
/api/v1/redfin/market | A region's median list and sale price, sale-to-list, days to pending and competition score | 1 |
For a side-by-side of every Redfin option, see the best Redfin listing data APIs.
Getting started
- Sign up at dashboard.scavio.dev/sign-up: 50 free credits, no card required.
- Copy your API key from the dashboard.
- Send a POST to
/api/v1/redfin/searchwith a ZIP code and your key in theAuthorizationheader.
Try the Redfin API free in the playground first, or call it from Claude and other agents through the MCP server.
Reference: Redfin API overview · search · property · market · sold homes, list vs sale price
Frequently asked questions
Can I search Redfin listings by city name through an API?
Not with Scavio's Redfin API: location takes a 5-digit ZIP or a redfin.com region URL for a city, neighborhood, county or ZIP, or a region_id with its region_type. A city such as Austin is https://www.redfin.com/city/30818/TX/Austin. Resolve each city once and store the URL or id in your pipeline config.
How many Redfin listings does one API call return?
Scavio's search returns up to 350 listings per call through its limit parameter, and page moves through the rest. Seattle's 98103 fit in one call with 254 listings on October 27, 2026, while downtown Miami's 33131 took three calls for 895. A page that comes back with fewer than 350 listings is the last one.
How do I track Redfin price drops?
Two ways. Diff each listing's price between daily pulls, keyed on property_id, or call the property endpoint, whose price_history lists dated Listed, Price Changed, Pending or Contingent and Sold events. 1812 West Ave #404 in Austin was listed at $595,000 and cut to $590,000 ten days later.
Why is days_on_market empty for some Redfin listings?
Redfin does not show a days-on-market value for every listing. On October 27, 2026 it was missing for 233 of the 254 listings in Seattle's 98103 and 75 of the 152 in Chicago's 60614, against 8 of 895 in downtown Miami. Treat the field as optional and fall back to the Listed date in the property price history.
How much does Redfin data cost with Scavio?
Every Redfin call costs 1 credit, whether it returns 350 listings, one property or a market summary. That is about $0.002 on the Growth plan billed yearly and $0.0043 on the $30 Project plan. New accounts get 50 free credits with no card.