Code Examples
Copy-paste examples for Python, JavaScript, and PHP. Drop them into your project and make your first API call in minutes — no dependencies, no setup.
Copy-paste or download. All three clients are single-file wrappers — drop them straight into your project with zero build step. npm and PyPI packages planned.
All clients target the V1 API (https://api.homedata.co.uk/api) with namespaced resources, typed errors, and rate-limit tracking built in.
Zero to first call
The fastest way to make your first API call — no wrapper, no installation. All you need is your API key and the language you already know.
Requires requests.
Install with pip install requests.
import requests API_KEY = "your_api_key_here" UPRN = "100023336956" # get UPRNs via /api/address/find response = requests.get( f"https://api.homedata.co.uk/api/properties/{UPRN}", headers={"Authorization": f"Api-Key {API_KEY}"}, ) data = response.json() print(data["address"], data["bedrooms"], "bed", data["property_type"])
# Step 1: resolve address → UPRN (API key required) resp = requests.get( "https://api.homedata.co.uk/api/address/find", headers={"Authorization": f"Api-Key {API_KEY}"}, params={"q": "10 Downing Street London"}, ) suggestions = resp.json()["data"] uprn = suggestions[0]["uprn"]
Full client libraries
Complete wrappers with all 8 V1 resource namespaces. Copy the single file directly into your project — no build step, no dependencies beyond your language's HTTP library. npm and PyPI packages planned.
Python Client
Requires Python 3.9+ and the requests library.
PyPI package planned
pip install homedata is not yet available. Copy the class below instead — save it as homedata.py and import it directly. One file, no build step.
"""Homedata V1 API client — namespaced resources, zero deps beyond requests.""" import requests BASE_URL = "https://api.homedata.co.uk/api" class HomedataError(Exception): def __init__(self, message: str, status: int, code: str): super().__init__(message) self.status = status self.code = code class _Resource: def __init__(self, client): self._client = client def _get(self, path: str, params: dict = None) -> dict: return self._client._request(path, params) class AddressResource(_Resource): """Address search and UPRN retrieve.""" def find(self, query: str, limit: int = 20) -> list: resp = self._get("/address/find", {"q": query, "limit": limit}) return resp.get("data", resp) def retrieve(self, uprn: int) -> dict: resp = self._get(f"/address/retrieve/{uprn}") return resp.get("data", resp) class PropertiesResource(_Resource): def search(self, postcode: str, page: int = 1) -> list: resp = self._get("/properties", {"postcode": postcode, "page": page}) return resp.get("data", resp) def get(self, uprn: int) -> dict: resp = self._get(f"/properties/{uprn}") return resp.get("data", resp) class ValuationsResource(_Resource): def estimate(self, uprn: int, type: str = "sale") -> dict: return self._get("/valuations/estimate/", {"uprn": uprn, "type": type}) class SchoolsResource(_Resource): def nearby(self, postcode: str = None, lat: float = None, lng: float = None, radius: float = 0.5, limit: int = 20, phase: str = None) -> list: params = {"radius": radius, "limit": limit} if postcode: params["postcode"] = postcode if lat: params["lat"] = lat if lng: params["lng"] = lng if phase: params["phase"] = phase resp = self._get("/schools/nearby", params) return resp.get("schools", resp) class BroadbandResource(_Resource): def get(self, postcode: str) -> dict: return self._get("/broadband", {"postcode": postcode}) class DemographicsResource(_Resource): def area(self, postcode: str = None, lat: float = None, lng: float = None) -> dict: params = {} if postcode: params["postcode"] = postcode if lat: params["lat"] = lat if lng: params["lng"] = lng return self._get("/demographics", params) class PriceGrowthResource(_Resource): def get(self, outcode: str) -> dict: return self._get(f"/price-growth/{outcode}") class PostcodeProfileResource(_Resource): def get(self, postcode: str) -> dict: return self._get("/postcode-profile", {"postcode": postcode}) class Homedata: """Homedata V1 API client. Usage: client = Homedata("hd_your_api_key") results = client.address.find("10 Downing Street") prop = client.properties.get(100023336956) schools = client.schools.nearby(postcode="SW1A 2AA") """ def __init__(self, api_key: str, base_url: str = BASE_URL, timeout: int = 30): if not api_key: raise ValueError("API key required — get one at homedata.co.uk/register") self._base_url = base_url.rstrip("/") self._timeout = timeout self._session = requests.Session() self._session.headers.update({ "Authorization": f"Api-Key {api_key}", "Accept": "application/json", }) self.rate_limit = {"limit": 0, "remaining": 0, "reset": 0} # Resource namespaces self.address = AddressResource(self) self.properties = PropertiesResource(self) self.valuations = ValuationsResource(self) self.schools = SchoolsResource(self) self.broadband = BroadbandResource(self) self.demographics = DemographicsResource(self) self.price_growth = PriceGrowthResource(self) self.postcode_profile = PostcodeProfileResource(self) def _request(self, path: str, params: dict = None) -> dict: url = f"{self._base_url}{path}" clean = {k: v for k, v in (params or {}).items() if v is not None} resp = self._session.get(url, params=clean, timeout=self._timeout) self.rate_limit = { "limit": int(resp.headers.get("X-RateLimit-Limit", 0)), "remaining": int(resp.headers.get("X-RateLimit-Remaining", 0)), "reset": int(resp.headers.get("X-RateLimit-Reset", 0)), } if not resp.ok: body = resp.json() if resp.content else {} err = body.get("error", {}) raise HomedataError( err.get("message", f"HTTP {resp.status_code}"), resp.status_code, err.get("code", "UNKNOWN"), ) return resp.json()
Usage Examples
from homedata import Homedata, HomedataError client = Homedata("hd_your_api_key") # Address search results = client.address.find("10 Downing Street") for addr in results: print(f"{addr['address']}, {addr['postcode']} — UPRN: {addr['uprn']}") # Full property record by UPRN prop = client.properties.get(100023336956) print(f"Type: {prop['property_type']}, Beds: {prop['bedrooms']}, EPC: {prop['epc_rating']}") # Automated valuation val = client.valuations.estimate(100023336956, type="sale") print(f"Estimate: £{val['estimate']:,} ({val['confidence']} confidence)") # Nearby schools schools = client.schools.nearby(postcode="SW1A 2AA", phase="Primary") for s in schools: print(f"{s['name']} — Ofsted: {s['ofsted']['rating']}, {s['distance_miles']:.1f}mi") # Rate limit tracking print(f"{client.rate_limit['remaining']}/{client.rate_limit['limit']} calls remaining") # Error handling try: prop = client.properties.get(999) except HomedataError as e: print(f"Error {e.status}: {e.code}")
# Get properties from a postcode + enrich each one from homedata import Homedata import time client = Homedata("hd_your_api_key") # Search properties at a postcode properties = client.properties.search("SW1A 2AA") for summary in properties[:5]: uprn = summary["uprn"] prop = client.properties.get(uprn) val = client.valuations.estimate(uprn) print(f"{prop['address']} — EPC: {prop.get('epc_rating', 'N/A')}, AVM: £{val.get('estimate', 0):,}") time.sleep(0.1) # respect rate limits # Full area profile in one call profile = client.postcode_profile.get("SW1A 2AA") print(profile.keys()) # deprivation, broadband, schools, transport, prices
Library Features
| Feature | Python | JavaScript | PHP |
|---|---|---|---|
| 8 V1 resource namespaces | ✓ | ✓ | ✓ |
| TypeScript types | — | ✓ | — |
| Typed error handling | ✓ | ✓ | ✓ |
| Rate limit tracking | ✓ | ✓ | ✓ |
| Zero external dependencies | requests | ✓ | ✓ |
| Configurable timeout | ✓ | ✓ | ✓ |
| Package manager install | pip (soon) | npm (soon) | — |
| Single file, copy-paste | ✓ | ✓ | ✓ |
Using Claude, Cursor, or Windsurf?
Skip the wrapper code entirely — our MCP server gives your AI tool direct access to all 16 endpoints. One config block, no code.
Prefer raw HTTP?
These wrappers are optional. The API is standard REST — any HTTP client works. See the Getting Started guide for cURL examples, or use the Interactive API Explorer to test endpoints in your browser.
Integrate into your own product
Free to startThe Homedata Python, JavaScript, and PHP clients are single-file wrappers with zero build steps — covering address lookup, property intelligence, EPC, risks, comparables, and live listings across 29M UK properties with typed errors and rate-limit tracking built in.
Structured as JSON · queryable by UPRN or postcode · ready to embed in any application
Exact measurements
Real values — distances, concentrations, counts — not rounded ratings
29M+ UK properties
Every address queryable by UPRN or postcode
REST API
JSON responses, OpenAPI docs, sandbox — first call in under 5 minutes
Free tier: 100 API calls/month across all endpoints, no credit card required. Paid plans from £29/month for production use. Compare plans →
Sources
Further reading
Getting Started · All endpoints · MCP Server for AI tools · Error codes