# Property24 Scraper | South Africa (`fatihtahta/property24-scraper-za`) Actor

Extract structured Real estate listings across South Africa from Property24.com with property details, agent profiles, full descriptions, media and more. Built for enterprise-grade real estate intelligence, lead enrichment, market analysis, and automated data pipelines.

- **URL**: https://apify.com/fatihtahta/property24-scraper-za.md
- **Developed by:** [Fatih Tahta](https://apify.com/fatihtahta) (community)
- **Categories:** Real estate, Automation, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 property listings

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Property24.com Scraper | Enterprise Grade

**Slug:** `fatihtahta/property24-scraper-za`

### Overview

Property24 Scraper | South Africa collects structured property listing data from Property24, including listing details, prices, locations, property attributes, media references, agency information, agent profiles, and source metadata when available. [Property24](https://www.property24.com) is one of South Africa's major public property portals, making its listing data useful for market research, pricing analysis, lead enrichment, and operational reporting. The actor turns repeatable property searches into normalized JSON records that can be used in analytics tools, CRMs, data warehouses, and downstream APIs. It is designed for automated, recurring data acquisition workflows where consistent output shape and clear run configuration matter. Results reflect the public data available at run time and should be validated against your business requirements before being used in production workflows.

### Why Use This Actor

- **Market research and analytics teams:** build structured extraction workflows for property supply, pricing bands, location coverage, listing movement, and portfolio-level market intelligence.
- **Product and content teams:** populate internal property experiences, comparison tools, editorial datasets, and search-quality reviews with normalized public listing attributes.
- **Developers and data engineering teams:** deliver repeatable collection into downstream systems, enrichment pipelines, warehouses, and operational reporting without manual copy-and-paste work.
- **Lead generation and enrichment teams:** create targeted prospect datasets using public listing, agency, and agent fields such as property category, area, price range, and contact-availability indicators.
- **Monitoring and competitive tracking teams:** schedule recurring runs to observe pricing changes, new availability, listing mix, property features, and geographic coverage over time.

### Common Use Cases

- **Market intelligence:** monitor supply, pricing, availability, property types, locations, and feature distribution across South African property markets.
- **Lead generation:** build targeted prospect lists from public property listings, agencies, and agent profiles.
- **Competitive monitoring:** track listing activity, pricing bands, inventory changes, and agent or agency presence across selected locations.
- **Catalog and directory building:** populate internal databases with structured public property records for review, search, or matching workflows.
- **Data enrichment:** add current public property attributes, media references, and location details to existing CRM, BI, or analytics datasets.
- **Recurring reporting:** schedule periodic runs for dashboards, alerts, historical trend analysis, and operational reporting.

### Quick Start

1. Add a required `location` value, such as `Western Cape`, `Cape Town`, or `woodstock, cape town`.
2. Choose the `deal_type` that matches your market scope: sale listings, rental listings, or sold property records.
3. Set a small `limit` for the first validation run, such as 10 or 25 results per location.
4. Add only the filters that matter for the first run, such as price range, property type, bedrooms, or features.
5. Run the actor in Apify Console and inspect the first dataset records to confirm the output shape.
6. Increase coverage, refine filters, keep or disable `enrich_data`, or schedule recurring runs once the records match your workflow.

### Input Parameters

The actor accepts Property24 location searches plus optional market, price, size, room, feature, sort, enrichment, limit, and connection settings.

| Parameter | Type | Description | Default |
| --- | --- | --- | --- |
| `location` | string | Required. City, suburb, neighborhood, area, or region to search. Use a name a Property24 user would naturally search for, such as `Western Cape`, `Cape Town`, or `woodstock, cape town`. | – |
| `deal_type` | string | Listing market to collect. Allowed values: `Properties For Sale`, `Properties For Rent`, `Sold Properties`. | `Properties For Rent` |
| `min_price` | integer | Minimum listing price to include, in South African rand (ZAR). Use whole numbers without currency symbols. | – |
| `max_price` | integer | Maximum listing price to include, in South African rand (ZAR). Use whole numbers without currency symbols. | – |
| `min_property_area` | integer | Minimum floor area to include, in square meters. | – |
| `max_property_area` | integer | Maximum floor area to include, in square meters. | – |
| `min_land_area` | integer | Minimum land area to include, in square meters. | – |
| `max_land_area` | integer | Maximum land area to include, in square meters. | – |
| `min_bedroom` | integer | Minimum number of bedrooms required. | – |
| `min_bathroom` | integer | Minimum number of bathrooms required. | – |
| `min_parking` | string | Minimum number of parking spaces. Allowed values: `1`, `2`, `3`, `4`, `5`. | – |
| `furnished` | string | Furnishing filter. Allowed values: `furnished_only`, `unfurnished_only`. Leave empty to include both where available. | – |
| `property_type` | array of strings | Property categories to include. Allowed values: `house`, `apartment_flat`, `townhouse`, `vacant_land_plot`, `farm`, `commercial_property`, `industrial_property`. | – |
| `features` | array of strings | Required listing features. Allowed values: `pet_friendly`, `garden`, `pool`, `flatlet`. | – |
| `rental_term` | array of strings | Rental billing terms to include when collecting rental listings. Allowed values: `monthly`, `weekly`, `daily`, `yearly`, `per_square_metre`. | – |
| `sort_by` | string | Result ordering before collection. Allowed values: `default`, `lowest_price`, `highest_price`, `most_recent`, `available_date_ascending`, `available_date_descending`, `property_type`, `size`. | – |
| `enrich_data` | boolean | When enabled, collects richer listing-level records when available, including descriptions, property overview details, media, agency, agent, and feature information. | `true` |
| `limit` | integer | Maximum number of listings to save per provided location or input. | – |
| `proxyConfiguration` | object | Apify proxy or custom proxy configuration for connection behavior. The default is suitable for most runs. | `{"useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"]}` |

### Choosing Inputs

Use `location` as the primary required scope control. Broader locations, such as `Western Cape` or large cities like `Cape Town`, improve discovery and are useful for market scans; narrower suburbs or neighborhoods, such as `woodstock, cape town`, produce more targeted datasets for local analysis.

Choose `deal_type` first because sale, rental, and sold-property records represent different market contexts. Add filters such as `min_price`, `max_price`, area ranges, bedrooms, bathrooms, parking, `property_type`, `features`, `furnished`, and `rental_term` when you need a focused segment. Narrower filters reduce noise and improve segmentation, while broader filters help you discover more inventory.

Use `sort_by` to prioritize which records are collected first when a `limit` is set. Start with a small `limit` to validate record shape and coverage, then increase it after confirming the dataset is suitable for your workflow. `enrich_data` is enabled by default for detailed listing records; turn it off for quick validation runs or summary-level collection.

### Example Inputs

#### Scenario: Rental Market Validation Run

```json
{
  "location": "Cape Town City Centre",
  "deal_type": "Properties For Rent",
  "min_price": 12000,
  "max_price": 35000,
  "property_type": ["apartment_flat"],
  "sort_by": "most_recent",
  "limit": 25
}
````

#### Scenario: For-Sale Family Homes

```json
{
  "location": "Sandton",
  "deal_type": "Properties For Sale",
  "min_price": 2500000,
  "max_price": 8000000,
  "min_bedroom": 3,
  "min_bathroom": 2,
  "property_type": ["house", "townhouse"],
  "limit": 50
}
```

#### Scenario: Furnished Apartments With Detailed Records

```json
{
  "location": "Umhlanga",
  "deal_type": "Properties For Rent",
  "furnished": "furnished_only",
  "features": ["pool"],
  "rental_term": ["monthly"],
  "enrich_data": true,
  "limit": 40
}
```

### Output

#### 9.1 Output Destination

The actor writes results to an Apify dataset as JSON records. The dataset is designed for direct consumption by analytics tools, ETL pipelines, and downstream APIs with minimal post-processing.

When multiple entity types or record shapes exist, this README documents each shape separately based on the provided Example Output. The provided output contains one listing record shape.

#### 9.2 Record Envelope And Stable Identifiers

Each dataset item represents a Property24 listing record with listing-level fields, nested pricing, location, property detail, media, agency, agent, and source context objects where available. The recommended idempotency key is `listing_id`; if your storage system requires a URL-based key, use `url` as a secondary stable identifier. Use `source_context.fingerprint` as an additional run-safe deduplication aid when comparing repeated collections.

For deduplication and upserts, store records by `listing_id` and update mutable fields such as price, media count, listing attributes, and `source_context.scraped_time` on later runs. Stable identifiers make records easier to merge, deduplicate, and sync across repeated runs. `source_context.source_url`, `source_context.loaded_url`, and `source_context.detail_url` document the public source context used for the record, while `source_context.fingerprint` provides a compact content-derived identifier for comparison workflows.

#### 9.3 Examples

##### Example: listing

```json
{
  "listing_id": "116494344",
  "url": "https://www.property24.com/for-sale/cape-town-city-centre/cape-town/western-cape/9138/116494344",
  "title": "2 Bedroom Apartment / Flat for sale in Cape Town City Centre",
  "property_type": "apartment_flat",
  "transaction_type": "for_sale",
  "description": "Wake up to breathtaking harbour and mountain views in this exquisitely renovated corner apartment at Harbour Arch, the perfect balance of luxury, comfort, and city sophistication. This two-bedroom, two-bathroom residence is designed for effortless modern living. Both spacious bedrooms feature stylish en-suite bathrooms, while floor-to-ceiling windows frame uninterrupted views and flood the apartment with natural light. Every detail has been considered, from the sleek electric curtains to the brand new appliances including a washer-dryer, dishwasher, and fridge that make day-to-day living seamless. The refined finishes and thoughtful layout create a home that is both elegant and practical. Life at Harbour Arch comes with access to world-class amenities: a state-of-the-art gym, sparkling outdoor pool, laundromat, and a communal workspace with a convenient coffee station. Round-the-clock security provides complete peace of mind, while the building’s policy against short-term rentals ensures a calm, private, and community-focused atmosphere that is perfect for those who value stability and quiet luxury in the heart of Cape Town. This is more than just an apartment, it is a lifestyle investment in one of the city’s most iconic developments.",
  "pricing": {
    "display_price": "R 3 900 000",
    "amount": 3900000,
    "currency": "ZAR",
    "price_per_square_meter": {
      "display": "R 53 425",
      "amount": 53425,
      "currency": "ZAR"
    },
    "levies": {
      "display": "R 3 500",
      "amount": 3500,
      "currency": "ZAR"
    },
    "rates_and_taxes": {
      "display": "R 2 300",
      "amount": 2300,
      "currency": "ZAR"
    }
  },
  "location": {
    "locality": "Cape Town City Centre",
    "region": "Western Cape",
    "country": "South Africa",
    "display": "Cape Town City Centre",
    "address": "Cape Town City Centre, Cape Town"
  },
  "property_details": {
    "bedrooms": 2,
    "bathrooms": 2,
    "kitchens": 1,
    "reception_rooms": 1,
    "floor_size": {
      "display": "73 m²",
      "value": 73,
      "unit": "m²"
    },
    "listed_date": "2025-10-01",
    "listed_date_text": "01 October 2025",
    "description_title": "Luxury Sky-High Living | Renovated 2-Bed, 2-Bath Corner Unit | Harbour Arch",
    "pets_allowed": false,
    "furnished": true,
    "features": {
      "pool": true
    }
  },
  "media": {
    "primary_image_url": "https://images.prop24.com/354768597/Crop526x328",
    "image_urls": [
      "https://images.prop24.com/354768611/Ensure1280x720",
      "https://images.prop24.com/354768611",
      "https://images.prop24.com/354768610/Ensure1280x720",
      "https://images.prop24.com/354768610",
      "https://images.prop24.com/354768613/Ensure1280x720",
      "https://images.prop24.com/354768613",
      "https://images.prop24.com/354768612/Ensure1280x720",
      "https://images.prop24.com/354768612",
      "https://images.prop24.com/354768614/Ensure1280x720",
      "https://images.prop24.com/354768614",
      "https://images.prop24.com/354768615/Ensure1280x720",
      "https://images.prop24.com/354768615",
      "https://images.prop24.com/354768616/Ensure1280x720",
      "https://images.prop24.com/354768616",
      "https://images.prop24.com/354768617/Ensure1280x720",
      "https://images.prop24.com/354768617",
      "https://images.prop24.com/354768618/Ensure1280x720",
      "https://images.prop24.com/354768618",
      "https://images.prop24.com/354768625/Ensure1280x720",
      "https://images.prop24.com/354768625",
      "https://images.prop24.com/354768623/Ensure1280x720",
      "https://images.prop24.com/354768623",
      "https://images.prop24.com/354768621/Ensure1280x720",
      "https://images.prop24.com/354768621",
      "https://images.prop24.com/354768627/Ensure1280x720",
      "https://images.prop24.com/354768627",
      "https://images.prop24.com/354768632/Ensure1280x720",
      "https://images.prop24.com/354768632",
      "https://images.prop24.com/354768630/Ensure1280x720",
      "https://images.prop24.com/354768630"
    ],
    "image_count": 63
  },
  "agency": {
    "name": "Sotheby's International Realty - Atlantic Seaboard & City Bowl",
    "url": "https://www.property24.com/estate-agents/sothebys-international-realty-atlantic-seaboard-and-city-bowl/33627",
    "image_url": "https://images.prop24.com/369545662/Fit450x225"
  },
  "agents": [
    {
      "id": "348161",
      "name": "Ben Gross",
      "job_title": "Candidate Property Practitioner",
      "profile_url": "https://www.property24.com/estate-agents/sothebys-international-realty-atlantic-seaboard-and-city-bowl/ben-gross/348161",
      "image_url": "https://images.prop24.com/287530573/UpperCrop200x200",
      "published": true,
      "has_contact_number": true,
      "can_show_whatsapp": true
    },
    {
      "id": "471169",
      "name": "Christy Watson",
      "job_title": "Candidate Property Practitioner",
      "profile_url": "https://www.property24.com/estate-agents/sothebys-international-realty-atlantic-seaboard-and-city-bowl/christy-watson/471169",
      "image_url": "https://images.prop24.com/315040879/UpperCrop200x200",
      "published": true,
      "has_contact_number": true,
      "can_show_whatsapp": true
    },
    {
      "id": "516154",
      "name": "The City Centre Administrator",
      "job_title": "Personal Assistant",
      "profile_url": "https://www.property24.com/estate-agents/sothebys-international-realty-atlantic-seaboard-and-city-bowl/the-city-centre-administrator/516154",
      "image_url": "https://images.prop24.com/346423443/UpperCrop200x200",
      "published": true,
      "has_contact_number": true,
      "can_show_whatsapp": true
    }
  ],
  "source_context": {
    "source": "Property24",
    "domain": "www.property24.com",
    "source_url": "https://www.property24.com/for-sale/cape-town-city-centre/cape-town/western-cape/9138",
    "loaded_url": "https://www.property24.com/for-sale/cape-town-city-centre/cape-town/western-cape/9138",
    "detail_url": "https://www.property24.com/for-sale/cape-town-city-centre/cape-town/western-cape/9138/116494344",
    "scraped_time": "2026-05-05T13:11:13.863684Z",
    "fingerprint": "ef18e121d66773b3f391",
    "seed": {
      "id": "cdc8fab7df8a",
      "type": "query",
      "value": "Cape Town City Centre"
    },
    "page_index": 1
  }
}
```

### Field Reference

#### Listing Record

**listing\_id** *(string, required)*: Stable Property24 listing identifier.

**url** *(string, required)*: Public listing URL.

**title** *(string, optional)*: Listing headline or title.

**property\_type** *(string, optional)*: Property category, such as apartment, house, townhouse, land, commercial, or industrial property.

**transaction\_type** *(string, optional)*: Transaction category, such as `for_sale`.

**description** *(string, optional)*: Public listing description.

**pricing.display\_price** *(string, optional)*: Human-readable listing price.

**pricing.amount** *(number, optional)*: Numeric price amount in `pricing.currency`.

**pricing.currency** *(string, optional)*: Currency code, typically `ZAR`.

**pricing.price\_per\_square\_meter.display** *(string, optional)*: Human-readable price per square meter.

**pricing.price\_per\_square\_meter.amount** *(number, optional)*: Numeric price per square meter.

**pricing.price\_per\_square\_meter.currency** *(string, optional)*: Currency code for price per square meter.

**pricing.levies.display** *(string, optional)*: Human-readable levy amount.

**pricing.levies.amount** *(number, optional)*: Numeric levy amount.

**pricing.levies.currency** *(string, optional)*: Currency code for levies.

**pricing.rates\_and\_taxes.display** *(string, optional)*: Human-readable rates and taxes amount.

**pricing.rates\_and\_taxes.amount** *(number, optional)*: Numeric rates and taxes amount.

**pricing.rates\_and\_taxes.currency** *(string, optional)*: Currency code for rates and taxes.

**location.locality** *(string, optional)*: Local area, suburb, or neighborhood.

**location.region** *(string, optional)*: Province or broader region.

**location.country** *(string, optional)*: Country name.

**location.display** *(string, optional)*: Display location label.

**location.address** *(string, optional)*: Public address or area-level address text.

**property\_details.bedrooms** *(number, optional)*: Number of bedrooms.

**property\_details.bathrooms** *(number, optional)*: Number of bathrooms.

**property\_details.kitchens** *(number, optional)*: Number of kitchens.

**property\_details.reception\_rooms** *(number, optional)*: Number of reception rooms.

**property\_details.floor\_size.display** *(string, optional)*: Human-readable floor size.

**property\_details.floor\_size.value** *(number, optional)*: Numeric floor size.

**property\_details.floor\_size.unit** *(string, optional)*: Floor-size unit, typically `m²`.

**property\_details.listed\_date** *(string, optional)*: Listing date in ISO date format when available.

**property\_details.listed\_date\_text** *(string, optional)*: Listing date as shown by the source.

**property\_details.description\_title** *(string, optional)*: Description heading or promotional listing subtitle.

**property\_details.pets\_allowed** *(boolean, optional)*: Whether pets are indicated as allowed.

**property\_details.furnished** *(boolean, optional)*: Whether the listing is indicated as furnished.

**property\_details.features.pool** *(boolean, optional)*: Whether a pool is indicated in listing features.

**media.primary\_image\_url** *(string, optional)*: Primary listing image URL.

**media.image\_urls** *(array of strings, optional)*: Listing image URLs.

**media.image\_count** *(number, optional)*: Number of images reported for the listing.

**agency.name** *(string, optional)*: Agency name.

**agency.url** *(string, optional)*: Public agency profile URL.

**agency.image\_url** *(string, optional)*: Agency image or logo URL.

**agents** *(array of objects, optional)*: Public agent records associated with the listing.

**agents.id** *(string, optional)*: Agent identifier.

**agents.name** *(string, optional)*: Agent name.

**agents.job\_title** *(string, optional)*: Agent role or title.

**agents.profile\_url** *(string, optional)*: Public agent profile URL.

**agents.image\_url** *(string, optional)*: Agent image URL.

**agents.published** *(boolean, optional)*: Whether the agent profile is publicly published.

**agents.has\_contact\_number** *(boolean, optional)*: Whether the source indicates a contact number is available.

**agents.can\_show\_whatsapp** *(boolean, optional)*: Whether the source indicates WhatsApp can be shown.

**source\_context.source** *(string, required)*: Source name.

**source\_context.domain** *(string, required)*: Source domain.

**source\_context.source\_url** *(string, optional)*: Public source URL associated with the listing collection context.

**source\_context.loaded\_url** *(string, optional)*: Public URL loaded for the source context.

**source\_context.detail\_url** *(string, optional)*: Public listing detail URL.

**source\_context.scraped\_time** *(string, required)*: UTC timestamp when the record was collected.

**source\_context.fingerprint** *(string, optional)*: Compact identifier useful for deduplication and repeated-run comparison.

**source\_context.seed.id** *(string, optional)*: Identifier for the input seed that produced the record.

**source\_context.seed.type** *(string, optional)*: Seed type, such as `query`.

**source\_context.seed.value** *(string, optional)*: Input seed value, such as the searched location.

**source\_context.page\_index** *(number, optional)*: Source result page index associated with the record.

### Data Quality, Guarantees, And Handling

- **Structured records:** results are normalized into predictable JSON objects for downstream use.
- **Best-effort extraction:** fields may vary by region, session, availability, listing type, source-side presentation, or public data quality.
- **Optional fields:** null-check optional fields in downstream code, especially descriptions, media, agent details, fees, features, and listing-specific attributes.
- **Deduplication:** use `listing_id` as the strongest stable key from the output, with `url` or `source_context.fingerprint` as supporting identifiers where useful.
- **Freshness:** results reflect the publicly available data at run time.
- **Repeated runs:** use the recommended idempotency key when syncing data into warehouses, CRMs, search indexes, or reporting systems.

### Tips For Best Results

- Start with a small `limit` to validate the output shape before scaling up.
- Use one geography or segment per run when you need cleaner reporting and easier comparison.
- Leave optional filters empty when the goal is broad discovery.
- Add price, area, room, property type, and feature filters gradually to understand how each field changes coverage.
- Use `sort_by` with `limit` when the order of collected results matters, such as newest listings or lowest price first.
- Keep `enrich_data` enabled when your workflow needs detailed listing descriptions, media, agency, and agent fields.
- Use `listing_id` for deduplication when storing results over time.

### How To Run On Apify

1. Open the Actor in Apify Console.
2. Configure the available input fields for the target scope, starting with `location` and `deal_type`.
3. Set the maximum number of outputs to collect with `limit`.
4. Click **Start** and wait for the run to finish.
5. Open the dataset and review the first records.
6. Download results in JSON, CSV, Excel, or other supported formats.

### Scheduling & Automation

#### Scheduling

**Automated Data Collection**

Schedule runs to keep property datasets fresh for dashboards, market monitoring, and enrichment workflows. Use a cadence that matches how often your team needs to review changes in inventory, pricing, or listing availability.

- Navigate to **Schedules** in Apify Console
- Create a new schedule, such as daily, weekly, or custom cron
- Configure input parameters
- Enable notifications for run completion
- Add webhooks for automated processing

#### Integration Options

- **BI dashboards:** monitor pricing, availability, property mix, geographic coverage, and listing counts over time.
- **Data warehouses:** store normalized listing records for historical analysis, modeling, and operational reporting.
- **CRM enrichment:** sync public property, agency, and agent attributes into account or lead records.
- **Google Sheets or Airtable:** review smaller market segments, validate output samples, and coordinate lightweight sourcing workflows.
- **Webhooks:** trigger ingestion, validation, alerting, or notification workflows after each completed run.
- **Data enrichment pipelines:** combine Property24 listing records with internal CRM, portfolio, or market datasets.

### Export Formats And Downstream Use

Apify datasets can be exported or consumed by downstream systems depending on your workflow and volume requirements.

- **JSON:** for APIs, applications, and data pipelines
- **CSV or Excel:** for spreadsheet workflows and manual review
- **API access:** for automated ingestion into internal systems
- **BI and warehouses:** for reporting, dashboards, and historical analysis

### Performance

Estimated run times:

- **Small runs (< 1,000 outputs):** ~3-5 minutes
- **Medium runs (1,000-5,000 outputs):** ~5-15 minutes
- **Large runs (5,000+ outputs):** ~15-30 minutes

Execution time varies based on filters, result volume, and how much information is returned per record. Highly filtered runs can finish faster, while broad discovery or detail-rich records may take longer.

### Limitations

- Availability depends on what <https://www.property24.com> publicly exposes at run time.
- Some optional fields may be missing on sparse listings, sold-property records, or records without full public details.
- Very broad searches may take longer or require higher `limit` values to collect enough records.
- Target-side changes can affect field availability, naming, or presentation.
- Regional, account, availability, or listing-type differences may change visible results.
- `enrich_data` can increase record detail and may also increase run time.

### Troubleshooting

- **No results returned:** check filters, location spelling, selected `deal_type`, and whether Property24 has matching public records for the requested scope.
- **Fewer results than expected:** broaden filters, raise `limit`, or verify that the target contains enough matching listings.
- **Some fields are empty:** optional fields depend on what each public listing provides.
- **Run takes longer than expected:** reduce scope, lower `limit` for validation, or split broad collection into smaller location or property-type segments.
- **Output changed:** compare the current output with the field reference and report a small sample if support is needed.

### FAQ

#### What data does this actor collect?

It collects public Property24 listing data for South Africa, including listing identifiers, URLs, titles, transaction type, prices, locations, property details, media, agency information, agent information, and source context when available.

#### Can I filter by location, category, date, price, or other criteria?

You can filter by `location`, `deal_type`, price range, property area, land area, bedrooms, bathrooms, parking, furnishing status, property type, features, rental terms, and sort order. Date-specific input filters are not part of the current input schema.

#### Why did I receive fewer results than my limit?

The `limit` is a maximum, not a guaranteed count. A run may return fewer records when the selected location, market, filters, or public availability do not contain enough matching listings.

#### Can I schedule recurring runs?

Yes. Use Apify schedules to run the actor on a daily, weekly, or custom cadence for monitoring, reporting, enrichment, or historical tracking.

#### How do I avoid duplicates across runs?

Use `listing_id` as the primary idempotency key. You can also store `url` and `source_context.fingerprint` to support validation, comparison, and audit workflows.

#### Can I export the data to CSV, Excel, or JSON?

Yes. Apify datasets support exports including JSON, CSV, Excel, and other formats available in Apify Console.

#### Does this actor collect private data?

No. The actor is intended to collect publicly available information from Property24. Users are responsible for using the data in accordance with applicable laws, regulations, and the target site's terms.

#### How do I control detailed listing data?

`enrich_data` is enabled by default for fuller listing descriptions, media, agency information, and agent fields. Set it to `false` for faster validation runs or when summary-level output is sufficient.

#### What should I include when reporting an issue?

Include the input used, the run ID, expected versus actual behavior, and a small output sample when relevant. Redact any sensitive operational information before sharing.

### Compliance & Ethics

#### Responsible Data Collection

This actor collects publicly available real estate listing information from <https://www.property24.com> for legitimate business purposes, including:

- **Real estate** research and market analysis
- Property inventory monitoring and pricing intelligence
- CRM, BI, and operational data enrichment

Users are responsible for ensuring that their use of collected data complies with applicable laws, regulations, contractual obligations, and the target site's terms. This section is informational and not legal advice.

#### Best Practices

- Use collected data in accordance with applicable laws, regulations, and the target site's terms
- Respect individual privacy and personal information
- Use data responsibly and avoid disruptive or excessive collection
- Do not use this actor for spamming, harassment, or other harmful purposes
- Follow relevant data protection requirements where applicable, such as GDPR and CCPA

### Support

For help, use the actor page or Issues channel associated with this actor. Include the input used with sensitive values redacted, the Apify run ID, expected versus actual behavior, and a small output sample if it helps illustrate the issue.

# Actor input Schema

## `location` (type: `string`):

Required. Enter a location name in a shape that Property24 recognizes. Accepted shapes include province or region, city, suburb, neighborhood, district, or area. Examples: "Western Cape" for a province or region, "Cape Town" for a city, or "Woodstock, Cape Town" for a suburb with its city.

## `deal_type` (type: `string`):

Choose whether the run should collect properties for sale, properties for rent, or sold property records for the locations you entered.

## `min_price` (type: `integer`):

Enter the lowest listing price to include, using whole numbers without currency symbols. Leaving this empty includes listings below any chosen maximum.

## `max_price` (type: `integer`):

Enter the highest listing price to include, using whole numbers without currency symbols. Leaving this empty includes listings above any chosen minimum.

## `min_property_area` (type: `integer`):

Enter the smallest property floor area to include, in square meters. Leave empty when floor area should not narrow the results.

## `max_property_area` (type: `integer`):

Enter the largest property floor area to include, in square meters. Use this with a minimum area for a defined floor-size range.

## `min_land_area` (type: `integer`):

Enter the smallest land area to include, in square meters. This is useful when plot size matters more than interior floor area.

## `max_land_area` (type: `integer`):

Enter the largest land area to include, in square meters. Leave empty when larger plots should remain eligible.

## `min_bedroom` (type: `integer`):

Enter the minimum number of bedrooms a listing must have. Leave empty to include studio, one-bedroom, and other smaller configurations.

## `min_bathroom` (type: `integer`):

Enter the minimum number of bathrooms a listing must have. Use this with bedroom filters when you need a specific layout profile.

## `min_parking` (type: `string`):

Choose the minimum number of parking spaces required for each listing. Leave blank when parking should not affect the search.

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

Choose furnished-only or unfurnished-only results when furnishing status is a required part of the brief. Leave blank to include both where available.

## `property_type` (type: `array`):

Select one or more property types to include. Leave empty to keep the search open across all supported property categories.

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

Select required features such as pet friendly, garden, pool, or flatlet. Each selected feature narrows the results toward listings that match those requirements.

## `rental_term` (type: `array`):

Select rental billing terms to include when collecting rental listings. This setting is most useful when the selected market is Properties For Rent.

## `sort_by` (type: `string`):

Select the ordering that best matches the workflow, such as newest listings first, price order, availability date, property type, or size.

## `enrich_data` (type: `boolean`):

Enable this for more complete property listing records. This may make the run slower because the actor may spend more time collecting details for each result. Turn it off for faster runs when the standard result fields are enough.

## `limit` (type: `integer`):

Enter the maximum number of listings to save for each provided location or input. Leave empty to collect without this per-input cap.

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

Choose an Apify proxy or custom proxy configuration when you need more controlled connection behavior. Keep the default unless your organization requires a different setup.

## Actor input object example

```json
{
  "location": "Cape Town",
  "deal_type": "Properties For Rent",
  "enrich_data": true,
  "limit": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `results` (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 = {
    "location": "Cape Town",
    "limit": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("fatihtahta/property24-scraper-za").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 = {
    "location": "Cape Town",
    "limit": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("fatihtahta/property24-scraper-za").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "location": "Cape Town",
  "limit": 100
}' |
apify call fatihtahta/property24-scraper-za --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=fatihtahta/property24-scraper-za",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Property24 Scraper | South Africa",
        "description": "Extract structured Real estate listings across South Africa from Property24.com with property details, agent profiles, full descriptions, media and more. Built for enterprise-grade real estate intelligence, lead enrichment, market analysis, and automated data pipelines.",
        "version": "0.0",
        "x-build-id": "McpyKCVMacB2vagRO"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/fatihtahta~property24-scraper-za/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-fatihtahta-property24-scraper-za",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/fatihtahta~property24-scraper-za/runs": {
            "post": {
                "operationId": "runs-sync-fatihtahta-property24-scraper-za",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/fatihtahta~property24-scraper-za/run-sync": {
            "post": {
                "operationId": "run-sync-fatihtahta-property24-scraper-za",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "location"
                ],
                "properties": {
                    "location": {
                        "title": "Add Search Location",
                        "minLength": 1,
                        "type": "string",
                        "description": "Required. Enter a location name in a shape that Property24 recognizes. Accepted shapes include province or region, city, suburb, neighborhood, district, or area. Examples: \"Western Cape\" for a province or region, \"Cape Town\" for a city, or \"Woodstock, Cape Town\" for a suburb with its city."
                    },
                    "deal_type": {
                        "title": "Select Listing Market",
                        "enum": [
                            "Properties For Sale",
                            "Properties For Rent",
                            "Sold Properties"
                        ],
                        "type": "string",
                        "description": "Choose whether the run should collect properties for sale, properties for rent, or sold property records for the locations you entered.",
                        "default": "Properties For Rent"
                    },
                    "min_price": {
                        "title": "Set Minimum Price",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Enter the lowest listing price to include, using whole numbers without currency symbols. Leaving this empty includes listings below any chosen maximum."
                    },
                    "max_price": {
                        "title": "Set Maximum Price",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Enter the highest listing price to include, using whole numbers without currency symbols. Leaving this empty includes listings above any chosen minimum."
                    },
                    "min_property_area": {
                        "title": "Set Minimum Floor Area",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Enter the smallest property floor area to include, in square meters. Leave empty when floor area should not narrow the results."
                    },
                    "max_property_area": {
                        "title": "Set Maximum Floor Area",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Enter the largest property floor area to include, in square meters. Use this with a minimum area for a defined floor-size range."
                    },
                    "min_land_area": {
                        "title": "Set Minimum Land Area",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Enter the smallest land area to include, in square meters. This is useful when plot size matters more than interior floor area."
                    },
                    "max_land_area": {
                        "title": "Set Maximum Land Area",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Enter the largest land area to include, in square meters. Leave empty when larger plots should remain eligible."
                    },
                    "min_bedroom": {
                        "title": "Set Minimum Bedrooms",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Enter the minimum number of bedrooms a listing must have. Leave empty to include studio, one-bedroom, and other smaller configurations."
                    },
                    "min_bathroom": {
                        "title": "Set Minimum Bathrooms",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Enter the minimum number of bathrooms a listing must have. Use this with bedroom filters when you need a specific layout profile."
                    },
                    "min_parking": {
                        "title": "Set Minimum Parking Spaces",
                        "enum": [
                            "1",
                            "2",
                            "3",
                            "4",
                            "5"
                        ],
                        "type": "string",
                        "description": "Choose the minimum number of parking spaces required for each listing. Leave blank when parking should not affect the search."
                    },
                    "furnished": {
                        "title": "Filter Furnishing Status",
                        "enum": [
                            "furnished_only",
                            "unfurnished_only"
                        ],
                        "type": "string",
                        "description": "Choose furnished-only or unfurnished-only results when furnishing status is a required part of the brief. Leave blank to include both where available."
                    },
                    "property_type": {
                        "title": "Choose Property Types",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Select one or more property types to include. Leave empty to keep the search open across all supported property categories.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "house",
                                "apartment_flat",
                                "townhouse",
                                "vacant_land_plot",
                                "farm",
                                "commercial_property",
                                "industrial_property"
                            ],
                            "enumTitles": [
                                "House",
                                "Apartment / Flat",
                                "Townhouse",
                                "Vacant Land / Plot",
                                "Farm",
                                "Commercial Property",
                                "Industrial Property"
                            ]
                        }
                    },
                    "features": {
                        "title": "Choose Listing Features",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Select required features such as pet friendly, garden, pool, or flatlet. Each selected feature narrows the results toward listings that match those requirements.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "pet_friendly",
                                "garden",
                                "pool",
                                "flatlet"
                            ],
                            "enumTitles": [
                                "Pet friendly",
                                "Garden",
                                "Pool",
                                "Flatlet"
                            ]
                        }
                    },
                    "rental_term": {
                        "title": "Choose Rental Terms",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Select rental billing terms to include when collecting rental listings. This setting is most useful when the selected market is Properties For Rent.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "monthly",
                                "weekly",
                                "daily",
                                "yearly",
                                "per_square_metre"
                            ],
                            "enumTitles": [
                                "Monthly",
                                "Weekly",
                                "Daily",
                                "Yearly",
                                "Per square metre"
                            ]
                        }
                    },
                    "sort_by": {
                        "title": "Choose Sort Order",
                        "enum": [
                            "default",
                            "lowest_price",
                            "highest_price",
                            "most_recent",
                            "available_date_ascending",
                            "available_date_descending",
                            "property_type",
                            "size"
                        ],
                        "type": "string",
                        "description": "Select the ordering that best matches the workflow, such as newest listings first, price order, availability date, property type, or size."
                    },
                    "enrich_data": {
                        "title": "Collect Richer Real Estate Listing Details",
                        "type": "boolean",
                        "description": "Enable this for more complete property listing records. This may make the run slower because the actor may spend more time collecting details for each result. Turn it off for faster runs when the standard result fields are enough.",
                        "default": true
                    },
                    "limit": {
                        "title": "Set Maximum Results per Input",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Enter the maximum number of listings to save for each provided location or input. Leave empty to collect without this per-input cap."
                    },
                    "proxyConfiguration": {
                        "title": "Set Up Proxy Connection",
                        "type": "object",
                        "description": "Choose an Apify proxy or custom proxy configuration when you need more controlled connection behavior. Keep the default unless your organization requires a different setup.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ]
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
