# Property24 Scraper (`solidcode/property24-scraper`) Actor

\[💰 $0.65 / 1K] Extract South African property listings from Property24 — prices, beds, baths, parking, floor & land size, photos, agency and agent contacts, levies and rates. Search any suburb for sale, to rent, or recently sold, or paste Property24 URLs directly.

- **URL**: https://apify.com/solidcode/property24-scraper.md
- **Developed by:** [SolidCode](https://apify.com/solidcode) (community)
- **Categories:** Real estate, Developer tools, Automation
- **Features:** Limited permissions
- **Stats:** 35 total users, 8 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.65 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
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

## Property24 Scraper

Pull live property listings from Property24 — South Africa's largest property portal — at scale, in clean rows with prices in Rand, agent contacts, and ZA-specific costs like levies and rates & taxes. Search any of the country's 9 provinces by suburb, city, or region name, or paste a Property24 URL to mirror an exact on-site search. Built for SA estate agents, property investors, and market analysts who need fresh, structured Property24 data without copying listings off the website one page at a time.

### Why This Scraper?

- **3 deal types in one actor** — for sale, to rent, and recently sold, switched with a single dropdown across all 9 South African provinces.
- **Search by suburb, city, region or province name** — Property24's location index runs to 9,000+ named areas, over 6,000 of them suburbs, and the actor resolves any of them from plain text; pass `"Suburb, City"` to separate same-named suburbs in different provinces.
- **7 property types** — house, apartment/flat, townhouse, vacant land, farm, commercial, and industrial, filtered individually or in combination.
- **South-Africa-native cost fields** — every detailed listing returns monthly `levies` and `ratesAndTaxes` in ZAR, the two numbers that decide a sectional-title deal's true monthly cost.
- **Prices both ways** — a clean numeric `price` for sorting and maths plus the exact on-page `priceDisplay` string ("R 2 450 000"), with `currency` set to ZAR. New-build project rows are labelled `development` and carry `priceFrom`/`priceTo` instead, so a R10m+ search never shows you a R1.8m entry price.
- **Two size dimensions** — `floorSize` (building m²) and `landSize` (erf m²) captured separately, so you can underwrite by build size or stand size.
- **Listing agent + agency contacts** — `agentName`, `agencyName`, agency logo and profile URL, plus a full `agents` array with each agent's name, photo, profile link, and phone/WhatsApp availability flags (detail mode) — ready for lead lists.
- **14 filters that map to Property24's own search** — price min/max, bedrooms, bathrooms, parking, floor & erf size ranges, furnished/unfurnished, rental period, pet-friendly, garden, pool, flatlet, and 5 sort orders.
- **Paste-a-URL mode** — drop any Property24 search or suburb URL straight in and the actor honours every filter already baked into that link, including combos the form doesn't expose.
- **Full photo galleries + amenity lists on demand** — the optional detail mode opens each listing for its complete description, the whole photo gallery (typically 20+ images, not just the thumbnail), and the full per-room `features` list (security, fibre, balcony, built-in cupboards, and dozens more).

### Use Cases

**Market Research**

- Track asking prices per suburb across all 9 provinces to map regional price movements.
- Build sold-price comparables with the Recently Sold deal type for valuations.
- Compare floor-size and erf-size value (price per m²) across competing areas.

**Lead Generation**

- Pull listing agent and agency names with profile links for outreach lists.
- Build broker directories filtered by area, property type, or price band.
- Find every flatlet or pet-friendly rental in a target suburb for a niche client base.

**Investment Analysis**

- Screen buy-to-let opportunities by rental period, furnished status, and yield inputs.
- Underwrite sectional-title deals using monthly levies and rates & taxes.
- Identify undervalued stock by combining land-size minimums with price ceilings.

**Property Portals & Aggregators**

- Keep a continuously refreshed feed of for-sale and to-rent inventory.
- Enrich your own database with descriptions, full galleries, and agent contacts.
- Mirror a curated on-site search by pasting its Property24 URL into your pipeline.

### Getting Started

#### Simple — one city, for sale

```json
{
  "searchLocations": ["Cape Town"],
  "dealType": "for_sale",
  "maxResults": 50
}
```

#### Filtered — family homes to rent

```json
{
  "searchLocations": ["Sandton", "Sea Point, Cape Town"],
  "dealType": "to_rent",
  "propertyTypes": ["house", "townhouse"],
  "priceMax": 35000,
  "bedroomsMin": 3,
  "features": ["pet_friendly", "garden"],
  "rentalPeriod": "monthly",
  "sortBy": "lowest_price",
  "maxResults": 200
}
```

#### Advanced — paste a fully-filtered Property24 URL

```json
{
  "startUrls": [
    "https://www.property24.com/houses-for-sale/cape-town/western-cape/432"
  ],
  "includeListingDetails": true,
  "maxResults": 0
}
```

### Input Reference

#### What to Scrape

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `searchLocations` | array of strings | `["Cape Town"]` | Cities, suburbs, or regions to search, e.g. `"Sandton"` or `"Sea Point, Cape Town"`. Each entry runs as its own search. |
| `startUrls` | array of strings | `[]` | Paste Property24 search or suburb URLs directly. Any filters already in the URL are kept and the filters below are ignored for these URLs. |

#### Search Filters

These apply only to Search Locations — pasted URLs use the filters already in the URL.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `dealType` | string | `"for_sale"` | One of For Sale, To Rent, or Recently Sold. |
| `propertyTypes` | array of strings | `[]` | Any of House, Apartment / Flat, Townhouse, Vacant Land / Plot, Farm / Smallholding, Commercial Property, Industrial Property. Empty means all types. |
| `priceMin` | integer | `null` | Lowest price to include, in South African Rand. |
| `priceMax` | integer | `null` | Highest price to include, in South African Rand. |
| `bedroomsMin` | integer | `null` | Minimum bedrooms (0–10). |
| `bathroomsMin` | integer | `null` | Minimum bathrooms (0–10). |
| `parkingMin` | integer | `null` | Minimum parking spaces (0–5). |
| `floorSizeMin` | integer | `null` | Minimum floor (building) area in m². |
| `floorSizeMax` | integer | `null` | Maximum floor (building) area in m². |
| `landSizeMin` | integer | `null` | Minimum erf (land) area in m². |
| `landSizeMax` | integer | `null` | Maximum erf (land) area in m². |
| `furnished` | string | `"any"` | Any, Furnished only, or Unfurnished only. Most relevant for rentals. |
| `features` | array of strings | `[]` | Any of Pet-friendly, Garden, Swimming pool, Flatlet / Granny flat. Listings must offer all selected. |
| `rentalPeriod` | string | `"any"` | Any, Monthly, Weekly, Daily, Yearly, or Per square metre. Applies when Listing Type is To Rent. |
| `sortBy` | string | `"default"` | Default (relevance), Most recent, Lowest price, Highest price, or Size. |

#### Options

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `maxResults` | integer | `100` | Maximum listings to collect across all locations and URLs. Set to `0` to collect everything available. |
| `includeListingDetails` | boolean | `false` | Open each listing's detail page for the full description, every photo, all listed features, agent contacts, levies, and rates & taxes. When off, only the fields visible on the results page are returned. |

### Output

Each listing is returned as one flat row. Detail-mode fields populate when `includeListingDetails` is on.

```json
{
  "listingId": "115678901",
  "url": "https://www.property24.com/for-sale/sea-point/cape-town/western-cape/9145/115678901",
  "recordType": "listing",
  "title": "3 Bedroom Apartment for Sale in Sea Point",
  "transactionType": "for_sale",
  "propertyType": "Apartment / Flat",
  "price": 4950000,
  "priceFrom": null,
  "priceTo": null,
  "priceDisplay": "R 4 950 000",
  "currency": "ZAR",
  "pricePerSqm": 41250,
  "bedrooms": 3,
  "bathrooms": 2,
  "parking": 1,
  "floorSize": 120,
  "landSize": null,
  "furnished": false,
  "petsAllowed": true,
  "features": ["Pet-friendly", "Balcony", "Built-in Cupboards", "Intercom", "Fibre"],
  "description": "Bright north-facing apartment with sweeping Atlantic views...",
  "levies": 3850,
  "ratesAndTaxes": 1620,
  "listedDate": "2026-05-18T00:00:00",
  "suburb": "Sea Point",
  "city": "Cape Town",
  "province": "Western Cape",
  "address": "Sea Point, Cape Town, Western Cape",
  "primaryImage": "https://images.prop24.com/.../image.jpg",
  "images": ["https://images.prop24.com/377657026", "https://images.prop24.com/377657027"],
  "imageCount": 18,
  "agencyName": "Seaboard Properties",
  "agencyUrl": "https://www.property24.com/estate-agents/seaboard-properties/123",
  "agencyLogo": "https://images.prop24.com/.../logo.png",
  "agentName": "Lerato Mokoena",
  "agents": [
    {"name": "Lerato Mokoena", "profileUrl": "https://www.property24.com/estate-agents/seaboard-properties/lerato-mokoena/456", "image": "https://images.prop24.com/.../agent.jpg", "hasPhone": true, "hasWhatsapp": true}
  ],
  "searchLocation": "Sea Point, Cape Town",
  "scrapedAt": "2026-06-01T09:30:00Z"
}
```

#### Core Fields

| Field | Type | Description |
|-------|------|-------------|
| `listingId` | string | Property24 listing identifier. |
| `url` | string | Canonical listing URL. |
| `recordType` | string | `listing` for an individual property, `development` for a new-build project card. |
| `title` | string | Listing headline, or the project name on a development row. |
| `transactionType` | string | `for_sale`, `to_rent`, or `sold`. |
| `propertyType` | string | House, Apartment / Flat, Townhouse, Vacant Land / Plot, Farm, Commercial Property, or Industrial Property. Filled on every row, detail mode or not. |
| `searchLocation` | string | The location or URL this row came from. |
| `scrapedAt` | string | ISO 8601 timestamp of collection. |

#### Price & Size

| Field | Type | Description |
|-------|------|-------------|
| `price` | integer | Numeric price in ZAR. Empty on a development row that spans a price range, so a project's entry price is never mistaken for a listing price. |
| `priceFrom` | integer | Cheapest unit in a development, in ZAR (development rows only). |
| `priceTo` | integer | Dearest unit in a development, in ZAR (development rows only). |
| `priceDisplay` | string | As-shown price text, e.g. `"R 2 450 000"` or `"From R 12 900 000 To R 15 900 000"`. |
| `currency` | string | Always `"ZAR"`. |
| `pricePerSqm` | number | Price per m² when available. |
| `floorSize` | number | Floor (building) area in m². |
| `landSize` | number | Erf (land) area in m². |
| `bedrooms` | number | Bedroom count. |
| `bathrooms` | number | Bathroom count. |
| `parking` | number | Parking spaces. |

#### Location & Media

| Field | Type | Description |
|-------|------|-------------|
| `suburb` | string | Suburb. |
| `city` | string | City. |
| `province` | string | Province. |
| `address` | string | Locality address (suburb, city, province), e.g. `"Sea Point, Cape Town, Western Cape"`. |
| `primaryImage` | string | Primary image URL. |
| `images` | array of strings | Gallery image URLs — the listing's full photo set, typically 20+ (detail mode). |
| `imageCount` | integer | The listing's own stated photo total (detail mode — results-page cards carry no photo count). |

#### Detail Mode & Agent

Populated when `includeListingDetails` is on.

| Field | Type | Description |
|-------|------|-------------|
| `furnished` | boolean | Furnished flag. |
| `petsAllowed` | boolean | Pets allowed. |
| `features` | array of strings | Listed features and amenities (security, fibre, fixtures, room features). Populated in detail mode. |
| `description` | string | Full description text. |
| `levies` | number | Monthly levies in ZAR. |
| `ratesAndTaxes` | number | Monthly rates & taxes in ZAR. |
| `listedDate` | string | Date the listing was published. |
| `agencyName` | string | Listing agency name. |
| `agencyUrl` | string | Agency profile URL. |
| `agencyLogo` | string | Agency logo URL. |
| `agentName` | string | Primary listing agent name. |
| `agents` | array of objects | Agents on the listing, each with `name`, `profileUrl`, `image`, `hasPhone`, and `hasWhatsapp` (contact-availability flags). |

### Tips for Best Results

- Start with `maxResults` set to 10–50 to preview a search's shape, then raise it or set `0` for everything.
- Disambiguate common suburb names by passing `"Suburb, City"` — e.g. `"Sea Point, Cape Town"` — so the right area is picked.
- Use Recently Sold for comparables: sold prices are the gold standard for valuations and CMA reports, though sold rows are richest at suburb level rather than city level.
- Power-user tip: build your perfect search on property24.com, copy the resulting URL into `startUrls`, and the actor reproduces it filter-for-filter — including combinations the form fields don't cover.
- Filter on `recordType == "listing"` when you want individual homes only. Property24 mixes new-build project cards into results pages, and those rows describe a whole development priced from `priceFrom` to `priceTo` rather than one property.
- Keep `includeListingDetails` on whenever you need levies, rates & taxes, full descriptions, or every gallery image; switch it off for a faster, lighter sweep of just the results-page fields.
- For rentals, set `rentalPeriod` to `monthly` and use `furnished` to separate furnished from unfurnished stock cleanly.
- Pass several entries in `searchLocations` to cover multiple suburbs or cities in a single run — each is searched independently.

### Pricing

**From $0.65 per 1,000 results** — undercuts comparable Property24 actors on the market. No compute or time-based charges — you pay per result, plus a small fixed $0.005 per-run start fee. Bronze, Silver, and Gold subscribers pay progressively less; the table below shows the result cost at each discount tier.

| Results | No discount | Bronze | Silver | Gold |
|---------|-------------|--------|--------|------|
| 100 | $0.078 | $0.075 | $0.070 | $0.065 |
| 1,000 | $0.78 | $0.75 | $0.70 | $0.65 |
| 10,000 | $7.80 | $7.50 | $7.00 | $6.50 |
| 100,000 | $78.00 | $75.00 | $70.00 | $65.00 |

A result is one property listing row. Add the flat $0.005 start fee once per run — a 1,000-result run at Gold is $0.655 all-in, and the fee stays immaterial at any real volume.

### Integrations

Export data in JSON, CSV, Excel, XML, or RSS. Connect to 1,500+ apps via:

- **Zapier** / **Make** / **n8n** — Workflow automation
- **Google Sheets** — Direct spreadsheet export
- **Slack** / **Email** — Notifications on new results
- **Webhooks** — Trigger custom APIs on run completion
- **Apify API** — Full programmatic access

### Legal & Ethical Use

This scraper collects publicly available property listing data for legitimate research, market analysis, and business use. You are responsible for using the data in compliance with Property24's terms of service, applicable data-protection laws (including South Africa's POPIA), and any other relevant regulations. Do not use collected personal data — such as agent contact details — for spam, harassment, or any unlawful purpose. Always respect the rights of data subjects and use this tool responsibly.

