Zoopla API & Scraper
The Zoopla API turns zoopla.co.uk, one of the UK's two big property portals, into clean JSON in seven actions.
🤖 Using an AI assistant? Copy this link into ChatGPT / Claude / Cursor — it reads every endpoint and parameter instantly and tells you if this API fits your use case.
location_search takes a place name, postcode or station and returns the area path the other actions take, together with every candidate when the name is ambiguous. Zoopla's own slugs are not guessable, Leeds being west-yorkshire/leeds while Liverpool is plain liverpool, so a plain name is resolved for you and the path actually used comes back in the response. search runs Zoopla's own listing search over homes for sale, homes to rent, new-build developments, or commercial property for sale or to let, 25 listings a page, with the filters the site itself exposes: price band, minimum and maximum bedrooms, minimum bathrooms, property type, floor-area band, search radius in miles, listed-within, a free-text keyword, features such as a garden or parking, sold and auction inclusion, and five sort orders. Every row carries the listing id, address, price, bedrooms, bathrooms, receptions, floor area in square feet, property type, tenure tags, coordinates, images and the marketing agent. Rent is always returned on a monthly basis, whatever basis the agent quoted: a commercial letting advertised at 40,000 pounds a year and a flat advertised at 508 pounds a week both come back with the monthly figure in price, the agent's own number in price_quoted and the basis they used in price_quoted_frequency, so the column you sort on always means the same thing. property_detail returns one listing in full: description, key features, tenure, service charge, ground rent, council tax band, EPC rating and certificate, floorplans, every photograph, the nearest stations with their distances, the postcode and the branch. sold_prices pages Zoopla's Land-Registry register for an area, with address, UPRN, last sale date and price, beds, baths, receptions, tenure and floor area in square metres, and property_history takes one UPRN and returns every recorded sale with its percentage change plus the property's past Zoopla listings. agent and agent_search cover the estate and letting agents: a branch's address, memberships, opening times, its own average asking price and weeks on market, and its live stock. In a live check on 2026-09-24, 126 of 126 calls across the seven actions succeeded, and on 20 listings compared against Zoopla's own page the price, bedrooms, property type and coordinates matched on 20 of 20. Prices are GBP. No Zoopla account, no browser, one ReefAPI key and the standard { ok, data, meta, error } envelope.
Zoopla publishes some things and withholds others, and the difference stays visible
A property portal shows a lot and estimates more. These are the fields callers ask about most, and what Zoopla actually serves to a logged-out reader. Measured 2026-09-24 over 1,363 search rows, 32 detail records, 100 sold-register rows and 12 address histories.
| What you want | What Zoopla serves logged out | API fields |
|---|---|---|
| Asking price or rent | The capital price, or the rent on the monthly basis Zoopla displays, whatever basis the agent quoted | price, price_display, price_frequency, price_quoted, price_quoted_frequency |
| Price reduction | How big the cut was and when it last happened, never the old price | price_drop.percent, price_drop.last_reduced, price_changes[].date |
| Sold history | Every Land-Registry sale with its price, date and percentage change | sales[].price, sales[].date, sales[].change_pct |
| Zoopla's own estimate | Only that one exists and when it was refreshed; the number itself needs a signed-in owner | has_sale_estimate, estimate_updated_at, and never a value |
| Floor area | Square feet on a listing, square metres on the sold register, not converted between them | floor_area_sqft, floor_area_sqm |
| Service charge, ground rent, council tax | Only when the agent supplied them; Ask agent comes back as null | service_charge, ground_rent, council_tax_band |
| The agent | Name, agency, branch, memberships and performance statistics; the direct phone number is off by default | agent.name, agent.branch_id, stats.for_sale.average_price, agent.phone with include_pii |
Fill rates follow the source rather than the parser. Bedrooms sit at 73 per cent across all sections because commercial cards carry none by definition, and a London search sorted cheapest first drops to 52 per cent because the cheapest London listings are land and parking spaces. Commercial rows are zero per cent on bedrooms, bathrooms and receptions in every area, which is correct.
Real request and response JSON
Captured from the indexed primary action, search, on .
{
"method": "POST",
"url": "https://api.reefapi.com/zoopla/v1/search",
"headers": {
"x-api-key": "$REEF_KEY",
"content-type": "application/json"
},
"body": {
"geo": "sw9"
}
}{
"ok": true,
"meta": {
"api": "zoopla",
"endpoint": "search",
"mode": "live",
"latency_ms": 664.7,
"record_count": 25,
"bytes": 219626,
"cache_hit": false,
"pagination": {
"page": 1,
"page_size": 25,
"total": 402,
"has_more": true
},
"charged_credits": 2,
"version": "1.0.0"
},
"data": {
"area": "sw9",
"area_name": "SW9",
"area_resolved_from": null,
"section": "for_sale",
"listings": [
{
"listing_id": "74343941",
"section": "for_sale",
"url": "https://www.zoopla.co.uk/for-sale/details/74343941/",
"title": "1 bed flat for sale",
"address": "Lidcote House, 35 Robsart Street, London SW9",
"summary": "This well-presented one-bedroom apartment offering approximately 540 sq ft of thoughtfully arranged accommodation, with a private terrace and a ...",
"price": 365000,
"price_display": "£365,000",
"price_frequency": null,
"price_quoted": 365000,
"price_quoted_frequency": null,
"price_per_week": null,
"price_per_week_display": null,
"price_qualifier": null,
"currency": "GBP",
"price_drop": null,
"property_type": "flat",
"bedrooms": 1,
"bathrooms": 1,
"receptions": 1,
"floor_area_sqft": 540,
"floor_area_sqft_max": null,
"floor_area_source": "structured_data",
"tenure_tags": [
"Leasehold"
],
"status": "Just added",
"under_offer": false,
"listed_on": "25th Sep 2026",
"listed_on_label": "Listed on",
"available_from": null,
"latitude": 51.470508,
"longitude": -0.114967,
"image": "https://lid.zoocdn.com/645/430/06c92561c6e4fed0e4c87ce0bbef4292cfa97e19.jpg",
"images": [
"https://lid.zoocdn.com/u/1024/768/7cbde4fe04cfda698ae3060e9ae003f7b67b44b9.jpg",
"https://lid.zoocdn.com/u/1024/768/68a9438073af32e774d26f5a3d0b0c46eaafa4f5.jpg",
"https://lid.zoocdn.com/u/1024/768/8c2c479a241e07c78a0c477c62cc611de57133f8.jpg"
],
"image_count": 8,
"floorplan_count": 1,
"video_count": 0,
"listing_class": "regular",
"is_premium": false,
"agent": {
"branch_id": 162870,
"name": "SOWN - Shared Ownership",
"profile_url": "https://www.zoopla.co.uk/find-agents/branch/sown-shared-ownership-camberley-162870/",
"logo_url": "https://st.zoocdn.com/zoopla_static_agent_logo_(766305).png",
"phone": "[redacted-phone]"
}
},
{
"listing_id": "74340838",
"section": "for_sale",
"url": "https://www.zoopla.co.uk/for-sale/details/74340838/",
"title": "Studio for sale",
"address": "Robsart Street, Vassall SW9",
"summary": "This Amazing Penthouse flat has breath-taking panoramic views across the London Iconic Skyline stunning landmarks covering from the City Canary ...",
"price": 650000,
"price_display": "£650,000",
"price_frequency": null,
"price_quoted": 650000,
"price_quoted_frequency": null,
"price_per_week": null,
"price_per_week_display": null,
"price_qualifier": null,
"currency": "GBP",
"price_drop": null,
"property_type": "studio",
"bedrooms": null,
"bathrooms": null,
"receptions": null,
"floor_area_sqft": null,
"floor_area_sqft_max": null,
"floor_area_source": null,
"tenure_tags": [
"Leasehold"
],
"status": "Just added",
"under_offer": false,
"listed_on": "25th Sep 2026",
"listed_on_label": "Listed on",
"available_from": null,
"latitude": 51.470204,
"longitude": -0.114748,
"image": "https://lid.zoocdn.com/645/430/2bb742b9a5e792c25a4cda8f59c9eccab7161fce.jpg",
"images": [
"https://lid.zoocdn.com/u/1024/768/cd873fd8cf566ea70218356fa98ce779862bf444.jpg",
"https://lid.zoocdn.com/u/1024/768/e45b412bdd1af40e0a306dc23895f665feb63e50.jpg",
"https://lid.zoocdn.com/u/1024/768/1112439f9c683a933278696907b0582f409b7b7c.jpg"
],
"image_count": 19,
"floorplan_count": 1,
"video_count": 1,
"listing_class": "regular",
"is_premium": false,
"agent": {
"branch_id": 18062,
"name": "Chestertons - Battersea Rise",
"profile_url": "https://www.zoopla.co.uk/find-agents/branch/chestertons-battersea-rise-battersea-18062/",
"logo_url": "https://st.zoocdn.com/zoopla_static_agent_logo_(253788).png",
"phone": "[redacted-phone]"
}
},
{
"listing_id": "74340622",
"section": "for_sale",
"url": "https://www.zoopla.co.uk/for-sale/details/74340622/",
"title": "2 bed flat for sale",
"address": "Burton Road, Oval SW9",
"summary": "A two bedroom apartment just moments from Myatt's Field Park, offering a bright and contemporary living space in an excellent location. The ...",
"price": 450000,
"price_display": "£450,000",
"price_frequency": null,
"price_quoted": 450000,
"price_quoted_frequency": null,
"price_per_week": null,
"price_per_week_display": null,
"price_qualifier": null,
"currency": "GBP",
"price_drop": null,
"property_type": "flat",
"bedrooms": 2,
"bathrooms": 1,
"receptions": 1,
"floor_area_sqft": 592,
"floor_area_sqft_max": null,
"floor_area_source": "comparables_epc",
"tenure_tags": [
"Chain free"
],
"status": "Just added",
"under_offer": false,
"listed_on": "25th Sep 2026",
"listed_on_label": "Listed on",
"available_from": null,
"latitude": 51.471575,
"longitude": -0.105481,
"image": "https://lid.zoocdn.com/645/430/f7b5c646934edad480137a834cb74ecfe1298a85.jpg",
"images": [
"https://lid.zoocdn.com/u/1024/768/5897c4e1f66ecfa3149df9f692fcff869c716ead.jpg",
"https://lid.zoocdn.com/u/1024/768/c1107962b50c7e684997ee45d5247837b9a19bd2.jpg",
"https://lid.zoocdn.com/u/1024/768/351263ac879378ee0edbf3d763d43709f784c095.jpg"
],
"image_count": 7,
"floorplan_count": 1,
"video_count": 0,
"listing_class": "regular",
"is_premium": false,
"agent": {
"branch_id": 121206,
"name": "Marsh & Parsons - Kennington",
"profile_url": "https://www.zoopla.co.uk/find-agents/branch/marsh-and-parsons-kennington-london-121206/",
"logo_url": "https://st.zoocdn.com/zoopla_static_agent_logo_(774069).png",
"phone": "[redacted-phone]"
}
}
],
"featured": [],
"count": 25,
"total_results": 402,
"total_results_capped": false,
"page": 1,
"page_size": 25,
"page_cap": 17,
"has_more": true,
"filters_applied": {
"area_name": "SW9",
"outcode": "SW9",
"region_name": "London",
"section": "for-sale"
},
"search_url": "https://www.zoopla.co.uk/for-sale/property/sw9/"
}
}What the Zoopla API does
| Action | Description | Concrete use case | Key params |
|---|---|---|---|
| location_search | Resolve a free-text place, postcode or station into the canonical Zoopla area path every other action takes. An unambiguous name returns one match; an ambiguous one ('Richmond', 'Kingston') returns every candidate Zoopla offers. | Real-estate investors call location_search to resolve a free-text place, postcode or station into the canonical Zoopla area path every othe…. | query, section |
| search | Search Zoopla listings in an area — homes for sale, homes to rent, new-build developments, or commercial property for sale or to rent — with the filters the site itself exposes: price band, minimum/maximum beds, minimum baths, property type, floor-area band, search radius, listed-within, free-text keyword, features, sold/auction inclusion and sort order. 25 listings a page. | Brokerage tools call search to search Zoopla listings in an area. | geo, section, page, price_min, price_max, ... |
| property_detail | One Zoopla listing in full: price (rent in both frequencies), full description, key features, tenure, service charge, ground rent, council tax band, EPC rating and certificate, floorplans, every image, nearest stations with distances, coordinates, postcode and the marketing agent. | Property dashboards call property_detail to get one Zoopla listing in full. | listing_id, max_rotations |
| sold_prices | Zoopla's Land-Registry sold-price register for an area: every recorded address with its UPRN, last sale date and price, bedrooms, bathrooms, receptions, tenure and floor area in square metres. 25 addresses a page, newest sale first. | Lead-generation teams call sold_prices to get zoopla's Land-Registry sold-price register for an area. | geo, page, max_rotations |
| property_history | One address by UPRN: every sale Zoopla holds from the Land Registry with its price, date and percentage change, plus the property's own past Zoopla listings with their asking prices, photos and floorplans, its EPC rating, tenure and floor area. | Real-estate investors call property_history to get one address by UPRN. | uprn, max_rotations |
| agent | One estate-agent branch: address, memberships, opening times, website, its own for-sale and to-rent averages and weeks-on-market, and the properties it currently has listed on Zoopla. A new-homes branch id resolves to the housebuilder's development instead (kind='developer'): its price and bedroom range, its plots and the schools, stations and shops Zoopla lists nearby. | Brokerage tools call agent to get one estate-agent branch. | branch_id, max_rotations |
| agent_search | The estate or letting agents covering an area, with each branch's average asking price, average weeks on market and live listing count. | Property dashboards call agent_search to get the estate or letting agents covering an area, with each branch's average asking price, avera…. | geo, kind, page, max_rotations |
Call search from your stack
curl -X POST https://api.reefapi.com/zoopla/v1/search \
-H "x-api-key: $REEF_KEY" \
-H "content-type: application/json" \
-d '{"geo":"sw9"}'import requests
r = requests.post(
"https://api.reefapi.com/zoopla/v1/search",
headers={"x-api-key": REEF_KEY},
json={
"geo": "sw9"
},
)
print(r.json()["data"])const res = await fetch("https://api.reefapi.com/zoopla/v1/search", {
method: "POST",
headers: {
"x-api-key": process.env.REEF_KEY,
"content-type": "application/json",
},
body: JSON.stringify({
"geo": "sw9"
}),
});
const { ok, data, meta, error } = await res.json();Ask your MCP-connected assistant: call reefapi.zoopla.search with {"geo":"sw9"}.Who uses this API and why
- Track a local market: page a postcode's for-sale listings each morning and flag new instructions, price reductions and the ones that went under offer.
- Value a property: pull the Land-Registry sale history for an address by UPRN, then pull comparable live listings in the same postcode with the same bedroom count.
- Build a rental yield model from to-rent rows, which carry monthly and weekly rent with floor area and coordinates, against for-sale prices in the same area.
- Monitor agents: agent_search gives every branch covering an area with its average asking price, weeks on market and live listing count.
- Watch commercial stock across offices, retail premises, industrial sites, hospitality and land, with each listing's floor-area range.
Questions developers ask before integrating
Do I need to know Zoopla's area codes?
No. Pass a place name, a postcode or a full Zoopla URL as geo and it is resolved for you, with the path that was used returned as area. Zoopla's slugs are genuinely inconsistent, Leeds being west-yorkshire/leeds and Liverpool plain liverpool, so guessing them is not worth anyone's time. When a name is ambiguous, location_search returns every candidate: Richmond gives Richmond in Surrey, Richmond in North Yorkshire and Richmond upon Thames. location_search costs nothing.
How many Zoopla results can I page through?
25 a page, up to page 40. Zoopla caps both its own result counter and its paging, and the response says so in total_results, total_results_capped and page_cap rather than pretending otherwise. Narrow the area or add a filter to reach deeper stock.
Does the API give me Zoopla's price estimate for a home?
No, because Zoopla does not give it to a logged-out reader. property_history tells you an estimate exists and when it was last refreshed, and returns every actual Land-Registry sale with its price and date. It never invents a valuation.
Can I get the estate agent's phone number?
The agent's name, agency, branch address, website, memberships, opening times and published statistics come back on every call, because those are business facts. A direct telephone number is personal contact data and is off by default; opt in with include_pii if your use requires it.
What is covered, and is commercial property included?
Yes. Five markets: homes for sale, homes to rent, new-build developments, and commercial property for sale or to let, plus the Land-Registry sold-price register and the agent directory, all for Great Britain. Commercial searches take their own property types, offices, retail premises, industrial sites, hospitality and land, and return a floor-area range instead of a bedroom count.
Is a Zoopla rent figure weekly or monthly?
Monthly, always, whatever the agent quoted. This is the one place the source can quietly hand you the wrong number: a card's raw figure is in the agent's own frequency and the card never names that frequency. Three measured lettings quoted 1,700 per month, 508 per week and 40,000 per annum, all displayed as a monthly figure. price is the monthly number, price_quoted keeps the agent's raw figure and price_quoted_frequency names the basis. When nothing matches, the frequency comes back null rather than guessed, and a listing marked Non quoting or POA returns null prices rather than zero.
What happens if I pass an area Zoopla does not have?
You get NOT_FOUND, after the name has been resolved once. That matters because Zoopla answers a wrong area path with HTTP 200 and an empty page, in two different shapes, which is the easiest way for a property feed to look healthy and be empty. A genuinely empty filtered search is different and stays a success with a count of zero, so you can tell a bad path from a narrow filter.
What is the Zoopla API?
Zoopla API is a ReefAPI endpoint group for uk property: homes and commercial for sale and to rent, full listing detail, land-registry sold prices and estate agents. It returns live JSON through POST requests under /zoopla/v1.
Is the Zoopla API free to try?
Yes. ReefAPI starts with 1,000 free credits, no card required. Zoopla calls use the same shared credit balance as every other ReefAPI engine.
Do I need a Zoopla login or account?
No login to Zoopla is needed for the API response. You call ReefAPI with your x-api-key header, and the playground can run live examples before you create a production key.
How fresh is the Zoopla data?
The page example is captured from a live location_search call, and production requests fetch live data through ReefAPI rather than a static sample.
How many credits does the Zoopla API use?
Zoopla actions currently cost 1-2 credits per successful call. Failed or blocked calls are free. All APIs draw from one credit pool.
Can I call Zoopla from an AI assistant or MCP client?
Yes. Connect ReefAPI once through MCP and your assistant can call zoopla actions with the same key, credit pool and JSON envelope used by normal REST requests.
Is the Zoopla API a Zoopla scraper?
It is the managed alternative to a DIY Zoopla scraper. Instead of building and maintaining your own scraper — proxies, headless browsers, captcha and constant breakage — you call one ReefAPI endpoint and get the same uk property: homes and commercial for sale and to rent, full listing detail, land-registry sold prices and estate agents back as clean JSON.