Install

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.

No reports yetRead-only, no login
Site
ImmoScout24, Germany
Version
v1
Runs, last 7 days
No reports yet
sha256
56335de55cb4…

Requests

sent from your browser, in order
  1. 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).
  2. 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 agent
citystringrequiredCity, 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 agent
citystringCity 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
}