     [Blog](https://scrapfly.io/blog)   /  [python](https://scrapfly.io/blog/tag/python)   /  [How to Scrape ImmobilienScout24.de Real Estate Data (2026)](https://scrapfly.io/blog/posts/how-to-scrape-immobilienscout24)   # How to Scrape ImmobilienScout24.de Real Estate Data (2026)

 by [Mazen Ramadan](https://scrapfly.io/blog/author/mazen) Jul 06, 2026 16 min read [\#python](https://scrapfly.io/blog/tag/python) [\#scrapeguide](https://scrapfly.io/blog/tag/scrapeguide) 

 [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-immobilienscout24 "Share on LinkedIn")    

 

 

   

Send a plain request to an ImmobilienScout24 listing and you won't get HTML back. You'll get an HTTP 401 from Amazon CloudFront. Germany's largest real estate portal sits behind one of the tougher anti-bot setups in the DACH region.

This guide pulls search results and listing details straight from the JSON that ImmoScout24 ships inside its own pages. You'll clear the AWS WAF block with a German IP, then read rent, size, rooms, and location without fragile CSS classes.



[**Latest ImmobilienScout24.de Scraper Code**github.com/scrapfly/scrapfly-scrapers/tree/main/immobilienscout24-scraper](https://github.com/scrapfly/scrapfly-scrapers/tree/main/immobilienscout24-scraper)

## Key Takeaways

The short version of a durable ImmobilienScout24 scraper in 2026:

- **AWS WAF on CloudFront guards ImmobilienScout24**, so a plain request returns HTTP 401.
- **A German IP plus anti-bot bypass is mandatory** to load any listing page.
- **The listing and search data ship as JSON** in `keyValues` and `searchResponseModel`.
- **Reading that JSON survives layout changes** that break class-based CSS selectors.
- **Paginate with `?pagenumber=`** and `paging.numberOfPages` to pull the full result set.
- **Building a real-estate dataset?** [Scrapfly](https://scrapfly.io/use-case/real-estate-web-scraping) handles AWS WAF so you focus on the data.

**Get web scraping tips in your inbox**Trusted by 100K+ developers and 30K+ enterprises. Unsubscribe anytime.







## Why Scrape ImmobilienScout24.de?

ImmobilienScout24 holds the most complete dataset of German residential and commercial real estate. That makes it the base layer for rent analysis, valuation, and lead work.

Its listings span every German city and cover rentals, sales, and commercial space (Wohnungen, Häuser, and Gewerbe).

That coverage feeds a few concrete jobs:

- **Rent and price-trend analysis** across the DACH region, including price per m² by city and district (Bezirk).
- **Investment and yield screening** by filtering listings against target returns.
- **Comparable-listings and inventory monitoring** to track how supply and asking prices move over time.
- **Lead generation** for agents, proptech, and CRM enrichment from fresh listing and realtor data.

A scraper turns those millions of listings into a table you can query, instead of pages you click through one by one. The catch is getting past the block that stops most of those requests before any data loads.



## How to Avoid ImmobilienScout24.de Scraping Blocking?

ImmobilienScout24 runs AWS WAF behind Amazon CloudFront, so a request without anti-bot bypass is blocked before any listing loads. On a datacenter IP, an expose page returns HTTP 401 Unauthorized. The fix is to route requests through bypass on a German IP.

### What Anti-Bot Does ImmobilienScout24 Use?

The protection is AWS WAF fronted by Amazon CloudFront, not DataDome or Cloudflare. The site sets an `aws-waf-token` cookie, fires challenge calls to `*.edge.sdk.awswaf.com`, and returns headers that name CloudFront.

ImmoScout24 is DACH-focused, so it treats non-German traffic with extra suspicion.

Most do-it-yourself tactics fail fast on this target. Developers on [r/webscraping](https://www.reddit.com/r/webscraping/comments/1esz9ql/a_beginners_experience_trying_to_scrape_the/) report the same wall when scraping ImmoScout24:

- A headless browser gets detected on the first request and lands on a CAPTCHA.
- Free proxy lists do not work here, since many lack HTTPS and the IPs are already blacklisted.
- User-agent rotation, request delays, and stealth plugins still trigger the challenge.
- Repeated requests from one IP hit rate limits and start returning CAPTCHAs or blocks.

Here is what the headless-browser route looks like when the site flags it:



Web scraping detection on immobilienscout24.deA German residential IP is what clears this consistently. The same request from a German datacenter IP, with no bypass, still returned the 401.

### Bypassing ImmobilienScout24 Blocking with Scrapfly

Scrapfly handles the AWS WAF challenge for you and rotates residential proxies, so you set two parameters and get the page. Turn on anti-scraping protection with `asp=True` and pin the exit IP to Germany with `country="de"`.

Scrapfly runs 130M+ residential proxies across 190+ countries with a 99.99% success rate, and clears AWS WAF Bot Control at a 96% rate. You can read how the bypass works on the [AWS WAF bypass page](https://scrapfly.io/bypass/aws-waf).

Here is the minimal request. The same URL returns 401 without `asp`, and returns the full listing with it:

python```python
from scrapfly import ScrapeConfig, ScrapflyClient, ScrapeApiResponse

scrapfly = ScrapflyClient(key="Your Scrapfly API key")

api_response: ScrapeApiResponse = scrapfly.scrape(
    ScrapeConfig(
        url="https://www.immobilienscout24.de/expose/160519246#/",
        # bypass the AWS WAF anti-bot challenge
        asp=True,
        # use a German residential IP
        country="de",
    )
)
# print the upstream status code
print(api_response.upstream_status_code)
"200"
```



No `render_js` is needed for the core listing fields, since ImmoScout24 ships them in the page source. Add rendering only when you want a lazy-loaded gallery or a revealed contact block. With the block cleared, set up the project and start pulling data.



# Project Setup

You need `scrapfly-sdk` to fetch and bypass, plus `parsel` to run selectors, with `asyncio` for concurrency. The `asyncio` module ships with Python, so only two packages need installing.

Install them with pip:

bash```bash
pip install scrapfly-sdk parsel
```



The SDK sends requests through the Scrapfly Web Scraping API and handles the AWS WAF bypass. `parsel` reads the parts of the page outside pure JSON with [XPath](https://scrapfly.io/blog/posts/parsing-html-with-xpath) selectors, and `asyncio` scrapes many pages at once to increase [scraping speed](https://scrapfly.io/blog/posts/web-scraping-speed).

That is the full toolkit. Property pages come first.



Scrapfly

#### Scale your web scraping effortlessly

Scrapfly handles proxies, browsers, and anti-bot bypass — so you can focus on data.

[Try Free →](https://scrapfly.io/register)## How to Scrape ImmobilienScout24.de Property Pages?

Each ImmobilienScout24 expose (listing) page embeds its data as a JSON object in the page source. The durable approach reads that object instead of chasing CSS classes. Open any [property page](https://www.immobilienscout24.de/expose/161168703#/) and you'll see a layout like this:



Property page on immobilienscout24.de### Finding the Listing Data in the Page

The listing fields sit in a JavaScript variable called `keyValues`, a flat JSON object near the top of the page source. To find it, open the [browser developer tools](https://scrapfly.io/blog/answers/browser-developer-tools-in-web-scraping) with the F12 key, then search the page source for `keyValues`.

Reading this object beats CSS selectors on ImmoScout24. Its rendered markup uses weak, repeated class names. Fields like rent and room count can sit in near-identical elements, so a class selector breaks on the next layout tweak.

The `keyValues` object stays stable because the site's own frontend depends on it.

[How to Scrape Hidden Web DataThe visible HTML doesn't always represent the whole dataset available on the page. In this article, we'll be taking a look at scraping of hidden web data. What is it and how can we scrape it using Python?](https://scrapfly.io/blog/posts/how-to-scrape-hidden-web-data)

### Parsing ImmobilienScout24 Property Data

The `keyValues` object uses `obj_` and `geo_` prefixes, and marks missing fields with the string `no_information`. A few small helpers turn those raw values into clean types, then `parse_property_page` maps them to the fields you want:

python```python
import re
import json
from scrapfly import ScrapeConfig, ScrapflyClient, ScrapeApiResponse
from typing import Dict, List

scrapfly = ScrapflyClient(key="Your Scrapfly API key")

BASE_CONFIG = {
    # bypass the AWS WAF anti-bot challenge
    "asp": True,
    # use a German residential IP
    "country": "de",
}


def clean(value):
    """drop ImmoScout24's 'no_information' sentinel and empty strings"""
    if value in (None, "", "no_information"):
        return None
    return value


def to_float(value):
    """convert a numeric keyValues string to float, keeping None for missing values"""
    value = clean(value)
    return float(value) if value is not None else None


def yes_no(value):
    """map ImmoScout24 'y'/'n' amenity flags to booleans"""
    return clean(value) == "y"


def parse_property_page(response: ScrapeApiResponse):
    """parse listing data from the expose page's embedded keyValues JSON object"""
    selector = response.selector
    # the expose page ships all listing fields in a single keyValues JSON object
    script = re.search(r"keyValues = (\{.+?\});", response.content, re.DOTALL)
    data = json.loads(script.group(1))
    # the human-readable title lives in the meta description
    meta = selector.xpath("//meta[@name='description']/@content").get() or ""
    title = meta.split(" bei ImmobilienScout24")[0].strip() or None

    return {
        "id": int(data["obj_scoutId"]),
        "title": title,
        "url": selector.xpath("//link[@rel='canonical']/@href").get(),
        "type": clean(data.get("obj_immotype")),
        "typeOfFlat": clean(data.get("obj_typeOfFlat")),
        "price": {
            "baseRent": to_float(data.get("obj_baseRent")),  # Kaltmiete
            "totalRent": to_float(data.get("obj_totalRent")),  # Warmmiete
            "serviceCharge": to_float(data.get("obj_serviceCharge")),  # Nebenkosten
            "heatingCosts": to_float(data.get("obj_heatingCosts")),
            "priceReductionPercentage": to_float(data.get("obj_priceReductionPercentage")),
            "currency": "EUR",
        },
        "specs": {
            "livingSpace": to_float(data.get("obj_livingSpace")),  # Wohnfläche, m²
            "rooms": to_float(data.get("obj_noRooms")),
            "floor": clean(data.get("obj_floor")),
            "numberOfFloors": clean(data.get("obj_numberOfFloors")),
            "yearConstructed": clean(data.get("obj_yearConstructed")),
            "condition": clean(data.get("obj_condition")),
            "hasKitchen": yes_no(data.get("obj_hasKitchen")),
            "balcony": yes_no(data.get("obj_balcony")),
            "cellar": yes_no(data.get("obj_cellar")),
            "garden": yes_no(data.get("obj_garden")),
            "lift": yes_no(data.get("obj_lift")),
            "barrierFree": yes_no(data.get("obj_barrierFree")),
            "newlyConstructed": yes_no(data.get("obj_newlyConst")),
            "petsAllowed": clean(data.get("obj_petsAllowed")),
        },
        "energy": {
            "heatingType": clean(data.get("obj_heatingType")),
            "firingTypes": clean(data.get("obj_firingTypes")),
            "energyType": clean(data.get("obj_energyType")),
            "thermalCharacteristic": to_float(data.get("obj_thermalChar")),
        },
        "location": {
            "street": clean(data.get("obj_streetPlain")),
            "houseNumber": clean(data.get("obj_houseNumber")),
            "zipCode": clean(data.get("obj_zipCode")),
            "city": clean(data.get("obj_regio2")),
            "quarter": clean(data.get("obj_regio3")),
            "state": clean(data.get("obj_regio1")),
        },
        "imageCount": int(data.get("obj_picturecount", 0)),
        "titleImage": clean(data.get("obj_picture")),
        "privateOffer": clean(data.get("obj_privateOffer")) == "true",
    }
```



The parser reads one JSON object and returns a clean dictionary, mapping German field names to plain keys with Kaltmiete, Warmmiete, and Wohnfläche labeled inline. Missing fields come back as `None`, so a Kaltmiete-only rental parses as cleanly as a full one.

Next, wrap the parser in async scraping logic to pull several listings at once:

python```python
import asyncio

async def scrape_properties(urls: List[str]) -> List[Dict]:
    """scrape listing data from immobilienscout24 property pages"""
    # add the property pages to a scraping list
    to_scrape = [ScrapeConfig(url, **BASE_CONFIG) for url in urls]
    properties = []
    # scrape all property pages concurrently
    async for response in scrapfly.concurrent_scrape(to_scrape):
        properties.append(parse_property_page(response))
    print(f"scraped {len(properties)} property listings")
    return properties
```



Run the codepython```python
if __name__ == "__main__":
    properties_data = asyncio.run(scrape_properties(
        urls=[
            "https://www.immobilienscout24.de/expose/161168703#/",
            "https://www.immobilienscout24.de/expose/162617109#/",
            "https://www.immobilienscout24.de/expose/160519246#/",
        ]
    ))
    # print the result in JSON format
    print(json.dumps(properties_data, indent=2, ensure_ascii=False))
```



Here, `scrape_properties` takes a list of expose URLs, scrapes them concurrently, and parses each response into the property dictionary. The result is one clean object per listing:

Sample outputjson```json
{
  "id": 161168703,
  "title": "Dachgeschosswohnung (Wohnung/Miete): 2 Zimmer - 69,9 qm - Pasing",
  "url": "https://www.immobilienscout24.de/expose/161168703",
  "type": "wohnung_miete",
  "typeOfFlat": "roof_storey",
  "price": {
    "baseRent": 1720.0,
    "totalRent": 1995.0,
    "serviceCharge": 230.0,
    "heatingCosts": null,
    "priceReductionPercentage": 3.0,
    "currency": "EUR"
  },
  "specs": {
    "livingSpace": 69.94,
    "rooms": 2.0,
    "floor": "5",
    "numberOfFloors": "5",
    "yearConstructed": "2023",
    "condition": "mint_condition",
    "hasKitchen": false,
    "balcony": true,
    "cellar": true,
    "garden": false,
    "lift": true,
    "barrierFree": true,
    "newlyConstructed": false,
    "petsAllowed": "negotiable"
  },
  "energy": {
    "heatingType": "central_heating",
    "firingTypes": "gas",
    "energyType": null,
    "thermalCharacteristic": null
  },
  "location": {
    "street": null,
    "houseNumber": null,
    "zipCode": "81241",
    "city": "München",
    "quarter": "Pasing_Obermenzing",
    "state": "Bayern"
  },
  "imageCount": 1,
  "titleImage": "https://pictures.immobilienscout24.de/listings/c6d94bde-5c5a-46f6-a4d5-bf01bec7d2dc-1932214860.jpg/ORIG/resize/118x118%3E/extent/118x118/format/webp/quality/73",
  "privateOffer": false
}
```



That is a full listing from one JSON read, with no CSS classes to maintain. Search pages hold the data you need to find those listing URLs in the first place.



## How to Scrape ImmobilienScout24.de Search Pages?

ImmobilienScout24 search pages embed every result as JSON inside a `searchResponseModel` script tag, so you extract that block and paginate with `?pagenumber=`. Open any [search page](https://www.immobilienscout24.de/Suche/de/bayern/muenchen/wohnung-mieten) and you'll see a grid like this:



Search page on immobilienscout24.de### Extracting the Hidden Search JSON

Rather than parse the HTML cards, read the results straight from the embedded JSON. To find it, open the developer tools with F12 and search the page source for the XPath `//script[contains(text(),'searchResponseModel')]`.



Hidden Immobilienscout24 hidden search dataThe listings sit under `resultlist.resultlist` in the `resultlistEntries` array, and the page count lives at `paging.numberOfPages`. Since the JSON is embedded in a script string, a small utility pulls it out before you parse it:

python```python
import json
import asyncio
from typing import Dict, List
from scrapfly import ScrapeConfig, ScrapflyClient, ScrapeApiResponse

scrapfly = ScrapflyClient(key="Your Scrapfly API key")

BASE_CONFIG = {
    # bypass the AWS WAF anti-bot challenge
    "asp": True,
    # use a German residential IP
    "country": "de",
}


def find_json_objects(text: str, decoder=json.JSONDecoder()):
    """Find JSON objects in text, and generate decoded JSON data"""
    pos = 0
    while True:
        match = text.find("{", pos)
        if match == -1:
            break
        try:
            result, index = decoder.raw_decode(text[match:])
            yield result
            pos = match + index
        except ValueError:
            pos = match + 1


def parse_search(response: ScrapeApiResponse) -> List[Dict]:
    """parse script tags for JSON search results"""
    selector = response.selector
    script = selector.xpath("//script[contains(text(),'searchResponseModel')]/text()").get()
    json_data = [i for i in list(find_json_objects(script)) if "searchResponseModel" in i][0]["searchResponseModel"]["resultlist.resultlist"]
    search_data = json_data["resultlistEntries"][0]["resultlistEntry"]
    max_pages = json_data["paging"]["numberOfPages"]
    return {"search_data": search_data, "max_pages": max_pages}
```



The `find_json_objects` helper decodes any JSON object from a string, and `parse_search` uses it to grab the result list and total page count from one search response.

Each entry carries rich fields. Expect price with currency and marketing type, living space, rooms, energy class, total rent, construction year, and realtor contact details.

### Handling ImmobilienScout24 Search Pagination

To collect a full search, read `paging.numberOfPages` from the first response, then scrape pages `2` through `N` by appending `?pagenumber=` to the URL. The `scrape_search` function does both in one pass:

python```python
async def scrape_search(url: str, scrape_all_pages: bool, max_scrape_pages: int = 10) -> List[Dict]:
    """scrape immobilienscout24 search pages"""
    first_page = await scrapfly.async_scrape(ScrapeConfig(url, **BASE_CONFIG))
    data = parse_search(first_page)
    search_data = data["search_data"]
    max_search_pages = data["max_pages"]

    # cap the crawl at max_scrape_pages unless scrape_all_pages is set
    if scrape_all_pages == False and max_scrape_pages < max_search_pages:
        max_scrape_pages = max_scrape_pages
    else:
        max_scrape_pages = max_search_pages
    print(f"scraping search {url} pagination ({max_scrape_pages - 1} more pages)")

    # scrape the remaining search pages concurrently
    to_scrape = [
        ScrapeConfig(url + f"?pagenumber={page}", **BASE_CONFIG)
        for page in range(2, max_scrape_pages + 1)
    ]
    async for response in scrapfly.concurrent_scrape(to_scrape):
        search_data.extend(parse_search(response)["search_data"])

    print(f"scraped {len(search_data)} properties from {url}")
    return search_data
```



Run the codepython```python
if __name__ == "__main__":
    search_data = asyncio.run(scrape_search(
        url="https://www.immobilienscout24.de/Suche/de/bayern/muenchen/wohnung-mieten",
        scrape_all_pages=False,
        max_scrape_pages=3
    ))

    # save the results to a JSON file
    with open("search_results.json", "w", encoding="utf-8") as f:
        json.dump(search_data, f, indent=2, ensure_ascii=False)
```



The scraper reads the first page, learns the page count, then scrapes the rest concurrently and appends each page's entries to one list.

Without a German IP and anti-bot bypass, this run stalls on rate limits and CAPTCHAs long before the last page. With them, it walks the pagination cleanly. The output is one JSON entry per listing:

Sample outputjson```json
{
  "@id": "168983220",
  "@modification": "2026-07-03T13:29:40.592+02:00",
  "@creation": "2026-07-01T12:55:36.000+02:00",
  "realEstateId": 168983220,
  "resultlist.realEstate": {
    "@xsi.type": "search:ApartmentRent",
    "title": "Modernisiertes großzügiges Apartment mit 42m² mit großem Balkon in München Laim - Provisionsfrei !!",
    "address": {
      "postcode": "80686",
      "city": "München",
      "quarter": "Laim",
      "description": {
        "text": "Friedenheim, München"
      }
    },
    "realtorCompanyName": "Rock Capital Group GmbH",
    "price": {
      "value": 1200,
      "currency": "EUR",
      "marketingType": "RENT",
      "priceIntervalType": "MONTH"
    },
    "livingSpace": 41.88,
    "numberOfRooms": 1,
    "energyEfficiencyClass": "E",
    "balcony": "true",
    "garden": "false",
    "calculatedTotalRent": {
      "totalRent": {
        "value": 1420,
        "currency": "EUR",
        "marketingType": "RENT",
        "priceIntervalType": "MONTH"
      },
      "calculationMode": "SUMMARIZED"
    },
    "constructionYear": 1972
  },
  "attributes": [
    {
      "attribute": [
        { "key": "baseRent", "label": "Kaltmiete", "value": "1.200 €" },
        { "key": "livingSpace", "label": "Wohnfläche", "value": "41,88 m²" },
        { "key": "rooms", "label": "Zimmer", "value": 1 }
      ]
    }
  ]
}
```



With both page types covered, you can move from a city search to a full set of listing details in a couple of calls.

## Scraping ImmobilienScout24 with Scrapfly



ScrapFly's [Web Scraping API](https://scrapfly.io/web-scraping-api) is a single HTTP endpoint for collecting web data at scale, with a **99.99% success rate** across **130M+ proxies in 190+ countries**.

- [Anti-Scraping Protection bypass](https://scrapfly.io/docs/scrape-api/anti-scraping-protection) - automatically defeats Cloudflare, DataDome, PerimeterX, Akamai, and 90+ other bot systems.
- [Smart proxy rotation](https://scrapfly.io/docs/scrape-api/proxy) - residential and datacenter pools with country and ASN level geo-targeting.
- [JavaScript rendering](https://scrapfly.io/docs/scrape-api/javascript-rendering) - render SPAs and dynamic pages through real cloud browsers.
- [Browser automation scenarios](https://scrapfly.io/docs/scrape-api/javascript-scenario) - scroll, click, fill forms, and wait for elements without managing a browser fleet.
- [Format conversion](https://scrapfly.io/docs/scrape-api/getting-started#api_param_format) - return pages as HTML, JSON, clean text, or LLM ready Markdown.
- [Session management](https://scrapfly.io/docs/scrape-api/session) - keep cookies, headers, and IPs consistent across multi step flows.
- [Smart caching](https://scrapfly.io/docs/scrape-api/getting-started#api_param_cache) - cache successful responses to cut cost on repeat scraping jobs.
- [Python](https://scrapfly.io/docs/sdk/python), [TypeScript](https://scrapfly.io/docs/sdk/typescript), [Scrapy](https://scrapfly.io/docs/sdk/scrapy), and [no-code integrations](https://scrapfly.io/docs/integration/getting-started) including [Make](https://scrapfly.io/integration/make), [n8n](https://scrapfly.io/integration/n8n), [Zapier](https://scrapfly.io/integration/zapier), [LangChain](https://scrapfly.io/integration/langchain), and [LlamaIndex](https://scrapfly.io/integration/llamaindex).



### Web Scraping API

Scrape any website with our powerful API. Anti-bot bypass, JavaScript rendering, and rotating proxies built-in.



[Try Web Scraping API](https://scrapfly.io/docs/scrape-api/getting-started)



## FAQ

What anti-bot protection does ImmobilienScout24 use?ImmobilienScout24 runs AWS WAF behind Amazon CloudFront, not DataDome. A request without anti-bot bypass returns an HTTP 401 before the listing loads, so a German IP (`country="de"`) plus bypass is required.







Does ImmobilienScout24 have a public API?There is no open public API for arbitrary listing data. ImmoScout24 runs an official partner API at [api.immobilienscout24.de](https://api.immobilienscout24.de), but it needs an approved permission request. Scraping the embedded JSON stays the practical route for most projects.







Can I scrape rent and price-per-square-meter data?Yes. Listing pages expose base rent (Kaltmiete), total rent (Warmmiete), service charges, living space (Wohnfläche), and rooms. From those you can compute price per m² by city or district.







Is scraping ImmobilienScout24 legal?Scraping publicly available listing data at reasonable rates is generally fine. Personal data such as private realtor contacts falls under GDPR in the EU, so handle it with care. See our [guide on web scraping legality](https://scrapfly.io/is-web-scraping-legal) for more.







Can I use this approach on other German or European real estate sites?Yes. The embedded-JSON technique transfers to siblings like [Immowelt.de](https://scrapfly.io/blog/posts/how-to-scrape-immowelt-de-real-estate-properties), [ImmoScout24.ch](https://scrapfly.io/blog/posts/how-to-scrape-immoscout24-ch-real-estate-property-data), [idealista](https://scrapfly.io/blog/posts/how-to-scrape-idealista), and [homegate.ch](https://scrapfly.io/blog/posts/how-to-scrape-homegate-ch-real-estate-property-data).









## Summary

ImmobilienScout24 is Germany's largest real estate portal, and it sits behind AWS WAF on Amazon CloudFront. A plain request returns HTTP 401, so the page never loads without a bypass.

Two choices keep an ImmoScout24 scraper working. Route requests through anti-bot bypass on a German IP, and read the embedded JSON rather than CSS classes.

Listing pages ship a `keyValues` object, search pages ship a `searchResponseModel` block, and `?pagenumber=` walks the full result set.

With those pieces, a city search becomes structured data. You get rent, size, rooms, energy class, and location for every listing. That output is ready for trend analysis or lead work.



Legal Disclaimer and PrecautionsThis tutorial covers popular web scraping techniques for education. Interacting with public servers requires diligence and respect:

- Do not scrape at rates that could damage the website.
- Do not scrape data that's not available publicly.
- Do not store PII of EU citizens protected by GDPR.
- Do not repurpose *entire* public datasets which can be illegal in some countries.

Scrapfly does not offer legal advice but these are good general rules to follow. For more you should consult a lawyer.

 

   Table of Contents















 

  Table of Contents- [Key Takeaways](#key-takeaways)
- [Why Scrape ImmobilienScout24.de?](#why-scrape-immobilienscout24-de)
- [How to Avoid ImmobilienScout24.de Scraping Blocking?](#how-to-avoid-immobilienscout24-de-scraping-blocking)
- [What Anti-Bot Does ImmobilienScout24 Use?](#what-anti-bot-does-immobilienscout24-use)
- [Bypassing ImmobilienScout24 Blocking with Scrapfly](#bypassing-immobilienscout24-blocking-with-scrapfly)
- [How to Scrape ImmobilienScout24.de Property Pages?](#how-to-scrape-immobilienscout24-de-property-pages)
- [Finding the Listing Data in the Page](#finding-the-listing-data-in-the-page)
- [Parsing ImmobilienScout24 Property Data](#parsing-immobilienscout24-property-data)
- [How to Scrape ImmobilienScout24.de Search Pages?](#how-to-scrape-immobilienscout24-de-search-pages)
- [Extracting the Hidden Search JSON](#extracting-the-hidden-search-json)
- [Handling ImmobilienScout24 Search Pagination](#handling-immobilienscout24-search-pagination)
- [Scraping ImmobilienScout24 with Scrapfly](#scraping-immobilienscout24-with-scrapfly)
- [FAQ](#faq)
- [Summary](#summary)
 
    Join the Newsletter  Get monthly web scraping insights 

 

  



Scale Your Web Scraping

Anti-bot bypass, browser rendering, and rotating proxies, all in one API. Start with 1,000 free credits.

  No credit card required  1,000 free API credits  Anti-bot bypass included 

 [Start Free](https://scrapfly.io/register) [View Docs](https://scrapfly.io/docs/onboarding) 

 Not ready? Get our newsletter instead. 

 

## Explore this Article with AI

 [ ChatGPT ](https://chat.openai.com/?q=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-immobilienscout24) [ Gemini ](https://www.google.com/search?udm=50&aep=11&q=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-immobilienscout24) [ Grok ](https://x.com/i/grok?text=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-immobilienscout24) [ Perplexity ](https://www.perplexity.ai/search/new?q=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-immobilienscout24) [ Claude ](https://claude.ai/new?q=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-immobilienscout24) 



 ## Related Articles

 [  

 python scrapeguide 

### How to Scrape Immowelt.de Real Estate Data

Immowelt.de is a major real estate website in Germany and it's suprisingly easy to scrape. In this tutorial, we'll be us...

 

 ](https://scrapfly.io/blog/posts/how-to-scrape-immowelt-de-real-estate-properties) [  

 http python 

### Web Scraping with Python

Introduction tutorial to web scraping with Python. How to collect and parse public data. Challenges, best practices and ...

 

 ](https://scrapfly.io/blog/posts/web-scraping-with-python) [  

 python scrapeguide 

### How to Scrape Real Estate Property Data using Python

Introduction to scraping real estate property data. What is it, why and how to scrape it? We'll also list dozens of popu...

 

 ](https://scrapfly.io/blog/posts/how-to-scrape-real-estate-property-data-using-python) 

  



   



 Scale your web scraping effortlessly, **1,000 free credits** [Start Free](https://scrapfly.io/register)