# Changelog of WG-Gesucht.de Listing Monitor (`cg_nguyen/wg-gesucht-de`) Actor

- **URL**: https://apify.com/cg\_nguyen/wg-gesucht-de/changelog.md
- **Full Actor documentation**: https://apify.com/cg\_nguyen/wg-gesucht-de.md

## Changelog

### 1.1.0 — Fail-fast on misconfigured proxies (2026-05-19)

**Fixes the silent-timeout problem** that caused 2 of 3 external runs in the first week to time out at 2 minutes with no useful error message.

- **new:** preflight proxy validation in `main.ts`. If the user supplies a proxy config that wg-gesucht.de cannot use (no Apify Residential + no external `proxyUrls`), the Actor now calls `Actor.fail()` within ~3 seconds with a clear, actionable error message instead of letting the crawler spin to timeout.
- **new:** `failedRequestHandler` watches the warm-up and first list page. If those fail after retries (the most common signal that a proxy is being blocked), the Actor fails the whole run immediately rather than continuing to burn compute on doomed downstream requests.
- **fix:** `proxy_config` default was `{ groups, countryCode }` (wrong shape) — switched to the canonical `{ useApifyProxy, apifyProxyGroups, apifyProxyCountry }`.
- **chore:** tightened crawler timeouts (`navigationTimeoutSecs` 60→45, `requestHandlerTimeoutSecs` 90→60, `maxRequestRetries` 3→2). Smaller blast radius for misconfigured runs.
- **docs:** README now leads with a "⚠️ Before you run — proxy is required" banner. Input schema's `proxy_config.description` warns users about the Free-plan caveat *before* they click Start.

**Why this matters:** A Store visitor on the Free plan who accepted the default input would have all proxy creation fail silently or fall through to no-proxy crawling, hit wg-gesucht's anti-bot wall, and time out 2 minutes later — burning $1-2 of their $5/mo credits with zero output. Now they see a clear "you need Starter plan or your own DE-IP proxy" message in under 5 seconds.

### 1.0.0 — Store launch (2026-05-15)

First public release on the Apify Store.

**Coverage:** Berlin, Munich, Hamburg, Frankfurt, Cologne, Vienna, Zurich.
**Output:** WG-Zimmer listings only (Wohngemeinschaft / flat-share). Full apartments coming in v1.2.

**Verified field fill-rate** on a 10-record Berlin smoke run (build 0.1.4):

- 100%: `listing_id`, `url`, `title`, `city`, `district`, `address_street`, `rooms`, `sqm`, `rent_warm_eur`, `rent_kalt_eur`, `furnished`, `available_from`, `language_pref`, `photos`, `description`, `contact_method`, `change_type`, `posted_at`, `scraped_at`
- 90%: `utilities_eur`
- 60%: `deposit_eur` (some listings legitimately omit Kaution)
- 40%: `available_until` (rest are `unbefristet` / open-ended — normal)

**Ground-truth verified:** Spot-check on listing `9883205` (Berlin Wedding) matched every scraped field byte-for-byte against the live page.

**Known caveats:**

- `description` field contains raw HTML whitespace from the source page. Use `.trim().replace(/\s+/g, ' ')` if you need a clean string.
- `contact_method` is always `in_app_message` — wg-gesucht intermediates all contact, no direct phone/email is exposed.
- `photos` array includes both full-size (`.sized.JPEG`) and thumbnail (`.small.JPEG`) URLs for the same image.

### 0.1.4 — internal (2026-05-15)

- **fix:** Kosten panel parsing — switched from DOM heading walk to body-text regex with word boundaries. `rent_kalt_eur` now 100%, `utilities_eur` 90%, `deposit_eur` 60% (was all 0%).

### 0.1.3 — internal

- Skipped (aborted push).

### 0.1.2 — internal (2026-05-15)

- **fix:** `max_results` cap was being silently ignored because the emission counter was stored in serialized request `userData`. Replaced with module-level counter in `routes.ts`. Now exact: input `max_results=10` ⇒ exactly 10 records emitted.
- **fix:** District field had embedded newlines from raw DOM; added `cleanDistrict()` helper.
- **fix:** Room count was null; added `parseRooms()` for the `Xer WG` pattern in listing-card location row.

### 0.1.1 — internal (2026-05-15)

- First cloud build. Scaffolded with Crawlee + Playwright + residential DE proxy. End-to-end crawl through Cloudflare challenge: 57/83 pages, 0 failures.

### 0.1.0 — internal (2026-05-15)

- Initial scaffold. Node 22, Apify SDK v3, Crawlee 3.x, Playwright.
