# Changelog of Kleinanzeigen.de Immobilien Scraper (Germany) (`stone_jadex/kleinanzeigen-immobilien-scraper`) Actor

- **URL**: https://apify.com/stone_jadex/kleinanzeigen-immobilien-scraper/changelog.md
- **Full Actor documentation**: https://apify.com/stone_jadex/kleinanzeigen-immobilien-scraper.md

## Changelog

### Unreleased

- Fix (review c9d5026): the next list page is no longer scheduled just to merge TOP/organic repeats, so list requests match 73439c3 again (maxItems 25: 1 list page, 50/default: 2). Merging with the next page happens only when it is already in flight (`concurrency` > 1); with the default `concurrency` 1, only same-page repeats are merged. README Duplicates rule and `isTop` text updated to match. Request-count regression test (baseline measured on 73439c3); `list-top-organic` run test now uses concurrency 2, plus a concurrency-1 case. Redlogs list-request-count red+green+mutation.

- Tests only: breadcrumb-only empty search ("Es wurden keine … gefunden", #saved-search-empty-result moved aside) gives noResults=true; counter-example without "keine" gives false (review 73439c3 non-blocking item 1). Redlogs no-results-breadcrumb red (on reviewer's loosened-regex mutant) + green + mutation.

- `isTop` is true if any card of the listing is TOP (same page or next list page), not just the kept card; new add-only field `organicPosition` (site organic rank, null if never organic). Dedupe still keeps the first card; README documents it (QA 73439c3 issue 2). Tests on live p1/p2 fixtures; redlogs list-top-organic red+green+mutation.

- `isGesuch` now only looks at the start of the spec line (`<p>Gesuch · …`); a title starting with "Gesuch" no longer sets it (QA 73439c3 issue 1). Counter-example test on real card 3554246978 with title changed to "Gesuch: …". Redlogs list-gesuch-title red+green+mutation.

- OUTPUT.duplicatesSkipped also counts cards repeated within one page (TOP repeat on page 1 was not counted, QA 2d0b8c7 issue 4); parseListPage adds `duplicatesInPage`. Tests; redlogs/in-page-duplicates red+green+mutation.

- New boolean list fields `isTop` (TOP promoted card) and `isGesuch` (wanted ad); add-only, no field renamed/removed (QA 2d0b8c7 issue 4). README field list. Tests; redlogs/list-flags red+green+mutation.

- Genuinely empty search (site banner `Es wurden keine … gefunden` / `#saved-search-empty-result`) ends SUCCEEDED: 0 rows, 0 charges, OUTPUT `stopReason: no-results` + `noResultsNote` (new field); no 5 s retry. Was FAILED at main.js:530 (QA 2d0b8c7 issue 3). First-page 403/404/410/429/5xx/network errors with 0 rows still FAIL. Parser adds `noResults` to parseListPage result. README Output note. Real trimmed fixture `list-live-20261101-empty-keine.html`; redlogs/empty-search red+green+mutation.

- List `area`/`rooms` parse spec lines with a `Gesuch · ` prefix (`Gesuch · 65 m² · 2 Zi.`, TOP wanted-ad 3548979518); were null (QA 2d0b8c7 issue 2). Tests; redlogs/list-specs-gesuch red+green+mutation.

- List `price` parses `1.200 € VB` (Verhandlungsbasis); regex required `<` right after `€`, so VB prices were null (QA 2d0b8c7 issue 1: 3558162645, 3548979518, 3540441508). Real trimmed fixture `list-live-20261101-vb-gesuch.html`; redlogs/list-price-vb red+green+mutation.

- README sample row: `city` null, `postcode` 13355, `location` "13355 Mitte" as the parser outputs since 0.1.1 (QA 9d33238 3d). Test ties sample to fixture output; redlogs/readme-sample-location.

- `siteTotal` / OUTPUT.siteTotalEntries from the live `#srp-breadcrumb-summary` ("1 - 25 von 7.278 …" -> 7278); was null in QA 9d33238. Tests; redlogs/site-total-breadcrumb.

- List `title` from the card heading link (`h2/h3.text-title3 > a`), img `alt` only as fallback (alt had a `Bezirk - Ortsteil` suffix, QA 9d33238 title 5/30 wrong). Real trimmed fixture `list-live-20261101-titles.html`; redlogs/list-title-heading.

### 0.1.1 — 2026-10-26

- Fix list-card location parsing: prefer `PLZ Place` text next to `locationOutline` (e.g. `10243 Friedrichshain`, `13355 Mitte`) instead of img `alt` / title fragments that previously filled `city`.
- `parseLocationLine`: `13355 Berlin - Mitte` → city+district; single place after PLZ → `district` (Ortsteil), `city` null until detail/`City - District`; postcode populates whenever PLZ is on the card.
- Unit tests for both location forms and a synthetic card (large SVG + misleading alt).

### 0.1.0 — 2026-10-26

- Initial Kleinanzeigen.de **Immobilien** scraper (Wohnungen mieten/kaufen list + optional detail) from willhaben-actor / otodom-actor template.
- Scope: Wohnungen only (not full-site marketplace).
- PPE draft: `listing` / `listing-detail` at $0.00075 each; no start fee; cost cap $0.09975/千.
- Privacy policy A: keep public commercial phones/emails; drop private seller phones/emails.
- Default input: Berlin Wohnung mieten; maxItems 50; scrapeDetails false; requestDelayMs 1200; concurrency 1; memory 256 MB; proxy off.
- Residential proxy cap fixed at 5 MB (not user-tunable). Prefer list-tier/direct; do not force residential for cost.
- Raise `maxItems` hard cap from 500 to 2000 (aligned with Otodom/Immowelt/Willhaben) for 1k calibration.
