Search Rental Apartments — Köln-Rodenkirchen (ImmobilienScout24)
Purpose
Find apartments available to rent on ImmobilienScout24 in a Cologne (Köln) district — here Rodenkirchen — filtered by living space (Wohnfläche), number of rooms (Zimmer), and monthly cold rent (Kaltmiete), and return the matching result-list entries (title, rent, size, rooms, address, expose URL). Read-only: this skill only reads the public search results; it never contacts a landlord, sends an application, or logs in.
Honesty up front: the search result pages (/Suche/...) are gated behind an AWS WAF JavaScript challenge ("Ich bin kein Roboter"). During testing every Browserbase cloud session — --verified --proxies, --verified only, and a bare session — was held on the challenge and then hard-blocked within ~45s. The homepage, the location autocomplete, and the cookie-consent flow all work cleanly; only the result list is walled. The recommended path below is the correct browser flow and the exact URL/filter schema to use; expect the WAF wall and treat a real (non-datacenter) residential browser as the prerequisite for actually rendering results.
When to Use
- A user wants current rental-apartment listings in a specific Köln district (Rodenkirchen, Sülz, Ehrenfeld, …) constrained by size, rooms, and budget.
- Monitoring new Mietwohnungen matching fixed criteria in a German city/district.
- Any task phrased as "Wohnung mieten in {district} mit {X}–{Y} m², {A}–{B} Zimmer, bis {price} €".
- Do not reach for this when you only have a residential proxy/datacenter egress — the WAF will block the result page (see Gotchas).
Workflow
Recommended method: browser (the result data is only reachable by executing the site's JS in a real browser; the HTTP/fetch and public-API paths are dead ends — see Gotchas). Drive a stealth Browserbase session; ideally from a genuine residential browser fingerprint, because the /Suche/ pages run an AWS WAF challenge that datacenter/proxy IPs fail.
-
Open the homepage first to seed cookies. Navigate to
https://www.immobilienscout24.de/. It returns HTTP 200 with no challenge. Title: "ImmoScout24 – Mit über 6,5 Mio. Immobilien." -
Accept the cookie/consent dialog. A GDPR dialog ("Wir verwenden Cookies…") renders shortly after load. Click the "Alle akzeptieren" button (accessibility label
button: Alle akzeptieren). This is required for the search UI to behave and for the WAF cookie (aws-waf-token) to be storable. -
Resolve the location to a Bezirk. Click the location combobox (
combobox: Gib ein, wonach du suchst, und starte deine Suche), typeKöln Rodenkirchen, wait ~2–3s for the autocomplete list, and pick theKöln - Rodenkirchen (Bezirk)option (this is the borough/district; there is also a smaller(Ortsteil)variant and street matches — pick Bezirk for the whole district). The Bezirk option is usually pre-highlighted[selected]. -
Ensure property type = "Wohnung Mieten" (apartment to rent — the homepage default) and click the
Suchenbutton. The UI builds and navigates to the canonical result URL:https://www.immobilienscout24.de/Suche/de/nordrhein-westfalen/koeln/rodenkirchen/wohnung-mieten?enteredFrom=one_step_search -
Apply the filters via URL query params (these are the long-standing IS24 filter params; min and max are joined with a hyphen and use
.0decimals). Navigate to:https://www.immobilienscout24.de/Suche/de/nordrhein-westfalen/koeln/rodenkirchen/wohnung-mieten ?numberofrooms=2.0-3.0 # rooms 2–3 &price=0.0-1800.0 # monthly Kaltmiete 0–1800 € &livingspace=60.0-90.0 # living space 60–90 m² &enteredFrom=result_listYou can also set the filters in the result-page filter bar (Zimmer / Wohnfläche / Preis) instead of editing the URL; the URL above is the deterministic equivalent. Note:
priceon awohnung-mietensearch is the Kaltmiete (cold rent), not Warmmiete. -
Wait for the WAF challenge to clear, then read results. If the page title is "Ich bin kein Roboter - ImmobilienScout24", the AWS WAF challenge is in progress — its
challenge.jspollsAwsWafIntegration.hasToken()~every 200ms for ~10s and self-reloads once a token is issued. Do not re-navigate while waiting (re-navigation resets the challenge). Once cleared, the page title becomes a results title (contains "Wohnung … mieten … Köln" / a count). -
Extract the result cards. On the rendered result list, each listing is a result card exposing: title, Kaltmiete (e.g.
1.250 €), Wohnfläche (72 m²), Zimmer (3 Zi.), address/district line, and a link to the detail page…/expose/{exposeId}. Read them viabrowse get text body/browse snapshotand the per-card anchor hrefs (/expose/<numeric-id>). Paginate with the&pagenumber=Nquery param if more than one page of results exists. Emit the JSON in Expected Output.
Verifying you are on the right search
- URL path is
/Suche/de/nordrhein-westfalen/koeln/rodenkirchen/wohnung-mieten(NRW → Köln → Rodenkirchen → rent-apartment). - Result count / heading mentions Köln and the active filters; cards show
€,m², andZi.. - A persistent filter chip bar reflects
2-3 Zimmer,60-90 m²,bis 1.800 €.
Site-Specific Gotchas
- AWS WAF wall on
/Suche/result pages is the headline blocker. Every result URL serves an AWS WAF interstitial titled "Ich bin kein Roboter - ImmobilienScout24" loadinghttps://…edge.sdk.awswaf.com/.../challenge.js. In testing it never cleared on Browserbase and converted to a terminal hard-block within ~45s, across all three session configs:--verified --proxies,--verifiedonly, and bare. The homepage and autocomplete are NOT walled — only the result list is. - Two challenge variants — know the difference. The page body contains a
fetch("/gk-id/t")handler and a polling/auto-reload script while it is still retrying (recoverable). When it switches tofetch("/gk-id/b")with the copy "…hat unser System dich fälschlicherweise als Roboter identifiziert… Bitte überprüfe deine Einstellungen oder kontaktiere unseren Support" and no polling script, the IP/session has been hard-blocked — abandon it and start a fresh session (preferably a different egress). - Plain fetch is useless here.
browse cloud fetch <result-url> --proxiesreturns HTTP 401 with the same WAF HTML. The result page is fully JS- and cookie-gated; there is no static HTML to scrape and no JSON endpoint reachable without executingchallenge.js. Don't waste turns fetching result URLs. - Public APIs are auth-walled — confirmed dead ends. The mobile API
api.mobile.immobilienscout24.de(OAuth1.0a, app consumer keys) and legacyrest.immobilienscout24.deWebservice both require partner/app credentials that are not publicly obtainable. There is no unauthenticated JSON search API. - robots.txt disallows the geocode/radius search forms (
Disallow: /*?*geocodes=,/immobilienpreise/radius/). Use the SEO district path (/Suche/de/<bundesland>/<stadt>/<bezirk>/wohnung-mieten) rather than a?geocodes=URL — it's both allowed and the form the UI itself generates. (ClaudeBot/GPTBot areAllow: /for the rest of the site.) - District path slug ≠ what you'd guess. Selecting "Köln - Rodenkirchen (Bezirk)" yields path
…/koeln/rodenkirchen/…(singlerodenkirchensegment underkoeln), not…/koeln-rodenkirchen/…. Resolve the slug through the autocomplete rather than hand-constructing it; a hand-builtkoeln-rodenkirchenmay redirect or 404. There is also a smaller (Ortsteil) Rodenkirchen — pick Bezirk for the whole district unless the user clearly wants the smaller Ortsteil. - Filter param schema:
numberofrooms=<min>.0-<max>.0,livingspace=<min>.0-<max>.0(m²),price=<min>.0-<max>.0. Onwohnung-mieten,price= Kaltmiete (cold rent). Min/max joined by-, both with.0decimals; open-ended ranges drop one side (e.g.price=0.0-1800.0).enteredFromis telemetry only (one_step_searchfrom the homepage,result_listwhen editing filters) and does not affect results. - Cookie consent is mandatory before the form works — accept "Alle akzeptieren". An ad iframe ("Advertisement") may also appear on the homepage; ignore it.
- German number formatting: rents render as
1.250 €(dot = thousands separator), sizes as72 m², rooms as3 Zi.. Parse the dot as a thousands grouping, not a decimal point.
Expected Output
Successful extraction (one object per result card). cold_rent_eur is the Kaltmiete; include warm_rent_eur only if the card shows a Warmmiete/Gesamtmiete line.
{
"success": true,
"search": {
"city": "Köln",
"district": "Rodenkirchen",
"bezirk_path": "/Suche/de/nordrhein-westfalen/koeln/rodenkirchen/wohnung-mieten",
"filters": { "rooms": "2-3", "livingspace_m2": "60-90", "cold_rent_eur": "0-1800" }
},
"total_results": 12,
"listings": [
{
"expose_id": "158923471",
"title": "Helle 3-Zimmer-Wohnung mit Balkon in Köln-Rodenkirchen",
"cold_rent_eur": 1250,
"warm_rent_eur": 1480,
"livingspace_m2": 78,
"rooms": 3,
"address": "50996 Köln (Rodenkirchen)",
"url": "https://www.immobilienscout24.de/expose/158923471"
}
]
}
Blocked outcome (what this skill actually hit from Browserbase — datacenter/proxy egress):
{
"success": false,
"search": {
"city": "Köln",
"district": "Rodenkirchen",
"filters": { "rooms": "2-3", "livingspace_m2": "60-90", "cold_rent_eur": "0-1800" }
},
"total_results": 0,
"listings": [],
"error_reasoning": "AWS WAF challenge ('Ich bin kein Roboter - ImmobilienScout24', awswaf challenge.js) never cleared on the /Suche/ result page and hard-blocked (gk-id/b) within ~45s across verified+proxies, verified-only and bare Browserbase sessions. Homepage + autocomplete + cookie consent succeed; only the result list is walled. A genuine residential browser fingerprint is required to render results."
}