Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Short answer: you cannot use a current public Zoopla listings API to scrape property pages. Zoopla’s official developer information says, “The Zoopla listings API is no longer publicly available.” Its Terms of Use also prohibit text or data mining and web scraping. If you need Zoopla data, request an authorised commercial feed, obtain the terms in writing, and build against the endpoint and limits Zoopla supplies.

The code below is a contract-first client template, not a way to bypass Zoopla’s controls. It becomes usable only after Zoopla gives you an approved base URL, credentials, fields, pagination rules and permission to store or redistribute the response.

Is there a public Zoopla listings API?

Not according to Zoopla’s current developer position as of 30 September 2026. The official developer portal states that “The Zoopla listings API is no longer publicly available.” Commercial users are directed to contact Zoopla to discuss data availability and possible listings API access.

That statement supersedes old blog posts, GitHub wrappers and tutorials that show API keys, listing-search endpoints or free quotas. Those materials describe a historical service; they do not establish that an endpoint, credential, quota or permission still exists.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Why a public-site scraper is not a compliant substitute

Zoopla’s Terms of Use say: “You shall not conduct, facilitate, authorise or permit any text or data mining or web scraping in relation to our Site.” The same section gives examples including a robot, bot, spider, scraper, automated device, program, tool, algorithm, code, process or methodology. The terms also state that site content may not be used for commercial purposes without a licence from Zoopla.

Rotating proxies, browser automation, CAPTCHA-solving services and generic scraping libraries change how requests are sent; they do not create permission to copy the site. Using them against public listing pages can breach the terms even when a page loads successfully. Do not present them as an API-access strategy.

What Zoopla documents today

The currently documented catalogue is aimed at members and business workflows rather than an open listing-search feed. Zoopla Member Support lists:

  • Authentication
  • Leads API
  • Push Delivery Service
  • Premium Listings
  • Featured Properties (weekly)

For example, the premium-listings documentation describes member operations such as a POST request to activate a premium listing for a supplied listing ID, followed by authenticated status or update operations. That is a product integration for authorised members, not an invitation to harvest every public property page.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How to request authorised Zoopla data

  1. Define the use case. State whether you need internal analytics, lead routing, valuation research or a customer-facing product. Identify whether you need sale listings, rentals, sold-price information, agent fields or another dataset.
  2. Describe the data envelope. Give Zoopla your geography, fields, expected record volume, refresh interval, historical depth and retention period. Say whether data will be shown to customers, supplied to another business or used only internally.
  3. Use Zoopla’s official business or developer route. Ask whether a listings feed is available for your use case and request the current technical documentation and commercial terms.
  4. Get the permission in writing. Confirm the permitted use, geography, fields, refresh frequency, retention, redistribution, authentication method, endpoint host, pagination, rate limits, pricing, support process and termination or deletion requirements.
  5. Test a small authorised integration. Start with a low-volume account or sandbox if Zoopla provides one. Record the contract version, credentials owner, request identifiers and response errors.
  6. Operationalise the feed. Keep secrets on the server, enforce the published limits, validate every response, preserve the source timestamp and implement the agreed deletion and retention rules.

Questions to settle before writing production code

Area Ask Zoopla to confirm
Permission Which applications and users may access the data, and is redistribution allowed?
Coverage Sale, rental, sold-price and agent fields; geographic boundaries; listing types and exclusions.
Freshness Update latency, change notifications, delisted-property handling and historical availability.
Transport Base URL, HTTP methods, authentication scheme, TLS requirements and request-id conventions.
Limits Page size, pagination cursor, rate limits, burst behaviour, maximum response size and retry guidance.
Storage Retention period, backup rules, deletion requests and whether derived analytics may be kept.
Commercial terms Price, billing metric, support hours, liability, suspension rules and termination procedure.

Build a client only after the contract supplies an endpoint

Because no public listing endpoint is available, a truthful example must leave the host and field names supplied by your agreement. The following Python client is runnable after you set those contract-specific values. It deliberately does not fetch Zoopla’s public pages.

Python template

import os
import time
import requests

BASE_URL = os.environ["ZOOPLA_AUTHORIZED_BASE_URL"]
TOKEN = os.environ["ZOOPLA_AUTHORIZED_TOKEN"]

session = requests.Session()
session.headers.update({
    "Authorization": f"Bearer {TOKEN}",
    "Accept": "application/json",
})

params = {
    # Replace these with names and values in your written agreement.
    "location": os.environ.get("ZOOPLA_LOCATION", ""),
    "page_size": int(os.environ.get("ZOOPLA_PAGE_SIZE", "100")),
}

records = []
next_cursor = None

while True:
    request_params = dict(params)
    if next_cursor:
        request_params["cursor"] = next_cursor

    response = session.get(BASE_URL, params=request_params, timeout=30)
    request_id = response.headers.get("X-Request-Id")

    if response.status_code == 429:
        delay = int(response.headers.get("Retry-After", "10"))
        time.sleep(delay)
        continue
    response.raise_for_status()

    payload = response.json()
    records.extend(payload.get("items", []))
    next_cursor = payload.get("next_cursor")
    print({"request_id": request_id, "received": len(payload.get("items", []))})

    if not next_cursor:
        break

