# Willhaben Commercial Real Estate Scraper (`studio-amba/willhaben-gewerbe-scraper`) Actor

Scrape commercial real estate from willhaben.at — offices, retail spaces, warehouses, gastronomy, and land plots across Austria. Structured price, surface, location, and agent data for rent and sale listings.

- **URL**: https://apify.com/studio-amba/willhaben-gewerbe-scraper.md
- **Developed by:** [Studio Amba](https://apify.com/studio-amba) (community)
- **Categories:** Real estate
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 result scrapeds

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 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

## Willhaben Commercial Real Estate Scraper

Scrape commercial real estate listings from [willhaben.at](https://www.willhaben.at), Austria's largest classifieds platform. This actor covers the Gewerbeimmobilien categories (offices, retail spaces, warehouses, workshops, gastronomy, hotels) and the Grundstücke category (building plots, commercial plots, agricultural land), for both rent and sale.

Willhaben lists around 15,000 commercial rental properties, 4,500 commercial sale properties, and 7,800 land plots at any given time. Each result comes back as a structured record with price, surface, location, coordinates, and agent details.

### What you get

- **Structured prices**: numeric price in EUR, the price unit (per month for rent, total for sale and land), the price per square meter where Willhaben publishes it, and the original display text. Listings with price on application ("Preis auf Anfrage") return `price: null` with the original wording preserved, which is normal in this vertical.
- **Full location data**: city, Austrian federal state (Bundesland), postal code, street address where published, and GPS coordinates on nearly every listing.
- **Commercial specifics**: usable area (Nutzfläche) or plot size in square meters, the Willhaben object type (Büro/Ordination, Lagerhalle, Baugrundstück, ...), and whether the seller is private or an agency.
- **Media and contact**: all listing photos, the agency or seller name, publication date, and the direct listing URL.

### Use cases

- Track office rents per district in Wien, Graz, or Linz over time
- Find warehouse and logistics space coming on the market in a region
- Monitor commercial plot prices for site acquisition
- Build a pipeline of gastronomy locations for expansion planning
- Feed Austrian commercial listings into a CRM or market analysis

### How to scrape Willhaben commercial real estate data

1. Create a free Apify account and open this actor.
2. Set **Location** to an Austrian place name, for example `Wien`, `Graz`, `Linz`, or `Salzburg`. The actor resolves it to a Willhaben region, so results stay in that area instead of matching the word anywhere in the ad text.
3. Pick a **Listing Type**: rent (Miete) or buy (Kauf). For land plots, rent maps to Pacht (lease).
4. Pick a **Segment**:
   - **All commercial** covers the whole Gewerbeimmobilien category
   - **Offices** (Büro/Ordination)
   - **Retail** (Geschäfts-/Ladenlokal, Ausstellungsfläche)
   - **Industrial** (Lagerhalle, Werkstatt)
   - **Gastronomy & hotels** (Gastronomie, Hotel/Pension)
   - **Land** switches to the Grundstücke category
5. Set **Max Results** and run. Results land in the dataset and can be exported as JSON, CSV, or Excel.

Alternatively, paste one or more Willhaben search URLs into **Start URLs**. Go to willhaben.at, filter the Gewerbeimmobilien or Grundstücke search exactly how you want it, and copy the address bar. Start URLs override the other filters.

### Example input

Offices for rent in Wien:

```json
{
    "searchQuery": "Wien",
    "listingType": "rent",
    "segment": "office",
    "maxResults": 100
}
```

Building plots for sale in Graz:

```json
{
    "searchQuery": "Graz",
    "listingType": "sale",
    "segment": "land",
    "maxResults": 50
}
```

### Example output

```json
{
    "title": "2-Raumbüro in Urfahr",
    "price": 677.81,
    "currency": "EUR",
    "priceUnit": "EUR/month",
    "priceText": "€ 677,81",
    "pricePerSqm": 10.12,
    "url": "https://www.willhaben.at/immobilien/d/gewerbeimmobilien-mieten/oberoesterreich/linz/2-raumbuero-in-urfahr-1429449278/",
    "listingType": "rent",
    "segment": "office",
    "propertyType": "Büro/Ordination",
    "city": "Linz",
    "postalCode": "4040",
    "state": "Oberösterreich",
    "address": "Linzerstraße 1",
    "surface": 67,
    "imageUrl": "https://cache.willhaben.at/mmo/8/142/944/9278_84140113.jpg",
    "agencyName": "Wohnbau 2000 Ges.m.b.H",
    "isPrivate": false,
    "datePublished": "2026-08-18T13:45:00Z",
    "listingId": "1429449278",
    "scrapedAt": "2026-08-18T14:02:11.000Z"
}
```

### Output fields

| Field | Description |
|---|---|
| `title` | Listing title |
| `price` | Numeric price in EUR, `null` when price is on application |
| `currency` | Always `EUR` |
| `priceUnit` | `EUR/month` for rent, `EUR` (total) for sale and land |
| `priceText` | Price exactly as displayed on Willhaben |
| `pricePerSqm` | Price per square meter where published |
| `listingType` | `rent` or `sale` |
| `segment` | `all`, `office`, `retail`, `industrial`, `gastronomy`, or `land` |
| `propertyType` | Willhaben object type label |
| `city`, `postalCode`, `state` | Location details |
| `address` | Street address where published |
| `surface` | Usable area or plot size in m² |
| `latitude`, `longitude` | GPS coordinates |
| `imageUrl`, `imageUrls` | Listing photos |
| `agencyName`, `isPrivate` | Seller details |
| `datePublished` | Publication date |
| `listingId`, `url` | Willhaben ad ID and direct link |

### Pricing and cost

The actor charges per result plus a small actor start fee. A run pulls 90 listings per page request, so compute cost stays low: a 100-result run typically finishes in under a minute. There are no detail-page visits, everything comes from the search results, which keeps the per-result cost predictable.

Note that a run's usage cost only settles after the run has SUCCEEDED. A failed run does not deliver (or charge for) results.

### Limits and behavior

- `maxResults` is a hard cap declared in the input. The actor stops as soon as it is reached.
- Results are deduplicated by Willhaben ad ID within a run.
- An empty input `{}` runs a default search (all commercial rentals in Wien) so you can try the actor without any configuration.
- If the search legitimately returns zero listings or the site blocks the request, the run FAILS instead of succeeding with an empty dataset, so you never silently get nothing.
- Austrian residential proxies are preconfigured and recommended.

### Related

For Austrian residential real estate (apartments and houses on willhaben.at), use the Willhaben Scraper for the mietwohnungen and eigentumswohnung categories.

# Actor input Schema

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

One or more Willhaben search result URLs from the Gewerbeimmobilien or Grundstücke categories. Go to willhaben.at, set your filters, and paste the URL(s) here. Overrides the other search filters when provided. Maximum 20 URLs.

## `searchQuery` (type: `string`):

Austrian location to search in (e.g. 'Wien', 'Graz', 'Linz', 'Salzburg'). Resolved to a Willhaben region so results stay in that area. Leave empty to default to Wien.

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

Rent or buy. For land plots, 'rent' maps to Pacht (lease) and 'sale' to Kauf.

## `segment` (type: `string`):

Commercial segment to scrape. 'All commercial' covers the whole Gewerbeimmobilien category; 'Land' switches to the Grundstücke category (building plots, commercial plots, agricultural land).

## `maxResults` (type: `integer`):

Maximum number of listings to return. Hard cap for the run.

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

Proxy settings. Austrian residential proxies recommended for reliability.

## Actor input object example

```json
{
  "searchQuery": "Wien",
  "listingType": "rent",
  "segment": "all",
  "maxResults": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "AT"
  }
}
```

# 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 = {
    "searchQuery": "Wien",
    "maxResults": 20,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "AT"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("studio-amba/willhaben-gewerbe-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 = {
    "searchQuery": "Wien",
    "maxResults": 20,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "AT",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("studio-amba/willhaben-gewerbe-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 '{
  "searchQuery": "Wien",
  "maxResults": 20,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "AT"
  }
}' |
apify call studio-amba/willhaben-gewerbe-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,studio-amba/willhaben-gewerbe-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/YbAX6BJaSYgKC2Xdu/builds/s4tOvZE3OGuLs5wgE/openapi.json
