Realtors dataset with 400K+ US property listings from all 50 states. Cleaned, typed, deduplicated listing-level records for pandas, Postgres, BigQuery or Excel.
Most real estate data projects get stuck in the same place. Not at the modeling stage. At the cleanup stage.
You pull listings from a few sources. Prices come through as text with dollar signs. Bathroom counts are sometimes "2", sometimes "2.5", sometimes "2 full, 1 half". City names are spelled three different ways. Half the rows are duplicates.
Two weeks disappear before you train a single model.
This realtors dataset skips that part. It holds 400,000+ residential property listings from Realtor.com, covering all 50 states and Washington D.C. Every record is cleaned, typed, and deduplicated. Load it into pandas, Postgres, BigQuery, or Excel and start working right away.
Many real estate data products give you aggregates: median price by ZIP code, inventory counts by metro, a monthly index. Those are fine for a headline. They are close to useless for modeling, because every individual property has been averaged away.
This dataset is the opposite. One row = one property listing, with its own ID, its own coordinates, its own price flags, its own brokerage.
If you want aggregates, you can build them. Grouping up is a one-line query. Going the other way — recovering individual homes from a median — is impossible.
That's why this format works for valuation models, comparable-property search, foreclosure screening, and anything where the thing you're studying is a house, not a market.
The schema is grouped into seven sections. Here's what each one gives you.
property_id · listing_id · region_id · ldp_slug · detail_url
Stable IDs let you remove duplicates, match records across different downloads, and build a history if you pull the data more than once. The detail URL takes you back to the original page whenever you want to check a record by hand.
address_line · address_line2 · city · state_code · postal_code · county_fips · latitude · longitude
Every record is already geocoded. Radius search, map rendering, and spatial joins work immediately — no geocoding bill, no address parser to write.
list_price · price_min · price_max · price_prefix · price_reduced_label · price_reduced_amount
The min/max fields cover new-construction listings priced as a range instead of a single number. Price cuts come with both a readable label and the exact dollar amount, so you can filter on the signal and measure it in the same query.
home_type · beds · baths · sqft · lot_sqft
status · status_text · status_dot_color · list_date · created_at · updated_at
is_new_listing · is_price_reduced · is_pending · is_contingent · is_foreclosure · is_new_construction · is_coming_soon
These are the quickest way to a filtered working set. One WHERE clause gets you every foreclosure in Ohio, or every coming-soon listing in Phoenix — no searching through free text.
primary_photo_url · photo_count · has_3d_tour · has_video_tour · has_virtual_tour · brokerage_name · attribution_text · raw
The raw column keeps the complete original JSON for every listing. If a field you need isn't broken out into its own column, it's still in there. Nothing is lost.
This sounds like a small thing. It saves more time than anything else in the dataset.
Field type | How it's stored | What that saves you |
|---|---|---|
Prices |
| No |
Baths |
|
In practice: pd.read_csv() or a Postgres COPY gives you a usable table on the first try. No coercion step. No errors='coerce' quietly swallowing bad rows. No audit afterward to find out how many records got mangled.
Beds, baths, square footage, lot size, home type, and exact coordinates give you a working feature set on day one. Add a few derived features — price per square foot, distance to a city center, neighborhood averages computed from the data itself — and you have a solid baseline model before touching any outside source.
400K+ rows is enough to train and validate properly, without borrowing data from unrelated markets to fill gaps.
Combine is_foreclosure with price_reduced_amount to surface motivated sellers. Add days-on-market (calculated from list_date) and you can rank opportunities by how stale the listing is and how deep the discount runs — all in one query.
is_new_construction and is_coming_soon show you inventory entering the market, before it appears in closed-sale figures. That's a leading indicator instead of a lagging one. Builders, lenders, and analysts see supply forming rather than reading about it a quarter later.
county_fips is the field that makes this dataset play well with everything else. These public sources all key on FIPS codes:
U.S. Census Bureau — population, income, household demographics
HUD User — affordability and fair market rent data
FEMA Flood Map Service Center — flood risk zones
Bureau of Labor Statistics — local employment and wages
You get exact joins instead of fuzzy matching on county names. No hand-fixing "St. Louis City" vs. "St. Louis County". No rows quietly disappearing.
brokerage_name sits at the listing level, so you can measure share of inventory by metro, state, or price band. Useful for competitive research, for brokerages weighing a new market, and for anyone selling software into the brokerage space.
Does better listing media actually sell homes faster? It gets claimed a lot and measured rarely.
photo_count and the three tour flags sit in the same table as the listing dates, so testing it is a GROUP BY — not a six-week data collection project.
With coordinates on every row, the data drops straight into PostGIS, Kepler.gl, Mapbox, or Deck.gl. Price-per-square-foot heatmaps, new-construction clusters, drive-time inventory counts — all standard once the coordinates are there and you can trust them.
You are… | You use it to… |
|---|---|
Proptech team | Seed a product with real inventory instead of dummy data |
ML engineer | Train a model that generalizes past one metro |
Real estate investor | Run systematic buy screens across several states |
Pick the format that matches where the data is going:
CSV — pandas, Excel, quick exploration
Parquet — Spark, BigQuery, large-scale work
JSON / JSONL — streaming ingestion, document stores
Postgres-ready output — relational warehouses
You can filter before delivery by state, metro, ZIP, price band, home type, bed and bath count, or any status flag. Take a single-market slice for a focused study, or the full national file for large modeling jobs.
The schema stays the same between downloads. Pipelines you write against one export keep working against the next — which matters once the dataset becomes a scheduled input rather than a one-off analysis.
Dataset: Realtors Datasets: 400K+ US Property Listings, 50 States
Load the file.
Run describe() or a couple of GROUP BY queries to get your bearings.
Check coverage in the areas you actually care about.
Most teams get their first useful output — a price distribution, a heatmap, a baseline regression — within an hour. Mostly because none of that hour goes to parsing.
After that it behaves like any well-formed table. Join it to your own data on FIPS codes or coordinates, filter with the boolean flags, and dig into the raw column whenever a niche field turns out to matter.
This is an independently compiled dataset of publicly visible real estate listing information. It is not affiliated with, endorsed by, or an official product of Realtor.com, Move, Inc., or the National Association of REALTORS®. Buyers are responsible for ensuring their use complies with applicable laws, platform terms, and data protection rules in their jurisdiction.
2.5Timestamps | Timezone-aware | Date comparisons across states are correct |
Booleans | Default | Filters don't silently drop rows |
Cite row-level, reproducible evidence |
BI or analytics team | Maintain a national inventory view that refreshes on a schedule |