# Changelog of Argenprop Property Scraper (`mfapitools/argenprop-property-scraper`) Actor

- **URL**: https://apify.com/mfapitools/argenprop-property-scraper/changelog.md
- **Full Actor documentation**: https://apify.com/mfapitools/argenprop-property-scraper.md

## Changelog

### 0.1.12 (2026-10-14)

- **Default memory 2048 → 1024 MB.** Measured peak on a 50-listing + 3-detail run (`qhxGwJhkbDmLePe1R`) was 141 MB, average CPU 3.9% — the run was paying for 14× the memory it uses. Compute is billed per GB-hour, so every run (and above all a run that grinds through WAF retries and fails) now costs half. Customers also pay one `apify-actor-start` unit instead of two. Context: on 2026-10-13 two public runs FAILED behind the WAF; each burns ~135 s of retries before giving up, at 2 GB ≈ $0.015 of compute per failed run against a $0.002 start fee.

### 0.1.11 (2026-10-09)

- **Detail pages returned `photos: []` on every listing.** The selectors targeted `<img>` gallery markup the site does not serve; the listing's own photos are CSS backgrounds on `[data-open-gallery]` elements. Now extracted from there (first 5 — the rest of the gallery is JS-loaded; README says so), with `og:image` as fallback. The old `img[src*="argenprop"]` selector is removed: on the real page `<img>` tags are the agency logo and *other* properties. A real detail page captured 2026-10-09 is checked in as a fixture.

### 0.1.10 (2026-10-09)

- **Definitive WAF detection.** AWS WAF answers a challenged request with HTTP 202/405 and an `x-amzn-waf-action: challenge|captcha` header. Both crawlers now check for it first, retire the session and retry — replacing guesswork from "zero cards parsed" (still kept as a second net).
- **Empty detail pages were pushed and charged as `listing-detailed`.** The detail crawler had no block detection at all, so a WAF interstitial became a record with no amenities, no photos, no floor — billed at $0.002. A detail page that yields nothing is now retried and, if it never yields data, counted as failed and reported; it is never pushed or charged.
- When a detail page parses with zero photos, one HTML sample per run is saved to the run's key-value store (`debug-detail-<id>`) as parser-health evidence.

### 0.1.9 (2026-10-09)

- **Pagination never worked on the live site — every run silently returned at most ~20 listings.** `extractPagination` looked for `ul.pagination__pages`; the real markup is `<ul class="pagination pagination--links">` (the test fixture had been hand-written, so the tests passed against markup the site never served). A run with the default `maxListings: 50` returned 20 and reported SUCCEEDED. Now matches the real control and prefers the dedicated `.pagination__page-next` link; a real page captured 2026-10-09 is checked in as a fixture and tested (20 cards, next = `?pagina-2`).
- **WAF blocks: Apify QA recorded 17 FAILED of 41 public runs in 30 days.** `maxRequestRetries` 4 → 9 (a refused attempt costs ~1–2s), bounded by a new 90s per-request wall-clock retry budget so genuine 45s timeouts cannot blow the 300s QA limit. Session pool reduced to one sticky session: blocking is per-IP, so the first IP that gets through is reused for the following pages instead of drawing a new, probably-blocked IP per page.
- **No silent incompleteness:** when fewer listings are returned than requested because a page could not be fetched or no pagination control was found, the run now ends with an `INCOMPLETE: collected X of Y …` status message and warning instead of a bare SUCCEEDED. Failed detail pages are counted and reported the same way.
- Blocked/empty responses now log the page title and HTML size, so a WAF interstitial can be told apart from a markup change.

### 0.1.7 (2026-07-30)

- Reliability fix for the intermittent QA failure (4/7 public runs failing): CheerioCrawler's default `navigationTimeoutSecs` (30s) sat right against argenprop.com's measured average response time (23.5s from Apify datacenter IPs), so normal-latency responses randomly blew the timeout and burned retries. Raised `navigationTimeoutSecs` to 45s (both the search-page and detail-page crawlers) so a typical response succeeds on the first attempt.
- Live re-verification surfaced a second, distinct failure mode not covered by the original timeout hypothesis: Argenprop's AWS WAF outright blocks some datacenter-IP requests with an immediate 403 (unrelated to slowness) and occasionally returns a 200 with a non-listing (challenge) page. Raised `maxRequestRetries` from the default 3 to 4 to give the session pool more chances to rotate to a working IP — blocked attempts fail in ~1s, so extra retries are cheap unless the target is genuinely down, in which case the run still fails fast (worst case ~225s, well under the 300s QA limit) rather than hanging.
- Added a `failedSearchPageRequests` counter and a more specific `statusMessage` that distinguishes "requests never succeeded (network/timeout)" from "pages fetched but zero listings extracted (selector break)" — both still fail loudly (`exitCode: 1`), per the no-silent-incompleteness rule; this just makes the diagnosis clearer.
- Verified on the platform (build 0.1.6 then 0.1.7) with 8 live runs against the exact QA prefill (`{"searchUrls": ["/departamentos"]}`): 5/8 SUCCEEDED pushing 20 listings each; all 8 runs (success or failure) finished in 6.5s–54.7s — none came close to the 300s ceiling, confirming the "burns the whole 5-minute budget" failure mode is eliminated. Residual failures are WAF blocking (403 / challenge page), not timeout exhaustion; `useResidentialProxy` default intentionally left `false` per scope.

### 0.1.3 (2026-07-25)

- Agent-consumability audit (LLM-as-tool-caller pass): `maxListings` default lowered 200 → 50 to match the ~50-item default convention used across the rest of the portfolio and cap naive-call cost. Clarified `minBedrooms`/`maxBedrooms` descriptions — 0 means "no filter", not "studio (0 bedrooms)"; there is currently no way to filter for exactly 0-bedroom studios.
- Platform `exampleRunInput` was the unedited Apify CLI placeholder (`{"helloWorld": 123}`) — replaced via direct API call with a runnable example.

### 0.1.0 (2026-07-24)

- Initial release. Scrape real estate listings from Argenprop.com.
- Search by property type, operation, bedrooms, and price range.
- CheerioCrawler with proxy fallback.
- Optional detail page enrichment (amenities, photos, floor number).
- Pay-per-event: `listing-scraped` ($0.001), `listing-detailed` ($0.002).
