Skip to main content

🏠 immoscout

PyPI CI Python License: MIT

A typed, unofficial Python client for ImmobilienScout24 — search real-estate listings, fetch expose details, and plug it all into AI agents.

Instead of a raw JSON blob, you get clean typed objects (Listing, Expose) — and a built-in MCP server so assistants like Claude can search real estate for you natively.

📖 Documentation · pip install immoscout

⚠️ Unofficial and not affiliated with ImmobilienScout24. For personal use, and gentle with request volume — see the DISCLAIMER.

✨ Features

  • 🚫 No captchas to solve — talks to ImmobilienScout24's mobile API, which returns clean JSON directly. No headless browser, no captcha-solving, no HTML scraping — where the website makes even human users pass captchas, the mobile endpoints just answer.
  • 🔍 Typed results — search() returns SearchResult with parsed Listing objects (price, rooms, m², address, URL) — not a nested dict you have to reverse-engineer.
  • 🎯 Validated filters — SearchFilter with price/rooms/space ranges and real-estate types.
  • 🗺️ Place names, not codes — region="München" is auto-resolved to the right geocode path.
  • 📄 Auto-pagination & counts — search_all() walks every page; count() returns totals only.
  • 🛡️ Robust HTTP — request timeouts, retries with backoff, and explicit rate-limit errors.
  • 🤖 Agent-native — an MCP server (immoscout-mcp) exposes search as tools for Claude & co.
  • ⌨️ CLI — immoscout search … and immoscout expose ….
  • 🧩 Nothing hidden — every object keeps the untouched API payload on .raw.

🚀 Quick Start

from immoscout import ImmoscoutClient

client = ImmoscoutClient()

result = client.search(region="Berlin", price_max=1200, rooms_min=2)  # place name auto-resolved
print(f"{result.total_results} results")

for listing in result.listings[:5]:
    print(listing.title)
    print(f"  {listing.price:.0f} {listing.currency} · {listing.rooms:g} rooms · {listing.living_space:g} m²")
    print(f"  {listing.address.line}")
    print(f"  {listing.url}")

Finding a region

You can pass a place name directly (region="München") and it's resolved for you. To see the options, or to store the exact path, look them up:

client.suggest_regions("münchen")[0].region   # -> "/de/bayern/muenchen"
immoscout regions münchen
# /de/bayern/muenchen          city       München
# /de/bayern/muenchen-kreis    district   München (Kreis)

🎯 Filters & pagination

from immoscout import ImmoscoutClient, RealEstateType, SearchFilter

client = ImmoscoutClient()

query = SearchFilter(
    region="/de/bayern/muenchen",
    real_estate_type=RealEstateType.APARTMENT_RENT,
    price_max=1500,
    rooms_min=2,
    living_space_min=50,
)

# Walk every result page (one request per page) — cap it to stay gentle:
for listing in client.search_all(query, max_pages=3):
    print(listing.price, listing.title)

📄 Expose details

expose = client.get_expose("169446368")
print(expose.title, expose.price, expose.rooms, expose.living_space)
print(expose.address)
print(expose.description)
print(expose.attributes)   # {"Wohnungstyp": "Etagenwohnung", "Etage": "2 von 4", ...}

⌨️ CLI

immoscout regions münchen                                   # find a region path
immoscout search --region /de/berlin/berlin --price-max 1200 --rooms-min 2
immoscout search --region /de/berlin/berlin --json          # machine-readable
immoscout expose 169446368

🤖 Use it from AI agents (MCP)

immoscout ships a Model Context Protocol server, so any MCP client (Claude Desktop, Claude Code, Cursor, …) can search real estate natively.

pip install "immoscout[mcp]"
immoscout-mcp        # runs the server (stdio)

Register it in your MCP client — e.g. Claude Desktop's mcpServers:

{
  "mcpServers": {
    "immoscout": { "command": "immoscout-mcp" }
  }
}

The agent then has these tools:

  • search_listings — region, real-estate type, price/rooms/space bounds, max results.
  • count_listings — how many match, without fetching them.
  • get_expose — full details for a listing ID.
  • suggest_regions — resolve a place name to region paths (so the agent can search any city).

Now you can ask "find me 2-room apartments in Berlin under 1200 € and summarize the three cheapest" and the agent does the lookup itself.

🧱 API overview

Object What it is
ImmoscoutClient(timeout, max_retries, backoff) HTTP client — search(), search_all(), count(), get_expose(), suggest_regions()
SearchFilter(...) Validated query; .to_params() compiles to API params
RealEstateType Enum: apartment/house rent & buy, flat-share room, garage
SearchResult total_results, number_of_pages, listings, raw
Listing Parsed result: price, rooms, living_space, address, url, raw
Expose Detail view: price, attributes, description, raw
ImmoscoutError Base; RequestError, NotFoundError, RateLimitError

🛠️ Development

pip install -e ".[dev]"
ruff check .
pytest              # unit tests are fully mocked — no network needed

CI runs ruff + pytest across Python 3.10–3.13.

⚖️ Responsible use

ImmobilienScout24 actively rate-limits and blocks automated traffic. Keep the built-in timeouts/retries, add delays, and don't scrape at scale. This project is for personal and educational use — see the DISCLAIMER.

📄 License

MIT

Metadata

Release files for immoscout 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for immoscout 0.2.0
File Size Uploaded
immoscout-0.2.0.tar.gz 18.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for immoscout 0.2.0
File Interpreter ABI Platform
immoscout-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 34.3 kB

Release files / immoscout-0.2.0.tar.gz

Download URL immoscout-0.2.0.tar.gz
Size 18.4 kB
Tags Source
SHA-256 checksum
How to use checksums
00205ee00dccae7c14b14c722ebfbd8bfbe3ab84e73b276420dff9f788bd685e
BLAKE2b-256 checksum
How to use checksums
ccc31963aad025c2a89631be199cb0ba5dd142b0fa37cb1eb4c3151a243e7bf3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / immoscout-0.2.0-py3-none-any.whl

Download URL immoscout-0.2.0-py3-none-any.whl
Size 15.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b3469a0881243741baff339525f6d289c970dc8626b00df575ec998e3cf4acf2
BLAKE2b-256 checksum
How to use checksums
44b3f478406e4529afa3c360298a863cf594022d9ff7a3a17b95e3f24a5127f5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page