Immowelt Scraper — Germany Rentals & Purchase
Pricing
from $1.01 / 1,000 results
Immowelt Scraper — Germany Rentals & Purchase
Scrape Immowelt.de rental and purchase listings with a full Kaltmiete/Nebenkosten/Heizkosten/Warmmiete price breakdown, energy certificate class, and geo-coordinates.
Pricing
from $1.01 / 1,000 results
Rating
0.0
(0)
Developer
Axery
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Immowelt Property Scraper (Germany)
Scrapes rental and purchase property listings from immowelt.de over plain HTTP — no browser, no login, no cookies.
What makes this different
Rent is never collapsed into one number. German rental listings separate Kaltmiete (base rent), Nebenkosten (utilities) and Heizkosten (heating) — Warmmiete, the sum of all three, is what a tenant actually pays each month. Most scrapers surface only one of these. This Actor keeps all four:
"price": {"amount": 2290, "currency": "EUR", "period": "month","cold_rent": 2290, "warm_rent": 2700,"utilities_cost": 279, "heating_cost": 131,"price_per_sqm": 21.99, "raw": "2.290 €"}
For purchase listings (distribution: BUY), only amount (asking price) and price_per_sqm are populated — the rent-only fields are null, since a purchase has no Nebenkosten/Heizkosten split.
Energy certificate data. energy_class (the EU A+–H efficiency rating), heating_system, energy_source and year_built come straight from the listing's own certificate — data most scrapers skip entirely.
Geo-coordinates. address.latitude/longitude come from the listing's own map pin, not a geocoding guess.
How it gets through
Detail pages are gated by TLS fingerprint, the same pattern as this suite's ZipRecruiter Actor: Chrome and Chrome-based fingerprints return HTTP 403, while firefox133 and safari17_0 return 200 with the full page. The client pins Firefox deliberately. The search page itself is unguarded under any fingerprint.
There is no JSON search API and no useful JSON-LD on detail pages — the full record lives in a JSON-escaped string assigned to window["__UFRN_LIFECYCLE_SERVERREQUEST__"], which the client decodes with two JSON parses (the outer layer is a JS string literal holding the actual JSON).
Input
| Field | Type | Notes |
|---|---|---|
city | string | A plain German place name Immowelt recognises, e.g. berlin, muenchen, hamburg — use the plain spelling, not münchen with an umlaut. |
distribution | enum | RENT (mieten) or BUY (kaufen). |
estateType | enum | APARTMENT (Wohnungen) or HOUSE (Häuser). |
maxItems | integer | See the pagination limit below. |
incremental | boolean | Only listings not seen in previous runs. |
proxyConfiguration | object | Residential recommended as a fallback if Immowelt tightens its fingerprint check further. |
Known limits
- No reachable pagination. Thirteen candidate query parameters (
page,p,sp,cp,offset,start,skip, and others) all returned the identical first page, and appending/2to the URL path returns 410 Gone. One run therefore returns at most the first page Immowelt serves for a given city/distribution/type combination — typically ~25 listings — regardless of how many thousands the market actually holds (a Berlin apartment-rental search reports "6.776 Angebote" but only the first page is reachable over HTTP). To reach a different set of listings, narrow by city or switch distribution/estate type rather than expecting deeper pages from the same query. flooris a raw German label, not normalized — expect values likeEG(ground floor) or1. OG(first floor).- Not every listing has an energy certificate on file —
energy_classand related fields are null when Immowelt has none to show.
Local development
pip install -r requirements.txtpython test_local.py berlin --max 10 --out sample_output.jsonpython test_local.py muenchen --distribution BUY --max 5python test_local.py hamburg --estate-type HOUSE --max 5
sample_output.json in this folder is real output from a live run, kept so the schema can be reviewed without running anything.