{
  "openapi": "3.0.1",
  "info": {
    "title": "ImmoScout24 ImmobilienScout24 (.de|.ch|.at) [From $1.14💰]",
    "description": "[From 💰$1.14] Extract comprehensive German real estate data: property details (rent, size, rooms, location), high-res images, agent info with verification status, pricing insights, amenities (balcony, kitchen, cellar), contact forms, market analytics, and 40+ targeting parameters for research.",
    "version": "0.0",
    "x-build-id": "qkJywY5nRSxYFiNqZ"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/memo23~immobilienscout24-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-memo23-immobilienscout24-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/memo23~immobilienscout24-scraper/runs": {
      "post": {
        "operationId": "runs-sync-memo23-immobilienscout24-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/memo23~immobilienscout24-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-memo23-immobilienscout24-scraper",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "startUrls": {
            "title": "Start URLs",
            "type": "array",
            "description": "URLs to scrape. **Germany:** search (`.../Suche/...`), expose (`.../expose/{id}`), **makler profile** (`.../anbieter/profil/{slug}`) — loads **residential BUY then RENT** listings via the agency API and merges `clientFields` + full mobile expose JSON. If the profile HTML is blocked, add `?realtorEncryptedId=...` (opaque id from `.../anbieter/contact/{slug}/{id}`, often ~32 chars). **Austria:** `immobilienscout24.at/regional/...`. Mix `.de` / `.at` in one run.",
            "items": {
              "type": "string"
            }
          },
          "maxItems": {
            "title": "Max results (safety cap — leave empty to scrape everything)",
            "minimum": 1,
            "type": "integer",
            "description": "Optional safety cap. Stops after roughly this many listings across all Start URLs. **Leave empty (the default) to scrape the full result set** — that is the normal behaviour and what most runs should do. Use it to test a URL cheaply before committing: a broad search can return 90,000+ listings (≈ $157 at $1.75/1,000), so set a small number first if you are unsure how big your search is. Note: capping a run <b>disables removed-listing detection</b> for that search, because detecting removals requires enumerating the complete result set."
          },
          "monitoringMode": {
            "title": "Monitoring mode — only scrape listings new since the last run",
            "type": "boolean",
            "description": "If checked, it will only scrape newly listings compared to what has been scraped in previous runs. Seen-listing state is kept per search URL, so keep the same startUrls between runs. Monitoring checks are billed at the cheaper additional-data rate ($0.50/1k), not the full result rate.",
            "default": false
          },
          "detectRemovedListings": {
            "title": "Also report removed (delisted) listings",
            "type": "boolean",
            "description": "Monitoring add-on. When on together with **monitoringMode**, each run also reports listings seen in prior runs that are no longer live — as `{ status: \"removed\", listingId, detectedRemovedAt, url, searchUrl, market }` rows. These are written to a **separate named dataset** `removed-<runId>` (not the main default dataset) and billed at the cheaper `additional-data` rate ($0.50/1k, the monitoring-check tier) — not the $1.75/1k result rate. With **detectPriceChanges** also on, removed rows gain `firstSeenAt` + `daysOnMarket`. Only fires when the run enumerates the **full** search (didn't stop at a maxItems cap) and the search is under the API's ~2000-page enumeration cap; otherwise it's skipped and the reason is logged, to avoid false positives on partial runs. Off by default.",
            "default": false
          },
          "detectPriceChanges": {
            "title": "Also report price changes (+ days-on-market)",
            "type": "boolean",
            "description": "Monitoring add-on. When on together with **monitoringMode**, each run compares every listing's current price against the price stored from the previous run and reports movements as `{ status: \"price_changed\", listingId, oldPrice, newPrice, priceDelta, pctChange, direction, isPrivate, firstSeenAt, url, searchUrl, market, detectedAt }` rows. Written to a **separate named dataset** `changes-<runId>` (not the main default dataset) and billed at the cheaper `additional-data` rate ($0.50/1k) — not the $1.75/1k result rate. No detail fetch is needed (price is read from the search list), so tracking a whole market's prices stays cheap. When **detectRemovedListings** is also on, removed rows additionally get `firstSeenAt` + `daysOnMarket`. Unlike removal detection this isn't limited by the page cap — a price diff is observed per-listing. Off by default.",
            "default": false
          },
          "instantAgencyDatabase": {
            "title": "⚡ Agency DB · use instant database",
            "type": "boolean",
            "description": "Serve agencies from the pre-collected directory database instead of live-scraping. Auto-enabled if you set any agency filter below.",
            "default": false
          },
          "dbPostalCodes": {
            "title": "⚡ Agency DB · office postal codes",
            "type": "array",
            "description": "Return agencies whose office is in these German postal codes — e.g. 13591, 13589, 10115. Any number at a time.",
            "items": {
              "type": "string"
            }
          },
          "dbCity": {
            "title": "⚡ Agency DB · city contains",
            "type": "string",
            "description": "Return agencies whose office city contains this text (case-insensitive), e.g. Berlin."
          },
          "dbAgencyNameContains": {
            "title": "⚡ Agency DB · agency name contains",
            "type": "string",
            "description": "Return agencies whose name contains this text (case-insensitive), e.g. Pilatus. Works without a location."
          },
          "dbMinListings": {
            "title": "⚡ Agency DB · minimum live listings",
            "type": "integer",
            "description": "Only agencies with at least this many current live listings (available only for agencies whose listing count we've recorded)."
          },
          "directoryLocations": {
            "title": "🔎 Agency directory · postal codes or cities",
            "type": "array",
            "description": "Filling this in runs the live-directory mode (no toggle needed). One or more German postal codes (e.g. `13591`) and/or city names (e.g. `Berlin`, `München`) — dozens at a time. Each returns the agencies registered/operating in that area, with full office contact details.",
            "items": {
              "type": "string"
            }
          },
          "directoryAgencyName": {
            "title": "🔎 Agency directory · name filter (optional)",
            "type": "string",
            "description": "Only return agencies whose name contains this text, case-insensitive — e.g. `Pilatus`. Combine with the postal codes / cities above to pinpoint a specific agency in an area."
          },
          "includeListingCount": {
            "title": "🔎 Agency directory · include live listing count",
            "type": "boolean",
            "description": "Also fetch how many properties each agency currently has live (split into buy + rent). Slower — an extra lookup per agency. Off by default.",
            "default": false
          },
          "instantDatabase": {
            "title": "👤 Agent DB · use instant database",
            "type": "boolean",
            "description": "Serve agents from the database instead of live-scraping. Auto-enabled if you set Agency name below.",
            "default": false
          },
          "dbAgencyName": {
            "title": "👤 Agent DB · agency name contains",
            "type": "string",
            "description": "e.g. Engel & Völkers. Optional. Filters the Instant Agent Database to agents whose agency name contains this text (case-insensitive); setting it auto-enables Instant Database mode."
          },
          "dbHasPhone": {
            "title": "👤 Agent DB · only agents with a phone",
            "type": "boolean",
            "description": "Only return agents that have a direct phone number on file (about 1 in 2 does). Records delivered with a phone bill the small contact-phone event; records without one never do.",
            "default": false
          },
          "excludeSections": {
            "title": "Exclude the `sections` block",
            "type": "boolean",
            "description": "Drop the per-listing `sections` array from each dataset row. This is the largest part of the payload (~70% of DE rows). The key data inside it — finance costs, image captions, available-from, fair-price rating — is already lifted into `normalized` (financeCosts, media[].caption, availableFrom, fairPrice). Turn this on to dramatically shrink output if you only consume the `normalized` block + a few `basicInfo` fields.",
            "default": false
          },
          "excludeZipCodeShapes": {
            "title": "Exclude `zipCodeShapes` (map polygons)",
            "type": "boolean",
            "description": "Drop just the `zipCodeShapes` polygon coordinates inside sections (typically 4-5 KB per listing of map polygon geometry you don't need unless you're rendering maps). Independent of `excludeSections` — surgical strip that keeps the rest of sections.",
            "default": false
          },
          "excludeTracking": {
            "title": "Exclude the `tracking` block",
            "type": "boolean",
            "description": "Drop the per-listing `tracking` object. Small (~500 B) but rarely useful to downstream consumers.",
            "default": false
          },
          "allowApproximateCoords": {
            "title": "Allow approximate (cluster-center) coordinates",
            "type": "boolean",
            "description": "OFF by default. With this off, `address.latitude/longitude` are filled only when ImmoScout returned a per-listing point (precise) — cluster-center coords (shared across many listings, off by hundreds of metres) are left null. Every coord-bearing row gets an `address.coordinatePrecision` tag ('exact' / 'approximate' / null) so downstream code can filter. Turning this ON fills in the cluster-center coords too, still flagged as 'approximate'.",
            "default": false
          },
          "geocodeAddresses": {
            "title": "Geocode decoded addresses for rooftop coordinates",
            "type": "boolean",
            "description": "OFF by default. When ON, listings whose street + house number we decoded (from `obj_telekomInternetUrlAddition` or the free-text description scan) but lack a per-listing coordinate are geocoded via the configured provider. Rooftop or street-level hits land in `address.latitude/longitude` with `coordinatePrecision: 'rooftop' | 'street'` and `coordinateSource: 'geocoder-photon' | 'geocoder-mapbox' | 'geocoder-google'`. City/locality-level hits are rejected as too coarse. Two-layer cache (in-memory + Apify KV `geocoder-cache`) keeps repeat addresses from re-hitting the provider.",
            "default": false
          },
          "geocoderProvider": {
            "title": "Geocoder provider",
            "enum": [
              "photon",
              "mapbox",
              "google"
            ],
            "type": "string",
            "description": "Which geocoder to use when `geocodeAddresses: true`. **Photon** (default, free, no key needed — Komoot's OSM-based service, ~10 req/sec). **MapBox** ($0.50 / 1k, higher rate, set `geocoderApiKey` to your `pk.…` token). **Google** ($5 / 1k, set `geocoderApiKey` to your Maps API key).",
            "default": "photon"
          },
          "geocoderApiKey": {
            "title": "Geocoder API key",
            "type": "string",
            "description": "API key for `geocoderProvider: 'mapbox'` or `'google'`. Ignored when using Photon. Stored in the run as a plaintext input — for production use Apify's input secrets feature."
          },
          "enrichEmails": {
            "title": "Enrich with contact emails (experimental, billed per email)",
            "type": "boolean",
            "description": "If enabled, finds a contact email for each result from its own website (or by discovering it from the name). Adds contactEmail + contactWebsite columns plus a detailed emailEnrichment object. Billed per contact email found; only charged when an email is returned, never for misses.",
            "default": false
          },
          "qualifyByPayment": {
            "title": "💳 Qualify by payment (flag businesses that take money online)",
            "type": "boolean",
            "description": "Requires \"Enrich with contact emails\". Scans each business's website — reusing the pages already fetched for email discovery, so no extra cost or time — for payment processors and e-commerce platforms (Stripe, Shopify, PayPal, Paddle, Lemon Squeezy, WooCommerce, Square, Chargebee and more). Adds takesPayments (is this a real paying business?), paymentProcessors (which stack), stripeLiveKey (the public key if exposed) and paymentConfidence. Turn raw contacts into monetization-qualified leads. No extra charge — included with each enriched company.",
            "default": false
          },
          "marketAnalysis": {
            "title": "🧠 AI Market Analysis + Deal Scoring per area ($0.15/area, cached)",
            "type": "boolean",
            "description": "If enabled, appends a `rowType: \"marketAnalysis\"` row per area found in your results (up to 8 areas per run, largest first). Each row carries the area's market intelligence AND a `deals` array (every scored listing: ROI %, cashflow, payback, strategy, flags) plus a `dealsSummary` (best clean deal). Billed per area row delivered via the `market-analysis` event — the deal scoring is included at no extra charge. Never charged when analysis fails or signal is too thin.",
            "default": false
          },
          "maxConcurrency": {
            "title": "Max Concurrency",
            "type": "integer",
            "description": "Maximum number of pages that can be processed at the same time.",
            "default": 10
          },
          "minConcurrency": {
            "title": "Min Concurrency",
            "type": "integer",
            "description": "Minimum number of pages that will be processed at the same time.",
            "default": 1
          },
          "maxRequestRetries": {
            "title": "Max Request Retries",
            "type": "integer",
            "description": "Number of times the crawler will retry a failed request before giving up.",
            "default": 100
          },
          "proxy": {
            "title": "Proxy configuration (optional override)",
            "type": "object",
            "description": "Leave empty — the actor already routes all traffic through its own built-in residential proxy at no extra cost to you. Only set this if you want to use your own proxies."
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}