# Actor input Schema

## `searchLocations` (type: `array`):

Cities, suburbs, or regions to search, e.g. "Cape Town", "Sandton", or "Sea Point, Cape Town". Each location runs as its own search. Leave empty if you are pasting Property24 URLs below.

## `startUrls` (type: `array`):

Paste Property24 search or suburb URLs directly, e.g. "https://www.property24.com/for-sale/cape-town/western-cape/432". Any filters already in the URL are kept. When provided, the filter settings below do NOT apply to these URLs.

## `dealType` (type: `string`):

Search properties for sale, to rent, or already sold. Only applies to Search Locations — ignored for pasted URLs.

## `propertyTypes` (type: `array`):

Only include these property types. Leave empty for all types.

## `priceMin` (type: `integer`):

Only include properties at or above this price, in South African Rand. Leave empty for no minimum.

## `priceMax` (type: `integer`):

Only include properties at or below this price, in South African Rand. Leave empty for no maximum.

## `bedroomsMin` (type: `integer`):

Only include properties with at least this many bedrooms. Leave empty for any.

## `bathroomsMin` (type: `integer`):

Only include properties with at least this many bathrooms. Leave empty for any.

## `parkingMin` (type: `integer`):

Only include properties with at least this many parking spaces. Leave empty for any.

