Two modes: search a city for every hotel + homestay, or monitor specific properties across dates with price-change deltas and next-available on sold-out. Each row: tax-inclusive price, availability, reviews, geo. 32 currencies verified end-to-end — no silent USD fallbacks. Covers Agoda Homes.
All notable, user-visible shipments to the Agoda Property Scraper. Latest on top. Format follows keep-a-changelog .
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.
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.