How to Measure the New-Build Price Premium in Python

On this page

Problem statement

New homes sell for more than existing ones, but by how much? Comparing the national median of new-build sales with the median of everything else gives a large, misleading number, because new homes are built in different places and in a different mix of types than the existing stock. A fair comparison holds the location and the type fixed. HM Land Registry's Price Paid Data flags every new build, and its postcodes allow the comparison to be made within small areas.

This page measures the new-build premium in England and Wales from the 2024 Price Paid file. It compares raw national medians, then medians by property type, then new and existing sales of the same type within the same postcode district, which is the fairest of the three.

Quick answer

Compare medians of new and existing homes within the same postcode district and property type:

A["district_pc"] = A.postcode.str.split(" ").str[0]
g = A.groupby(["district_pc", "property_type", "old_new"]).price.agg(["size", "median"]).unstack("old_new")
g = g[(g[("size", "Y")] >= 10) & (g[("size", "N")] >= 10)]
ratio = g[("median", "Y")] / g[("median", "N")] - 1
print(f"postcode district x type cells with 10+ sales of each: {len(ratio):,}")
print(f"new-build premium within cells: median {ratio.median():+.1%}; middle half {ratio.quantile(0.25):+.1%} to {ratio.quantile(0.75):+.1%}")
postcode district x type cells with 10+ sales of each: 1,963
new-build premium within cells: median +13.6%; middle half +2.6% to +29.1%

1,963 combinations of postcode district and type have at least 10 new and 10 existing sales. Within them, new builds sold for a median of 13.6% more, with the middle half of cells between 2.6% and 29.1%.

Raw against like-for-like new-build premium. raw vs like for likeraw: +22.8%βœ“Β£350,000 vs Β£285,000βœ“45% of new builds detachedβœ“mixes type and placewithin district and type: +13.6%βœ“1,963 comparison cellsβœ“middle half +2.6% to +29.1%βœ“20% of cells negative2024 standard sales spatialworkflow.io
The raw premium mixes the types and places new homes are built in.

The raw comparison, by type, where it is largest

1. The raw comparison

raw = A.groupby("old_new").price.median()
print(f"national median: new {raw['Y']:,.0f}, existing {raw['N']:,.0f}; raw premium {raw['Y'] / raw['N'] - 1:+.1%}")
print("share of each type among new builds:", A[A.old_new == "Y"].property_type.value_counts(normalize=True).round(2).to_dict())
print("among existing homes:", A[A.old_new == "N"].property_type.value_counts(normalize=True).round(2).to_dict())
national median: new 350,000, existing 285,000; raw premium +22.8%
share of each type among new builds: {'D': 0.45, 'S': 0.26, 'F': 0.19, 'T': 0.09}
among existing homes: {'S': 0.3, 'T': 0.29, 'D': 0.24, 'F': 0.17}

Nationally, new builds sold for a median of Β£350,000 against Β£285,000, a raw premium of 22.8%. But 45% of new builds were detached, against 24% of existing homes, so the raw figure partly measures the mix.

Histogram of new-build premiums in 1,963 postcode district and type groups Histogram of new-build premiums in 1,963 postcode district and type groups
Median +13.6%; new builds sell for less in 20% of groups.

2. By property type

t = A.groupby(["property_type", "old_new"]).price.median().unstack()
t["premium"] = t.Y / t.N - 1
print(t.loc[["D", "S", "T", "F"]].round(3).to_string())
old_new               N         Y  premium
property_type                             
D              417000.0  401983.5   -0.036
S              265000.0  285000.0    0.075
T              230000.0  273000.0    0.187
F              230000.0  355000.0    0.543

By type, the picture changes completely. New detached houses sold for 3.6% less than existing ones, while new flats sold for 54.3% more, consistent with new flats being built where flats are expensive.

3. Where the premium is largest

r = ratio.reset_index(); r.columns = ["district_pc", "type", "premium"]
print("premium by type within postcode districts:", r.groupby("type").premium.median().round(3).to_dict())
print(f"cells where new builds sell for less: {(r.premium < 0).mean():.0%}")
premium by type within postcode districts: {'D': 0.057, 'F': 0.396, 'S': 0.145, 'T': 0.238}
cells where new builds sell for less: 20%

Within postcode districts, the premium is 5.7% for detached houses, 14.5% for semis, 23.8% for terraces and 39.6% for flats. In 20% of cells, new builds sold for less than existing homes.

Districts with the most new building

The data used on this page

