# Changelog of BEST Agoda Scraper (`bestscraper/agoda-property-scraper`) Actor

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

## Changelog

All notable, user-visible shipments to the Agoda Property Scraper. Latest on top. Format follows [keep-a-changelog](https://keepachangelog.com/).

### 0.1.3 — honest currency handling (bug fix)

Rows used to be stamped with a `currency` that didn't match the actual price numbers. The prior `CURRENCY_ID` map had the wrong Agoda numeric id for every non-USD entry (EUR, GBP, AUD, JPY, THB, MYR, PHP, IDR, HKD, VND) — each request silently fell back to USD while the row still claimed the requested currency. Downstream consumers saw e.g. "SGD 195" that was actually 195 USD (~263 SGD).

Now ships with 32 empirically verified currencies (probed directly against Agoda's room-grid) plus response-side reconciliation: if the response currency disagrees with the requested one, the row is stamped with the actual response currency and a `[currency]` warning is logged. Ambiguous locale symbols (`¥` for JPY vs CNY, `kr` for SEK/NOK/DKK, `S$` for SGD) are resolved against the requested currency and normalized to ISO codes in output.

### v8 schema — `findNextAvailable` on discovery rows

Search-result rows now support the same "nearest available date" hop as monitor mode. When a requested check-in is sold out, set `findNextAvailable: true` and the row gains a `nextAvailableCoverage` block with the next bookable check-in, the price on that date, and how many days of the ± window were scanned. Useful for discovery runs where you want a signal even on fully-booked stretches.

### `sortBy` + `skipSeen` + `skipPropertyIds` — multi-sort city fanout

Agoda paginates any single sort to roughly 650–1000 properties per city. Run the same input four times with `bestMatch`, `reviewScore`, `lowestPriceFirst`, and `highestPriceFirst`, then set `skipSeen: true` (or pass explicit IDs via `skipPropertyIds`) to dedup across runs. Typical uplift: 1.5–2× more unique properties versus a single sort. No external storage required — dedup state lives in the actor's key-value store.

### `canaryTtlMinutes` — schema-drift early warning

A lightweight canary probe runs alongside your scrape on a configurable TTL. If Agoda changes the shape of their search or room-grid responses, the next run flags the drift in `run-report.anomalies` before rows start going blank in production.

### `apiProxyDatacenter` default-on — cheaper price monitoring

Price monitoring API calls now route through the datacenter proxy pool by default. Validated byte-identical to residential on the endpoints we use, at a fraction of the cost. The initial property page load still uses residential (Agoda gates datacenter IPs there). Flip `apiProxyDatacenter: false` to route everything through residential if you need geo-accurate local pricing on every cell.

### City-day summary rows

Every run now emits one `city-day-summary` row per `cityId × checkIn`, in addition to the per-property quote rows. Fields include `priceRankInCity`, `priceCategory`, median/p25/p75 price across the pool, and property counts. Feed this into a dashboard for instant "is today cheap or expensive for Bangkok?" visuals without post-processing the main dataset.

### `run-report` row

Every run appends one `run-report` row to the dataset with totals, fill-rate percentages, and anomalies. Wire a webhook on `anomalies.length > 0` to catch upstream breakage the moment it happens, instead of hours later when blank rows show up in your BI tool.
