Zoopla API

UK property as JSON: live listings, sold prices and the agents behind them

The Zoopla API turns zoopla.co.uk, one of the UK's two big property portals, into clean JSON in seven actions.

no credit card1,000 free credits · instant API key · pay by card or crypto
Missing a Zoopla endpoint, or need a source we don't have yet?Contact us real people · same-day reply.
Z
/zoopla/v1

7 active endpoints, on 0, 1 and 2 credit tiers.

  • POST/zoopla/v1/location_search
  • POST/zoopla/v1/search
  • POST/zoopla/v1/property_detail
  • POST/zoopla/v1/sold_prices
  • POST/zoopla/v1/property_history
  • POST/zoopla/v1/agent
  • POST/zoopla/v1/agent_search

What Zoopla endpoints does ReefAPI ship?

7 live read endpoints. Read-only data API: no writes, no account actions, no dashboard access on the target site.

7 endpoints

location_search

0 cr

Resolve a free-text place, postcode or station into the canonical Zoopla area path every othe…

required
query
optional
section

search

2 cr

Search Zoopla listings in an area.

required
geo
optional
section, page, price_min, price_max, beds_min, beds_max, baths_min, floor_area_min, floor_area_max, property_type, radius, added, keywords, features, new_homes, sort, include_sold, auctions_only, furnished_state, price_frequency, student_only, shared_only, bills_included, available_from, max_rotations

property_detail

2 cr

One Zoopla listing in full.

required
listing_id
optional
max_rotations

sold_prices

2 cr

Zoopla's Land-Registry sold-price register for an area.

required
geo
optional
page, max_rotations

property_history

1 cr

One address by UPRN.

required
uprn
optional
max_rotations

agent

1 cr

One estate-agent branch.

required
branch_id
optional
max_rotations

agent_search

1 cr

The estate or letting agents covering an area, with each branch's average asking price, avera…

required
geo
optional
kind, page, max_rotations

Every parameter, every allowed value →

Zoopla API

4 of 7 endpoints, ready to run

View docs ↗

Zoopla's own listing search: listing id, address, price on a single consistent basis, bedrooms, bathrooms, receptions, floor area in square feet, property type, tenure tags, coordinates, images and the marketing agent. 25 a page.

2 credits1 required · 9 optional
POST/zoopla/v1/search
idle
// Press "Try it" and this pane shows exactly what the
// live site returned this second — including an empty
// result, if that is the truth. No key, no account.

How the Zoopla API works

Zoopla is a normal ReefAPI surface — the same four rules that hold for every other engine on the key.

01
Authenticate
x-api-key header

No OAuth app, no request signing, no per-site account. One key covers all 294 engines.

02
Call
POST /zoopla/v1/…

Every route is a POST with a JSON body. Parameters are validated against the published schema before anything is charged.

03
Pay
0 or 1 or 2 credits per call

Credits, not seats. Failed and blocked calls are never charged, and cache hits cost nothing.

04
Read
{ ok, data, meta, error }

One envelope everywhere. meta carries latency_ms, record_count and the endpoint that answered.

From a place name to a sale history, in four calls

Zoopla's area slugs are inconsistent enough that guessing them wastes calls. Resolving one costs nothing, and from there the live market and the sold register share the same area input.

01location_search
POST/zoopla/v1/location_search
{"query": "Clapham, London"}

Zero credits. Returns the canonical area path, and every candidate when a name is ambiguous. Richmond returns Richmond in Surrey, Richmond in North Yorkshire and Richmond upon Thames.

02search
POST/zoopla/v1/search
{"geo": "sw9", "beds_min": 2, "sort": "newest_listings"}

2 credits for 25 rows. Sorting newest and stopping when you reach ids you already hold is the cheapest way to keep an area current. added=24_hours narrows it further at the source.

03sold_prices
POST/zoopla/v1/sold_prices
{"geo": "sw9"}

2 credits for 25 addresses from the Land-Registry register, newest sale first, each with a UPRN.

04property_history
POST/zoopla/v1/property_history
{"uprn": "<a sold row's uprn>"}

1 credit. Every recorded sale for that address with its price, date and percentage change, plus its past Zoopla listings. No valuation is ever invented.

A current asking-price picture for an area and a verifiable sale history for any address in it, joined on the UPRN the register itself publishes.

request
curl -X POST https://api.reefapi.com/zoopla/v1/search \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"geo":"sw9"}'
response envelope
{
  "ok": true,
  "data": { … },
  "meta": {
    "api": "zoopla",
    "endpoint": "search",
    "mode": "live",
    "latency_ms": …,
    "record_count": …
  },
  "error": null
}

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 wantWhat Zoopla serves logged outAPI fields
Asking price or rentThe capital price, or the rent on the monthly basis Zoopla displays, whatever basis the agent quotedprice, price_display, price_frequency, price_quoted, price_quoted_frequency
Price reductionHow big the cut was and when it last happened, never the old priceprice_drop.percent, price_drop.last_reduced, price_changes[].date
Sold historyEvery Land-Registry sale with its price, date and percentage changesales[].price, sales[].date, sales[].change_pct
Zoopla's own estimateOnly that one exists and when it was refreshed; the number itself needs a signed-in ownerhas_sale_estimate, estimate_updated_at, and never a value
Floor areaSquare feet on a listing, square metres on the sold register, not converted between themfloor_area_sqft, floor_area_sqm
Service charge, ground rent, council taxOnly when the agent supplied them; Ask agent comes back as nullservice_charge, ground_rent, council_tax_band
The agentName, agency, branch, memberships and performance statistics; the direct phone number is off by defaultagent.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.

