Find a House on Sea Ranch Escape
Purpose
Given user constraints — date range, party size, bedroom count, pet allowance, ocean-view preference, etc. — return one or more Sea Ranch vacation-rental homes from the Sea Ranch Escape catalog (booksearanchescape.escapia.com, an Escapia-powered booking portal) with availability, pricing, amenities, and a deep-link to the unit detail page. Read-only — never click "Book Now" or submit the booking form.
When to Use
- "Find a 3-bedroom house in Sea Ranch for Thanksgiving week 2026, dog-friendly."
- "What's available at The Sea Ranch from July 4–7 for 4 adults?"
- "Cheapest oceanfront 2BR cottage on Sea Ranch under $400/night this fall."
- "List every Sea Ranch Escape property — I'll filter myself."
- A trip-planning agent comparing vacation rentals across coastal Sonoma/Mendocino.
Booking flows (taking payment, holding a slot) are a separate skill — this one stops at the rate-quote / detail page.
Workflow
The Sea Ranch Escape portal exposes four undocumented but stable URL-parameter endpoints. Do not drive the booking form — the form posts to DesktopDefault.aspx with ASP.NET __VIEWSTATE (rotates per session, painful to script). Every piece of data the form exposes is reachable via these direct GET endpoints instead.
1. Enumerate the full catalog (≈30 units across 4 pages)
GET https://booksearanchescape.escapia.com/DesktopDefault.aspx?PageID=11977&page_num={1..4}
(Equivalent pretty-URL alias for page 1: /site/PropertyList/11977/default.aspx.)
Each response embeds a <ul id="propertyList"> block with one <li> per unit. Parse each <li> for:
| Field | XPath / regex anchor |
|---|---|
pid | href="/Unit/Details/(\d+)" |
name | <h3><a href="/Unit/Details/{pid}">{name}</a></h3> |
price_summary | <span class="rate">…{value}…</span> (free-text — "Starts @ 3 Nights $2075/ Weekly $3903") |
bedrooms | <dt>Bedrooms:</dt><dd>{n}</dd> |
bathrooms | <dt>Bathrooms:</dt><dd>{n}</dd> |
sleeps | <dt>Sleeps:</dt><dd>{n}</dd> |
pets | <dt>Pets:</dt><dd>{None|Dogs|...}</dd> |
guest_rating | Guest Rating: (\d+) in the trailing <p> |
image_url | <img class="pic" src="//pictures.escapia.com/SEARES/{pid}/{hash}.jpg"> |
description | Trailing <p> after stripping the rating image |
Loop page_num from 1 to 4 (the pager UI also reports <TotalPagesLabel>4</TotalPagesLabel> — read it instead of hardcoding if you want to be safe).
2. Check per-unit availability (JSON, day-by-day)
GET https://booksearanchescape.escapia.com/Unit/Availability/{pid}?startDate=MM/DD/YYYY&endDate=MM/DD/YYYY
Returns application/json — an array of one entry per calendar day from startDate (inclusive) to endDate (inclusive). Entry shape:
{"S": "A", "M": 3}
S | Meaning |
|---|---|
"A" | Available |
"U" | Unavailable |
"I" | Check-in only (this day can be an arrival but not a mid-stay night) |
"O" | Check-out only (this day can be a departure but not a mid-stay night) |
M is the minimum stay in nights for a booking that starts on (or includes) that day. Common values seen: 3, 5, 7, 255 (encoded "not bookable / no minimum applies because day is U").
Availability rule for a candidate trip with arrive → depart:
- Day
arrivemust haveS ∈ {"A", "I"}. - Every day in
(arrive, depart)(exclusive on both ends) must haveS == "A". - Day
depart - 1(the last night) — covered by rule 2. Daydepartitself is the checkout day and need not beA. (depart - arrive)in nights ≥M[arrive].
If any rule fails, the unit is not bookable for that range.
3. Get the full rate quote (HTML)
GET https://booksearanchescape.escapia.com/Booking/RateDetails/{pid}?arrive=MM/DD/YYYY&depart=MM/DD/YYYY&adults=N&children=N
- HTTP
200+ HTML: parse<dd class="total-price">$X,XXX.XX</dd>for the total. The full breakdown (base rent, fees, taxes, promo savings) lives in a<dl>immediately above it; the booking summary (check-in, check-out, nights, adults, children, pets) is in the same<dl>. - HTTP
302→Location: /Error/UnitUnavailable: dates are not bookable for this unit (despite what the calendar might suggest — Escapia rolls min-stay, blackout, and inventory rules into this single check). Treat this as the canonical "unavailable" signal; it is more authoritative than the/Unit/Availability/...JSON alone.
For a robust availability check, hit /Unit/Availability/... first to fail-fast on calendar conflicts, then call /Booking/RateDetails/... to confirm bookability and read the total price.
4. Get rich unit metadata (HTML)
GET https://booksearanchescape.escapia.com/Unit/Details/{pid}
Stable extractable regions:
<title>The Sea Ranch, CA United States - {name} | Sea Ranch Escape</title><p id="longDescription">…</p>— full marketing description (much richer than the catalog<li>blurb).<table id="unitAmenities">— twelvetd.amenity-grouping/tdpairs covering Property Type, Unit Code, Beds, Bathrooms, Rooms, Pets, Living, Kitchen, Entertainment, Outdoor, Geographic, Convenience, Children.- Photo carousel:
<img>tags under<ul id="thumbnailCarousel1">withpictures.escapia.com/SEARES/{pid}/*.jpg. - Average ratings: regex
Manager Rating[^(]*\(Based on (\d+) reviews\)andRental Rating[^(]*\(Based on (\d+) reviews\).
5. Issue the requests via Browserbase Fetch
Every endpoint above is plain HTTP with no JavaScript dependency. The site sits behind AWS ALB + ASP.NET, not Akamai/Cloudflare/PerimeterX — a bare browse cloud fetch with --proxies is sufficient. No CAPTCHA, no rate-limit observed across ~25 requests in iteration. Stealth + verified-session flags are not required for these endpoints.
browse cloud fetch \
"https://booksearanchescape.escapia.com/DesktopDefault.aspx?PageID=11977&page_num=1" \
--proxies
Browser fallback
If for some reason the URL endpoints regress (Escapia retires the /Unit/Availability JSON route, etc.), drive the form interactively:
browse open https://booksearanchescape.escapia.com/ --remotebrowse fill #ctl03_ctl06_ctl02_arrive "07/04/2026"and same for_depart.- Set
#ctl03_ctl06_ctl02_adultsand#ctl03_ctl06_ctl02_childrenviabrowse fill. browse click #ctl03_ctl06_ctl02_submit— triggers an__doPostBacktoDesktopDefault.aspx.- Parse the resulting SearchResults page (same
<ul id="propertyList">schema as catalog). - Note: Even the form-submit path does not filter results to actually available units — Escapia's SearchResults module shows all matching catalog units; the only authoritative availability gate is
/Booking/RateDetails/{pid}returning200vs302.
Site-Specific Gotchas
- GET-param search filters are cosmetic, not functional.
/site/SearchResults/default.aspx?arrive=…&depart=…&adults=…&bedrooms=…&pets=…pre-fills the form widgets but returns the same shuffled catalog page regardless of date/party/bedroom values. We verified: a search forarrive=01/01/2020&depart=01/03/2020&adults=30(impossible) still returned 10 listings; a search withbedrooms=4returned[3, 1, 3, 2, 3, 3, 1, 4, 2, 2]bedroom counts. Never trust the SearchResults listing as "these units are available for your dates." Use/Unit/Availability/{pid}per unit instead. - Catalog ordering is randomized per request. Two back-to-back fetches of
/site/PropertyList/11977/default.aspx(or/DesktopDefault.aspx?PageID=11977&page_num=1) return different 10-unit subsets — the SortingGuid cookie reshuffles per session. To enumerate the full catalog, walk all 4page_numvalues; expect overlap. The published total is ~30+ properties but a single 4-page walk may surface ~20-25 unique pids due to shuffle collisions. If completeness matters, repeat the 4-page walk 2-3 times and union the pid sets. page_numonly works on/DesktopDefault.aspx?PageID=11977. On the dated/site/SearchResults/default.aspxpath,?page_num=Nis silently ignored — the pager UI shows "Page 1 of 4" for every request because pagination state lives in__VIEWSTATE(POST-only). If you want paginated dated-search results from the browser-fallback path, you must POST with the rotating ViewState — not worth it; just paginate the catalog endpoint and filter availability per-unit./Booking/RateDetails/{pid}redirects on unavailability. A302withLocation: http://booksearanchescape.escapia.com/Error/UnitUnavailableis the canonical "no" signal. Do NOT follow the redirect (--allow-redirectsoff — Browserbase Fetch defaults to off, which is what you want). If your client follows the redirect blindly, you'll get the error page HTML and have to detect failure by string-match on "UnitUnavailable" — slower and noisier.- Date format is US
MM/DD/YYYY. ISO 8601 (2026-12-24) on the Availability or RateDetails endpoints returns 500 withparameters dictionary contains a null entry for parameter 'startDate'. The error page leaks the controller signature (Escapia.Portal.Controllers.UnitController.Availability(Int32, DateTime, DateTime)) — useful debug breadcrumb if the path ever changes. M: 255in the Availability JSON is a sentinel, not a real min-stay. It appears on everyU(unavailable) day and on days that fall outside the bookable window. Treat anyM >= 90as "ignore min-stay; use theSflag alone."Bedrooms: -in the catalog<li>renders as0or an em-dash in metadata. Some studio/loft units list a dash. Parse defensively: if the bedroom value is non-numeric, fall back to the detail page'sunitAmenitiestable where "Property Type" usually includes the property classification ("Studio", "Loft", etc.).- All photo URLs are protocol-relative (
//pictures.escapia.com/...). Prefix withhttps:before storing or rendering. - The portal-alias subdomain matters.
booksearanchescape.escapia.comis the canonical host; the parentwww.searanchescape.comis a separate marketing site that redirects/proxies into the same Escapia portal but with different markup. Always use the*.escapia.comhost for the endpoints in this skill. - Read-only stop point. The booking flow continues at
/Booking/RateDetails/{pid}→/Booking/Details→/Booking/Payment. Do not POST or click past RateDetails — that creates a tentative reservation in the manager's system.
Expected Output
The skill returns one of three shapes depending on input.
Shape A — Listing query (no dates)
User asked "what houses does Sea Ranch Escape have?" — no date constraint, just discovery.
{
"success": true,
"query": {
"type": "catalog"
},
"results": [
{
"pid": "38550",
"name": "Masthead Dunes (TOT ID #2162)",
"url": "https://booksearanchescape.escapia.com/Unit/Details/38550",
"price_summary": "Starts @ 3 Nights $2075/ Weekly $3903",
"bedrooms": 4,
"bathrooms": 2.0,
"sleeps": 8,
"pets": "None",
"guest_rating": 5,
"image_url": "https://pictures.escapia.com/SEARES/38550/9883760465.jpg",
"description": "Unit 28 Lot 96. Exquisite new home located within minutes to tide pools and Walk On Beach…"
}
],
"total_results": 24,
"total_pages_walked": 4,
"note": "Catalog ordering is randomized per request; repeat the page walk to union additional unit IDs."
}
Shape B — Dated availability query
User asked "what's available July 4–7 2026 for 4 adults, dog-friendly?".
{
"success": true,
"query": {
"type": "availability",
"arrive": "07/04/2026",
"depart": "07/07/2026",
"adults": 4,
"children": 0,
"pets_required": "Dogs"
},
"results": [
{
"pid": "116598",
"name": "Alta Pacifica (TOT #2927N)",
"url": "https://booksearanchescape.escapia.com/Unit/Details/116598",
"bedrooms": 3,
"bathrooms": 3.0,
"sleeps": 6,
"pets": "Dogs",
"available": true,
"min_stay_nights": 3,
"total_price_usd": 1247.55,
"nights": 3,
"rate_details_url": "https://booksearanchescape.escapia.com/Booking/RateDetails/116598?arrive=07/04/2026&depart=07/07/2026&adults=4&children=0"
}
],
"candidates_screened": 24,
"available_count": 1
}
Shape C — No-match outcome
User asked for an impossible/unavailable combination.
{
"success": true,
"query": {
"type": "availability",
"arrive": "12/24/2026",
"depart": "12/28/2026",
"adults": 2,
"children": 0
},
"results": [],
"candidates_screened": 24,
"available_count": 0,
"reason": "all_unavailable",
"note": "Christmas week — every screened unit returned 302 → /Error/UnitUnavailable from RateDetails, or had U (Unavailable) days in the requested span."
}
Shape D — Unit-detail enrichment (optional)
If the caller requests rich amenities for a returned pid, add this object alongside the listing entry:
{
"pid": "38550",
"detail": {
"long_description": "Unit 28 Lot 96 Ocean Front / HIGHLIGHTS: Hot tub with some views, internet access, gas fireplace, gas BBQ, easy walk to Walk On Beach, children welcome. FLOOR PLAN: Open kitchen, dining and living room…",
"amenities": {
"Property Type": "House, 1 story, Built in 2009",
"Unit Code": "MAST",
"Beds": "1 king bed, 2 queen beds, 2 twin beds",
"Bathrooms": "2 bathrooms",
"Rooms": "Sleeps 8",
"Pets": "No pets allowed.",
"Living": "Forced Air Heat, Gas Fireplace, Washer & Dryer, Wireless Internet",
"Kitchen": "Coffee Maker, Cookware, Dishwasher, Full Kitchen, Gas Oven and Stovetop, Ice Maker, Microwave, Refrigerator, Toaster, Washer/Dryer, Coffee Grinder, Blender",
"Entertainment": "CD Player, DVD Player, i Pod Dock, Satellite TV, Stereo System, Wireless Internet",
"Outdoor": "Deck, Gas Grill, Hot Tub",
"Geographic": "Close to Town, Near Beach",
"Convenience": "Area FitnessCenter, Golf Course, Nearby Grocery, Nearby Medical Services",
"Children": "Children allowed"
},
"reviews": {
"manager_count": 6682,
"unit_count": 100,
"would_recommend_pct": 99
},
"photos": [
"https://pictures.escapia.com/SEARES/38550/9883760465.jpg",
"https://pictures.escapia.com/SEARES/38550/6379990312.jpg"
]
}
}