Immowelt Scraper — Germany Real Estate Listings | $1.19/1K
Pricing
from $1.00 / 1,000 immowelt scraper — germany real estate listings | $1.19/1ks
Immowelt Scraper — Germany Real Estate Listings | $1.19/1K
Scrape Immowelt.de (German real estate portal) from a search-results URL you paste. Returns title, price, rooms, living space m², location, provider/agent contact, images, and listing URL.
Pricing
from $1.00 / 1,000 immowelt scraper — germany real estate listings | $1.19/1ks
Rating
0.0
(0)
Developer
Vitalii Bondarev
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Immowelt Listings Scraper
Scrape Immowelt.de (German real estate portal) from a search-results URL you paste — no need to configure filters in this actor, just set them on immowelt.de and copy the resulting URL.
Features
- Scrape any Immowelt search (buy or rent, any city/price/room filter you set on their site)
- Returns per-listing: price, rooms, living space m², location, provider/agent contact, images, and listing URL
- Uses Immowelt's own embedded Next.js
__NEXT_DATA__search-results JSON — no HTML scraping, no browser - Pay per result — you only pay for listing records actually extracted
- Automatic pagination up to
maxItems, with residential-proxy session rotation on a block
Input
| Field | Type | Default | Description |
|---|---|---|---|
searchUrl | string | (required) | An immowelt.de search-results URL. Set your filters on immowelt.de, then copy the URL from your browser. |
maxItems | integer | 100 | Max listings to return (0 = unlimited) |
proxyConfiguration | proxy | RESIDENTIAL DE | Apify Residential proxy, Germany |
Why a search URL instead of filter fields?
Traction-proven Store competitors for Immowelt (igolaizola/immowelt-scraper, azzouzana/immowelt-scraper, ninhothedev/immowelt-scraper) mostly accept either a location/locationID pair or a raw search URL. This actor takes the URL directly — simplest, safest contract, and it avoids guessing Immowelt's internal location-ID scheme wrong.
Output fields
| Field | Description |
|---|---|
listing_id | Immowelt internal listing/online ID |
url | Direct URL to the listing |
title / description | |
price / price_display / price_type | price_type is best-effort (kaufpreis/kaltmiete/warmmiete) |
rooms / living_space_m2 / plot_size_m2 | |
city / district / postal_code / street / country | |
latitude / longitude | |
provider_name / provider_phone / provider_type | Listing agent/agency contact |
images / image_count | |
energy_info / building_state | Best-effort; full energy certificate detail lives on the classified detail page |
publication_date / update_date | |
page_number / source / parse_confidence / warnings / scraped_at | Provenance/QA fields. source is next_data or ufrn_fetcher depending on which embedded blob supplied the record. |
Access path
Immowelt has no public search API. It's a Next.js SPA — the search-results page embeds the result set as JSON, primarily via <script id="__NEXT_DATA__" type="application/json"> (standard Next.js page-data, parsed directly, no unescaping) at documented path props.pageProps.classifiedsData. This actor fetches the page with curl_cffi (Chrome TLS impersonation, no browser). As a fallback (only tried when __NEXT_DATA__ yields nothing), it also decodes a second observed bootstrap blob, window["__UFRN_FETCHER__"] = JSON.parse("..."), which uses the same double-encoding scheme as the sibling seloger-listings-scraper actor's initialData — the decode routine is the same shape, ported here rather than shared, per this fleet's per-actor _shared/ convention.
Apify RESIDENTIAL (DE) proxy is recommended for production reliability; third-party vendors document general anti-scraping blocking on this target though the specific mechanism (Cloudflare/DataDome/other) wasn't confirmed against a live run for this build.
Honest caveats (read before relying on this in production)
- Field-name mapping is unverified against a live Immowelt response. The field names used here (
hardFacts.facts[],hardFacts.price,location.address,gallery.images,provider,metadata.publishDate, …) come from ScrapFly's public engineering write-up on scraping Immowelt.de, not from an authenticated cloud run against the live site (out of scope for this build).normalize.pyis defensive: every field falls back toNoneand deductsparse_confidencerather than raising. Spot-check the exact field set against a real cloud run (with RESIDENTIAL DE proxy) before publishing or relying on this for paid delivery. - The exact
pagePropswrapper key for the listings array is unconfirmed — the parser tries several candidate keys (classifiedsData,classifieds,searchResult,initialGeoSearchResult) then falls back to a tolerant structural walk (first list of dicts with anidplus a signal field), same pattern as the siblingseloger-listings-scraperand the fleet's existingimmoscout24-listingsactor. hardFacts.facts[]label matching (rooms/living-space/plot-size) is heuristic (substring match on German/English label text), not a confirmed fixed key list — a mislabeled fact silently stays unmapped rather than crashing, which trades some recall for robustness under an unconfirmed schema.- Full energy certificate detail, exact address (house number), and construction-year data live on the classified detail page (
props.pageProps.classifiedper the same source), not the search-results payload — this actor is search-summary-only; detail-page enrichment is a straightforward v2 addition once the search path is verified live. - Termination is by empty-page detection (30 results/page per source docs), not a parsed
totalPagesfield, since the exact count-field name is also unconfirmed.
Tests
Unit tests (tests/) run entirely offline against synthetic fixtures — no live network calls: cd actors/REAL_ESTATE/immowelt-listings-scraper && python3 -m pytest -q.