print(f"Received {len(records)} authorised records")

Do not assume that items, cursor or page_size are Zoopla field names. Replace them with the names in the documentation attached to your agreement. Keep the access token in a secret manager or environment variable, never in source control or browser JavaScript.

Equivalent cURL request

curl --fail-with-body 
  -H "Authorization: Bearer $ZOOPLA_AUTHORIZED_TOKEN" 
  -H "Accept: application/json" 
  --get "$ZOOPLA_AUTHORIZED_BASE_URL" 
  --data-urlencode "location=$ZOOPLA_LOCATION" 
  --data-urlencode "page_size=100"

Use the exact authentication header, query names and endpoint Zoopla gives you. A successful HTTP response from another URL is not evidence that it is an authorised Zoopla feed.

Equivalent Node.js request

const baseUrl = process.env.ZOOPLA_AUTHORIZED_BASE_URL;
const token = process.env.ZOOPLA_AUTHORIZED_TOKEN;

const url = new URL(baseUrl);
url.searchParams.set('location', process.env.ZOOPLA_LOCATION || '');
url.searchParams.set('page_size', '100');

const response = await fetch(url, {
  headers: {
    'Authorization': `Bearer ${token}`,
    'Accept': 'application/json'
  }
});

if (response.status === 429) {
  throw new Error('Rate limited; apply the Retry-After value specified by the contract.');
}
if (!response.ok) {
  throw new Error(`Zoopla request failed: ${response.status} ${await response.text()}`);
}

const payload = await response.json();
console.log(payload);

Data-quality and reliability controls

  • Identity: retain the authorised listing identifier and source timestamp. Do not use an address alone as a permanent key.
  • Duplicates: detect repeated identifiers across pages and runs before loading records into your warehouse.
  • Staleness: track the last-seen time and the provider’s status or update timestamp. Treat missing updates as an operational alert, not proof that a property is still available.
  • Schema changes: reject or quarantine responses with missing required fields; log unknown fields so an upstream change is visible.
  • Retries: retry only transient failures and honour the documented back-off and Retry-After behaviour. Do not retry authentication or permission failures indefinitely.
  • Observability: store request IDs, status codes, latency, page counts and validation failures without logging access tokens or unnecessary personal data.
  • Retention: run deletion jobs that match the contract. Backups and derived tables need the same review as the primary dataset.

Common errors and what they mean

Symptom Likely cause Fix
401 or 403 Missing, expired or unauthorised credentials; wrong product entitlement. Check the account and authentication instructions with Zoopla. Do not try a public-page scraper as a workaround.
404 Legacy endpoint, wrong host or a path that is not part of your agreement. Use the current endpoint supplied by Zoopla and verify the documentation version.
429 Rate or concurrency limit exceeded. Stop, honour Retry-After, reduce concurrency and ask for the contractual limit if your workload needs more capacity.
Empty pages Invalid filter, exhausted cursor, geographic restriction or no matching records. Log the complete request parameters, validate them against the contract and distinguish an empty result from an expired cursor.
Fields disappear Schema or entitlement change. Quarantine the response, alert an owner and obtain the current schema before resuming.
Old tutorial returns data Cached example, a different product or a legacy service. Treat it as historical until Zoopla confirms current permission, endpoint, quota and credentials in writing.

What to do with old wrappers and tutorials

Historical Python wrappers can help you recognise terminology or understand why older articles mention instant keys and listing queries. They cannot prove that those requests still work or that their use is permitted. The official developer position controls the current answer. Remove legacy credentials from copied examples, and do not publish a scraper based on an old request shape.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

If Zoopla cannot provide the required feed

Evaluate another licensed UK property-data provider whose contract explicitly covers your intended fields, geography, refresh rate, storage and redistribution. Compare providers on permission and liability first, then coverage, freshness, pagination, rate limits, authentication, support and price. A page that can be fetched is not equivalent to a licensed data source.

Or skip the browser setup

If your actual requirement is a visual record of a page you are authorised to view—not a structured feed of Zoopla listings—ScreenshotNeo can take the screenshot through one API call. It is not a Zoopla listings API and does not grant permission to copy or republish site data. Use it only for pages and purposes your agreement allows.

ScreenshotNeo removes cookie-consent banners, newsletter popups and chat widgets before capture. Bot checks, blank pages, failed loads, timeouts and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients.

Here is the supplied one-call example; replace the target with a page you are authorised to capture:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://zoopla.co.uk -o shot.webp

See the ScreenshotNeo API documentation for request options. The free plan includes 1,000 screenshots per month with no card, and paid plans start at $5 for 3,000 shots. Create a free ScreenshotNeo account when a compliant screenshot workflow is what you need.

FAQ

Frequently Asked Questions

Can an old Zoopla API key still be used?

Do not rely on it. Ask Zoopla to confirm in writing that the credential, endpoint, quota and intended use remain active.

Can I store data returned through an authorised feed?

Only if the written agreement permits that retention. Confirm backup, deletion, derived-data and redistribution rules before storing responses.

Is a screenshot the same as a listings data feed?

No. A screenshot is an image of an authorised page; it does not provide structured listing fields or permission to extract and republish them.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.