# Domain.com.au Property Listings Scraper (`bracing_hero/domain-au-scraper`) Actor

Scrape for-sale, rental and sold property listings from domain.com.au: prices, address, coordinates, beds, baths, land size, sold prices, agency and agents. Pay only for listings you receive.

- **URL**: https://apify.com/bracing_hero/domain-au-scraper.md
- **Developed by:** [Dc Tech](https://apify.com/bracing_hero) (community)
- **Categories:** Real estate, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 listings

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## Domain.com.au Property Listings Scraper

Get property listings from [domain.com.au](https://www.domain.com.au) as clean, structured data: homes **for sale**, **for rent** and **recently sold**, anywhere in Australia.

Give it a suburb (like `Bondi NSW 2026`) or paste any Domain search URL. You get one tidy row per listing with price, address, coordinates, bedrooms, bathrooms, parking, land size, property type, photos, agency and agents. Turn on **full details** to also get the description, floorplans, every inspection time, features, building size, date listed and days on market.

### Who it's for

- **Property investors**: track asking prices, rents and recent sales in the suburbs you're watching.
- **Buyer's agents**: build shortlists and comparable-sales sheets quickly.
- **Proptech and data teams**: feed listings into dashboards, valuation models, alerts or your CRM.
- **Researchers and journalists**: analyse rents and prices across suburbs over time.

### What you get

| Field | Example | Notes |
|---|---|---|
| `id`, `url` | `2021155139`, listing link | `id` is unique; results are de-duplicated by it |
| `listingType` | `sale`, `rent`, `sold` | From your search |
| `status` | `forSale`, `forRent`, `underOffer`, `leased`, `sold` | Normalised status. Rentals marked "DEPOSIT TAKEN" are `underOffer` |
| `statusText` | `"Sold by private treaty 13 Oct 2026"`, `"DEPOSIT TAKEN"`, `"New"` | Domain's original label, word for word; `null` when Domain shows none |
| `address` | `{ full, street, suburb, state, postcode }` | |
| `latitude`, `longitude` | `-37.77129`, `144.9542` | |
| `priceText` | `"Guide $1,350,000 - $1,400,000"` | As displayed, with any phone numbers removed |
| `priceMin`, `priceMax`, `pricePeriod` | `1350000`, `1400000`, `null` | Parsed numbers; rent is per `week` |
| `bedrooms`, `bathrooms`, `parking` | `2`, `1`, `0` | |
| `landSizeM2`, `buildingSizeM2` | `151`, `88` | Building size needs full details |
| `propertyType` | `"House"` | |
| `images` | photo URLs | Full details give the full gallery |
| `inspectionTimes`, `auctionDate` | local Australian time | Search results show the next inspection only |
| `soldPrice`, `soldDate`, `saleMethod` | `1052000`, `"2026-10-13"`, `"privateTreaty"` | Sold listings; `null` if the price was withheld |
| `agencyName` | `"Ray White Brunswick"` | |
| `agencyPhone` | `"03 93878023"` | Agency office phone; full details only |
| `agents` | `[{ "name": "...", "phone": "03 9387 8023" }]` | Agent names always; agent phone needs full details. Mobile numbers are never included (see FAQ) |
| `headline`, `description`, `features`, `floorplans`, `dateListed`, `daysOnMarket` | | Full details only (`null` otherwise) |
| `detailsScraped`, `scrapedAt` | `true`, ISO timestamp | |

Every row has every field. Anything not available is `null`, never missing.

### How to use it

1. Add one or more **Locations** (`Suburb STATE postcode`), or paste **Start URLs** from a Domain search you've already filtered on the website.
2. Choose **Listing type**: for sale, for rent or sold. Start URLs work this out from the URL.
3. Optional filters (for Locations): price range, minimum bedrooms, property types.
4. Set **Maximum listings** and decide whether to **Include full listing details**.
5. Run it, then download the results as JSON, CSV, Excel or via the API.

#### Input examples

**Suburb search.** Houses for sale in two suburbs, 3+ bedrooms, up to $2.5m:

```json
{
    "locations": ["Bondi NSW 2026", "Coogee NSW 2034"],
    "listingType": "sale",
    "minBedrooms": 3,
    "maxPrice": 2500000,
    "propertyTypes": ["house"],
    "maxItems": 500
}
```

Sold listings with full details (good for comparable sales):

```json
{
    "locations": ["Brunswick VIC 3056"],
    "listingType": "sold",
    "maxItems": 200,
    "includeDetails": true
}
```

**URL search.** Set up a search on domain.com.au with the filters you want, then paste the address bar URL. Filters in the URL are kept as they are, and the listing type comes from the URL (`/sale/`, `/rent/` or `/sold-listings/`):

```json
{
    "startUrls": [{ "url": "https://www.domain.com.au/rent/parramatta-nsw-2150/?bedrooms=2-any&price=0-800" }],
    "maxItems": 1000
}
```

**State-wide search.** Everything for sale in NSW, newest first. Domain has tens of thousands of these, so set `maxItems` to what you need:

```json
{
    "startUrls": [{ "url": "https://www.domain.com.au/sale/nsw/" }],
    "maxItems": 5000
}
```

#### Sample output (sold listing, full details on)

```json
{
    "id": 2021155139,
    "url": "https://www.domain.com.au/2-munro-street-brunswick-vic-3056-2021155139",
    "listingType": "sold",
    "status": "sold",
    "statusText": "Sold by private treaty 13 Oct 2026",
    "address": { "full": "2 Munro Street, Brunswick VIC 3056", "street": "2 Munro Street", "suburb": "Brunswick", "state": "VIC", "postcode": "3056" },
    "latitude": -37.7712908,
    "longitude": 144.9541862,
    "priceText": "$1,052,000",
    "priceMin": 1052000,
    "priceMax": 1052000,
    "pricePeriod": null,
    "bedrooms": 2,
    "bathrooms": 1,
    "parking": 0,
    "landSizeM2": 151,
    "buildingSizeM2": 88,
    "propertyType": "House",
    "headline": "North Facing Easy Living",
    "features": ["Air conditioning", "Floorboards", "Built in wardrobes", "Internal Laundry", "Gas"],
    "description": "Perfectly positioned to take advantage of all the conveniences this desirable locale offers...",
    "images": ["https://rimh2.domainstatic.com.au/..."],
    "floorplans": ["https://rimh2.domainstatic.com.au/..."],
    "inspectionTimes": [],
    "auctionDate": null,
    "dateListed": "2026-09-15T09:38:40",
    "daysOnMarket": 28,
    "soldPrice": 1052000,
    "soldDate": "2026-10-13",
    "saleMethod": "privateTreaty",
    "agencyName": "Ray White Brunswick",
    "agencyPhone": "03 93878023",
    "agents": [
        { "name": "Matthew Schroeder", "phone": "(03) 9387 8023" },
        { "name": "Yusuf Eissa", "phone": "03 9387 8023" }
    ],
    "detailsScraped": true,
    "scrapedAt": "2026-10-14T10:29:48.343Z"
}
```

### Pricing

This Actor uses **pay-per-event** pricing. You pay a small start fee per run, then only for the listings you actually receive:

| Event | When it's charged | Price |
|---|---|---|
| Actor start | Once per run, at the default 4 GB memory (Apify charges this per GB of memory, so a 2 GB run pays half) | $0.05 |
| `listing` | Each listing saved to your dataset | $0.001 ($1.00 per 1,000) |
| `listing-detail` | Each listing whose full detail page was fetched (only when **Include full listing details** is on) | $0.0015 ($1.50 per 1,000) |

**Cost examples** (default 4 GB memory):

| Run | Search only | With full details |
|---|---|---|
| 100 listings | about $0.15 | about $0.30 |
| 1,000 listings | about $1.05 | about $2.55 |
| 10,000 listings | about $10.05 | about $25.05 |

- Blocked, failed or invalid requests are **never charged**, and a listing found by two overlapping searches is only saved and charged once.
- If a detail page can't be fetched after several retries, you still get the listing from the search results and pay only the `listing` price for it.
- Set a **maximum cost per run** in Apify Console (run options) and the Actor stops cleanly when it's reached, keeping everything collected so far.
- Platform usage (compute and proxies) is included in these prices; you don't pay it separately.

### Good to know

- **More than 1,000 results:** Domain shows at most 1,000 results per search. When you ask for more, the Actor splits the search into price bands (then bedroom counts if needed) and de-duplicates the results. Without splitting you get Domain's default order (newest first).
- **Speed:** the Actor uses a few real browser sessions in parallel and paces its requests politely, so it's steady rather than instant. In our own test runs (October 2026, default settings), search-only runs saved roughly 400 to 900 listings per minute once running, and runs with full details about 50 listings per minute. Your speed will vary.
- **Memory:** the default 4 GB runs 4 browser sessions. If you lower memory to 2 GB, set **Parallel browser sessions** to 2.
- **Proxy:** keep the default (Apify residential proxies in Australia). Domain blocks most data-centre traffic.
- **Reliability safeguard:** if Domain starts blocking most requests, the Actor switches to fresh sessions. If blocking continues, it stops with a clear message instead of running on and producing nothing.

### FAQ

**Is scraping Domain legal?**
This Actor collects only publicly visible listing information. It doesn't log in, doesn't bypass paywalls, and doesn't collect personal data beyond the agent name and business phone that the listing itself shows publicly. You're responsible for how you use the data, including Domain's terms of use and privacy laws such as the Australian Privacy Act. If in doubt, get legal advice.

**Why are some prices `null`?**
Many listings don't show a dollar figure: auctions ("Auction"), expressions of interest ("EOI", "Expressions of Interest"), "Contact Agent", or sold listings where the price was withheld ("Price Withheld"). `priceText` always shows exactly what Domain displays; `priceMin`/`priceMax` (and `soldPrice` for sold listings) are only filled when there is an actual dollar figure. A range such as "$1.2m - $1.3m" fills both; "Offers over $900k" fills only `priceMin`.

**Domain only shows 1,000 results per search. Can I get more?**
Yes. Domain shows at most 50 pages of 20 results (1,000 listings) for any single search. When a search has more than 1,000 results and you ask for more than 1,000, the Actor first collects that search's own 1,000 results (newest first), then automatically splits it into smaller price bands, and if a single price still has more than 1,000 listings, by bedroom count. Each smaller search stays under the limit. Listings that appear in more than one band are de-duplicated and charged once. A small amount of extra work is spent on those overlaps; you don't pay for it.

**When is a search too big to fully collect?**
Only if a single exact price with a single bedroom count still has more than 1,000 listings, which is rare. The log tells you if it happens.

**What does "Include full listing details" add?**
The Actor opens each listing's own page and adds: the full description and headline, all photos, floorplans, every upcoming inspection time (search results show only the next one), the features list, building size, date listed, days on market, the agency's office phone and each agent's business phone. It's slower, and it's charged as an extra `listing-detail` event per listing. Leave it off if you only need prices, addresses, beds/baths/parking, land size, coordinates and sold results.

**Why do search-only rows have `null` for description, features and floorplans?**
Those appear only on the listing page. Turn on **Include full listing details** to get them.

**Are agents' mobile numbers or emails included?**
No. You get the agent's name, the agency name and the agency office phone. An agent's phone is included only when it's a business number (landline, 1300, 13 or 1800). Any number that looks like an Australian mobile (starting with 04 or +61 4 after removing spaces and brackets) is replaced with `null`, even if the agent shows it on the listing. Emails are never collected. Phone numbers that agents put inside the price text are removed too.

**What does `status` mean for rentals marked "DEPOSIT TAKEN"?**
They're reported as `underOffer`, since the property is effectively taken but not yet leased. The original label is always in `statusText`, so you can filter on it yourself.

**Can I schedule it?**
Yes. Use Apify Schedules (for example, daily at 7am) and connect results to Google Sheets, Slack, webhooks or the API.

**Something's wrong or missing?**
Open an issue on the Actor's Issues tab with the run link and we'll look into it.

# Actor input Schema

## `locations` (type: `array`):

Suburbs to search, written as "Suburb STATE postcode", for example "Bondi NSW 2026". Each location is searched with the listing type and filters below. Leave empty if you use Start URLs instead.

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

What to search for in the locations above. Start URLs ignore this: their type comes from the URL (/sale/, /rent/ or /sold-listings/).

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

Domain.com.au search result URLs, e.g. https://www.domain.com.au/sale/bondi-nsw-2026/?bedrooms=2-any. Any filters already in the URL are kept as they are. The filters below only apply to Locations.

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

Applies to Locations. For rentals this is the weekly rent in AUD; otherwise the price in AUD.

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

Applies to Locations. For rentals this is the weekly rent in AUD; otherwise the price in AUD.

## `minBedrooms` (type: `integer`):

Applies to Locations.

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

Applies to Locations. Leave empty for all property types.

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

Stop after saving this many listings in total (across all searches). Searches with more than 1,000 results are split automatically into smaller price bands so you can go past Domain's 1,000-result limit.

## `includeDetails` (type: `boolean`):

Also open each listing page to get the description, all photos, floorplans, all inspection times, features, building size, date listed, days on market and agents' business phone numbers. This is charged as an extra "listing-detail" event per listing and makes the run slower.

## `maxSessions` (type: `integer`):

How many browser sessions run in parallel. More is faster but needs more memory (about 0.5 GB each). The default of 4 suits the default 4 GB of memory; use 2 sessions if you run with 2 GB.

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

Domain.com.au blocks most data-centre traffic. Apify residential proxies in Australia are strongly recommended.

## Actor input object example

```json
{
  "locations": [
    "Bondi NSW 2026"
  ],
  "listingType": "sale",
  "startUrls": [],
  "propertyTypes": [],
  "maxItems": 100,
  "includeDetails": false,
  "maxSessions": 4,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "AU"
  }
}
```

# 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 = {
    "locations": [
        "Bondi NSW 2026"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "AU"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("bracing_hero/domain-au-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 = {
    "locations": ["Bondi NSW 2026"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "AU",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("bracing_hero/domain-au-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 '{
  "locations": [
    "Bondi NSW 2026"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "AU"
  }
}' |
apify call bracing_hero/domain-au-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bracing_hero/domain-au-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/LTohgKEGX5baGXEyz/builds/ynet5cdJ9fED8idYM/openapi.json
