# UK Estate Agent Leads (Rightmove & Zoopla) (`xtracto/uk-agent-leads`) Actor

Find UK estate agent and letting agent branch contacts by area or postcode: agent/branch name, phone number, office address, and logo — sourced live from Rightmove and Zoopla listings. Built for B2B lead generation, not property research.

- **URL**: https://apify.com/xtracto/uk-agent-leads.md
- **Developed by:** [Farhan Febrian Nauval](https://apify.com/xtracto) (community)
- **Categories:** Lead generation, Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## UK Estate Agent Leads (Rightmove & Zoopla)

Find UK estate agent and letting agent branch contacts by area or postcode — agent/branch name, phone number, office address, and logo — pulled live from Rightmove and Zoopla property listings. This is a lead-generation tool for reaching estate agents (for software, marketing, supply, or partnership outreach), not a property-listings scraper: the output is one row per agent branch, not one row per house for sale.

### Why use this actor

- Turns any search area into a clean list of estate agent branches operating there — no manual copy-pasting from listing pages
- Real phone numbers and, for Rightmove, the branch's full office postal address
- Automatically deduplicates: an agent with 20 listings in your search area shows up once, with a count of how many listings they had
- Covers both major UK portals (Rightmove and Zoopla) from one actor
- No account or login needed on either site
- Stable JSON output ready for a CRM, spreadsheet, or outreach tool

### How it works

1. You give the actor a search area — either a Rightmove/Zoopla search-results URL (copy it from your browser's address bar after searching) or, for Zoopla, just a location name like `london`.
2. The actor pages through the listings in that area and reads the selling/letting agent attached to each one.
3. Agents are merged into one lead per branch (by branch ID), with a running count of how many listings they had.
4. For Rightmove, each branch also gets one extra lookup to pull its full office address.
5. Results stream into your dataset as one row per agent branch — ready to download as JSON, CSV, or Excel.

You don't need to manage proxies, retries, or figure out how either site's pages are structured — the actor handles all of that.

### Input

```json
{
  "source": "rightmove",
  "searchUrls": ["https://www.rightmove.co.uk/property-for-sale/find.html?locationIdentifier=REGION%5E87490"],
  "channel": "for-sale",
  "propertyUrls": [],
  "maxItems": 100,
  "maxListingsPerSearch": 500,
  "enrichBranches": true,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": ["RESIDENTIAL"],
    "apifyProxyCountry": "GB"
  }
}
```

| Field | Type | Description |
|---|---|---|
| `source` | string | `"rightmove"` (default) or `"zoopla"`. |
| `searchUrls` | array | The search area(s) to scan. For Rightmove: a full search-results URL. For Zoopla: a full search URL, or just a location slug (`london`, `manchester`, `se15`, `bristol`). |
| `channel` | string | Zoopla only: `"for-sale"` (default) or `"to-rent"`. Ignored for Rightmove — its search URL already encodes this. |
| `propertyUrls` | array | Optional. Specific property/listing URLs instead of, or alongside, a search area. Each yields one enriched agent lead. |
| `maxItems` | integer | Cap on unique agent branches returned (not listings scanned). `0` = no limit. Default `100`. |
| `maxListingsPerSearch` | integer | How many listings to scan per search area while looking for agents. Default `500`. |
| `enrichBranches` | boolean | When true, each Rightmove branch found gets one extra lookup for its full office address. Default `true`. |
| `maxConcurrency` | integer | Parallel workers. Default `3`. |
| `proxyConfiguration` | object | Proxy settings. **A UK residential proxy is required for reliable Rightmove data** — it blocks non-UK and datacenter connections. Recommended for Zoopla too. Default: Apify Residential, country GB. |

### Output

Real sample, Rightmove (`source: "rightmove"`, London search area):

```json
{
  "source": "rightmove",
  "branchId": 271223,
  "agentName": "Global 1, London",
  "companyName": "Global 1",
  "phone": "020 3910 8302",
  "address": "23 Berkeley Square,\r\nMayfair,\r\nLondon,\r\nW1J 6HE",
  "logoUrl": "https://media.rightmove.co.uk:443/partner-logo/31973465-PRODUCTS_LOGO-1766056090.png",
  "profileUrl": "https://www.rightmove.co.uk/estate-agents/agent/Global-1/London-271223.html",
  "listingsSeen": 3,
  "sampleListingUrl": "https://www.rightmove.co.uk/properties/148711631#/?channel=RES_BUY",
  "sampleListingAddress": "One Hyde Park, Knightsbridge, London, SW1X",
  "_input": "https://www.rightmove.co.uk/property-for-sale/find.html?locationIdentifier=REGION%5E87490",
  "_scrapedAt": "2026-08-06T09:51:27Z",
  "_source": "S1-search"
}
```

Real sample, Zoopla (`source: "zoopla"`, `searchUrls: ["london"]`):

```json
{
  "source": "zoopla",
  "branchId": 57254,
  "agentName": "Savills - Kensington",
  "companyName": null,
  "phone": "020 8022 3223",
  "address": null,
  "logoUrl": "https://st.zoocdn.com/zoopla_static_agent_logo_(648969).png",
  "profileUrl": "https://www.zoopla.co.uk/new-homes/developers/branch/savills-kensington-london-57254/",
  "listingsSeen": 1,
  "sampleListingUrl": "https://www.zoopla.co.uk/for-sale/details/73902989/",
  "sampleListingAddress": "St. Mary Abbots Court, Warwick Gardens, London W14",
  "_input": "https://www.zoopla.co.uk/for-sale/property/london/?pn=1",
  "_scrapedAt": "2026-08-06T09:52:40Z",
  "_source": "S1-search"
}
```

| Field | Type | Description |
|---|---|---|
| `source` | string | Which site the lead came from: `rightmove` or `zoopla`. |
| `branchId` | number | The site's internal ID for this agent branch. |
| `agentName` | string | Branch display name, e.g. `"Global 1, London"`. |
| `companyName` | string | null | Trading/company name where the site separates it from the branch name (Rightmove only). |
| `phone` | string | Branch contact phone number. |
| `address` | string | null | Full office postal address. Populated for Rightmove (when `enrichBranches` is on); always `null` for Zoopla — Zoopla does not publish a branch office address anywhere on the site. |
| `logoUrl` | string | Agent's logo image. |
| `profileUrl` | string | Link to the agent's profile/branch page on the source site. |
| `listingsSeen` | number | How many listings from this branch were found in this run — a rough gauge of how active the branch is in the search area. |
| `sampleListingUrl` | string | One example listing from this branch, for context. |
| `sampleListingAddress` | string | The address of that sample listing (a property, not the branch office). |

### Other Real-Estate Actors

| Actor | What it does |
|---|---|
| Rightmove Property Scraper | Full property listings (price, beds, price history) from Rightmove. |
| Zoopla UK Property Scraper | Full property listings (price, EPC, floor area) from Zoopla. |
| Daft.ie Property Scraper | Irish property listings from Daft.ie. |
| Idealista Property Scraper | Spanish/Portuguese/Italian property listings. |

# Actor input Schema

## `source` (type: `string`):

Which UK property site to pull agent/branch contacts from.

## `searchUrls` (type: `array`):

For Rightmove: paste a full search-results URL (copy the address bar after searching on rightmove.co.uk). For Zoopla: paste a full search URL OR just a location slug (e.g. london, manchester, se15, bristol). Every listing found is scanned for its selling/letting agent, deduplicated into one lead per branch.

## `channel` (type: `string`):

Zoopla only. Ignored for Rightmove (its search URL already encodes sale vs rent).

## `propertyUrls` (type: `array`):

Optional. Paste specific Rightmove property URLs or Zoopla listing URLs instead of, or in addition to, a search area. Each yields one enriched agent/branch lead.

## `maxItems` (type: `integer`):

Cap on the number of UNIQUE agent branches returned (not listings scanned). 0 = no limit.

## `maxListingsPerSearch` (type: `integer`):

How many listings to page through per search area while looking for agent branches. Higher = more unique branches found, but more requests. Rightmove/Zoopla cap browsable results around 1000 per search.

## `enrichBranches` (type: `boolean`):

When on, each Rightmove branch found via search gets one extra detail-page fetch to pull its full postal office address (Rightmove only — Zoopla does not expose a branch office address anywhere on the site).

## `maxConcurrency` (type: `integer`):

How many search areas / property pages to fetch in parallel. Keep low with residential proxies.

## `proxyConfiguration` (type: `object`):

REQUIRED for Rightmove: it returns 403 to datacenter and non-UK IPs, so a UK (GB) residential proxy is mandatory. Recommended for Zoopla too. Default is Apify Residential, country GB.

## Actor input object example

```json
{
  "source": "rightmove",
  "searchUrls": [
    "https://www.rightmove.co.uk/property-for-sale/find.html?locationIdentifier=REGION%5E87490"
  ],
  "channel": "for-sale",
  "propertyUrls": [],
  "maxItems": 100,
  "maxListingsPerSearch": 500,
  "enrichBranches": true,
  "maxConcurrency": 3,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "GB"
  }
}
```

# Actor output Schema

## `agentName` (type: `string`):

Agent Name as reported by the source.

## `phone` (type: `string`):

Phone number as published by the business.

## `address` (type: `string`):

Street address.

## `source` (type: `string`):

Name of the source the row came from.

## `listingsSeen` (type: `string`):

Listings Seen as reported by the source.

## `profileUrl` (type: `string`):

Link to the profile.

## `branchId` (type: `string`):

Branch Id as reported by the source.

## `companyName` (type: `string`):

Company name.

## `logoUrl` (type: `string`):

Link to the logo.

## `sampleListingUrl` (type: `string`):

Link to the sample listing.

## `sampleListingAddress` (type: `string`):

Sample Listing Address.

## `_input` (type: `string`):

The input value this row was produced from.

## `_scrapedAt` (type: `string`):

UTC timestamp of the scrape, ISO 8601.

## `_source` (type: `string`):

Which extraction strategy produced the row.

## `_error` (type: `string`):

Set only on diagnostic rows - why that target produced no data.

## `_errorDetail` (type: `string`):

Extra context for the error.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "searchUrls": [
        "https://www.rightmove.co.uk/property-for-sale/find.html?locationIdentifier=REGION%5E87490"
    ],
    "propertyUrls": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("xtracto/uk-agent-leads").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "searchUrls": ["https://www.rightmove.co.uk/property-for-sale/find.html?locationIdentifier=REGION%5E87490"],
    "propertyUrls": [],
}

# Run the Actor and wait for it to finish
run = client.actor("xtracto/uk-agent-leads").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "searchUrls": [
    "https://www.rightmove.co.uk/property-for-sale/find.html?locationIdentifier=REGION%5E87490"
  ],
  "propertyUrls": []
}' |
apify call xtracto/uk-agent-leads --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,xtracto/uk-agent-leads"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ZzqOuIedtYQ2sbIjt/builds/jknhuDg0NYiq6oSJm/openapi.json
