GET /price-history real-estate-market-data.p.rapidapi.com

Returns 12 months of median sale price, list price, sales count, and days-on-market data for any US city. Use it to chart price trends, detect seasonal patterns, identify peak buying months, and calculate how much prices have appreciated (or fallen) over the past year. Optionally filter by property type for a more precise picture.

Authentication

Requires a valid RapidAPI subscription. Include both headers on every request:

X-RapidAPI-Key: YOUR_RAPIDAPI_KEY X-RapidAPI-Host: real-estate-market-data.p.rapidapi.com

Request Parameters

Parameter Type Required Constraints Description Example
city string Required Min length: 2 City name. Case-insensitive — "austin" and "Austin" both work. Austin
state string Required Exactly 2 characters US state abbreviation. Must be 2 letters (e.g. TX, not Texas). TX
property_type string Optional Enum (see below) Filter data by property type. Defaults to "all" if omitted. single_family

property_type Values

ValueDescription
allAll property types combined (default)
single_familySingle-family homes only
condoCondominiums only
townhouseTownhouses only
City + state matching The API matches against 3,200+ cities with real Redfin data. For cities not yet in the dataset, a clearly-labelled state-anchored estimate is returned. The response always includes a data_source field so you can distinguish real from estimated data.

Response Schema

Top-level fields

FieldTypeAlways PresentDescription
citystringYesCity name (title-cased)
statestringYes2-letter state code (uppercased)
property_typestringYesThe requested property_type filter
monthly_dataarrayYesArray of monthly data objects, sorted oldest first
appreciation_12m_pctfloat|nullYesTotal price change from first to last month as a percentage (e.g. 5.8 = +5.8%). Null if only one month is available.
peak_monthstringYesMonth with the highest median sale price, in YYYY-MM format
months_availableintegerYesNumber of months returned (usually 12)
data_sourcestringYes"redfin_mls" for real data, "estimated" for state-anchored fallback
estimate_anchorstringWhen estimatedThe anchor used: "{state}_state_avg" or "national_avg"
data_notestringWhen estimatedHuman-readable explanation of the fallback

monthly_data array — each object

FieldTypeDescription
monthstringMonth in YYYY-MM format (e.g. "2025-06")
median_sale_priceintegerMedian closed sale price for that month in USD
median_list_priceintegerMedian active list price for that month in USD
sales_countintegerNumber of closed sales recorded that month
days_on_marketintegerMedian days from list to pending/sold that month

Full Example Response

{ "city": "Austin", "state": "TX", "property_type": "single_family", "monthly_data": [ { "month": "2025-04", "median_sale_price": 578000, "median_list_price": 595000, "sales_count": 412, "days_on_market": 28 }, { "month": "2025-05", "median_sale_price": 591000, "median_list_price": 609000, "sales_count": 487, "days_on_market": 24 }, { "month": "2025-06", "median_sale_price": 604000, "median_list_price": 618000, "sales_count": 531, "days_on_market": 21 }, { "month": "2025-07", "median_sale_price": 612000, "median_list_price": 628000, "sales_count": 498, "days_on_market": 22 }, { "month": "2025-08", "median_sale_price": 608000, "median_list_price": 622000, "sales_count": 461, "days_on_market": 25 }, { "month": "2025-09", "median_sale_price": 597000, "median_list_price": 614000, "sales_count": 388, "days_on_market": 29 }, { "month": "2025-10", "median_sale_price": 589000, "median_list_price": 607000, "sales_count": 342, "days_on_market": 33 }, { "month": "2025-11", "median_sale_price": 581000, "median_list_price": 597000, "sales_count": 297, "days_on_market": 36 }, { "month": "2025-12", "median_sale_price": 577000, "median_list_price": 594000, "sales_count": 271, "days_on_market": 38 }, { "month": "2026-01", "median_sale_price": 586000, "median_list_price": 601000, "sales_count": 306, "days_on_market": 35 }, { "month": "2026-02", "median_sale_price": 598000, "median_list_price": 614000, "sales_count": 341, "days_on_market": 31 }, { "month": "2026-03", "median_sale_price": 611000, "median_list_price": 626000, "sales_count": 408, "days_on_market": 26 } ], "appreciation_12m_pct": 5.71, "peak_month": "2025-07", "months_available": 12, "data_source": "redfin_mls" }

Code Examples

