# Property24 South Africa Scraper 🏠 (`shahidirfan/property24-south-africa-scraper`) Actor

Scrape live property listings from South Africa's #1 real estate platform. Extract prices, addresses, descriptions, agent details & photos. Ideal for investment analytics, market research, competitor tracking, price benchmarking & real estate AI datasets. Structured JSON ready.

- **URL**: https://apify.com/shahidirfan/property24-south-africa-scraper.md
- **Developed by:** [Shahid Irfan](https://apify.com/shahidirfan) (community)
- **Categories:** Real estate, Developer tools, Automation
- **Stats:** 3 total users, 0 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 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 South Africa Scraper

Extract property and real estate listings from Property24 South Africa with ease. Collect pricing, location, property features, listing URLs, and images from search result pages. Perfect for real estate market research, investment analysis, and property trend monitoring.

***

### Features

- **Direct Location and Category Crawling** - Collect listings from any Property24 search results URL.
- **Smart Keyword Search Resolution** - Converts location keywords into matching listing areas automatically.
- **Clean Property Records** - Includes listing identifiers, prices, locations, images, and normalized feature values.
- **Duplicate Filtering** - Removes repeated listings by listing identity and URL.
- **Smart Pagination** - Detects how many result pages exist and stops as soon as the listings run out, so small suburbs finish quickly instead of scanning empty pages.
- **Fast Search Collection** - Handles multi-page extraction with result and page limits.

***

### Use Cases

#### Real Estate Market Analysis

Monitor listing prices and property sizes in specific suburbs of South Africa. Track changes over time to identify emerging high-value zones.

#### Investment Property Scouting

Filter and scan listing attributes like bedrooms, bathrooms, and floor sizes to discover undervalued properties that fit your portfolio criteria.

#### Agency Competitor Intelligence

Analyze which real estate agencies and agents are most active in particular regions and track their listings.

***

### Input Parameters

| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| `startUrl` | String | No | - | Start scraping from a specific search results URL. |
| `keyword` | String | No | - | Location keyword used when `startUrl` is not provided. |
| `results_wanted` | Integer | No | `20` | Maximum number of property listings to collect. |
| `max_pages` | Integer | No | `10` | Safety cap on the number of search result pages to visit. |
| `proxyConfiguration` | Object | No | `{ "useApifyProxy": true }` | Proxy configuration options. |

***

### Output Data

Each property listing contains:

| Field | Type | Description |
|-------|------|-------------|
| `listing_id` | String | Listing identifier from the listing URL |
| `title` | String | Property name or title |
| `url` | String | Direct property listing URL |
| `price` | Number | Property price value |
| `currency` | String | Price currency (ZAR) |
| `property_type` | String | Property category (e.g. House, Apartment) |
| `bedrooms` | Number | Number of bedrooms |
| `bathrooms` | Number | Number of bathrooms |
| `parking_spaces` | Number | Number of parking spaces |
| `floor_size` | Number | Floor size value |
| `floor_size_unit` | String | Unit of floor size (e.g. m²) |
| `erf_size` | Number | Erf or land size value |
| `erf_size_unit` | String | Unit of erf or land size |
| `locality` | String | Locality or suburb name |
| `city` | String | City or municipality path value |
| `region` | String | Region or province name |
| `latitude` | Number | Listing latitude |
| `longitude` | Number | Listing longitude |
| `agency_name` | String | Real estate agency name |
| `agent_name` | String | Listing agent name |
| `agency_logo_url` | String | Agency logo image URL when available |
| `image_urls` | Array | Listing photo URLs published on the search results page || `features` | Object | Parsed feature map from listing cards |
| `source` | String | Source page type used for the record |

***

### Usage Examples

#### Search by Location Keyword

To search for listings in a specific suburb:

```json
{
  "keyword": "Mandalay",
  "results_wanted": 20
}
```

#### Crawl a Specific Search URL

To extract listings from a pre-filtered category page:

```json
{
  "startUrl": "https://www.property24.com/for-sale/western-cape/9",
  "results_wanted": 50
}
```

***

### Sample Output

```json
{
  "listing_id": "117400230",
  "title": "4 Bedroom House",
  "url": "https://www.property24.com/for-sale/wilderness-central/wilderness/western-cape/17495/117400230",
  "price": 15000000,
  "currency": "ZAR",
  "transaction_type": "for-sale",
  "locality": "Wilderness Central",
  "city": "wilderness",
  "region": "western-cape",
  "bedrooms": 4,
  "bathrooms": 4.5,
  "parking_spaces": 4,
  "floor_size": 971,
  "floor_size_unit": "m²",
  "erf_size": 6971,
  "erf_size_unit": "m²",
  "agency_name": "Jawitz Properties Wilderness",
  "image_urls": [
    "https://images.prop24.com/382793673/Crop600x400"
  ],
  "features": {
    "bedrooms": 4,
    "bathrooms": 4.5,
    "parking_spaces": 4,
    "floor_size": 971,
    "erf_size": 6971,
    "erf_size_unit": "m²"
  },
  "source": "listing_page"
}
```

***

### Tips for Best Results

- **Use Precise Location Keywords** - Use specific suburb names rather than broad terms to match the platform's categorization.
- **Enable Residential Proxies** - For high volume runs, use residential proxies to reduce rate limits and blocking.
- **Test with Smaller Datasets First** - Start with 20 results to confirm listing patterns before collecting larger datasets.

***

### Integrations

Connect your scraped data to third-party tools:

- **Google Sheets** - Export directly to spreadsheets.
- **Airtable** - Build property databases.
- **Slack** - Get alerts for new properties.
- **Webhooks** - Send results to your own system.

***

### Frequently Asked Questions

#### Can I scrape multiple pages?

Yes. The scraper follows the search result pages automatically until your results limit is reached. It also checks how many pages actually exist and stops once there are no more listings, so small locations finish fast without scanning empty pages.

#### Why did I get fewer results than requested?

Your `results_wanted` value is a maximum, not a guarantee. Some suburbs and filters only have a handful of active listings, so the run ends when every available listing has been collected.

#### What if some fields are missing?

The scraper removes null and empty values dynamically. Some listings may lack features like floor size or agent details.

***

### Support

For issues or feature requests, contact support via the Apify Console.

***

### Legal Notice

This scraper is designed for legitimate data collection. Users are responsible for complying with the website terms of service and relevant local privacy laws.

# Actor input Schema

## `startUrl` (type: `string`):

Property24 search results URL (e.g., https://www.property24.com/for-sale/western-cape/9). If provided, it overrides the keyword.

## `keyword` (type: `string`):

Location or keyword to search (e.g. 'Mandalay', 'Western Cape').

## `results_wanted` (type: `integer`):

The maximum number of property listings to collect.

## `max_pages` (type: `integer`):

A safety cap on the number of search result pages to visit.

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

Use Apify Proxy for reliable scraping.

## Actor input object example

```json
{
  "keyword": "Mandalay",
  "results_wanted": 20,
  "max_pages": 10,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

No description

# 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 = {
    "keyword": "Mandalay",
    "results_wanted": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("shahidirfan/property24-south-africa-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 = {
    "keyword": "Mandalay",
    "results_wanted": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("shahidirfan/property24-south-africa-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 '{
  "keyword": "Mandalay",
  "results_wanted": 20
}' |
apify call shahidirfan/property24-south-africa-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,shahidirfan/property24-south-africa-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/ld0ftVr1HMCMjzxp8/builds/fvkSTmk48IIGPyQoq/openapi.json
