Plaza Museum District Amenities & Floor Plans

Site plazamuseumdistrictapts.comTask browse-amenities-and-floor-plans-mp7yefVersion v1Updated Jul 13, 2026Category real-estate

Extract The Plaza Museum District (1615 Hermann Dr, Houston TX) building & neighborhood amenities plus the full floor-plan catalog — layout types, bed/bath/sqft, starting and per-unit rent, lease terms, move-in dates, and live availability. Read-only. This skill was captured from a live agent session on plazamuseumdistrictapts.com and publishes here verbatim, exactly as an agent receives it.

NoteSelectors and URL schemes drift as sites change. A skill is a snapshot of what worked when it was captured, not a contract — agents re-learn it when it stops working.

Purpose

Extract a complete, read-only summary of The Plaza Museum District apartments (1615 Hermann Dr, Houston, TX 77004) — a Berkshire-managed, Jonah-Digital-built marketing site. Returns three things:

  1. Building (community + in-apartment) amenities — the full feature lists.
  2. Neighborhood amenities — nearby restaurants, coffee, shopping, recreation, plus the Walk Score.
  3. Floor plans — the full 12-layout catalog (A1–A6l, D1–D6) with bed/bath/square-feet metadata, starting/per-unit base rent, lease terms, move-in dates, and live availability.

The optimal path is hybrid: the /amenities/ and /neighborhood/ pages are static server-rendered HTML you can grab with a single proxied fetch, while the /floorplans/ page is a client-side widget whose live pricing/availability requires a rendered browser session. Nothing here is a purchase or booking flow — never submit the tour/apply forms.

When to Use

  • "What amenities does The Plaza Museum District offer (in-unit and community)?"
  • "What's near the building — restaurants, shopping, walkability?"
  • "List Plaza Museum District floor plans with prices, square footage, and what's available."
  • A rental-aggregator or relocation agent collecting current availability + starting rents for one property.

Workflow

Part A — Amenities & neighborhood (cheap fetch, no browser)

Both pages are fully server-rendered — no client-side widget, so parse them in-page. Run one browserless_agent call per page: goto then an evaluate that strips tags and projects the bullet text. A residential proxy is the verified-working config (a proxy-less load also returns 200):

// browserless_agent — amenities (repeat for /neighborhood/ swapping the url)
{
  "proxy": { "proxy": "residential", "proxyCountry": "us" },
  "commands": [
    {
      "method": "goto",
      "params": {
        "url": "https://plazamuseumdistrictapts.com/amenities/",
        "waitUntil": "load",
        "timeout": 45000,
      },
    },
    {
      "method": "evaluate",
      "params": {
        "content": "(()=>{const grab=h=>{const el=[...document.querySelectorAll('h2,h3')].find(n=>n.textContent.trim().startsWith(h));if(!el)return[];const items=[];let n=el.parentElement;return [...document.querySelectorAll('li,.amenity')].map(x=>x.textContent.trim()).filter(Boolean);};return JSON.stringify({apartment:[...document.querySelectorAll('li')].map(x=>x.textContent.trim()).filter(Boolean)});})()",
      },
    },
  ],
}

Both /amenities/ and /neighborhood/ are static HTML, so a raw same-origin HTTP fetch would also work; the browserless_agent goto + evaluate path above is cleaner because it parses in-page instead of shipping raw HTML.

  • Amenities live under two headings: "Your Apartment" (in-unit features) and "Your Community" (building/community features). Items flagged with a trailing * are "Available in select units." There is a "Show All" toggle in the DOM, but all items are already present in the static HTML — no expansion click needed.
  • Neighborhood lists POIs grouped into four tabs — Restaurants, Coffee, Shopping, Recreation — plus a Walk Score ("71 — Very Walkable"). All four groups are present in the static HTML regardless of which tab is visually active.

Strip tags and read the bullet text. (Both pages also share a /p/pet-friendly/ pet policy block: up to 2 pets, $400 fee/pet, $35/mo rent/pet, breed restrictions.)

Part B — Floor plans (browser render required)

The /floorplans/ page boots the Jonah Digital floor-plan widget (/fp-assets/js/app.js). Cards are injected client-side from a session-bound AJAX endpoint, so you must render the page in a real browser. Run the whole flow — nav → wait → surface the Floorplans tab → read text → grab the JSON-LD roster — inside one browserless_agent call so the PHPSESSID cookie + widget instance are established and used without round-trips (the session persists across calls, keyed by proxy, so repeating the same proxy reconnects to it; there is no separate release step — nothing to release). No stealth needed — a residential proxy is verified across this run.