cURL — basic request
curl -s \ -H "X-RapidAPI-Key: YOUR_KEY" \ -H "X-RapidAPI-Host: real-estate-market-data.p.rapidapi.com" \ "https://real-estate-market-data.p.rapidapi.com/price-history?city=Austin&state=TX"
cURL — filter to condos
curl -s \ -H "X-RapidAPI-Key: YOUR_KEY" \ -H "X-RapidAPI-Host: real-estate-market-data.p.rapidapi.com" \ "https://real-estate-market-data.p.rapidapi.com/price-history?city=Miami&state=FL&property_type=condo"
Python — compare all property types for one city
import requests, os API_KEY = os.environ["RAPIDAPI_KEY"] HEADERS = { "X-RapidAPI-Key": API_KEY, "X-RapidAPI-Host": "real-estate-market-data.p.rapidapi.com" } CITY, STATE = "Denver", "CO" TYPES = ["all", "single_family", "condo", "townhouse"] results = {} for prop_type in TYPES: resp = requests.get( "https://real-estate-market-data.p.rapidapi.com/price-history", params={"city": CITY, "state": STATE, "property_type": prop_type}, headers=HEADERS, timeout=10 ) results[prop_type] = resp.json() print(f"\n{CITY}, {STATE} — 12-month appreciation by property type\n") print(f"{'Type':<15} {'Start Price':>12} {'End Price':>11} {'Appreciation':>13} {'Peak Month'}") print("─" * 70) for prop_type, data in results.items(): months = data["monthly_data"] start = months[0]["median_sale_price"] end = months[-1]["median_sale_price"] appre = data["appreciation_12m_pct"] sign = "+" if appre >= 0 else "" print( f"{prop_type:<15} ${start:>11,} ${end:>10,} " f"{sign}{appre:>11.1f}% {data['peak_month']}" )
Python — plot price history with matplotlib
import requests, os import matplotlib.pyplot as plt import matplotlib.dates as mdates from datetime import datetime API_KEY = os.environ["RAPIDAPI_KEY"] HEADERS = { "X-RapidAPI-Key": API_KEY, "X-RapidAPI-Host": "real-estate-market-data.p.rapidapi.com" } # Compare two cities cities = [ {"city": "Austin", "state": "TX", "color": "#c83800"}, {"city": "Denver", "state": "CO", "color": "#1a3a7a"}, ] fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(10, 8), sharex=True) fig.suptitle("12-Month Price & Sales Comparison", fontsize=14, fontweight="bold") for c in cities: resp = requests.get( "https://real-estate-market-data.p.rapidapi.com/price-history", params={"city": c["city"], "state": c["state"]}, headers=HEADERS, timeout=10 ) data = resp.json() months = data["monthly_data"] dates = [datetime.strptime(m["month"], "%Y-%m") for m in months] prices = [m["median_sale_price"] for m in months] sales = [m["sales_count"] for m in months] label = f"{c['city']}, {c['state']} ({data['appreciation_12m_pct']:+.1f}%)" ax1.plot(dates, [p/1000 for p in prices], color=c["color"], linewidth=2, marker="o", markersize=4, label=label) ax2.bar([d.toordinal() for d in dates], sales, color=c["color"], alpha=0.6, width=20, label=c["city"]) ax1.set_ylabel("Median Sale Price ($k)") ax1.legend(fontsize=9) ax1.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, _: f"${x:.0f}k")) ax1.grid(True, alpha=0.3) ax2.set_ylabel("Monthly Sales Count") ax2.xaxis.set_major_formatter(mdates.DateFormatter("%b '%y")) ax2.xaxis.set_major_locator(mdates.MonthLocator(interval=2)) ax2.legend(fontsize=9) ax2.grid(True, alpha=0.3) plt.xticks(rotation=30) plt.tight_layout() plt.savefig("price_history_comparison.png", dpi=150, bbox_inches="tight") print("Saved: price_history_comparison.png")
JavaScript — build a price history chart with Chart.js
// Next.js page or React component — calls server-side proxy // See /docs/use-cases for the proxy API route setup import { useState, useEffect, useRef } from "react"; import { Chart, registerables } from "chart.js"; Chart.register(...registerables); export default function PriceHistoryChart({ city, state }) { const canvasRef = useRef(null); const chartRef = useRef(null); const [error, setError] = useState(null); useEffect(() => { if (!city || !state) return; fetch(`/api/price-history?city=${city}&state=${state}`) .then(r => r.json()) .then(data => { const months = data.monthly_data; const labels = months.map(m => m.month); const prices = months.map(m => m.median_sale_price / 1000); // Destroy previous chart instance if (chartRef.current) chartRef.current.destroy(); chartRef.current = new Chart(canvasRef.current, { type: "line", data: { labels, datasets: [{ label: `${city}, ${state} Median Price ($k)`, data: prices, borderColor: "#c83800", backgroundColor: "rgba(200, 56, 0, 0.08)", fill: true, tension: 0.3, pointRadius: 4, }] }, options: { responsive: true, plugins: { legend: { position: "top" }, tooltip: { callbacks: { label: ctx => `$${ctx.raw.toFixed(0)}k` } } }, scales: { y: { ticks: { callback: v => `$${v}k` } } } } }); }) .catch(() => setError("Could not load price history.")); }, [city, state]); return ( <div> {error && <p style={{ color: "#c83800" }}>{error}</p>} <canvas ref={canvasRef} /> </div> ); }
R — price history analysis with tidyverse
library(httr2) library(dplyr) library(ggplot2) library(lubridate) api_key <- Sys.getenv("RAPIDAPI_KEY") fetch_price_history <- function(city, state, property_type = "all") { resp <- request("https://real-estate-market-data.p.rapidapi.com/price-history") |> req_url_query(city = city, state = state, property_type = property_type) |> req_headers( "X-RapidAPI-Key" = api_key, "X-RapidAPI-Host" = "real-estate-market-data.p.rapidapi.com" ) |> req_perform() data <- resp_body_json(resp) # Convert monthly_data list to data frame df <- bind_rows(data$monthly_data) |> mutate( date = ym(month), city = data$city, state = data$state ) list(df = df, appreciation = data$appreciation_12m_pct, peak = data$peak_month) } # Fetch data for two markets austin <- fetch_price_history("Austin", "TX") denver <- fetch_price_history("Denver", "CO") combined <- bind_rows(austin$df, denver$df) # Plot ggplot(combined, aes(x = date, y = median_sale_price / 1e3, color = paste(city, state), group = paste(city, state))) + geom_line(linewidth = 1.2) + geom_point(size = 2) + scale_y_continuous(labels = function(x) paste0("$", x, "k")) + scale_color_manual(values = c("#c83800", "#1a3a7a")) + labs( title = "12-Month Median Sale Price Comparison", subtitle = sprintf("Austin: %+.1f%% | Denver: %+.1f%%", austin$appreciation, denver$appreciation), x = NULL, y = "Median Sale Price", color = "Market", caption = "Source: ZipMarketData / Redfin MLS" ) + theme_minimal(base_size = 12)

Using price-history for Seasonality Analysis

Real estate markets are highly seasonal. The monthly_data array lets you identify peak and trough months, helping you time purchases and sales more effectively.

Python — seasonal pattern analysis
import requests, os from statistics import mean API_KEY = os.environ["RAPIDAPI_KEY"] HEADERS = { "X-RapidAPI-Key": API_KEY, "X-RapidAPI-Host": "real-estate-market-data.p.rapidapi.com" } resp = requests.get( "https://real-estate-market-data.p.rapidapi.com/price-history", params={"city": "Seattle", "state": "WA"}, headers=HEADERS, timeout=10 ) data = resp.json() months = data["monthly_data"] avg_price = mean(m["median_sale_price"] for m in months) print(f"Seattle, WA — 12-month price vs. average (${avg_price:,.0f})\n") for m in months: price = m["median_sale_price"] delta = (price - avg_price) / avg_price * 100 bar = "█" * abs(int(delta)) sign = "+" if delta >= 0 else "-" print( f" {m['month']} ${price:>8,} {sign}{abs(delta):4.1f}% " f"{'▲' if delta > 0 else '▼'} {bar}" ) peak = max(months, key=lambda m: m["median_sale_price"]) trough = min(months, key=lambda m: m["median_sale_price"]) print(f"\n Peak: {peak['month']} ${peak['median_sale_price']:,}") print(f" Trough: {trough['month']} ${trough['median_sale_price']:,}") print(f" Spread: ${peak['median_sale_price'] - trough['median_sale_price']:,} " f"({(peak['median_sale_price']/trough['median_sale_price']-1)*100:.1f}%)")

Error Responses

StatusCauseResponse Body
400 City name is 0 or 1 characters {"detail": "City name too short"}
400 State is not exactly 2 characters {"detail": "State must be a 2-letter code, e.g. TX"}
403 Missing or invalid RapidAPI key {"detail": "Access this API through RapidAPI"}
422 property_type value not in allowed enum Validation error listing allowed values
429 Rate limit exceeded RapidAPI rate limit error

Related Endpoints