HM Land Registry Price Paid Data for 2024, standard sales (category A), Β© Crown copyright 2026, Open Government Licence v3.0. The postcode district is the outward part of the postcode, such as SW1A or M1.

from pathlib import Path

import pandas as pd
import requests

Path("data").mkdir(exist_ok=True)
CSV = Path("data/pp-2024.csv")
if not CSV.exists():
    r = requests.get("http://prod1.publicdata.landregistry.gov.uk.s3-website-eu-west-1.amazonaws.com/pp-2024.csv", timeout=1800); r.raise_for_status(); CSV.write_bytes(r.content)
COLS = ["transaction_id", "price", "date", "postcode", "property_type", "old_new", "duration", "paon", "saon",
        "street", "locality", "town", "district", "county", "ppd_category", "record_status"]
A = pd.read_csv(CSV, header=None, names=COLS, usecols=["price", "postcode", "property_type", "old_new", "district", "ppd_category"]).query("ppd_category == 'A'").dropna(subset=["postcode"]).copy()
print(f"{len(A):,} standard sales with a postcode; new builds {(A.old_new == 'Y').mean():.1%}")
763,740 standard sales with a postcode; new builds 9.5%

763,740 standard sales have a postcode, and 9.5% of them are new builds.

Example 1: districts with the most new building

Where were most new homes sold in 2024?

nb = A[A.old_new == "Y"].district.value_counts().head(5)
print("districts with the most new-build sales:", nb.to_dict())
districts with the most new-build sales: {'NORTH YORKSHIRE': 1190, 'EAST RIDING OF YORKSHIRE': 1021, 'NORTH NORTHAMPTONSHIRE': 936, 'LEEDS': 902, 'CHESHIRE EAST': 872}

North Yorkshire, East Riding of Yorkshire, North Northamptonshire, Leeds and Cheshire East had the most new-build sales in 2024, between 872 and 1,190 each.

Paired bars of raw and within-district new-build premium by property type Paired bars of raw and within-district new-build premium by property type
Detached new builds look cheaper nationally but carry a premium like for like.

A ratio of medians needs alike groups

New-build premium by property type, national and within postcode districts. premium by typetypenational medianswithin districtdetached-3.6%+5.7%semi-detached+7.5%+14.5%terraced+18.7%+23.8%flat+54.3%+39.6%cells need 10+ new and 10+ existing salesold_new = Y against N spatialworkflow.io
Flats show the largest premium both ways.

A premium measured as the ratio of two medians is only meaningful if the two groups are otherwise alike, and new and existing homes are not. New homes are concentrated where land is available, often on the edges of towns and in growing regions, and they include more flats and detached houses in some places, more terraces in others. A national comparison mixes all of that into the "premium". Comparing within property types removes the biggest difference. Comparing within small areas as well, here postcode districts, removes most of the location effect, at the cost of using only areas where both kinds of home sold.

What remains still reflects more than newness. New homes are often larger or smaller than the local existing stock, carry developer incentives or warranties, and are sold at asking prices set before completion. Studies that model size and features find premiums that shrink further, and premiums tend to fade as a new home becomes a second-hand one, which is why the first resale of new builds often shows weak price growth. The within-area estimate is a much better starting point than the raw ratio, and it is easy to compute from open data.

Minimum counts, leasehold and Help to Buy

Which new-build comparison answers which question. which premium do you need?What are you comparing?what buyers pay overallraw medians+22.8%, mix includedsame type, same areawithin-cell medians+13.6% mediansame home over timerepeat salesnew builds excludedState which comparison a premium comes from spatialworkflow.io
Each comparison answers a different question.
  • Minimum counts: small cells give noisy medians; require a minimum number of sales of each kind.
  • Leasehold: many new flats and some new houses are leasehold; compare within tenure for a stricter test.
  • Help to Buy: government-backed purchases of new builds may affect prices in some periods.
  • Postcode sectors: the next level down (for example SW1A 1) is finer but leaves fewer comparable cells.

FAQ

How much more do new-build homes cost?

Much less than the raw national comparison suggests; within the same postcode district and property type, the 2024 premium in England and Wales was smaller than the national ratio.

How do I identify new builds in Land Registry data?

The old_new column is Y for a newly built property and N for an established one.

Why is the raw new-build premium misleading?

New homes are built in different places and mixes of types than the existing stock; compare within type and area.

What is a postcode district?

The outward code of a UK postcode, the part before the space, covering a few thousand to tens of thousands of addresses.