# Austria Real Estate Aggregator - 4 Sites, Deduped (`aidnurs/austria-realestate-aggregator`) Actor

One search across willhaben.at, ImmoScout24.at, derStandard Immobilien and FindMyHome.at. Apartments, houses, land and commercial property in Austria in one schema, cross-listed duplicates merged. Price, €/m², area, rooms, district, agency, photos. Only-new mode.

- **URL**: https://apify.com/aidnurs/austria-realestate-aggregator.md
- **Developed by:** [Nursultan Imanov](https://apify.com/aidnurs) (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 $2.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

### Austria real estate scraper: willhaben, ImmoScout24, derStandard and FindMyHome in one search

**Austria Real Estate Aggregator** searches the four big Austrian property portals at once: [willhaben.at](https://www.willhaben.at/iad/immobilien), [ImmoScout24.at](https://www.immobilienscout24.at), [derStandard Immobilien](https://immobilien.derstandard.at) and [FindMyHome.at](https://www.findmyhome.at). Pick rent or buy, a property type and a place, and get every matching listing in **one clean schema: price, price per m², area, rooms, postcode, district, city, coordinates, agency, publish date and photos**.

The same flat is often advertised on two, three or all four sites. The Actor **merges these cross-listed duplicates** into one record and tells you where else the property is listed (`alsoListedOn`), so you see the real market, not the same apartment four times, and **you pay once per property**.

Use it as an **Austrian real estate API** (Immobilien Österreich) for rent and price benchmarks, market research, investment screening, agency lead lists, or your own alerts for new apartments in Vienna, Graz, Linz, Salzburg or anywhere in Austria.

### Why use this Austria real estate aggregator?

- 🇦🇹 **Four portals, one search.** willhaben, ImmoScout24, derStandard Immobilien and FindMyHome in one run and one table. derStandard Immobilien and FindMyHome are not covered by any other Actor in the Store.
- 🔁 **Cross-site duplicates merged.** In a test search of Vienna rentals, 931 of 2,603 properties (36%) were listed on 2 or more sites. You get one record each, with links and prices of the other listings.
- 💶 **Unified fields.** Price, €/m², area, rooms, postcode, Vienna district, state, agency and dates look the same whatever site the listing came from.
- 🎯 **One form for all sites.** Rent or buy, apartment, house, land or commercial, Bundesland plus district, town or postcode (`Neubau`, `1070`, `Graz`, `Mödling`), price, area, rooms and keywords. Each site gets the closest search it supports; the rest is filtered by the Actor.
- 🔔 **Only new listings since the last run.** Schedule it and get only what you have not seen, including a known flat that just appeared on another site. Already-seen listings are free.
- 📋 **Optional details:** full description, operating costs, deposit, commission, energy certificate (HWB, fGEE), year built, heating, availability and features.
- 🛡️ **GDPR-friendly by default.** Private sellers' names, phones, streets and house numbers are not saved, their coordinates are rounded to about 1 km, and phone numbers and personal e-mails in texts are masked. Turn on *Include personal data* only if you have a legal basis.
- ⚡ **Fast and cheap.** Pure HTTP, no browser. 3,800 listings from four sites were read and merged in about 80 seconds in our test.

### How much does it cost to scrape Austrian real estate sites?

You pay only for unique listings saved to the dataset (pay per result): **$2.00 per 1,000 listings**, plus **$1.00 per 1,000 listings** for *Include details*. A property listed on three sites is one listing and is charged once. Duplicates, already-seen listings in monitoring mode and empty searches cost nothing, and listings whose detail page could not be loaded are not charged for details. Cap spending with *Max listings* and the run's maximum cost.

### How to scrape willhaben, ImmoScout24, derStandard and FindMyHome at once

1. Choose **Rent or buy** and a **Property type**, for example *Rent* and *Apartment*.
2. Choose a **Federal state** and, optionally, a **City, district or postcode** (`Neubau`, `1070`, `Graz`, `8010`).
3. Optionally set **Min/Max price**, **Min/Max area**, **Min rooms** and **Keywords**.
4. Leave all four **Sites** selected (or pick some) and keep **Merge cross-listed duplicates** on.
5. Set **Max listings** and click **Start**. Download the results as JSON, CSV, Excel or HTML, or get them via the Apify API.

### Input example

```json
{
  "dealType": "rent",
  "propertyType": "apartment",
  "state": "wien",
  "location": "1070",
  "priceMax": 2000,
  "roomsMin": 2,
  "keywords": "balkon, terrasse, loggia",
  "sources": ["willhaben", "immoscout24", "derstandard", "findmyhome"],
  "dedupe": true,
  "maxItems": 200,
  "includeDetails": false,
  "onlyNew": false
}
```

### Output example

```json
{
  "id": "willhaben:1555475257",
  "source": "willhaben",
  "sourceId": "1555475257",
  "url": "https://www.willhaben.at/iad/immobilien/d/mietwohnungen/oberoesterreich/linz/wohnung-mit-ausblick-lentia-city-1555475257/",
  "title": "Wohnung mit Ausblick - Lentia City",
  "dealType": "rent",
  "propertyType": "apartment",
  "propertySubtype": "Wohnung",
  "price": 618.29,
  "priceText": "€ 618,29",
  "pricePerM2": 13.74,
  "area": 45,
  "rooms": 2,
  "floor": null,
  "street": "Blütenstraße 23",
  "postcode": "4040",
  "district": "Linz",
  "city": "Linz",
  "state": "Oberösterreich",
  "coordinates": {"lat": 48.314328, "lng": 14.283503},
  "coordinatesApproximate": false,
  "sellerType": "agency",
  "agencyName": "Wohnbau 2000 Ges.m.b.H",
  "publishedAt": "2026-10-13T07:49:03Z",
  "isSponsored": false,
  "images": ["https://cache.willhaben.at/mmo/7/155/547/5257_1478949944.jpg", "..."],
  "searchUrl": "https://www.willhaben.at/iad/immobilien/mietwohnungen/mietwohnung-angebote?sort=1&rows=200&page=2",
  "alsoListedOn": [
    {"source": "immoscout24", "url": "https://www.immobilienscout24.at/expose/6acde39a7e120aae468bb5cf", "price": 618.29},
    {"source": "derstandard", "url": "https://immobilien.derstandard.at/detail/15282179", "price": 618.29}
  ],
  "sources": ["willhaben", "immoscout24", "derstandard"],
  "scrapedAt": "2026-10-13T09:34:01Z"
}
```

### Fields you get

| Field | Description |
|---|---|
| `id`, `source`, `sourceId`, `url` | `site:id`, the site the record comes from, its own listing ID and link |
| `title`, `images` | Title and photo URLs |
| `dealType`, `propertyType`, `propertySubtype` | rent or buy; apartment, house, land, commercial; the site's own sub-type |
| `price`, `priceText`, `pricePerM2` | Monthly rent or purchase price in EUR, as shown, and per m² |
| `area`, `rooms`, `floor` | Living area (or usable/plot area), rooms, floor where the site gives it |
| `street`, `postcode`, `district`, `city`, `state` | Location; street only for agencies (or with personal data on); Vienna districts by name |
| `coordinates`, `coordinatesApproximate` | Exact for agencies; rounded to ~1 km for private sellers unless *Include personal data* is on (then exact on every site) |
| `sellerType`, `agencyName` | Private seller or agency, agency name |
| `publishedAt`, `isSponsored` | Publish date; promoted / top-listed flag |
| `alsoListedOn`, `sources` | The same property on other sites (`source`, `url`, `price`); all sites it was found on |
| **With details:** `description`, `operatingCosts`, `deposit`, `commission`, `totalMonthlyCost` | Full text and costs |
| `yearBuilt`, `condition`, `buildingType`, `heating`, `availableFrom`, `features` | Building and availability |
| `energyHwb`, `energyHwbClass`, `energyFgee`, `energyFgeeClass` | Energy certificate |
| **With personal data:** `contactName`, `contactPhone`, `contactEmail` | Contact person where published |
| `searchUrl`, `detailsScraped`, `scrapedAt` | The search page the listing was found on; whether its detail page was loaded (only with *Include details*); time of the run |

The key-value store record `RUN_STATS` shows, for each site, how many listings it reported, how many were read and matched, and how many properties were listed on several sites.

### How does the duplicate detection work?

Two listings from **different** sites are treated as one property when they have the same postcode, the same deal type, living area within ±2%, the same number of rooms and a price within ±3%. The wording of the titles adjusts this: identical wording allows prices within ±6% (one site shows rent with, the other without some costs); completely different wording needs area and price within ±1%, because the usual false match is another flat of the same size in the same new-build project. Exact coordinates more than 1 km apart veto a match. Listings from the same site are never merged.

On a Vienna rentals sample (3,830 listings, 12 October 2026), a hand check of 40 merged pairs found 38 clear matches and 2 uncertain ones (≈95% precision). Of 1,516 pairs with identical titles, the same room count and area within ±1% on different sites, 98.8% were merged; the rest differ in price by 7–10% (net vs. gross rent). Turn *Merge cross-listed duplicates* off to get every listing separately.

### FAQ

**Is it legal to scrape willhaben, ImmoScout24, derStandard and FindMyHome?**
This Actor collects only publicly available real estate listings, the same pages any visitor sees. It never logs in, never uses accounts or cookies of real users, and never solves or bypasses CAPTCHAs. It requests only pages that each site's robots.txt leaves open to crawlers; filters it may not send are applied by the Actor itself.

**Personal data is off by default.** For private sellers the output has no name, no phone, no street and no profile ID, house numbers in their texts are masked, and coordinates are rounded to about 1 km. Phone numbers and personal e-mails inside descriptions are masked (role mailboxes like `office@` stay), and agency contact persons and direct phones are not saved. Names that an advertiser writes into the free text of a description can still appear as published.

If you turn on **Include personal data**, you get everything the sites show publicly, including the contact person's name, phone and e-mail where available, the street and exact coordinates. Personal data is protected by the GDPR in the EU and by similar laws elsewhere. Only enable it if you have a legal basis (for example, a documented legitimate interest), keep only what you need, and do not use it for unsolicited marketing. If you are unsure, consult a lawyer.

You are responsible for how you use the data and for complying with applicable laws and the sites' terms. This Actor is not affiliated with or endorsed by willhaben.at, ImmoScout24, DER STANDARD or FindMyHome.at. Read more: [Is web scraping legal?](https://blog.apify.com/is-web-scraping-legal/)

Found something that should not be here? Open an issue on the Actor's Issues tab and we will look at it promptly.

**Can I filter by keyword, price or area?**
Yes. ImmoScout24 and derStandard filter price, area and rooms themselves; willhaben and FindMyHome are filtered by the Actor (willhaben and FindMyHome results are sorted by price when you set a price range, so the search stops as soon as prices leave it). Keywords: `balkon, terrasse` = either word, `altbau lift` = both, `-befristet` = exclude. ImmoScout24 and derStandard search simple keywords themselves; on willhaben and FindMyHome the Actor reads listings and keeps the matching ones, and stops a site after 400 listings in a row without a match (150 on FindMyHome), so a rare word deep in a big result set can be missed: add a district or price range to narrow the search.

**Where does a site not support my location?**
FindMyHome has no Vienna district pages, so for a Vienna district the Actor reads all Vienna listings there and keeps your postcode. A plain postcode outside Vienna searches its federal state (`8010` = Styria) and is filtered by the Actor. A town without a federal state on FindMyHome is looked up in the district list; set the state if it is not found. FindMyHome has no commercial section and is skipped for commercial property.

**Can I search land to rent?**
Only ImmoScout24 has a land-to-rent section (a few dozen plots in all of Austria). willhaben and derStandard mix leased and sold plots in one list without a reliable label, and FindMyHome sells plots only, so they are skipped for *Land* + *Rent* and cost nothing. *Land* + *Buy* uses all four sites.

**How do I get only new listings every day?**
Turn on *Only new listings since last run*, save the task and add a schedule. Use a different *Monitoring key* for each saved search. A property you already received is skipped even when it shows up on another site.

**Do I need a proxy?**
No. The Actor starts without a proxy and switches to an Austrian residential proxy by itself if a site rate-limits it, at no extra cost to you. You can add your own proxies under *Advanced*.

**Known gaps**

- FindMyHome search pages show no agency and no publish date: those come with *Include details*. FindMyHome search results have no coordinates.
- FindMyHome Vienna districts are filtered by postcode from the Vienna list sorted by price, reading up to 1,500 listings: fine for rentals (about 830 in all of Vienna), but for apartments to buy (about 6,500) only the cheaper part is covered. The other three sites search the district directly.
- derStandard land search mixes the few plots for lease into *Buy*.
- If a site fails in the middle of paging, the listings read so far are saved and `RUN_STATS` shows the site's error as "results are partial".
- ImmoScout24 shows at most 1,500 results per search; narrow the search (district, price) for more.
- "Price on request" listings never match a price range.

**Something broke or a field is missing?**
Open an issue on the Issues tab. We usually respond within 24 hours.

# Actor input Schema

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

Rental listings (Miete) or properties for sale (Kauf).

## `propertyType` (type: `string`):

Apartments, houses, land or commercial property. FindMyHome.at has no commercial section and is skipped for it. Land to rent exists only on ImmoScout24; the other sites are skipped for it.

## `state` (type: `string`):

Bundesland. Leave empty for all of Austria.

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

Optional. A Vienna district ("Neubau", "1070", "7"), a town or Bezirk ("Graz", "Mödling", "Innsbruck") or a 4-digit postcode ("8010"). Each site gets its own location; where a site has no such location, the Actor filters by postcode or town itself.

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

Monthly rent for rentals, purchase price for sales.

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

Monthly rent for rentals, purchase price for sales. Listings with "price on request" are left out when a price range is set.

## `areaMin` (type: `integer`):

Living area (usable or plot area when a listing has no living area).

## `areaMax` (type: `integer`):

Living area (usable or plot area when a listing has no living area).

## `roomsMin` (type: `integer`):

Minimum number of rooms.

## `keywords` (type: `string`):

Optional. Commas mean OR, spaces mean AND, a minus excludes: "balkon, terrasse", "altbau lift", "-befristet". Simple AND keywords use the full-text search of ImmoScout24 and derStandard; everything else is matched by the Actor in the title and teaser. On willhaben and FindMyHome a site stops after 400 (FindMyHome 150) listings in a row without a match.

## `sources` (type: `array`):

Which sites to search. All four by default.

## `dedupe` (type: `boolean`):

The same flat is often advertised on several sites. On: one record per property, the other sites in alsoListedOn, and you pay once. Off: every site's listing separately.

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

Maximum number of unique listings to save (after merging duplicates). Each site is searched up to this number, then the merged results are mixed across sites.

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

Open each listing's page for the full description, operating costs, deposit, commission, energy certificate (HWB, fGEE), year built, heating, availability and features. Slower; charged as an extra event only when the details were loaded.

## `onlyNew` (type: `boolean`):

Monitoring mode: skip listings saved by earlier runs with the same Monitoring key, including the same property newly posted on another site. Already-seen listings are free.

## `stateKey` (type: `string`):

Name of the memory for 'Only new listings'. Use a different key for each saved search.

## `includePersonalData` (type: `boolean`):

Off by default: private sellers' names, phones, streets and house numbers are not saved, their coordinates are rounded to about 1 km, phone numbers and personal e-mails in texts are masked (\[phone removed], \[email removed]; role mailboxes like office@ stay), and contact-person names, direct phones and e-mails are not saved.<br><br>Turn it on to get everything the sites show publicly, including the contact person's name, phone and e-mail where published, streets and exact coordinates.<br><br>⚠️ This returns personal data. You're responsible for having a legal basis to collect and use it under privacy laws (e.g. GDPR).

## `proxyUrls` (type: `array`):

Optional. Your own proxies (http://user:pass@host:port), used for all sites. Not needed: without them the Actor starts direct and switches to an Austrian residential proxy by itself if a site blocks it, at no extra cost to you.

## Actor input object example

```json
{
  "dealType": "rent",
  "propertyType": "apartment",
  "state": "wien",
  "sources": [
    "willhaben",
    "immoscout24",
    "derstandard",
    "findmyhome"
  ],
  "dedupe": true,
  "maxItems": 20,
  "includeDetails": false,
  "onlyNew": false,
  "stateKey": "default",
  "includePersonalData": false
}
```

# Actor output Schema

## `listings` (type: `string`):

Unique listings after cross-site deduplication (table view).

## `listingsFull` (type: `string`):

All fields, including alsoListedOn and details when enabled.

## `runStats` (type: `string`):

Per-site counts and how many listings were cross-listed.

# 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 = {
    "dealType": "rent",
    "propertyType": "apartment",
    "state": "wien",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("aidnurs/austria-realestate-aggregator").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 = {
    "dealType": "rent",
    "propertyType": "apartment",
    "state": "wien",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("aidnurs/austria-realestate-aggregator").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 '{
  "dealType": "rent",
  "propertyType": "apartment",
  "state": "wien",
  "maxItems": 20
}' |
apify call aidnurs/austria-realestate-aggregator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,aidnurs/austria-realestate-aggregator"
        }
    }
}
```

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/qiwd0pt9ICVDqfick/builds/OH8F1NkqzGMSsthvc/openapi.json
