Property Sales Data: Downloading Real Estate Transaction Records from Government Sources
Published 2026-08-04 · DataForge team
Every US property sale is a public record: deed recorded, price disclosed (in most states), parcel characteristics maintained by the county assessor. Zillow and CoreLogic built billion-dollar data businesses on exactly these records. The records themselves? Free, if you know where each jurisdiction hides them and can stomach the schema archaeology. This guide covers the best open sources — NYC, Philadelphia, Cook County — what makes assessor data treacherous, and working code for turning it into a sales table.
Where the free data lives
New York City. The gold standard of property open data. PLUTO gives one row per tax lot (~860k lots) with land use, zoning, building class, floor area and coordinates. The DOF Rolling Sales and Annualized Sales files add every transaction with price, date and building class. Join on borough-block-lot (BBL).
Philadelphia. The Office of Property Assessment publishes all ~580k parcels plus a full transfers/sales history on OpenDataPhilly — one of the cleanest city property datasets anywhere.
Cook County (Chicago). The Assessor’s office publishes parcels, assessments and a deeply documented sales file on the county data portal — including the data they use for their own published assessment models.
Everywhere else. ~3,000 counties, each its own recorder/assessor, ranging from Socrata portals to $0.50-per-page PDF deeds. Multi-market coverage is exactly why national aggregators charge what they charge. (Also worth knowing: ~a dozen non-disclosure states — TX, ID, UT… — don’t publish sale prices at all.)
The traps in assessor data
Non-arm’s-length sales. Raw transfer files include $1 family transfers, foreclosure deeds, and intra-LLC shuffles. Any price analysis must filter these (NYC data has explicit flags; elsewhere you infer from price ratios and deed types). Skipping this filter is the classic beginner error — it poisons medians badly.
Parcel ID drift. Lots merge, split and get renumbered; condo buildings map one lot to hundreds of units. Longitudinal analysis needs careful key handling.
Schema divergence. “Building class B3” means something different in NYC vs Philadelphia; land-use taxonomies, units conventions and even date formats vary per jurisdiction. Cross-market work requires a normalization layer — which is precisely what our dataset ships: 7,009,514 property and sale-event records across NYC, Philadelphia and Cook County in one harmonized schema.
Working code
NYC rolling sales via the Socrata API:
import pandas as pd
# NYC DOF Rolling Sales (Socrata) — Manhattan residential, last year
url = (
"https://data.cityofnewyork.us/resource/usep-8jbt.csv"
"?$where=borough='1' AND sale_price > 10000"
"&$limit=50000"
)
sales = pd.read_csv(url, parse_dates=["sale_date"])
res = sales[sales["building_class_category"].str.contains("ONE FAMILY|TWO FAMILY|CONDOS", na=False)]
monthly = res.set_index("sale_date").resample("ME")["sale_price"].median()
print(monthly.tail(12))
Note the sale_price > 10000 guard — a crude arm’s-length filter that already removes the $0/$1 transfers dominating raw files.
With a harmonized multi-market table, comparative analysis is one query:
-- Median residential sale price per market, trailing 12 months
SELECT market,
COUNT(*) AS sales,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY sale_price_usd) AS median_price
FROM sale_events
WHERE is_arms_length
AND property_type = 'residential'
AND sale_date >= CURRENT_DATE - INTERVAL '12 months'
GROUP BY market
ORDER BY median_price DESC;
Assessments vs. sales: the join that unlocks valuation work
The two halves of property data answer different questions and are far more valuable joined. Sales tell you price — but only for the ~5% of properties that trade in a given year. Assessments cover every parcel annually — but assessed values are modeled, lagged, and legally smoothed (assessment caps, homestead exemptions). The workhorse metric bridging them is the assessment-to-sale ratio: assessed value divided by subsequent arm’s-length sale price, computed per parcel. In a well-functioning assessment system it clusters tightly around the statutory ratio; in reality it varies systematically — by price tier, by neighborhood, by property age — and every one of those variations is either a research finding (assessment-equity studies) or a money-making screen (appeal candidates trade below the fee to file).
Practically, the join needs three ingredients done carefully: the parcel key handled through splits/merges (BBL in NYC, PIN in Cook County, OPA number in Philadelphia — each with its own condo quirks), the sale filtered to arm’s-length, and the timing aligned — you must compare a sale against the assessment that was current before the sale, or the assessor’s post-sale chase re-assessment contaminates the ratio. Our pre-joined parcels↔sale-events tables keep both record types with their effective dates precisely so this alignment is a window function instead of an archaeology project.
What people build with this
- Valuation models (AVMs). Sales + parcel characteristics are the training data for every price model; assessor data adds the features (square footage, year built, lot size) that listings data lacks.
- Investment screening. Price-per-square-foot dispersion within a neighborhood flags mispriced parcels; assessment-to-sale ratios flag appeal opportunities.
- Market research. Volume, mix and price trends by neighborhood from primary records rather than portal estimates.
- Assessment-equity studies. A major research genre: do lower-value homes get over-assessed relative to sales? (Cook County’s own data made this famous.)
- Urban planning. PLUTO-style parcel data underlies most NYC-focused academic and civic-tech work.
Worth stating plainly for anyone sizing the DIY route: each covered jurisdiction is roughly a week of focused work to ingest properly — finding the right files among each portal’s dozens, decoding the building-class and deed-type code tables (NYC’s building classification alone has ~200 codes), implementing the arm’s-length rules, and validating row counts against the portal’s published totals. It’s tractable, well-documented work for one city; it compounds linearly with each additional market, and the maintenance (portals reorganize, schemas add columns) never ends. That’s the entire economics of the harmonized dataset in one sentence.
Free portals vs. the harmonized dataset
| City/county portals | DataForge dataset | |
|---|---|---|
| Cost | Free | From $99 |
| Coverage | One jurisdiction per portal/schema | NYC + Philadelphia + Cook County, one schema, 7.0M records |
| Sales linkage | DIY parcel-key joins | Parcels ↔ sale events pre-joined |
| Arm’s-length handling | DIY per-jurisdiction | Flagged with documented rules |
| Format | CSV/Socrata/Shapefile mix | CSV/Parquet + data dictionary + QA report |
Honest guidance: analyzing a single covered city? Go straight to its portal — NYC and Philadelphia especially are excellent, and it’s free. The dataset’s value is the cross-market harmonization and the pre-built parcel↔sale joins. City slices start at $99 (Philadelphia) / $399 (NYC); see the free 500-row sample first.
FAQ
Is property data legal to use commercially? Yes — deeds and assessments are public records published as open data by the jurisdictions themselves. Some portals request attribution; the datasheet documents each source’s terms.
Does it include owner names? Public records include owners (often LLCs). Our packaged dataset focuses on parcel characteristics and transaction facts; the datasheet details exact fields.
Why not just use Zillow’s ZHVI? ZHVI is a modeled index, excellent for trend context, useless for parcel-level work. Primary records are the ground truth beneath every index.
How do I handle condos — they seem to break everything? They do, in every jurisdiction, differently. NYC: a condo building has one billing BBL but each unit gets its own lot number in the 75xx range, while co-ops (a huge share of NYC housing) are the reverse — one lot, sales recorded as shares transferring, prices per-unit but characteristics per-building. Philadelphia and Cook County have their own unit-parcel conventions. The practical rules: never compute price-per-square-foot from a building-level record joined to a unit-level sale; segment condo/co-op/single-family analyses from the start; and treat any market-level median that doesn’t state its unit-handling convention as suspect. Our schema carries an explicit property-type field and unit-level keys where the source provides them.
What about off-market and new-construction sales? Recorded deeds capture all transfers, including off-MLS sales that listing-based datasets (Redfin/Zillow data files) never see — one of public records’ quiet advantages. New construction is the edge case: the first sale often records against a parent parcel before unit subdivision completes, producing apparent outliers (one “sale” at the price of thirty units). Filter by deed type and watch for parcel-birth dates near the sale date.
Can I link sales to mortgages? In jurisdictions that publish recorder data (NYC’s ACRIS does this beautifully), mortgage documents record alongside deeds — amount, lender, satisfaction dates — enabling loan-to-value analysis, cash-buyer identification, and refinance tracking. It’s a separate document stream keyed to the same parcels; our NYC slice’s datasheet covers what’s included.
What formats and documentation ship with the dataset? CSV and Parquet, with a data dictionary covering every field, a per-source datasheet (portal, collection date, known limitations, code-table translations) and a QA report with row counts validated against portal-published totals.
National coverage? Not yet — we cover jurisdictions with high-quality open publication (NYC, Philadelphia, Cook County) rather than reselling aggregator data of uneven provenance. Coverage grows as more markets meet that bar.