// ONE browserless_agent call — session persists across calls (keyed by proxy); no release step
{
  "proxy": { "proxy": "residential", "proxyCountry": "us" },
  "commands": [
    // 1. Open. The load event may not fire because of long-tail trackers — that's
    //    harmless (content paints first). Fall through to a fixed wait rather than
    //    depending on the load event.
    {
      "method": "goto",
      "params": {
        "url": "https://plazamuseumdistrictapts.com/floorplans/",
        "waitUntil": "load",
        "timeout": 45000,
      },
    },
    { "method": "waitForTimeout", "params": { "time": 5000 } },

    // 2. The widget has two tabs: `Map` (default — sightmap + a "List View" of every
    //    currently-available *unit*) and `Floorplans` (a grid of *layout types* with
    //    starting rent). Click the Floorplans tab to also surface the per-layout
    //    starting-rent cards. Confirm the tab selector via `snapshot` if the click misses.
    {
      "method": "click",
      "params": {
        "selector": "[data-tab='floorplans'], a:has-text('Floorplans'), button:has-text('Floorplans')",
      },
    },
    { "method": "waitForTimeout", "params": { "time": 3500 } },

    // 3. Read the body — now contains BOTH the unit list and the layout grid.
    { "method": "text", "params": { "selector": "body" } },

    // 4. Grab the embedded JSON-LD for the full 12-layout roster (all names +
    //    /floorplans/{slug}/ detail URLs), even layouts with no current availability.
    {
      "method": "evaluate",
      "params": {
        "content": "JSON.stringify([...document.querySelectorAll('script[type=\"application/ld+json\"]')].map(s=>s.textContent))",
      },
    },
  ],
}

Parse what comes back:

  • Layout cards (Floorplans tab, in the text result): <PlanCode> + N bed N bath NNN sq. ft. + Base Rent $X,XXX + optional Only N left! scarcity badge.
  • Unit cards (Map tab "List View", in the text result): <PlanCode> + #<unit> + Available <Mon DD> + N bed N bath NNN sq. ft. + Base Rent $X,XXX + NN months lease term.
  • 12-layout roster (from the evaluate .value — a schema.org ApartmentComplex block whose accommodationFloorPlan array lists all 12 layout names with /floorplans/{slug}/ detail URLs). 1-bedroom A-types: A1, A2, A3, A4l, A5, A6l · 2-bedroom D-types: D1, D2, D3, D4, D5, D6.

If snapshot is needed to locate the Floorplans tab ref, add a { "method": "snapshot" } before the click in the same commands array and read the tab's selector from the a11y tree.

Site-Specific Gotchas

  • READ-ONLY. Stop at the floor-plan / availability screen. Never submit the "Schedule a Tour", "Find Your Home", or "Apply Now" (securecafe.com online leasing) forms. The site uses reCAPTCHA v3 — a passive, hidden-badge token that only matters on form submit; it does not block page loads or floor-plan rendering. No CAPTCHA challenge, no Akamai, no login wall was hit anywhere (0 × 4xx across the run).
  • fetch works for amenities/neighborhood but NOT floor plans. /amenities/ and /neighborhood/ are static and fully fetchable. /floorplans/ returns only an empty widget shell on a plain fetch.
  • The floor-plan data endpoint is session-bound — do not try to replay it. The widget calls GET /floorplans/_fp-renderable/params:instance=<hash>&action=render&type=listing-chunks/?forcecache=1. The <hash> (e.g. 20f4d721…) is minted per session and tied to the PHPSESSID cookie; calling the endpoint (any variant, with/without proxies) without that live session + XHR headers 302-redirects to /floorplans/ with an empty body. Confirmed across multiple out-of-band attempts. Render the page instead.
  • "twelve distinct layouts" but only ~7 show pricing. The widget only renders layout/unit cards for floor plans that currently have available units. At capture time the Floorplans tab showed 7 layout types (A1, A2, A3, A5, D1, D2, D6); the other 5 layouts (A4l, A6l, D3, D4, D5) appear only in the JSON-LD roster + have /floorplans/{slug}/ detail pages, with no live price/availability. To report bed/bath/sqft for an unavailable layout, open its detail page; expect it to lack a current rent.
  • The embedded JSON-LD per-unit numeric fields are a BROKEN scaffold — do not trust them. Every accommodationFloorPlan unit entry repeats numberOfBedrooms:1, numberOfBathroomsTotal:1, floorSize.value:686 regardless of the real layout (the D2 1175-sqft 2BR unit is mislabeled as 1BR/686). The rendered card text ("2 bed 2 bath 1175 sq. ft.") is authoritative; the JSON-LD is reliable only for the 12 layout names and detail URLs.
  • "Outside price filter range" badge is noise. Every unit in the Map-tab List View was tagged "Outside price filter range" even when its base rent ($1,629–$2,288) sits inside the default filter window ($1,600–$2,600). The widget's default price slider compares against a different (likely market/effective) price field, so this badge does not mean the unit is excluded. Ignore it; report the unit.
  • Sightmap floor-level "avail" counts don't reconcile with the unit list. The Map tab's floor selector showed Floor 1 = 7, Floor 2 = 3, Floor 3 = 5, Floors 4–6 = 0 avail (sum 15), while "List View" said 7 available and listed 7 units. Treat the per-unit List View as the authoritative availability count; the floor-selector tallies (Engrain/sightmap embed, asset_id 28411) are supplementary and can diverge.
  • The load event doesn't settle (~30s) on this site because of long-lived third-party trackers (MeetElise/EliseAI chat, CallRail, GTM). The content paints well before that. Add a waitForTimeout of 4–5s after goto instead of relying on the load event.
  • No separate trace/capture step needed. browserless_agent drives the page directly; there is no CDP-tracer attachment to sequence or misconfigure. Batch the gotowaitForTimeoutevaluate/text steps in one call's commands array.
  • Dynamic phone number. The footer/header phone is swapped by a GET /get-dni-phone-number/?format=dash call (CallRail DNI), so you may see (713) 597-7732 in the rendered DOM vs (713) 874-1311 in the raw HTML. Both reach the property.
  • Data is live & changes. Prices, lease terms, move-in dates, and which layouts are available are pulled fresh each load — re-render for current values rather than caching.

