← back to Homesonspec
docs(toll): wave-2 SOLVED — QMI homes are plain-fetch via sitemap /Quick-Move-In/<id> pages (JSON-LD + __NEXT_DATA__), no browser needed
acd6564e75ec4a18345375d409a2cf6928db5c6f · 2026-08-03 07:44:43 -0700 · Steve Abrams
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M collectors/toll-brothers/WAVE2-RECON.md
Diff
commit acd6564e75ec4a18345375d409a2cf6928db5c6f
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Aug 3 07:44:43 2026 -0700
docs(toll): wave-2 SOLVED — QMI homes are plain-fetch via sitemap /Quick-Move-In/<id> pages (JSON-LD + __NEXT_DATA__), no browser needed
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
collectors/toll-brothers/WAVE2-RECON.md | 39 ++++++++++++++++++++++-----------
1 file changed, 26 insertions(+), 13 deletions(-)
diff --git a/collectors/toll-brothers/WAVE2-RECON.md b/collectors/toll-brothers/WAVE2-RECON.md
index f5db3700..bcccf705 100644
--- a/collectors/toll-brothers/WAVE2-RECON.md
+++ b/collectors/toll-brothers/WAVE2-RECON.md
@@ -22,19 +22,32 @@ object carries **`numQDH`** (quick-delivery-home count), `comingSoonQMICount`,
337KB). It has NO embedded homes JSON, NO `__NEXT_DATA__`, and NO visible
`/api/` references — homes load via a **runtime XHR** after hydration.
-## The remaining crack (the fresh-session task)
-Browser-trace ONE Toll community detail page (Playwright/Browserbase network
-capture) to catch the XHR that loads its QDH homes. Community `3131 Camino`
-(communityId **14614**, California, numQDH **7**) is a good probe target.
-Once the endpoint + params are known, build a Pulte-style JSON adapter:
-1. `fetch()`: get homesearchV5.json → filter communities to numQDH>0 → for each,
- call the (traced) QMI endpoint.
-2. `extract()`: emit `entityType:"community"` (as today) PLUS `inventory_home`
- records from the QMI payload. Capture core fields + a `specs` map (Toll should
- expose was-price/incentives/plan — follow the DR-Horton/Pulte specs pattern,
- commit `7c3609c`).
-3. Respect robots: `/siteplans /nse /compare /new-homes /sitesearch` are
- disallowed; `/api/` is allowed. NO bot-wall circumvention (standing rule).
+## SOLVED (2026-08-03 browser-trace) — it's PLAIN-FETCH, no browser needed
+The community amplify pages render homes client-side (dead end — don't chase).
+But the INDIVIDUAL QMI home pages are plain-fetch with clean structured data:
+- **URL pattern (in the sitemap):**
+ `https://www.tollbrothers.com/luxury-homes-for-sale/<State>/<Community>/Quick-Move-In/<id>`
+ e.g. `.../Quick-Move-In/283595`. Also a `.../Quick-Move-In/MLS-<n>` alias for the
+ same home — DEDUPE (prefer the numeric-id URL; drop the MLS- duplicate).
+- Each page (~80KB, HTTP 200, plain curl w/ a real UA) carries BOTH:
+ - **JSON-LD `SingleFamilyResidence`** (the clean parse target): `name` (plan),
+ `floorSize.value`→sqft, `address.{streetAddress,addressLocality,addressRegion,postalCode}`,
+ `geo`→lat/lon, `numberOfBedrooms`, `numberOfFullBathrooms`+`numberOfPartialBathrooms`,
+ `containedIn`→community, `image`, `description`. **NOTE: price is NOT in the JSON-LD.**
+ - **`__NEXT_DATA__`** — carries `price` + `lotNumber` (+ likely status, incentives,
+ was-price for the `specs` map). Pin the exact props path during the build.
+
+### Build plan (Pulte-style adapter, plain-fetch)
+1. `fetch()`: GET Toll's sitemap → collect `/Quick-Move-In/<numeric-id>` URLs, drop
+ `MLS-` alias duplicates → plain-fetch each (LiveFetcher; contentHash dedup makes
+ re-runs cheap + resumable, so the ~11k volume is fine over recurring runs).
+2. `extract()`: parse JSON-LD SingleFamilyResidence for core fields; parse
+ `__NEXT_DATA__` for price + lotNumber; emit an `inventory_home` record + a `specs`
+ map (was-price/incentives/plan — follow DR-Horton/Pulte pattern, commit `7c3609c`).
+ The COMMUNITY comes from `containedIn.name` — wave-1 already publishes communities,
+ so the FK target exists (extract community-first only if a home's community is new).
+3. Respect robots: `/siteplans /nse /compare /new-homes /sitesearch` disallowed;
+ `/luxury-homes-for-sale/` + `/api/` allowed. NO bot-wall circumvention (standing rule).
## Watch-outs
- Toll Akamai bot-blocks the Kamatera **datacenter** IP under load (Taylor
← f98e35a7 docs(toll): wave-2 recon — ~298 per-community fetches not 11
·
back to Homesonspec
·
feat(toll): wave-2 QMI home ingestion (adapter v2.0.0) — pla 1f01a75d →