# Immowelt Scraper - Immowelt.de Rent & Sale Listings (`amitaviv/immowelt-scraper`) Actor

Scrape immowelt.de apartments and houses for rent and sale from any search URL. One record per listing: price, cold and warm rent, m², rooms, address, coordinates, features, energy data, photos, agency, private/commercial flag, dates. New-listings monitoring. $0.60 per 1,000 listings on Bronze.

- **URL**: https://apify.com/amitaviv/immowelt-scraper.md
- **Developed by:** [Amit Aviv](https://apify.com/amitaviv) (community)
- **Categories:** Real estate, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

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

## Immowelt Scraper (immowelt.de)

Returns rent and sale listings for apartments and houses from Immowelt Germany, from search URLs you copy out of the browser. No browser is started: the actor reads the site's own page data through Apify's German residential proxy (included in the price), so 300 listings from the result pages take under a minute and 1,000 listings with full details about 11 minutes. Apart from the start fee you pay only for delivered listings, and a run that delivers nothing because of an error ends as Failed, never as a green empty run.

**Not for re-publication.** Immowelt's listings are likely protected by database rights. This actor is for analysis, research and monitoring; re-publishing listings or building a competing listings portal from the output is not permitted. See "Legal and responsible use".

Searching ImmobilienScout24 too? Our [ImmoScout24 Scraper](https://apify.com/amitaviv/immoscout24-scraper) uses the same names for the main fields (price, warmRent, livingSpace, rooms, postcode, city, district, latitude, longitude, advertiserType, agencyName, url), so the two outputs are easy to merge.

### What you get

- Price, cold rent, warm rent, service charges, heating costs, deposit, commission, broker-fee flag, price per m² (computed: price divided by living space)
- Living space, plot area, rooms, floor and number of floors, availability, construction year, condition, new-build flag and project link
- Address exactly as the advertiser published it (a hidden street stays hidden), postcode, city, district; coordinates when Immowelt shows the location on its map (almost always together with the exact street address)
- Features (lift, balcony, fitted kitchen, cellar, parking, ...), energy class (one spelling: `A+`, `A++`, `B`, ...), certificate type and validity, energy demand or consumption value, heating type, energy sources
- Headline and full descriptions (property, location, other), all photo and floor-plan URLs, video and virtual-tour flags
- Publication date and last update date, to the second
- Private/commercial flag; for commercial advertisers the company name, business address, business phone numbers, website, profile URL, logo, rating and partner badge
- One record per listing, as JSON, CSV or Excel, or through the API
- A run summary (`OUTPUT_SUMMARY` in the run's key-value store): what was requested, delivered and charged; per search, how many results Immowelt reports and how many were listed and delivered; which inputs failed or were ignored; warnings; why the run stopped

What it does not return by default: the names and photos of agencies' contact persons, any advertiser data of private advertisers, and phone numbers or e-mail addresses written into listing texts (see "Personal data"). Never: anything behind a login, listings of immowelt.at or immowelt.ch, the separate new-build project pages (`/projekte/...`; the units of those projects appear in ordinary searches and are delivered with `isNewBuild: true` and `projectUrl`).

### How to use

1. Open immowelt.de, make the search you want (place, rent or buy, property type, any filters) and copy the URL of the result list from the browser.
2. Paste it into **Search URLs**. Several entries are fine.
3. Set **Max listings per search** and press Start.
4. Download the results from the Output tab, or read them from the API.

### Input

| Field | Type | Default | What it does |
|---|---|---|---|
| `startUrls` | list of text | none (required) | Search URLs from immowelt.de: `https://www.immowelt.de/classified-search?...` (what the search form produces; its filters and sort order are applied as they are) or the short ones such as `https://www.immowelt.de/suche/berlin/wohnungen/mieten` (read once for the search they show, then paged like a classified-search URL). A listing URL (`/expose/...`) returns that listing. URLs without `https://` are accepted, duplicates are ignored, other sites are ignored and listed in the summary. |
| `maxItemsPerQuery` | number | 100 | Stop after this many listings for each URL. Set it above the number of results to take a whole search. |
| `includeDetails` | yes/no | yes | Yes: each listing is completed from its detail record (coordinates, features, energy certificate, costs, full descriptions; one extra request per listing). No: only what the result list shows; about 4 times faster. Same price. |
| `onlyNew` | yes/no | no | Monitoring: return and charge only listings that earlier runs have not delivered. See "Monitoring". With it on, the same search pasted twice with different sort orders counts once. |
| `monitorKey` | text | empty | Name of the monitor memory, to keep two schedules apart. |
| `includePrivateSellerData` | yes/no | no | See "Personal data". |
| `proxyConfiguration` | proxy | Apify residential, Germany | Immowelt refuses datacenter addresses. If you switch the proxy off or choose another group (automatic, datacenter, your own proxies), the German residential proxy is used anyway and a warning says so; with the residential group you may pick another country. |

```json
{
  "startUrls": ["https://www.immowelt.de/classified-search?distributionTypes=Rent&estateTypes=Apartment&locations=AD08DE8634"],
  "maxItemsPerQuery": 40
}
```

This input (Berlin, apartments for rent) was run as `pM5lZqOnWIF9W7gib` on 2026-10-14: 40 listings in 30 seconds, all 40 with details, 32 of them with coordinates (Immowelt shows the other 8 only as an area, not as a point on its map).

### Example result

From run `pM5lZqOnWIF9W7gib` (2026-10-14). The four description texts and the image list (17 URLs) are shortened here; nothing else is edited.

```json
{
  "id": "26RTTVYZCK5U",
  "legacyId": "c12c2381-edf7-409d-98e7-738b28c20efb",
  "url": "https://www.immowelt.de/expose/c12c2381-edf7-409d-98e7-738b28c20efb",
  "title": "Own Your Style - Stylisches 1-Zimmer-Apartment mit Loggia im Herzen Berlins",
  "propertyTitle": "Wohnung zur Miete - Erstbezug",
  "dealType": "rent",
  "propertyType": "apartment",
  "propertySubType": null,
  "price": 1315,
  "priceLabel": "Kaltmiete",
  "currency": "EUR",
  "pricePerSqm": 28.12,
  "coldRent": 1315,
  "warmRent": 1545,
  "serviceCharges": 230,
  "heatingCosts": "in Warmmiete enthalten",
  "deposit": "3945",
  "commission": null,
  "hasBrokerageFee": false,
  "livingSpace": 46.77,
  "plotArea": null,
  "rooms": 1,
  "floor": 11,
  "numberOfFloors": null,
  "availableFrom": null,
  "constructionYear": 2022,
  "condition": "Neubau, Erstbezug",
  "heatingType": "Fußbodenheizung",
  "energySources": "Fernwärme",
  "energyEfficiencyClass": "B",
  "energyCertificateType": "Bedarfsausweis",
  "energyValue": 63.8,
  "energyValueType": "Energiebedarf",
  "energyCertificateValidity": "14.12.2022 bis 13.12.2032",
  "street": "Lisa-Fittko-Straße 11",
  "postcode": "10557",
  "city": "Berlin",
  "district": "Moabit",
  "country": "DEU",
  "addressPublished": true,
  "latitude": 52.53130340576172,
  "longitude": 13.365840911865234,
  "features": [
    "Bezug: ab sofort",
    "11. Geschoss",
    "Personenaufzug",
    "Einbauküche",
    "Keller",
    "Balkon",
    "Stellplatz"
  ],
  "featuresText": "Moderne Architektur trifft auf exklusiven Komfort im Herzen Berlins: Der Turm beeindruckt mit einer zeitgemäßen Außenfassade und Wohnungen m…",
  "description": "Wohnen im Spring:\nDas Spring steht für urbanes Wohnen mit Charakter - zentral in der lebendigen EuropaCity, nur wenige Minuten vom Berliner …",
  "locationDescription": "Wohnen mitten in Mitte - Urbaner Komfort mit perfekter Anbindung und hoher Lebensqualität. Einkaufsmöglichkeiten wie REWE, Aldi und DM sind …",
  "otherDescription": "Sonstiges\nWir bitten Sie Terminanfragen über das Kontaktformular zu senden, Sie erhalten dann automatisch eine Termineinladung.\n\nhttps://woh…",
  "imageUrl": "https://mms.immowelt.de/6/0/6/7/60676849-f6ef-4717-bc38-1a023bf4bb07.jpg",
  "images": [
    "https://mms.immowelt.de/6/0/6/7/60676849-f6ef-4717-bc38-1a023bf4bb07.jpg",
    "https://mms.immowelt.de/5/4/a/8/54a8fc4a-62ac-4a4d-bada-b8fe8039a3f5.jpg",
    "https://mms.immowelt.de/b/a/6/d/ba6d203c-d31c-43cd-bd93-74bb429877a7.jpg",
    "…"
  ],
  "floorplanUrls": [
    "https://mms.immowelt.de/b/e/4/7/be47bfaf-3c50-4d8b-a434-2567c2581fc5.jpg"
  ],
  "imageCount": 17,
  "hasVideo": false,
  "hasVirtualTour": true,
  "isNewBuild": true,
  "projectUrl": "https://www.immowelt.de/projekte/expose/k25f932",
  "createdAt": "2026-10-13T09:57:56.557Z",
  "updatedAt": "2026-10-13T10:06:51.139Z",
  "isPrivate": false,
  "advertiserType": "commercial",
  "agencyName": "Müller Merkle Immobilien GmbH",
  "agencyAddress": "Galileistraße 1, 69115 Heidelberg",
  "agencyPhones": [],
  "agencyWebsite": "http://www.mueller-merkle.de/",
  "agencyProfileUrl": "https://www.immowelt.de/profil/d985605b97534fafb3e12efc03eaef34",
  "agencyLogoUrl": "https://mms.immowelt.de/1/0/3/1/10310299-3c09-4a14-9e39-8cf3a24d1c21.jpg",
  "agencyRating": 4.2,
  "agencyRatingCount": 399,
  "agencyBadge": "Platin Partner",
  "contactName": null,
  "contactPhotoUrl": null,
  "privateDataRedacted": false,
  "detailsFetched": true,
  "query": "https://www.immowelt.de/classified-search?distributionTypes=Rent&estateTypes=Apartment&locations=AD08DE8634",
  "scrapedAt": "2026-10-14T14:41:34.292Z"
}
```

| Field | Meaning |
|---|---|
| `id` | Immowelt's online id; stable between runs. `legacyId` is the older id some listings still carry. |
| `url` | The listing's own page, also for units of new-build projects (whose project page is in `projectUrl`). |
| `price`, `priceLabel` | For rentals the cold rent (`Kaltmiete`), or the warm rent when that is all the advertiser gives; for sales the purchase price. EUR. With details on, `price`, `coldRent` and `warmRent` are exact to the cent as in the listing's price section (1678.08); with details off they are whole euros, as on the result list (1678). |
| `pricePerSqm` | `price` / `livingSpace`, rounded to cents (1315 / 46.77 = 28.12 above). Immowelt's own figure can differ where it divides by another area. |
| `heatingCosts`, `deposit`, `commission` | As the advertiser wrote them: a number or a text such as "in Warmmiete enthalten" or "3 Kaltmieten". |
| `energyValue`, `energyValueType` | kWh/(m²·a), and whether it is the demand (`Energiebedarf`) or consumption (`Energieverbrauch`) value. |
| `street`, `latitude`, `longitude` | `street` only when the advertiser publishes the exact address (`addressPublished`). `latitude`/`longitude` when Immowelt shows the location as a point on its map (almost always together with the exact street address; rarely a point with only the district shown); otherwise `null`. Coordinates need details on. |
| `energyEfficiencyClass` | `A+`, `A++`, `A` to `H`, in this one spelling whether it comes from the result list or the detail record. |
| `createdAt`, `updatedAt` | When the listing was first published and last changed on Immowelt (UTC). |
| `isPrivate`, `advertiserType` | `private` or `commercial`; `null` when Immowelt does not say (treated like private). Listings that platforms such as OhneMakler publish for private owners are `private`, although Immowelt marks them commercial. |
| `privateDataRedacted` | `true` when the advertiser's data was withheld because the advertiser is private (see "Personal data"). Masking of phone numbers and e-mail addresses in texts applies to every listing and is not flagged. |
| `detailsFetched` | `false` when details were off, or the listing had gone between the result page and its detail record. |
| `query` | The search URL that found the listing. |

Fields the site does not provide for a given listing are `null`, never missing.

### Pricing

Pay per event. You pay for what is delivered, not for time, memory or proxy traffic.

| Event | Free plan | Bronze | Silver | Gold and above |
|---|---|---|---|---|
| Actor start (once per run at the default 512 MB) | $0.0042 | $0.0035 | $0.00315 | $0.0028 |
| Listing delivered (with or without details) | $0.00072 | $0.0006 | $0.00054 | $0.00048 |

Worked example on Bronze: 1 search, 1,000 listings with details = 1,000 x $0.0006 + $0.0035 = $0.6035 (run `tSqZsmxs3DvzGFajM`: charged 1 start and 1,000 listings). A scheduled monitoring run that finds 3 new listings costs 3 x $0.0006 + $0.0035 = $0.0053; a run that finds nothing new costs $0.0035.

- Listings that could not be delivered are not charged. A listing that two of your searches return is delivered and charged once per run.
- The start event is charged by the platform once per GB of memory (minimum one); at the default 512 MB that is one.
- The maximum total charge you set for a run is respected: the actor stops before it would go over, keeps what was delivered, and says so in the status message (run `o0rekKPJTwtdG62Ag`: limit $0.0095, 10 listings delivered and charged, Succeeded).

### Reliability and failure behaviour

| What happened | Run status | Status message |
|---|---|---|
| Listings delivered | Succeeded | `Scraped 40 listings from 1 query` |
| Immowelt has no results for your search | Succeeded | `0 results: immowelt.de has no listings for this query` |
| Some entries worked, some failed | Succeeded | `Scraped 120 listings from 2 queries — 1 of 2 queries failed ("…": …)` |
| Nothing delivered because Immowelt refused every attempt | **Failed** | `No listings delivered: immowelt.de blocked every attempt; try again later. No listings were charged (the start fee applies).` |
| Input the actor cannot use | **Failed**, within seconds | `Nothing to do: … Add at least one entry to "startUrls", e.g. … No listings were charged (the start fee applies).` |
| Maximum charge reached | Succeeded | `… — stopped at the maximum charge set for this run` |
| Run timeout close | Succeeded | `… — stopped just before the run timeout; raise the timeout to get the rest` (run `ck6scmkzFHBLFIlk4`, timeout 75 s: 80 listings). If requests were failing at that point, the message says Immowelt was refusing them instead. |

- Immowelt is protected by DataDome. Through residential addresses most requests are answered; a refused one is retried at once from another address, up to 9 attempts per request. In the 1,000-listing run, 310 of 1,348 requests were refused first and every one of them succeeded on a later attempt.
- Listings are saved page by page. A run that is aborted, times out or is resurrected keeps what was delivered and never delivers or charges the same listing twice.
- A detail record that cannot be fetched because the listing has gone leaves the listing's result-page data in place (`detailsFetched: false`) and the status message says how many; a refused detail request stops the search instead of delivering half-filled records.
- Measured on 2026-10-14: every test run with usable input and the residential proxy succeeded with every listing it was asked for (19 runs of the developer's tests on builds 0.1.1 to 0.1.5, up to 1,000 listings), and in every run the charged listings equal the delivered ones. "Blocked every attempt" was seen live only with a non-residential proxy (run `7BhAAccBa5IFemxis`, before such a choice was replaced by the residential proxy).

### Limits

- Speed: about 1.5 listings per second with details (1,000 in 11 minutes, run `tSqZsmxs3DvzGFajM`), about 6 per second without (300 in 49 seconds, run `6DLcYKzadxIq8Xbhq`).
- Immowelt shows 30 to 40 listings per result page. No page limit was found: the last page of a 6,002-result Berlin search was served (measured with direct requests).
- Coordinates: only where Immowelt shows the location as a point on its map, almost always together with the exact street address (32 of 40 listings in the Berlin rental run). Street: only where the advertiser publishes it.
- Energy data, construction year and features come from the detail record: with `includeDetails` off they are `null` (the energy class is still filled when the result list shows it).
- Germany only (immowelt.de). immonet.de now redirects to immowelt.de, so its listings are Immowelt's.

### Monitoring: only new listings

1. Turn on **Only new listings** and save the input as a task.
2. Schedule the task (hourly or daily).
3. The first run delivers the newest listings, up to the maximum. Every later run delivers and charges only listings it has not delivered before for the same search; a run with nothing new ends as Succeeded with `0 new listings…` and charges only the start event.

How "new" is decided: searches are read newest first. Immowelt's "newest" order is not the update date it shows: a new listing appears at about the time it was created, private owners' listings appear only after Immowelt has checked them (sometimes the next morning), and a listing its advertiser re-publishes moves back to the top, while other updates do not move a listing. So a later run does not stop at the first older listing it meets. It reads down to the result page that lies, as a whole, two hours before the previous run started (after a first run that its maximum cut short: down to where that run stopped), and delivers every listing on those pages that this monitor has not delivered before. That includes listings Immowelt shows late, and older listings that their advertiser re-published and you have not received before (delivered once). In a Berlin rental search a later run reads 2 to 3 result pages.

Tested on 2026-10-14 with Berlin rentals (runs `Hh09x1YzFZPSbLpfq`, `Uev63vBfbJFFfnzLq`, `ksJB6BCNrutyfUMkp`): the first run delivered 60, the second 0, the third, 13 minutes later, 2, both created after the first run; a fourth, 6 minutes after that, 1 listing that Immowelt had not yet shown to the third run (run `mvemdMQBiPgAcsGTw`). An offline replay of 360 listings in the order Immowelt served them (with listings up to 25 hours out of place) delivers all 48 listings created in the 12 hours since the previous run.

The memory is a key-value store named `immowelt-scraper-monitor` in your own account (one record per search and monitor name, at most 10,000 ids each, oldest forgotten first). Delete the store or change **Monitor name** to start over. If a later run finds more new listings than its maximum, the next run delivers the rest. To be notified, add an integration to the task (email, Slack, webhook) on "run succeeded".

### FAQ

**Do I need a proxy?** No setup: the actor always uses Apify's German residential proxy, and its cost is included in the listing price.

**Why did I get fewer listings than the site shows?** Check your maximum per search first. Otherwise, Immowelt's result pages shift while they are read when listings are added or updated during the run; the run summary shows per search how many results Immowelt reported and how many distinct listings were met.

**Can I run it from code?** Yes: the API, the Apify clients for JavaScript and Python, Make, Zapier, n8n. The Output tab shows the URLs.

**What happens when the site changes?** Runs fail loudly instead of returning empty data; report the run id under Issues.

### Personal data

Most Immowelt listings come from agencies; some from private owners. By default:

- For private advertisers (`advertiserType: "private"`, or no flag at all) no advertiser data is delivered (`agency*` fields `null`, `privateDataRedacted: true`). Listings that platforms such as OhneMakler or 123provisionsfrei publish for private owners are treated the same way.
- In the texts of every listing (headline, descriptions, features text), phone numbers, e-mail addresses and names after "Herr", "Frau" or "Familie" (first and last name) are replaced with `[removed]`: owners and agents write their own mobile numbers there. Other names written into a text are not recognised. An agency's object reference written right after a label such as "Objektreferenz" or "Objekt-Nr." without spaces (`Objektreferenz: 10-00911-00016-1263`) is kept; other long numbers that look like phone numbers (a reference written with spaces, an order number without a label, the digits of a company's VAT number) can also be masked. Agencies' business phone numbers from their profile stay in `agencyPhones`.
- For agencies, the company name, business address, business phone numbers, website, logo and rating are delivered; the contact person's name and photo are not.
- The property's address and coordinates are delivered as the advertiser published them, for every advertiser.

`includePrivateSellerData` switches the masking off and adds `contactName` and `contactPhotoUrl`. Switch it on only if you have a lawful basis under the GDPR (for example a legitimate interest with a documented balancing test) to process these personal data; you are then responsible for that processing, including informing the people concerned.

### Legal and responsible use

This actor collects property listings that immowelt.de shows publicly without a login. Check Immowelt's terms of use before you use the data (they were not reviewed for this README; comparable portals forbid automated collection). Immowelt's robots.txt asks robots not to read the result-list and data paths this actor reads, and its listings collection is likely protected as a database (sections 87a ff. of the German Copyright Act). Use the data for your own analysis, research or monitoring; do not re-publish listings, texts or photos, and do not build a competing listings service from them. Respect data-protection law (GDPR) and do not use the output for unsolicited marketing to individuals. If you are unsure, ask a lawyer before you build on it.

### Changelog

- 2026-10-14 0.1: first version. Before release: exact prices with cents when details are on, one spelling of the energy class (`A+` instead of `A_PLUS`), agencies' object reference numbers no longer masked, first and last name after Herr/Frau both masked.

### Related actors

- [ImmoScout24 Scraper](https://apify.com/amitaviv/immoscout24-scraper): Germany's other large property portal, with the same names for the main fields, so the two outputs stack into one table; no proxy needed and a little cheaper per run.
- [Kleinanzeigen Scraper](https://apify.com/amitaviv/kleinanzeigen-scraper): the property categories of Germany's largest classifieds site (rental flats, houses, flat shares), where many private landlords advertise instead of on the portals.
- [Property Listing Status Checker](https://apify.com/amitaviv/property-listing-status-checker): checks whether ImmoScout24 and Kleinanzeigen listings you already have are still online and whether their price changed (Immowelt URLs are not supported).
- [Idealista Scraper](https://apify.com/amitaviv/idealista-scraper): the same kind of listing data for Spain, Portugal and Italy.

### Support

Open an issue on the actor's **Issues** tab with the run id.

# Actor input Schema

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

Required. immowelt.de search URLs copied from the browser's address bar, e.g. https://www.immowelt.de/classified-search?distributionTypes=Rent\&estateTypes=Apartment\&locations=AD08DE8634 (Berlin, apartments for rent) or the short form https://www.immowelt.de/suche/berlin/wohnungen/mieten. Make the search on immowelt.de (place, rent or buy, property type, any filters) and paste the URL of the result list. Each URL is one search; several are fine. The URL's filters and sort order are applied as they are. A listing URL (…/expose/…) returns that one listing. URLs without https:// are accepted. Only immowelt.de (not .at or .ch).

## `maxItemsPerQuery` (type: `integer`):

Maximum number of listings delivered for each search URL, from 1 to 100,000; default 100. Apart from the start fee you pay only per delivered listing, so this also caps the cost. To take a whole search, set this above the number of results immowelt.de shows.

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

On (default): each listing is completed from its detail record: coordinates (when Immowelt shows the location on its map, almost always with the exact street address), exact prices with cents, features, energy certificate, construction year, heating, service charges, deposit, commission and the full description; one extra request per listing. Off: only what the result list shows (prices, living space, rooms, address, energy class, all photos, agency, dates); about 4 times faster. The price per listing is the same either way.

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

Off (default): every run delivers the listings it finds. On: return and charge only listings that earlier runs of this actor in your account have not delivered for the same search, for scheduled monitoring. Searches are then read newest first (a sort order in a pasted URL is replaced); the first run delivers the newest listings up to the maximum, later runs what immowelt.de has added to the top since (new listings, listings shown late, and older listings their advertiser re-published that you have not received before). The memory is a key-value store named immowelt-scraper-monitor in your account; delete it to start over.

## `monitorKey` (type: `string`):

Only with onlyNew. A free name for the monitor memory, e.g. berlin-daily. Runs with the same search and the same monitor name share one memory; give two schedules different names to keep their memories apart. Default: empty (one shared memory per search).

## `includePrivateSellerData` (type: `boolean`):

Off (default): for listings of private advertisers (including owners' ads relayed by platforms such as OhneMakler) no advertiser data is delivered; in the texts of every listing phone numbers, e-mail addresses and names after Herr/Frau/Familie are masked; agencies' contact persons (name, photo) are not delivered. Agencies' company name, business address and business phone numbers are always delivered. On: masking off, plus contactName and contactPhotoUrl. Switch on only if you have a lawful basis under the GDPR (for example legitimate interest with a documented balancing test) to process these personal data; you are responsible for that processing.

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

Default: Apify residential proxy in Germany, included in the price; no change needed. Immowelt refuses requests from datacenter addresses, so if you switch the proxy off or choose another group (automatic, datacenter, own proxies), the German residential proxy is used anyway and a warning says so. With the residential group you may pick another country.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.immowelt.de/classified-search?distributionTypes=Rent&estateTypes=Apartment&locations=AD08DE8634"
  ],
  "maxItemsPerQuery": 100,
  "includeDetails": true,
  "onlyNew": false,
  "includePrivateSellerData": false,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "DE"
  }
}
```

# Actor output Schema

## `results` (type: `string`):

All delivered listings as JSON, one object per listing. Main fields: id, url, title, dealType (rent or buy), propertyType, price (EUR: cold rent per month for rentals, purchase price for sales), priceLabel, pricePerSqm, coldRent, warmRent, serviceCharges, heatingCosts, deposit, commission, livingSpace (m²), plotArea, rooms, floor, constructionYear, condition, energyEfficiencyClass, energyValue, heatingType, street, postcode, city, district, latitude, longitude, features, description, imageUrl, images, createdAt, updatedAt (UTC), advertiserType (private or commercial), agencyName, agencyPhones, privateDataRedacted, detailsFetched, query, scrapedAt. A value the site does not give is null.

## `resultsCsv` (type: `string`):

All delivered listings as a CSV file, one row per listing, with the same fields as the JSON output (lists are flattened into numbered columns).

## `summary` (type: `string`):

JSON record OUTPUT_SUMMARY: what was requested, delivered and charged; per search what Immowelt reports against what was listed and delivered; which inputs failed or were ignored and why; warnings; why the run stopped.

# 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 = {
    "startUrls": [
        "https://www.immowelt.de/classified-search?distributionTypes=Rent&estateTypes=Apartment&locations=AD08DE8634"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "DE"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("amitaviv/immowelt-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 = {
    "startUrls": ["https://www.immowelt.de/classified-search?distributionTypes=Rent&estateTypes=Apartment&locations=AD08DE8634"],
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "DE",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("amitaviv/immowelt-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 '{
  "startUrls": [
    "https://www.immowelt.de/classified-search?distributionTypes=Rent&estateTypes=Apartment&locations=AD08DE8634"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "DE"
  }
}' |
apify call amitaviv/immowelt-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,amitaviv/immowelt-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/bhGfLzeWTAVz8LHW1/builds/5CLKFDw5m26vNUr5A/openapi.json