## `floorSizeMin` (type: `integer`):

Only include properties with at least this floor (building) area, in square metres. Leave empty for any.

## `floorSizeMax` (type: `integer`):

Only include properties with at most this floor (building) area, in square metres. Leave empty for any.

## `landSizeMin` (type: `integer`):

Only include properties with at least this erf (land) area, in square metres. Leave empty for any.

## `landSizeMax` (type: `integer`):

Only include properties with at most this erf (land) area, in square metres. Leave empty for any.

## `furnished` (type: `string`):

Filter by furnishing. Most relevant for rentals.

## `features` (type: `array`):

Only include properties that offer all of these features. Leave empty for no feature filter.

## `rentalPeriod` (type: `string`):

Rental term to filter by. Only applies when Listing Type is "To Rent".

## `sortBy` (type: `string`):

Order in which results are returned by Property24.

## `maxResults` (type: `integer`):

Maximum number of listings to collect across all locations and URLs. Set to 0 to collect all available results (each search reads up to 1,000 result pages, far more than any Property24 area holds). Tip: start with 10-50 to test, then increase.

## `includeListingDetails` (type: `boolean`):

Open each listing's detail page for richer data: full description, all photos, agent and agency contacts, levies, and rates & taxes. Much more complete, but noticeably slower. Leave off for a fast run that returns the fields shown on the search results.

