Initial release — Apartments.com Scraper & Floor Plan Units.
New capabilities
- Per-unit child rows (
type: "unit"): unit number, exact rent, beds, baths, square feet, price per square foot, availability date (raw + ISO), unit / model keys, external application URL and portal vendor. Capped per property by maxUnitsPerProperty.
- Floor-plan model child rows (
type: "floorPlan"): plan name, beds/baths, square-foot range, plan rent band, pricing model, currently-listed unit count and the plan image URL.
- Property-level unit economics: rent min / median / max / spread, average and median price per square foot, units available now and the percentage available now, and the bedroom mix.
- Unit filters: availability (any / now / future) and exact-rent floor and ceiling.
Engine
- Replaced the static HTTP client with headless Firefox (Playwright) over a sticky Apify US residential exit IP — the static client is challenged by Akamai on effectively every exit IP and returned zero rows.
- Block detection now keys on the actual Akamai interstitial markers instead of a page-length heuristic that the current 2.5 KB challenge passes.
- Wait-for-marker polling rather than a fixed sleep; images, fonts and media are blocked to cut transfer.
- A fresh exit IP is rolled only on a challenged page, and only before any row for that target has been pushed.
- Page-completeness gate: a property page is accepted only once the
ApartmentComplex ld+json block has arrived (it is emitted last, after the unit list). The previous id="propertyName" / rel="canonical" check passed on a half-streamed document, which could silently empty the photo, tour and neighbourhood columns. Search pages settle until the card count stops growing.
Fixes carried over from the base actor
includeAllImages and includeVirtualTours are implemented rather than accepted-and-ignored.
location.neighborhood now carries the real neighbourhood; the old breadcrumb-derived value is preserved as location.neighborhoodFromBreadcrumb.
- Added
lastUpdatedIso (ISO-8601) alongside the base's US-format lastUpdated.
- The dead
maxRetriesPerRequest input was removed; requestDelay is now declared in the schema.
- Failed URLs push an uncharged, typed error row instead of being silently dropped.
- The search page cap is one consistent number (28) in the code, schema and README.