Expected Output

{
  "success": true,
  "property": {
    "name": "The Plaza Museum District",
    "address": "1615 Hermann Dr, Houston, TX 77004",
    "phone": "(713) 874-1311",
    "managedBy": "Berkshire",
    "petPolicy": "Up to 2 pets/apartment, no weight limit. Pet fee $400/pet, pet rent $35/pet/mo. Breed restrictions apply; service animals exempt."
  },
  "amenities": {
    "apartment": [
      "Modern One & Two Bedroom Apartments",
      "Scenic Views Of Hermann Park",
      "9Ft Ceilings",
      "Expansive Windows",
      "Hardwood-Inspired Flooring*",
      "Chef-Inspired Kitchen with Custom Cabinets",
      "Stainless Steel Appliance Package",
      "Breakfast Bar",
      "Granite Countertops",
      "Kitchen Pantry",
      "Dining Space or Home Office",
      "Ceiling Fans In Living Room & Bedroom",
      "Office Space*",
      "Carpeted Floors",
      "Spa Bathroom with Garden Soaking Bathtub",
      "Dual Vanities*",
      "Spacious Closets",
      "In Home Washer & Dryer",
      "Private Balconies and Patios",
      "Intrusion Alarm Available",
      "Central Air/Heating",
      "Pet Friendly Community"
    ],
    "community": [
      "Resort Inspired Pool with Water Features",
      "Poolside Cabana with Outdoor Kitchen",
      "Tanning Ledge",
      "Soothing Spa/Hot Tub",
      "24/7 State-Of-The-Art Fitness Center",
      "Free Weight Station",
      "Resident Lounge & Business Center",
      "Package Lockers",
      "Free Wi-Fi In Common Areas",
      "Valet Trash Pick Up and Recycling Program",
      "Pet Friendly Community",
      "Elevator Access",
      "Gated Access",
      "Parking Garage",
      "Assigned Parking Available",
      "On-Site Maintenance",
      "24/7 Emergency Maintenance",
      "In the Heart of the Houston Medical District",
      "Public Parks Nearby",
      "Walking Distance To Houston Museum District",
      "Access To Public Transportation",
      "Easy Access To Freeways"
    ],
    "note": "Items marked * are available in select units only."
  },
  "neighborhood": {
    "walkScore": 71,
    "walkScoreLabel": "Very Walkable",
    "restaurants": [
      "MF Sushi",
      "Fadi's Mediterranean Eatery",
      "Dak & Bop",
      "Fia's Pizzeria",
      "Granger's Restaurant & Bar",
      "Lien's Viet Kitchen"
    ],
    "coffee": [
      "Pinewood Cafe",
      "Shipley Do-Nuts",
      "Barnaby's Cafe",
      "Mo' Brunch + Brews",
      "Kin Café",
      "Koko Cafe"
    ],
    "shopping": [
      "Ross Dress for Less",
      "Almeda Center",
      "Target",
      "Hawthorne Square",
      "H-E-B",
      "Southmore Market"
    ],
    "recreation": [
      "Grace and Grit Fitness",
      "Outdoor Workouts",
      "Museum of Fine Arts",
      "Rice Cinema",
      "Children's Museum Outdoor Park",
      "Memorial Hermann Centennial Park"
    ]
  },
  "floorPlans": {
    "totalLayouts": 12,
    "allLayoutCodes": [
      "A1",
      "A2",
      "A3",
      "A4l",
      "A5",
      "A6l",
      "D1",
      "D2",
      "D3",
      "D4",
      "D5",
      "D6"
    ],
    "availableLayouts": [
      {
        "code": "A1",
        "beds": 1,
        "baths": 1,
        "sqft": 686,
        "startingRent": 1629,
        "scarcity": null,
        "detailUrl": "https://plazamuseumdistrictapts.com/floorplans/a1/"
      },
      {
        "code": "A2",
        "beds": 1,
        "baths": 1,
        "sqft": 752,
        "startingRent": 1817,
        "scarcity": null,
        "detailUrl": "https://plazamuseumdistrictapts.com/floorplans/a2/"
      },
      {
        "code": "A3",
        "beds": 1,
        "baths": 1,
        "sqft": 886,
        "startingRent": 2072,
        "scarcity": "Only 2 left!",
        "detailUrl": "https://plazamuseumdistrictapts.com/floorplans/a3/"
      },
      {
        "code": "A5",
        "beds": 1,
        "baths": 1,
        "sqft": 947,
        "startingRent": 2167,
        "scarcity": "Only 2 left!",
        "detailUrl": "https://plazamuseumdistrictapts.com/floorplans/a5/"
      },
      {
        "code": "D1",
        "beds": 2,
        "baths": 2,
        "sqft": 1139,
        "startingRent": 2302,
        "scarcity": "Only 1 left!",
        "detailUrl": "https://plazamuseumdistrictapts.com/floorplans/d1/"
      },
      {
        "code": "D2",
        "beds": 2,
        "baths": 2,
        "sqft": 1175,
        "startingRent": 2288,
        "scarcity": "Only 1 left!",
        "detailUrl": "https://plazamuseumdistrictapts.com/floorplans/d2/"
      },
      {
        "code": "D6",
        "beds": 2,
        "baths": 2,
        "sqft": 1292,
        "startingRent": 2584,
        "scarcity": "Only 1 left!",
        "detailUrl": "https://plazamuseumdistrictapts.com/floorplans/d6/"
      }
    ],
    "unavailableLayouts": ["A4l", "A6l", "D3", "D4", "D5"],
    "availableUnits": [
      {
        "unit": "#2105",
        "plan": "A1",
        "beds": 1,
        "baths": 1,
        "sqft": 686,
        "baseRent": 1685,
        "leaseTermMonths": 14,
        "availableFrom": "Jun 05"
      },
      {
        "unit": "#2104",
        "plan": "A1",
        "beds": 1,
        "baths": 1,
        "sqft": 686,
        "baseRent": 1649,
        "leaseTermMonths": 14,
        "availableFrom": "Jun 25"
      },
      {
        "unit": "#1120",
        "plan": "A1",
        "beds": 1,
        "baths": 1,
        "sqft": 686,
        "baseRent": 1629,
        "leaseTermMonths": 13,
        "availableFrom": "Jul 09"
      },
      {
        "unit": "#1138",
        "plan": "A1",
        "beds": 1,
        "baths": 1,
        "sqft": 686,
        "baseRent": 1840,
        "leaseTermMonths": 13,
        "availableFrom": "Jul 24"
      },
      {
        "unit": "#1112",
        "plan": "D2",
        "beds": 2,
        "baths": 2,
        "sqft": 1175,
        "baseRent": 2288,
        "leaseTermMonths": 15,
        "availableFrom": "Jul 24"
      },
      {
        "unit": "#1132",
        "plan": "A3",
        "beds": 1,
        "baths": 1,
        "sqft": 886,
        "baseRent": 2118,
        "leaseTermMonths": 12,
        "availableFrom": "Aug 10"
      },
      {
        "unit": "#1107",
        "plan": "A3",
        "beds": 1,
        "baths": 1,
        "sqft": 886,
        "baseRent": 2072,
        "leaseTermMonths": 13,
        "availableFrom": "Aug 21"
      }
    ],
    "totalAvailableUnits": 7,
    "disclaimer": "Floor plans are artist's rendering; dimensions approximate. Base rent is monthly; additional fees may apply (utilities, package, trash, water, amenities). Prices & availability subject to change.",
    "capturedAt": "2026-05-30"
  }
}

Notes for the consuming agent:

  • beds/baths/sqft on availableUnits come from the rendered card text, NOT the JSON-LD (which is bugged — see gotchas).
  • startingRent on a layout is the lowest base rent across its available units; per-unit rent varies (see availableUnits[].baseRent).
  • unavailableLayouts have detail pages but no live pricing at capture time; fetch detailUrl (e.g. /floorplans/d3/) for their static bed/bath/sqft if needed.
  • All rent values are USD/month base rent; lease terms in months.

Call it

GET https://production-sfo.browserless.io/skills?token=TOKEN-HERE&domain=plazamuseumdistrictapts.com&task=browse-amenities-and-floor-plans-mp7yef