Search rental flats or houses in a German city with rent, rooms and size filters.
Searches ImmoScout24 rentals like the site's own result list: cold and warm rent, rooms, living space, address (as far as the landlord shows it), publish date, private or agent listing, balcony and fitted kitchen, and the expose link. Swap-only listings (Tauschwohnung) are dropped by default. Runs only in the user's browser: AWS WAF rejects every request without the browser's own aws-waf-token cookie.
- Site
- ImmoScout24, Germany
- Version
- v1
- Runs, last 7 days
- No reports yet
- sha256
- 56335de55cb4…
Requests
sent from your browser, in order- 1GET/geoautocomplete/v4.0/DEU?dataset&i&lang&lpt&tCity name to ImmoScout24 geopath (e.g. /de/sachsen/leipzig). Needs the public frontend key from the page (X-IS24-GAC).
- 2GET/Suche{{steps.geo.geopath}}/{{params.property_type}}?livingspace&numberofrooms&pagenumber&price&pricetype&sortingThe result-list URL answers JSON (searchResponseModel) when sent Accept: application/json. Ranges are always sent closed (defaults) so no empty '-' values reach the site.
Parameters
from your agentcitystringrequiredCity, e.g. 'Leipzig', 'Köln', 'Hamburg'
include_swapbooleanKeep swap-only listings (Tauschwohnung) = false
max_rentnumberMaximum cold rent (Kaltmiete), EUR/month = 100000
max_roomsnumber = 99
min_area_m2numberMinimum living space in m² = 0
min_rentnumberMinimum cold rent (Kaltmiete), EUR/month = 0
min_roomsnumber = 0
pageinteger20 listings per page = 1
property_typeenumFlat or house for rent "wohnung-mieten" | "haus-mieten" = "wohnung-mieten"
sortenum0 = relevance, 2 = newest first, 3 = highest rent first, 4 = lowest rent first 0 | 2 | 3 | 4 = 0
Returns
to your agentcitystringCity actually searched
listingsobject[]address_text, area_m2, balcony, city, cold_rent_eur, district, fitted_kitchen, house_number, id, private_offer, published, rooms, street, swap_only, title, url, warm_rent_eur, zip
pageinteger
pagesinteger
totalintegerAll matching listings on ImmoScout24
Where it can send
- www.immobilienscout24.de
Anything else is blocked by the extension.
Reads from your session
- gac_key from dom
Used only in requests to the addresses on the left. Never sent to wield.run or your agent.
Checks
a run passes when- length(output.listings) > `0`
- output.city == 'Leipzig'
- output.total > `20`
- length(output.listings[?cold_rent_eur > `800`]) == `0`
- starts_with(output.listings[0].url, 'https://www.immobilienscout24.de/expose/')
Raw recipe
Served as canonical JSON from /api/v1/recipes/immobilienscout24.de/search-rentals, so its sha256 matches the ETag and the index.
Check it yourself
curl -s https://wield.run/api/v1/recipes/immobilienscout24.de/search-rentals | shasum -a 256 # 56335de55cb456889ac84703fa35cc278b4bf9c7b183671fcc11d902b384fc91
immobilienscout24.de/search-rentals.json, v1
{ "auth": { "derive": [ { "from": "dom", "name": "gac_key", "regex": "(?:NEXT_PUBLIC_GAC_API_KEY|gacApiKey)\\W{1,10}([0-9a-f]{16,64})", "selector": "script:not([src])" } ] }, "description": "Searches ImmoScout24 rentals like the site's own result list: cold and warm rent, rooms, living space, address (as far as the landlord shows it), publish date, private or agent listing, balcony and fitted kitchen, and the expose link. Swap-only listings (Tauschwohnung) are dropped by default. Runs only in the user's browser: AWS WAF rejects every request without the browser's own aws-waf-token cookie.", "effect": "read", "id": "immobilienscout24.de/search-rentals", "keywords": [ "immobilienscout24", "immoscout", "wohnung mieten", "mietwohnung", "wohnungssuche", "haus mieten", "miete", "zimmer", "apartment", "flat for rent", "rental", "housing", "apartment search germany" ], "output": { "schema": { "properties": { "city": { "description": "City actually searched", "type": "string" }, "listings": { "items": { "properties": { "address_text": { "type": [ "string", "null" ] }, "area_m2": { "type": [ "number", "null" ] }, "balcony": { "type": "boolean" }, "city": { "type": [ "string", "null" ] }, "cold_rent_eur": { "description": "Kaltmiete per month", "type": [ "number", "null" ] }, "district": { "type": [ "string", "null" ] }, "fitted_kitchen": { "type": "boolean" }, "house_number": { "type": [ "string", "null" ] }, "id": { "type": "string" }, "private_offer": { "description": "Listed by a private landlord rather than an agent", "type": "boolean" }, "published": { "description": "ISO timestamp", "type": [ "string", "null" ] }, "rooms": { "type": [ "number", "null" ] }, "street": { "type": [ "string", "null" ] }, "swap_only": { "description": "Tauschwohnung (title heuristic)", "type": "boolean" }, "title": { "type": "string" }, "url": { "format": "uri", "type": "string" }, "warm_rent_eur": { "description": "Warmmiete (total rent) per month, when given", "type": [ "number", "null" ] }, "zip": { "type": [ "string", "null" ] } }, "type": "object" }, "type": "array" }, "page": { "type": "integer" }, "pages": { "type": [ "integer", "null" ] }, "total": { "description": "All matching listings on ImmoScout24", "type": "integer" } }, "required": [ "city", "total", "page", "listings" ], "type": "object" }, "value": "let $inc = params.include_swap in {city: steps.geo.label, total: steps.search.total, page: params.page, pages: steps.search.pages, listings: steps.search.listings[?$inc || !swap_only]}" }, "params": { "additionalProperties": false, "properties": { "city": { "description": "City, e.g. 'Leipzig', 'Köln', 'Hamburg'", "maxLength": 80, "minLength": 2, "type": "string" }, "include_swap": { "default": false, "description": "Keep swap-only listings (Tauschwohnung)", "type": "boolean" }, "max_rent": { "default": 100000, "description": "Maximum cold rent (Kaltmiete), EUR/month", "minimum": 1, "type": "number" }, "max_rooms": { "default": 99, "minimum": 1, "type": "number" }, "min_area_m2": { "default": 0, "description": "Minimum living space in m²", "minimum": 0, "type": "number" }, "min_rent": { "default": 0, "description": "Minimum cold rent (Kaltmiete), EUR/month", "minimum": 0, "type": "number" }, "min_rooms": { "default": 0, "minimum": 0, "type": "number" }, "page": { "default": 1, "description": "20 listings per page", "maximum": 50, "minimum": 1, "type": "integer" }, "property_type": { "default": "wohnung-mieten", "description": "Flat or house for rent", "enum": [ "wohnung-mieten", "haus-mieten" ], "type": "string" }, "sort": { "default": 0, "description": "0 = relevance, 2 = newest first, 3 = highest rent first, 4 = lowest rent first", "enum": [ 0, 2, 3, 4 ], "type": "integer" } }, "required": [ "city" ], "type": "object" }, "provenance": { "method": "browser-inspect", "notes": "spikes/immobilienscout24.md (verified in a real browser: Leipzig ≤800 €, ≥2 rooms → 1,865 hits). AWS WAF Bot Control in front of /Suche: without the browser's aws-waf-token cookie every request gets 401 'Ich bin kein Roboter' (curl, credentials omit). C4's automated browser was also challenged on 2026-11-07, so this recipe is verified only in a human-driven Chrome with the extension. The GAC key is a public frontend constant read from the page (homepage RSC payload NEXT_PUBLIC_GAC_API_KEY, or IS24.resultList.gacApiKey on result pages; regex matched the homepage in-browser). The JSON is a legacy XML-to-JSON mapping: a single hit is an object, not an array (to_array), keys like @id and resultlist.realEstate need quoting. Range values: spike used 800.0 style; integers and wide default bounds are assumed equivalent (unverified).", "recorded_at": "2026-11-07T12:35:00+01:00", "recorded_by": "C4" }, "requires_login": false, "schema": "https://wield.run/schema/recipe/v1.json", "site": { "country": "DE", "id": "immobilienscout24.de", "language": "de", "login_url": "https://www.immobilienscout24.de/anmelden", "name": "ImmoScout24", "origin": "https://www.immobilienscout24.de", "origins": [ "https://www.immobilienscout24.de" ] }, "steps": [ { "description": "City name to ImmoScout24 geopath (e.g. /de/sachsen/leipzig). Needs the public frontend key from the page (X-IS24-GAC).", "expect": { "assert": "length(body[?entity.type=='city' && entity.geopath.uri != null]) > `0`", "content_type": "json", "status": [ 200 ] }, "extract": { "json": { "geopath": "[?entity.type=='city' && entity.geopath.uri != null] | [0].entity.geopath.uri", "label": "[?entity.type=='city' && entity.geopath.uri != null] | [0].entity.label" } }, "id": "geo", "request": { "headers": { "Accept": "application/json", "X-IS24-GAC": "{{vars.gac_key}}" }, "method": "GET", "query": { "dataset": "nextgen", "i": "{{params.city}}", "lang": "de", "lpt": "5", "t": "city" }, "url": "/geoautocomplete/v4.0/DEU" } }, { "description": "The result-list URL answers JSON (searchResponseModel) when sent Accept: application/json. Ranges are always sent closed (defaults) so no empty '-' values reach the site.", "expect": { "assert": "body.searchResponseModel.\"resultlist.resultlist\" != null", "content_type": "json", "status": [ 200 ] }, "extract": { "json": { "listings": "to_array(searchResponseModel.\"resultlist.resultlist\".resultlistEntries[0].resultlistEntry || `[]`)[].let $r = \"resultlist.realEstate\" in {id: to_string(\"@id\"), title: $r.title, cold_rent_eur: $r.price.value, warm_rent_eur: $r.calculatedTotalRent.totalRent.value || `null`, rooms: $r.numberOfRooms, area_m2: $r.livingSpace, street: $r.address.street || `null`, house_number: $r.address.houseNumber || `null`, zip: $r.address.postcode || `null`, city: $r.address.city || `null`, district: $r.address.quarter || `null`, address_text: $r.address.description.text || `null`, published: \"@publishDate\" || `null`, private_offer: $r.privateOffer == 'true' || $r.privateOffer == `true`, balcony: $r.balcony == 'true' || $r.balcony == `true`, fitted_kitchen: $r.builtInKitchen == 'true' || $r.builtInKitchen == `true`, swap_only: contains(lower($r.title || ''), 'tausch'), url: join('', ['https://www.immobilienscout24.de/expose/', to_string(\"@id\")])}", "pages": "searchResponseModel.\"resultlist.resultlist\".paging.numberOfPages", "total": "searchResponseModel.\"resultlist.resultlist\".paging.numberOfHits" } }, "id": "search", "request": { "headers": { "Accept": "application/json" }, "method": "GET", "query": { "livingspace": "{{params.min_area_m2}}-100000", "numberofrooms": "{{params.min_rooms}}-{{params.max_rooms}}", "pagenumber": "{{params.page}}", "price": "{{params.min_rent}}-{{params.max_rent}}", "pricetype": "rentpermonth", "sorting": "{{params.sort}}" }, "url": "/Suche{{steps.geo.geopath}}/{{params.property_type}}" } } ], "task": "Search rental flats or houses in a German city with rent, rooms and size filters", "tos": { "notes": "ImmoScout24's terms forbid automated querying and data collection. One user-initiated search page at a time from the user's own browser (2 requests). Never try to solve or bypass the WAF challenge: if it appears, the user loads the site normally. Listing contact data is not returned.", "reviewed": false }, "verify": { "checks": [ "length(output.listings) > `0`", "output.city == 'Leipzig'", "output.total > `20`", "length(output.listings[?cold_rent_eur > `800`]) == `0`", "starts_with(output.listings[0].url, 'https://www.immobilienscout24.de/expose/')" ], "example_params": { "city": "Leipzig", "max_rent": 800, "min_rooms": 2 }, "max_ms": 6000 }, "version": 1 }