# Private Property Scraper - South Africa Real Estate Listings (`igolaizola/privateproperty-scraper`) Actor

Scrape privateproperty.co.za for South African real estate homes, rentals, farms, commercial listings, and developments with prices, rooms, sizes, amenities, security, photos, links, and advertiser details. Export JSON, CSV, or Excel datasets and connect property research to API or MCP workflows

- **URL**: https://apify.com/igolaizola/privateproperty-scraper.md
- **Developed by:** [Iñigo Garcia Olaizola](https://apify.com/igolaizola) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Private Property Scraper — South Africa Listings

Find and organize property listings from [Private Property](https://www.privateproperty.co.za/) for sale and rent. Collect prices, locations, property details, photos, listing links, features, status information, and contact-ready advertiser details—including available phone numbers—for market research, lead generation, investment analysis, and property monitoring.

### 🤖 What does Private Property Scraper do?

Private Property Scraper helps you discover South African real estate listings in a clean, export-ready dataset. Search by city, suburb, or area and narrow results by price, rooms, property type, size, amenities, security, and listing status.

- **For-sale listings** — homes, apartments, townhouses, land, farms, commercial properties, and developments.
- **Rental listings** — residential, commercial, and farm properties with rental price-period options.
- **Property research data** — prices, addresses, floor and land areas, photos, descriptions, listing status, and advertiser information.
- **Contact-ready details** — enable detailed results to capture available advertiser mobile, work, and home numbers alongside the matching contact.
- **Flexible exports** — download JSON, CSV, or Excel files, or connect your results to an API or MCP workflow.

**Great for:** property market research, real-estate lead generation, investment shortlists, agency prospecting, and price monitoring.

> SEO keywords: **Private Property scraper**, **privateproperty.co.za scraper**, **South Africa real estate data**, **property listing scraper**, **rental listings scraper**, **real estate API alternative**, **Apify actor**.

### 💡 Why use Private Property Scraper?

- 📈 **Track local markets** — compare asking prices and property supply across cities and suburbs.
- 🎯 **Build prospect lists** — find relevant listings with contact names and available phone numbers for agency and broker workflows.
- 🏠 **Find investment opportunities** — combine budgets, room counts, property types, and area requirements.
- 🔎 **Monitor changes** — identify new, featured, exclusive, on-show, or price-reduced listings.
- 📊 **Create reusable datasets** — send structured property data to spreadsheets, dashboards, CRMs, and research tools.

### 🚀 How to use

1. Open **Private Property Scraper** in Apify Store and click **Try for free**.
2. Keep the prefilled **Cape Town** location or enter a city, suburb, or area.
3. Choose **For sale** or **For rent**, then add the filters you need.
4. Set `maxItems` and click **Start**.
5. Review listings in the Dataset tab and download them as JSON, CSV, or Excel.

The default location is **Cape Town**, so the first run starts with a realistic local search. Use `maxItems: 0` when you want all available matching listings.

### 💳 Pricing

Apify's **Free plan** includes monthly credits for testing and small collections. For larger market research projects, recurring monitoring, and high-volume exports, choose the Apify plan that fits your usage.

### 📝 Input parameters

All inputs are optional. The default search is for residential properties for sale in Cape Town.

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `maxItems` | Integer | No | Maximum listings to save. Use `0` for all available matching listings. Default: `100`. |
| `location` | Text | No | City, suburb, or area name, such as `Cape Town`, `Sandton`, or `Durban`. Default: `Cape Town`. |
| `listingType` | `sale` · `rent` | No | Choose **For sale** or **For rent**. Default: `sale`. |
| `category` | `residential` · `commercial` · `farm` · `development` | No | Broad property category. `development` is available for sale searches. Default: `residential`. |
| `minPrice` | Integer in ZAR | No | Minimum asking price. Use `0` for any price. |
| `maxPrice` | Integer in ZAR | No | Maximum asking price. Use `0` for any price. |
| `bedrooms` | Integer | No | Minimum bedrooms. Applies to residential and farm searches. |
| `bathrooms` | Integer | No | Minimum bathrooms. Applies to residential and farm searches. |
| `garages` | Integer | No | Minimum garages. Applies to residential searches. |
| `parkings` | Integer | No | Minimum parking spaces. Applies to residential searches. |
| `minFloorSize` | Integer in m² | No | Minimum indoor floor area. |
| `maxFloorSize` | Integer in m² | No | Maximum indoor floor area. |
| `minLandSize` | Integer in m² | No | Minimum land area. |
| `maxLandSize` | Integer in m² | No | Maximum land area. |
| `propertyTypes` | List of text values | No | Choose from `house`, `townhouse`, `apartment`, `vacant_land`, `garden_cottage`, `commercial`, `industrial`, `retail`, `office`, `hospitality`, `farm`, `smallholding`, `farm_with_house`, `farmland`, `agricultural_holding`, `commercial_farm`, or `game_farm`. |
| `amenities` | List of text values | No | Choose from `garden`, `patio_or_balcony`, `pets_allowed`, `pool`, `furnished`, `sea_view`, `staff_quarters`, `borehole`, `flatlet`, or `scenic_view`. |
| `securityFeatures` | List of text values | No | Choose from `alarm`, `access_gate`, `electric_fencing`, `security_post`, or `intercom`. |
| `specialFeatures` | List of text values | No | For sale: `on_show` or `bank_sale`. For rent: `electricity_included` or `water_included`. |
| `sortBy` | `relevance` · `newest` · `price` · `size` · `available_from` | No | Primary result ordering. `available_from` is for rental searches. Default: `relevance`. |
| `sortOrder` | `ascending` · `descending` | No | Direction of the selected ordering. Default: `descending`. |
| `rentalPricePeriod` | `monthly` · `weekly` · `daily` · `per_square_metre` | No | Price period for rental searches. |
| `fetchDetails` | Boolean | No | Add extra detail information under `_details`, including available advertiser phone numbers matched to their contacts. This takes longer and uses more resources. Default: `false`. |

#### Example inputs

**1️⃣ Residential homes for sale**

```json
{
  "location": "Cape Town",
  "listingType": "sale",
  "category": "residential",
  "maxItems": 50,
  "minPrice": 1000000,
  "maxPrice": 3500000,
  "bedrooms": 3,
  "amenities": ["garden", "pool"],
  "securityFeatures": ["access_gate", "electric_fencing"],
  "sortBy": "newest"
}
```

**2️⃣ Furnished Johannesburg rentals**

```json
{
  "location": "Johannesburg",
  "listingType": "rent",
  "category": "residential",
  "maxItems": 100,
  "maxPrice": 18000,
  "bedrooms": 2,
  "propertyTypes": ["apartment"],
  "amenities": ["furnished", "pets_allowed"],
  "specialFeatures": ["water_included"],
  "rentalPricePeriod": "monthly",
  "sortBy": "price",
  "sortOrder": "ascending"
}
```

**3️⃣ Commercial property research**

```json
{
  "location": "Durban",
  "listingType": "sale",
  "category": "commercial",
  "propertyTypes": ["office", "retail"],
  "minFloorSize": 250,
  "maxItems": 25,
  "fetchDetails": true
}
```

### 📊 Output and results

Each dataset item is a property listing. The actor preserves the listing information available for that result and adds `_details` when `fetchDetails` is enabled and additional information is available.

#### Field reference

- **`listingId`** *(number)* — Private Property listing identifier.
- **`portalRef`** *(text)* — Listing reference shown by the advertiser.
- **`propertyTitle`** *(text)* — Listing headline.
- **`propertyTypeDescription`** *(text)* — Human-readable property type.
- **`listingPrice`** *(object)* — Asking price and price-status information.
- **`propertyAttributes`** *(object)* — Bedrooms, bathrooms, garages, floor area, and land area.
- **`propertyAddress`** *(text)* — Property address when provided.
- **`propertySuburbName`** *(text)* — Suburb or local area.
- **`shareUrl`** *(link)* — Link to the listing.
- **`mediaImageUrls`** *(list)* — Listing photo links.
- **`propertyDescription`** *(text)* — Advertiser's property description.
- **`listingAdvertiser`** *(object)* — Agency, office, and contact information when provided. With `fetchDetails` enabled, `_details.listingAdvertiser.contacts` includes available mobile, work, and home numbers matched to each contact.
- **`listingStatuses`** *(object)* — New, on-show, and price-reduced status flags.
- **`isFeaturedListing`** *(boolean)* — Whether the listing is featured.
- **`isExclusiveListing`** *(boolean)* — Whether the listing is exclusive.
- **`_details`** *(object, optional)* — Additional detail data when `fetchDetails` is enabled.

#### Example result

```json
{
  "listingId": 11998043,
  "portalRef": "T5580025",
  "propertyTitle": "13 Bedroom House",
  "propertyTypeDescription": "House",
  "listingPrice": {
    "price": 8500000,
    "isPoa": false,
    "isOnAuction": false
  },
  "propertyAttributes": {
    "beds": 13,
    "baths": 10,
    "garages": 3,
    "floorArea": "735 m²",
    "landArea": "1200 m²"
  },
  "propertySuburbName": "Baysville",
  "mediaImageUrls": [
    "https://images.pp.co.za/listing/11998043/example/600/450/contain/jpegorpng"
  ],
  "shareUrl": "https://www.privateproperty.co.za/ld/T5580025",
  "propertyDescription": "Spacious family home close to schools and local amenities.",
  "listingAdvertiser": {
    "contact": { "name": "Violet Omwansa" },
    "office": { "officeName": "Chas Everitt East London" }
  },
  "listingStatuses": {
    "isNew": true,
    "isOnShow": false,
    "isPriceReduced": false
  },
  "isFeaturedListing": true,
  "isExclusiveListing": false,
  "_details": {
    "listingAdvertiser": {
      "contacts": [
        {
          "id": 1812854,
          "name": "Violet Omwansa",
          "mobile": "082 555 0147",
          "workNumber": "021 555 0198",
          "homeNumber": ""
        }
      ]
    }
  }
}
```

### 🧭 Tips and common recipes

- **Focused suburb search:** use a suburb such as `Sandton` or `Sea Point` in `location`.
- **Broad city search:** use a city such as `Cape Town` or `Johannesburg` for more coverage.
- **Investor shortlist:** combine `minPrice`, `maxPrice`, bedrooms, bathrooms, and size limits.
- **New listing monitoring:** set `sortBy` to `newest` and run the actor on a schedule.
- **Rental comparison:** set `listingType` to `rent`, choose `rentalPricePeriod`, and add rental inclusions.
- **Contact-ready records:** enable `fetchDetails` to include available advertiser phone numbers beside the matching contact.
- **More complete records:** enable `fetchDetails` when the extra information is worth the additional time.

### ⚙️ Best practices

- Start with a small `maxItems` value while checking that your location and filters return the right inventory.
- Use `maxItems: 0` for an unlimited collection, subject to any account or usage limits that apply to your run.
- Keep price and area ranges realistic for the selected location to avoid unnecessarily broad collections.
- Some filters apply only to particular property categories or sale/rent searches; incompatible choices are skipped.
- Treat advertiser contact information as business data and store it securely.

### ⚖️ Legal and ethical considerations

- Respect Private Property's terms, policies, and any applicable access restrictions.
- Use listing and advertiser information responsibly and only for lawful purposes.
- Follow privacy requirements such as GDPR or POPIA when handling contact information.
- Avoid unsolicited communications, misleading outreach, or republishing information in a way that harms people or businesses.
- Use reasonable collection volumes and retain exported data only as long as needed.

This Actor is an independent tool and is **not** affiliated with, endorsed by, or sponsored by Private Property. Private Property and related trademarks belong to their respective owners.

### ❓ FAQ

**Can I collect both sale and rental listings?**

Yes. Set `listingType` to `sale` or `rent`. Rental searches can also use a rental price period and rental-specific inclusions.

**What happens when I leave `location` empty?**

A location is required for a useful search. The Store input is prefilled with `Cape Town`; enter a city, suburb, or area before starting a run if you remove that value.

**Does `maxItems: 0` return everything?**

It requests all available matching listings, subject to the inventory returned and any account or usage limits that apply to the run.

**Why did a filter not change my results?**

Some choices are specific to sale, rent, or a property category. Check that the filter matches the selected `listingType` and `category`, and test with a small result limit first.

**When should I use `fetchDetails`?**

Use it when you need additional listing information beyond the search result. It adds extra work for each listing, so it is best for targeted collections.

**Does detailed output include advertiser phone numbers?**

Yes. When available, mobile, work, and home numbers appear beside the matching advertiser contact in `_details.listingAdvertiser.contacts`. Listings without disclosed numbers simply keep their available contact details.

**Can I export the results for another tool?**

Yes. Download JSON, CSV, or Excel from the Dataset tab, or connect the dataset through your preferred API or MCP workflow.

### 🛟 Support

Need a custom field or export workflow? Open an issue or contact [igolaizola.com/#contact](https://igolaizola.com/#contact).

# Actor input Schema

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

Maximum number of listings to return. Use 0 for all available listings.

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

City, suburb, or area to search. Example: Cape Town or Sandton.

## `listingType` (type: `string`):

Whether to find properties offered for sale or rent.

## `category` (type: `string`):

Broad property category to search. Development listings are available for sale searches only.

## `minPrice` (type: `integer`):

Lowest acceptable listing price in South African rand.

## `maxPrice` (type: `integer`):

Highest acceptable listing price in South African rand.

## `bedrooms` (type: `integer`):

Minimum number of bedrooms.

## `bathrooms` (type: `integer`):

Minimum number of bathrooms.

## `garages` (type: `integer`):

Minimum number of garages.

## `parkings` (type: `integer`):

Minimum number of parking spaces.

## `minFloorSize` (type: `integer`):

Minimum indoor floor area in square metres.

## `maxFloorSize` (type: `integer`):

Maximum indoor floor area in square metres.

## `minLandSize` (type: `integer`):

Minimum land area in square metres.

## `maxLandSize` (type: `integer`):

Maximum land area in square metres.

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

Limit results to one or more property types. Allowed values: house (House), townhouse (Townhouse), apartment (Apartment), vacant\_land (Vacant land), garden\_cottage (Garden cottage), commercial (Commercial), industrial (Industrial), retail (Retail), office (Office), hospitality (Hospitality), farm (Farm), smallholding (Smallholding), farm\_with\_house (Farm with house), farmland (Farmland), agricultural\_holding (Agricultural holding), commercial\_farm (Commercial farm), or game\_farm (Game farm).

## `amenities` (type: `array`):

Select amenities required in the listing. Allowed values: garden (Garden), patio\_or\_balcony (Patio or balcony), pets\_allowed (Pets allowed), pool (Swimming pool), furnished (Furnished), sea\_view (Sea view), staff\_quarters (Staff quarters), borehole (Borehole), flatlet (Flatlet), or scenic\_view (Scenic view).

## `securityFeatures` (type: `array`):

Select security features required in the listing. Allowed values: alarm (Alarm), access\_gate (Access gate), electric\_fencing (Electric fencing), security\_post (Security post), or intercom (Intercom).

## `specialFeatures` (type: `array`):

Choose sale features or rental inclusions. Allowed values: on\_show (On show), bank\_sale (Bank sale), electricity\_included (Electricity included), or water\_included (Water included).

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

Choose the primary ordering for returned listings.

## `sortOrder` (type: `string`):

Choose ascending or descending order.

## `rentalPricePeriod` (type: `string`):

For rental searches, choose the period used for the price filter.

## `fetchDetails` (type: `boolean`):

Request one additional detail record per listing and add it under \_details. This increases runtime and usage.

## Actor input object example

```json
{
  "maxItems": 100,
  "location": "Cape Town",
  "listingType": "sale",
  "category": "residential",
  "sortBy": "relevance",
  "sortOrder": "descending",
  "fetchDetails": false
}
```

# 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"
};

// Run the Actor and wait for it to finish
const run = await client.actor("igolaizola/privateproperty-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 = { "location": "Cape Town" }

# Run the Actor and wait for it to finish
run = client.actor("igolaizola/privateproperty-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 '{
  "location": "Cape Town"
}' |
apify call igolaizola/privateproperty-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,igolaizola/privateproperty-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/y4ZKh7fFtf2GEGf7V/builds/7ntIb2KBHqUOAqfWi/openapi.json