Great Britain, five markets, and the price basis that changes row by row

Measured 2026-09-24: 126 of 126 calls succeeded across the seven actions, over 1,363 search rows, 32 detail records, 100 sold-register rows, 75 agent rows and 12 address histories. Four of these lines go against us.

Great Britain, in GBP, across 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, per-address sale history and the estate-agent directory. Commercial rows carry a floor-area range instead of a bedroom count, which is why bedrooms are zero per cent on them in every area.

Against us: the rent basis changes row by row and the card never says so

A search card's raw figure is in the agent's own quoted frequency. Three measured lettings quoted 1,700 per month, 508 per week and 40,000 per annum, and all three display as a monthly figure. price is therefore always the monthly number for a letting and the capital price for a sale, price_quoted keeps the agent's raw figure and price_quoted_frequency names the basis. When nothing matches it comes back null rather than guessed, and Non quoting or POA listings return null prices rather than zero, on 26 of 1,363 rows.

You do not need Zoopla's area codes, and guessing them does not work

Leeds is west-yorkshire/leeds while Liverpool is plain liverpool. Pass a name, a postcode or a full URL as geo and it is resolved, with the path used returned as area and the resolution source alongside it. location_search costs nothing and returns every candidate for an ambiguous name.

A wrong area is an HTTP 200 with no rows, and it is caught

Zoopla answers a wrong area path with 200 and an empty page, in two different shapes, which is the easiest way for a property feed to look healthy and be empty. Both become NOT_FOUND here, after the name has been resolved once. A genuinely empty filtered search stays a success with a count of zero, so a bad path and a narrow filter are not confused.

An unknown filter value is accepted upstream and quietly ignored

A mistyped property type or feature returns the unfiltered market with no signal at all, and several filter names that read plausibly are not Zoopla filters and change nothing. Every enum is therefore validated before the call and a bad value is rejected with the accepted list. The published filters were each proven to narrow against the same area's unfiltered total in the same run.

Against us: no price estimate and no previous asking price

Zoopla's own valuation is behind a signed-in owner, so property_history returns has_sale_estimate and estimate_updated_at and never a number. A reduced listing publishes how big the cut was and when, never the old price. Broadband speed, mobile coverage and parking read Ask agent on most listings and come back null.

Against us: paging stops at 40 pages and the counter is capped

25 listings a page and no deeper than page 40. Both limits are Zoopla's own, and the response reports them in total_results, total_results_capped and page_cap rather than pretending otherwise. Narrow the area or add a filter to reach deeper stock.

Against us: the sparse fields are sparse at the source

Across 1,363 rows: floor area 81 per cent, tenure tags 77, bathrooms 74, receptions 63. A card with no bath icon has no published bathroom count and comes back null rather than zero. A London search sorted cheapest first drops to 52 per cent on bedrooms because the cheapest London listings are land and parking spaces, which is correct. Lettings agents fill in less than sale agents in every area measured.

Business facts always, a direct phone number only on request

The agent's name, agency, branch address, website, memberships, opening times and published performance statistics come back on every call. A direct telephone number is personal contact data and is off by default; opt in with include_pii if your use requires it.

Price

location_search is free. search, property_detail and sold_prices are 2 credits each; property_history, agent and agent_search are 1. A 25-row page and a single record cost the same at each tier, so ask for the page.

What people build with Zoopla

The jobs this data is most often used for.

7

endpoints

0/1/2

credits per call

01

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.

02

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.

03

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.

04

Monitor agents: agent_search gives every branch covering an area with its average asking price, weeks on market and live listing count.

What Zoopla data costs

The cheapest call here is 0 credits, so $15/mo (Pro) buys 10,000 of them — $1.50 per 1,000 credits. Credits roll over and never expire, and failed or blocked calls are not charged.

Full pricing →
$0.67–$1.50 / 1,000 credits
  • 1,000 free credits on signup, no card
  • One key, all 294 APIs, one credit pool
  • Failed and blocked calls are never charged
  • Credits roll over and never expire

Call it in two lines

Sign up, get 1,000 credits and one key that works on every engine. Then this is the whole protocol.

curl
curl -X POST https://api.reefapi.com/zoopla/v1/search \
  -H "x-api-key: $REEF_KEY" \
  -H "content-type: application/json" \
  -d '{"geo":"sw9"}'
python
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"])
FAQ

Have a question? We got answers.

The questions people actually ask before wiring up Zoopla.

Get a free key →
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.

16 Real Estate APIs on the same key

One key, one credit pool, one response envelope. If you are pulling Zoopla, you are one call away from the rest of the category — no second contract, no second integration.

Already paying for something else?Zoopla vs Bright Data

Need something this API does not do?

Name the endpoint, the field, or a source we do not carry yet. We ship new APIs every week and you would be first to get the key. Real people read every message and reply the same day.

0/4000

No account needed · we reply from [email protected]

Try it on your own data before you pay anything

The call above is the real endpoint, not a recording. A free key gives you 1,000 credits, the other 293 APIs, and the same envelope everywhere.

Endpoints, parameters and credit costs on this page are read from the live catalog and cannot drift from what the API accepts. Field notes were captured on 2026-09-24.