## Actor input object example

```json
{
  "searchLocations": [
    "Cape Town"
  ],
  "startUrls": [],
  "dealType": "for_sale",
  "propertyTypes": [],
  "furnished": "any",
  "features": [],
  "rentalPeriod": "any",
  "sortBy": "default",
  "maxResults": 100,
  "includeListingDetails": false
}
```

# Actor output Schema

## `overview` (type: `string`):

Table of scraped property listings with key fields.

## `details` (type: `string`):

Full per-listing detail including agent contacts and costs.

# 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 = {
    "searchLocations": [
        "Cape Town"
    ],
    "startUrls": [],
    "dealType": "for_sale",
    "propertyTypes": [],
    "furnished": "any",
    "features": [],
    "rentalPeriod": "any",
    "sortBy": "default",
    "maxResults": 100,
    "includeListingDetails": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("solidcode/property24-scraper").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 = {
    "searchLocations": ["Cape Town"],
    "startUrls": [],
    "dealType": "for_sale",
    "propertyTypes": [],
    "furnished": "any",
    "features": [],
    "rentalPeriod": "any",
    "sortBy": "default",
    "maxResults": 100,
    "includeListingDetails": False,
}

# Run the Actor and wait for it to finish
run = client.actor("solidcode/property24-scraper").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 '{
  "searchLocations": [
    "Cape Town"
  ],
  "startUrls": [],
  "dealType": "for_sale",
  "propertyTypes": [],
  "furnished": "any",
  "features": [],
  "rentalPeriod": "any",
  "sortBy": "default",
  "maxResults": 100,
  "includeListingDetails": false
}' |
apify call solidcode/property24-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,solidcode/property24-scraper"
        }
    }
}
```

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/pLmv5acRqJlt4Y3TX/builds/mZzVMHGmZGS23xmk4/openapi.json
