| Title: | Access UK Housing Data from Land Registry, Planning, and 'ONS' |
| Version: | 0.2.0 |
| Description: | Fetch UK housing data from official sources. Access the UK House Price Index and Price Paid Data from 'HM Land Registry' https://landregistry.data.gov.uk/, planning application, brownfield land, and local plan data from 'planning.data.gov.uk' https://www.planning.data.gov.uk/, and the Price Index of Private Rents from the 'Office for National Statistics'. Data covers all 441 UK local authorities from 1995 to the present. Functions accept flexible filters (postcode, local authority, property type, date range) and return tidy data frames. Downloaded data is cached locally for subsequent calls. |
| Depends: | R (≥ 4.1.0) |
| License: | MIT + file LICENSE |
| Encoding: | UTF-8 |
| Language: | en-US |
| Imports: | cli (≥ 3.6.0), httr2 (≥ 1.0.0), jsonlite, tools, utils |
| Suggests: | readxl, sf, testthat (≥ 3.0.0) |
| Config/testthat/edition: | 3 |
| URL: | https://charlescoverdale.github.io/ukhousing/, https://github.com/charlescoverdale/ukhousing |
| BugReports: | https://github.com/charlescoverdale/ukhousing/issues |
| Config/roxygen2/version: | 8.1.0 |
| NeedsCompilation: | no |
| Packaged: | 2026-11-03 08:37:54 UTC; charlescoverdale |
| Author: | Charles Coverdale [aut, cre] |
| Maintainer: | Charles Coverdale <charlesfcoverdale@gmail.com> |
| Repository: | CRAN |
| Date/Publication: | 2026-11-03 08:50:02 UTC |
ukhousing: Access UK Housing Data from Land Registry, Planning, and 'ONS'
Description
Fetch UK housing data from official sources. Access the UK House Price Index and Price Paid Data from 'HM Land Registry' https://landregistry.data.gov.uk/, planning application, brownfield land, and local plan data from 'planning.data.gov.uk' https://www.planning.data.gov.uk/, and the Price Index of Private Rents from the 'Office for National Statistics'. Data covers all 441 UK local authorities from 1995 to the present. Functions accept flexible filters (postcode, local authority, property type, date range) and return tidy data frames. Downloaded data is cached locally for subsequent calls.
Author(s)
Maintainer: Charles Coverdale charlesfcoverdale@gmail.com
Authors:
Charles Coverdale charlesfcoverdale@gmail.com
See Also
Useful links:
Report bugs at https://github.com/charlescoverdale/ukhousing/issues
Inspect the local ukhousing cache
Description
Returns information about the local cache: where it lives, how many
files it contains, and how much disk space they take. Useful when
debugging stale results or deciding whether to call ukh_clear_cache().
Usage
ukh_cache_info()
Value
A list with elements dir, n_files, size_bytes,
size_human, and files (a data frame).
See Also
Other configuration:
ukh_clear_cache()
Examples
op <- options(ukhousing.cache_dir = tempdir())
try({
ukh_cache_info()
})
options(op)
Clear the ukhousing cache
Description
Deletes all locally cached UK housing data files. The next call to any data function will re-download fresh data.
Usage
ukh_clear_cache()
Value
Invisibly returns NULL.
See Also
Other configuration:
ukh_cache_info()
Examples
op <- options(ukhousing.cache_dir = tempdir())
try({
ukh_clear_cache()
})
options(op)
UK House Price Index
Description
Fetches monthly UK House Price Index data for a region from the HM Land Registry linked data service. Coverage: 441+ areas (countries, regions, counties, local authorities) from January 1995 (England and Wales), January 2004 (Scotland), January 2005 (Northern Ireland).
Usage
ukh_hpi(region, from = NULL, to = NULL, refresh = FALSE)
Arguments
region |
Character. Region slug, GSS code, or common name (e.g.
|
from, to |
Optional character or Date. Start and end dates in ISO format (YYYY-MM-DD). Default returns the full available history. |
refresh |
Logical. Re-download even if cached? Default |
Details
The returned data frame includes the headline index, average price, monthly and annual percentage change, sales volume, and breakdowns by property type (detached, semi-detached, terraced, flat) and by buyer type (cash, mortgage, first-time buyer, former owner occupier, new build, existing property).
Sales volumes lag the headline index by approximately five months because the Land Registry needs the full transaction set to settle.
Value
A data frame with one row per month. Columns include date,
region, hpi, avg_price, pct_change_monthly,
pct_change_annual, sales_volume, plus property-type and
buyer-type average prices.
See Also
Other house price index:
ukh_hpi_compare(),
ukh_transactions()
Examples
op <- options(ukhousing.cache_dir = tempdir())
try({
# All UK average house prices
uk <- ukh_hpi("united-kingdom")
head(uk)
# London, last 10 years
london <- ukh_hpi("london", from = "2016-01-01")
tail(london)
})
options(op)
Compare UK HPI across multiple regions
Description
Fetches the UK House Price Index for several regions and returns a wide data frame with one measure (e.g. average price or annual % change) as a column per region. Useful for regional comparison charts.
Usage
ukh_hpi_compare(
regions,
measure = "avg_price",
from = NULL,
to = NULL,
refresh = FALSE
)
Arguments
regions |
Character vector of region slugs, GSS codes, or names. |
measure |
Character. Which measure to return. One of
|
from, to |
Optional character or Date. Date range. |
refresh |
Logical. Re-download even if cached? Default |
Value
A wide data frame with a date column and one column per
region.
See Also
Other house price index:
ukh_hpi(),
ukh_transactions()
Examples
op <- options(ukhousing.cache_dir = tempdir())
try({
prices <- ukh_hpi_compare(
c("london", "manchester", "newcastle-upon-tyne"),
measure = "avg_price",
from = "2015-01-01"
)
head(prices)
})
options(op)
ONS Price Index of Private Rents
Description
Downloads the ONS Price Index of Private Rents (PIPR), UK: monthly price statistics. PIPR replaced the Index of Private Housing Rental Prices in 2024 and is published monthly from January 2015 for the UK, its countries, the English regions and local authorities (around 350 areas in all), including average rents in pounds.
Usage
ukh_pipr(property = "all", refresh = FALSE)
Arguments
property |
Which series to return: |
refresh |
Logical. Re-download even if cached? Default |
Details
The ONS stopped updating the rental index on its Beta API at January
2024, so this function reads the monthly workbook from the ONS website
instead. The cached copy is refreshed once it is more than
getOption("ukhousing.cache_max_age", 7) days old.
Value
A data frame with columns date (first of the month),
gss_code, region (area name), parent_region (the region or
country an area belongs to; NA for the UK and its countries),
index (January 2023 = 100), monthly_change_pct,
annual_change_pct and rental_price_gbp (average monthly rent,
rounded to the nearest pound). Values the ONS marks as unavailable
or not applicable are NA. Requires the readxl package.
Source
Office for National Statistics, Price Index of Private Rents, UK: monthly price statistics. Official statistics in development. https://www.ons.gov.uk/economy/inflationandpriceindices/datasets/priceindexofprivaterentsukmonthlypricestatistics
Examples
op <- options(ukhousing.cache_dir = tempdir())
try({
rents <- ukh_pipr()
tail(rents[rents$region == "United Kingdom", ])
flats <- ukh_pipr(property = "flat maisonette")
})
options(op)
Query planning.data.gov.uk
Description
Fetches records from the Digital Land planning data platform, which hosts over 100 datasets on planning applications, brownfield land, local plans, conservation areas, listed buildings, flood risk zones, and more.
Usage
ukh_planning(
dataset,
la = NULL,
limit = 1000L,
format = c("data.frame", "raw", "sf")
)
Arguments
dataset |
Character. Dataset slug. Common values:
|
la |
Optional character. Local authority name (matched
case-insensitively against the |
limit |
Integer. Maximum records to return. Default |
format |
Character. Response format. |
Value
A data frame (or list if format = "raw").
See Also
Other planning:
ukh_planning_datasets()
Examples
op <- options(ukhousing.cache_dir = tempdir())
try({
bf <- ukh_planning("brownfield-land", limit = 100)
head(bf)
})
options(op)
List available planning datasets
Description
Returns a data frame of datasets hosted by planning.data.gov.uk, with their slugs, names, and descriptions.
Usage
ukh_planning_datasets()
Value
A data frame with slug, name, typology, and
record_count.
See Also
Other planning:
ukh_planning()
Examples
op <- options(ukhousing.cache_dir = tempdir())
try({
ds <- ukh_planning_datasets()
head(ds)
})
options(op)
Price Paid Data
Description
Fetches individual property transaction records from the HM Land Registry Price Paid Data, filtered by local authority, postcode, property type, and other criteria.
Usage
ukh_ppd(
year = as.integer(format(Sys.Date(), "%Y")),
la = NULL,
postcode = NULL,
property_type = NULL,
new_build = NULL,
tenure = NULL,
from = NULL,
to = NULL,
refresh = FALSE
)
Arguments
year |
Integer. Year of transactions to fetch. Defaults to the current calendar year. |
la |
Optional character. Local authority name, matched against
the |
postcode |
Optional character. Postcode or postcode prefix. |
property_type |
Optional character. One of |
new_build |
Optional logical. If |
tenure |
Optional character. |
from, to |
Optional character or Date. Date range within the year (YYYY-MM-DD). |
refresh |
Logical. Re-download the yearly file even if cached?
Default |
Details
The full yearly CSV is ~150 MB (about 900,000 transactions). This
function downloads the yearly file, caches it, and then filters in
memory. Memory footprint during the call is roughly 1 GB because R
data frames are considerably larger than the source CSV; on
memory-constrained machines, prefer ukh_ppd_address() for
postcode lookups or ukh_ppd_summary() for aggregated stats.
Subsequent queries against the same year use the cache. For
multi-year queries, call the function once per year or use
ukh_ppd_years().
Value
A data frame of individual transactions with columns
transaction_id, price, date, postcode, property_type,
new_build, tenure, paon, saon, street, locality,
town, district, county, category, record_status.
See Also
Other price paid data:
ukh_ppd_address(),
ukh_ppd_bulk(),
ukh_ppd_summary(),
ukh_ppd_transaction(),
ukh_ppd_years()
Examples
op <- options(ukhousing.cache_dir = tempdir())
try({
# Westminster flats sold in 2024
wm <- ukh_ppd(2024, la = "Westminster", property_type = "flat")
head(wm)
})
options(op)
Look up Price Paid transactions by postcode address
Description
Uses the Land Registry linked data address lookup to find all transactions at a given postcode. Faster than downloading the yearly bulk file when you only want a single postcode.
Usage
ukh_ppd_address(postcode)
Arguments
postcode |
Character. Full UK postcode (e.g. |
Value
A data frame of transactions at addresses matching the postcode.
See Also
Other price paid data:
ukh_ppd(),
ukh_ppd_bulk(),
ukh_ppd_summary(),
ukh_ppd_transaction(),
ukh_ppd_years()
Examples
op <- options(ukhousing.cache_dir = tempdir())
try({
tx <- ukh_ppd_address("SW1A 1AA")
head(tx)
})
options(op)
Download a Price Paid Data bulk file
Description
Downloads and caches a yearly (or the complete) Price Paid Data CSV from HM Land Registry. Returns the path to the cached file. Yearly files are typically 100-200 MB; the complete file (1995-present) is approximately 5.3 GB.
Usage
ukh_ppd_bulk(
year = as.integer(format(Sys.Date(), "%Y")),
full = FALSE,
refresh = FALSE
)
Arguments
year |
Integer. Year to download. Ignored when |
full |
Logical. If |
refresh |
Logical. Re-download even if cached? Default |
Value
Character. The path to the cached CSV file.
See Also
Other price paid data:
ukh_ppd(),
ukh_ppd_address(),
ukh_ppd_summary(),
ukh_ppd_transaction(),
ukh_ppd_years()
Examples
op <- options(ukhousing.cache_dir = tempdir())
try({
path <- ukh_ppd_bulk(2025)
})
options(op)
Price Paid Data summary
Description
Returns summary statistics from Price Paid Data for a given year, aggregated by month, property type, or local authority. Useful when the user wants counts and median prices without loading 150 MB of individual transactions.
Usage
ukh_ppd_summary(
year = as.integer(format(Sys.Date(), "%Y")),
by = c("month", "property_type", "la"),
la = NULL,
refresh = FALSE
)
Arguments
year |
Integer. Year to summarise. |
by |
Character. Aggregation dimension: |
la |
Optional character. Restrict to one local authority. |
refresh |
Logical. Re-download even if cached? Default |
Value
A data frame with one row per group and columns n,
median_price, mean_price, total_value.
See Also
Other price paid data:
ukh_ppd(),
ukh_ppd_address(),
ukh_ppd_bulk(),
ukh_ppd_transaction(),
ukh_ppd_years()
Examples
op <- options(ukhousing.cache_dir = tempdir())
try({
# Monthly transaction counts and medians, nationally
s <- ukh_ppd_summary(2025, by = "month")
head(s)
})
options(op)
Look up a single Price Paid transaction by ID
Description
Fetches the full metadata for one transaction from the Land Registry linked data service by its transaction unique identifier.
Usage
ukh_ppd_transaction(id)
Arguments
id |
Character. A transaction unique identifier (GUID, with or without curly braces). |
Value
A one-row data frame with the transaction fields, or an empty data frame if the transaction is not found.
See Also
Other price paid data:
ukh_ppd(),
ukh_ppd_address(),
ukh_ppd_bulk(),
ukh_ppd_summary(),
ukh_ppd_years()
Examples
op <- options(ukhousing.cache_dir = tempdir())
try({
tx <- ukh_ppd_transaction("{A4C5B0C6-4D5D-47E2-E053-6C04A8C07E7C}")
tx
})
options(op)
Price Paid Data across multiple years
Description
Convenience wrapper that calls ukh_ppd() for each year in a
vector and row-binds the results. Caches each year independently.
Usage
ukh_ppd_years(years, ...)
Arguments
years |
Integer vector. Years to fetch. |
... |
Additional arguments passed to |
Value
A single data frame combining transactions from all requested years.
See Also
Other price paid data:
ukh_ppd(),
ukh_ppd_address(),
ukh_ppd_bulk(),
ukh_ppd_summary(),
ukh_ppd_transaction()
Examples
op <- options(ukhousing.cache_dir = tempdir())
try({
five_year <- ukh_ppd_years(2020:2024, la = "Westminster",
property_type = "flat")
nrow(five_year)
})
options(op)
List valid UK HPI region slugs
Description
Returns a data frame of common UK HPI region slugs with their names,
GSS codes, and tier (country, region, county, or local authority).
Useful for looking up the slug to pass to ukh_hpi().
Usage
ukh_regions(tier = c("all", "country", "region", "county", "la"))
Arguments
tier |
Character. Filter by tier: |
Details
This is a selection of the most commonly used regions, not an
exhaustive list. The UK HPI covers 441+ areas total; any valid slug
can be passed to ukh_hpi() directly.
Value
A data frame with columns slug, name, gss_code, and
tier.
See Also
Other helpers:
ukh_sparql()
Examples
# All regions
head(ukh_regions())
# Just the nine English regions
ukh_regions(tier = "region")
# Country-level series
ukh_regions(tier = "country")
Run a SPARQL query
Description
Runs a SPARQL query against one of the supported endpoints and returns the result as a data frame. Useful for queries that aren't covered by the dedicated helpers, including custom HPI aggregations and Price Paid Data lookups by postcode.
Usage
ukh_sparql(query, endpoint = "land-registry", timeout = 60L)
Arguments
query |
Character. A SPARQL query string. |
endpoint |
Character. |
timeout |
Integer. Request timeout in seconds. Default |
Details
The Land Registry endpoint is free, requires no authentication, and
covers HPI and Price Paid Data. MHCLG's Open Data Communities
endpoint was retired in 2026, so endpoint = "opendatacommunities"
now stops with an error.
Value
A data frame of bindings. Column names match the SELECT variables in the query.
See Also
Other helpers:
ukh_regions()
Examples
op <- options(ukhousing.cache_dir = tempdir())
try({
# All HPI observations for Westminster in January 2020
q <- '
PREFIX ukhpi: <http://landregistry.data.gov.uk/def/ukhpi/>
SELECT ?hpi ?avgPrice WHERE {
<http://landregistry.data.gov.uk/data/ukhpi/region/city-of-westminster/month/2020-01>
ukhpi:housePriceIndex ?hpi ;
ukhpi:averagePrice ?avgPrice .
}'
ukh_sparql(q)
})
options(op)
Transaction volumes for a region
Description
Returns monthly residential transaction counts for a UK region.
This is a thin wrapper over ukh_hpi() that extracts the
sales_volume column with its date. Transaction volumes lag the
headline index by approximately five months because the Land
Registry needs the full transaction set to settle.
Usage
ukh_transactions(region, from = NULL, to = NULL, refresh = FALSE)
Arguments
region |
Character. Region slug, GSS code, or common name. |
from, to |
Optional. Date range (YYYY-MM-DD). |
refresh |
Logical. Re-download? Default |
Value
A data frame with date, region, and sales_volume.
See Also
Other house price index:
ukh_hpi(),
ukh_hpi_compare()
Examples
op <- options(ukhousing.cache_dir = tempdir())
try({
tx <- ukh_transactions("england", from = "2020-01-01")
head(tx)
})
options(op)
Defunct Energy Performance Certificate functions
Description
The Energy Performance Certificate functions were removed in ukhousing 0.2.0. MHCLG retired the EPC Open Data service they wrapped and replaced it with the Get energy performance of buildings data service (https://get-energy-performance-data.communities.gov.uk/), which needs a GOV.UK One Login account and a bearer token, has no per-local-authority bulk files and no property type filter. Every function below now stops with an error.
Usage
ukh_epc_set_key(...)
ukh_epc_search(...)
ukh_epc_certificate(...)
ukh_epc_summary(...)
ukh_epc_bulk(...)
ukh_epc_recommendations_summary(...)
Arguments
... |
Ignored. |
Details
Certificates can be searched and downloaded from the new service directly.
Value
None. Each function signals an error.