{"id":"99f8a54b-7116-45e6-bf1e-e1e8a1f39ab8","entityType":"agent","slug":"clawhub-chrischall-zillow-fpx","name":"zillow-fpx","canonicalUrl":"https://www.xpersona.co/agent/clawhub-chrischall-zillow-fpx","canonicalPath":"/agent/clawhub-chrischall-zillow-fpx","generatedAt":"2026-10-10T13:33:25.951Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T11:28:07.451Z","emptyReason":null},"description":"Query zillow.com (US real-estate portal) from a shell with the fpx CLI (@fetchproxy/cli) instead of running the zillow-mcp server — search listings, pull a full property record by zpid, price/tax/Zestimate history, photos, market reports, and your signed-in saved searches/homes, all via one-shot HTTP calls through a signed-in browser tab. Use when you want Zillow data without the MCP, in a script, or on a machine where the MCP isn't installed.","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.5K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s17cjx1a349nz5apaqp02vgz4h85728z:zillow-fpx","sourceUrl":"https://clawhub.ai/chrischall/zillow-fpx","homepage":"https://clawhub.ai/chrischall/skills/zillow-fpx","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/chrischall/zillow-fpx","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/chrischall/skills/zillow-fpx","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":63,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"zillow-fpx technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T11:28:07.451Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T11:28:07.451Z","emptyReason":null},"stars":null,"forks":null,"downloads":1464,"packageName":null,"latestVersion":"1.2.2","tractionLabel":"1.5K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T11:28:07.451Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T11:28:07.451Z","lastCrawledAt":"2026-10-10T11:28:07.451Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T11:28:07.451Z","lastVerifiedAt":null,"highlights":[{"version":"1.2.2","createdAt":"2026-10-09T23:28:25.699Z","changelog":"- Removed the file: skill-card.md - No user-facing functionality changes—documentation cleanup only","fileCount":4,"zipByteSize":8533},{"version":"1.2.1","createdAt":"2026-10-07T13:40:01.886Z","changelog":"- Removed the file skill-card.md. - No user-facing changes in functionality or documentation.","fileCount":4,"zipByteSize":8635},{"version":"1.2.0","createdAt":"2026-10-06T13:23:47.473Z","changelog":"- Removed the sample file skill-card.md for cleanup. - No changes to user-facing features or documentation.","fileCount":4,"zipByteSize":8572},{"version":"1.1.8","createdAt":"2026-10-05T17:08:24.387Z","changelog":"- Removed the skill-card.md file. - No functional changes to the skill or its documentation.","fileCount":4,"zipByteSize":8455},{"version":"1.1.7","createdAt":"2026-10-05T02:52:21.264Z","changelog":"- Removed the file skill-card.md. - No changes to functionality or documentation in SKILL.md. - Version bump to 1.1.7.","fileCount":4,"zipByteSize":8529},{"version":"1.1.6","createdAt":"2026-10-03T14:01:11.414Z","changelog":"- Removed the skill-card.md file. - No changes to behavior or core usage; documentation and functionality remain the same.","fileCount":4,"zipByteSize":8423},{"version":"1.1.5","createdAt":"2026-10-03T01:47:20.414Z","changelog":"- Removed the redundant skill-card.md file. - No changes to core functionality or documentation.","fileCount":4,"zipByteSize":8574},{"version":"1.1.4","createdAt":"2026-09-28T13:55:30.603Z","changelog":"- Switched browser extension requirement from \"fetchproxy\" to \"ContextMint Bridge\" (recently renamed), including updated setup instructions and verification guidance. - Updated documentation to reference \"ContextMint Bridge\" throughout, replacing prior mentions of the fetchproxy extension. - Removed skill-card.md file from the project.","fileCount":4,"zipByteSize":8466}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17cjx1a349nz5apaqp02vgz4h85728z:zillow-fpx","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s17cjx1a349nz5apaqp02vgz4h85728z:zillow-fpx` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/chrischall/zillow-fpx before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-zillow-fpx/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-zillow-fpx/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-zillow-fpx/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-zillow-fpx/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-zillow-fpx/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-zillow-fpx/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T13:33:25.946Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-zillow-fpx/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-zillow-fpx/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-zillow-fpx/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-zillow-fpx/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T11:28:07.451Z","emptyReason":null},"readme":"Skill: zillow-fpx\n\nOwner: chrischall\n\nSummary: Query zillow.com (US real-estate portal) from a shell with the fpx CLI (@fetchproxy/cli) instead of running the zillow-mcp server — search listings, pull a full property record by zpid, price/tax/Zestimate history, photos, market reports, and your signed-in saved searches/homes, all via one-shot HTTP calls through a signed-in browser tab. Use when you want Zillow data without the MCP, in a script, or on a machine where the MCP isn't installed.\n\nTags: latest:1.2.2\n\nVersion history:\n\nv1.2.2 | 2026-10-09T23:28:25.699Z | auto\n\n- Removed the file: skill-card.md\n- No user-facing functionality changes—documentation cleanup only\n\nv1.2.1 | 2026-10-07T13:40:01.886Z | auto\n\n- Removed the file skill-card.md.\n- No user-facing changes in functionality or documentation.\n\nv1.2.0 | 2026-10-06T13:23:47.473Z | auto\n\n- Removed the sample file skill-card.md for cleanup.\n- No changes to user-facing features or documentation.\n\nv1.1.8 | 2026-10-05T17:08:24.387Z | auto\n\n- Removed the skill-card.md file.\n- No functional changes to the skill or its documentation.\n\nv1.1.7 | 2026-10-05T02:52:21.264Z | auto\n\n- Removed the file skill-card.md.\n- No changes to functionality or documentation in SKILL.md.\n- Version bump to 1.1.7.\n\nv1.1.6 | 2026-10-03T14:01:11.414Z | auto\n\n- Removed the skill-card.md file.\n- No changes to behavior or core usage; documentation and functionality remain the same.\n\nv1.1.5 | 2026-10-03T01:47:20.414Z | auto\n\n- Removed the redundant skill-card.md file.\n- No changes to core functionality or documentation.\n\nv1.1.4 | 2026-09-28T13:55:30.603Z | auto\n\n- Switched browser extension requirement from \"fetchproxy\" to \"ContextMint Bridge\" (recently renamed), including updated setup instructions and verification guidance.\n- Updated documentation to reference \"ContextMint Bridge\" throughout, replacing prior mentions of the fetchproxy extension.\n- Removed skill-card.md file from the project.\n\nv1.1.3 | 2026-09-25T15:53:16.945Z | auto\n\n- Removed the sample file skill-card.md.\n- No user-facing feature or documentation changes.\n\nv1.1.2 | 2026-09-23T21:43:34.359Z | auto\n\n- Removed sample skill card file (skill-card.md) for simplification and cleanup.\n- No changes to core functionality or documentation.\n\nv1.1.1 | 2026-09-23T15:42:39.795Z | auto\n\n- Removed the file skill-card.md.\n- No changes to the SKILL.md content.\n\nv1.1.0 | 2026-09-20T02:52:26.339Z | auto\n\n- Removed the documentation file skill-card.md.\n- No changes to user-facing functionality or core documentation in SKILL.md.\n\nv1.0.0 | 2026-09-19T11:19:11.781Z | auto\n\n- Removed the sample file skill-card.md.\n- No changes to functionality or usage; documentation remains unchanged.\n\nv0.13.4 | 2026-09-15T18:45:58.387Z | auto\n\n- Removed the file skill-card.md.\n- No changes to functionality or usage; documentation and code otherwise unchanged.\n\nv0.13.3 | 2026-09-14T14:08:42.606Z | auto\n\n- Removed the skill-card.md file from the repository.\n- No changes to code or user functionality; documentation content and behavior remain unchanged.\n\nv0.13.2 | 2026-09-10T17:51:53.740Z | auto\n\n- Removed the skill-card.md file.\n- No changes to code or functionality; this is a documentation/filesystem cleanup only.\n\nv0.13.1 | 2026-09-09T21:16:43.687Z | auto\n\n- Removed the file: skill-card.md\n- No changes to core functionality or documentation in SKILL.md\n\nv0.13.0 | 2026-09-04T22:23:32.805Z | auto\n\n- Removed the file skill-card.md.\n- No changes to code or user-facing documentation in SKILL.md.\n- No new features or bugfixes in this release.\n\nv0.12.0 | 2026-08-29T13:54:56.025Z | auto\n\n- Removed the skill-card.md file to streamline documentation.\n- No changes to core functionality or usage—only documentation cleanup.\n\nv0.11.5 | 2026-08-28T21:07:57.885Z | auto\n\n- Removed the file: skill-card.md\n- No user-facing functionality or documentation changes; internal documentation file cleanup only.\n\nv0.11.4 | 2026-08-28T11:35:20.290Z | auto\n\n- Removed the sample file skill-card.md.\n- No functional or user-facing changes in this release.\n\nv0.11.3 | 2026-08-06T00:43:30.190Z | auto\n\n- Removed the sample file skill-card.md.\n- No user-facing functional changes; documentation and usage remain the same.\n\nv0.11.2 | 2026-07-30T12:54:25.822Z | auto\n\n- Initial release of zillow-fpx for querying zillow.com via the fpx CLI, as an alternative to the zillow-mcp server.\n- Fetch Zillow data—including listings, property records by zpid, price/tax/Zestimate history, photos, market reports, and saved searches/homes—using one-shot HTTP calls routed through a signed-in browser tab.\n- No credentials are stored; requires the fetchproxy browser extension and a signed-in zillow.com tab.\n- All data is scraped from server-rendered HTML pages; there is no direct JSON API.\n- Offers clear instructions for setup, usage, and handling authentication/browser wall issues.\n\nArchive index:\n\nArchive v1.2.2: 4 files, 8533 bytes\n\nFiles: references/pages.md (10041b), skill-card.md (1990b), SKILL.md (4854b), _meta.json (129b)\n\nFile v1.2.2:SKILL.md\n\n---\nname: zillow-fpx\ndescription: >-\n  Query zillow.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the zillow-mcp server — search\n  listings, pull a full property record by zpid, price/tax/Zestimate\n  history, photos, market reports, and your signed-in saved\n  searches/homes, all via one-shot HTTP calls through a signed-in browser\n  tab. Use when you want Zillow data without the MCP, in a script, or on\n  a machine where the MCP isn't installed.\n---\n\n# Zillow via fpx (no MCP)\n\nZillow fronts `www.zillow.com` with a PerimeterX bot-wall that blocks\nplain `curl`/Node requests, and several tools (saved searches/homes)\nneed an actual signed-in session. `fpx` routes every request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), so the\nsame page loads that a real visit would.\n\nThis is the same data the `zillow_*` MCP tools return — every property\ntool is a scrape of Zillow's server-rendered Next.js pages\n(`__NEXT_DATA__`), not a documented JSON API. No credentials are stored\nanywhere; auth (for the saved-data endpoints) is just \"have a signed-in\nzillow.com tab open.\"\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli             # provides `fpx`\nfpx profile add zillow --domain zillow.com # only the fetch capability is needed\nfpx pair -p zillow                         # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n([releases](https://github.com/nullnet-app/contextmint-bridge/releases)), with an\nopen `www.zillow.com` tab, and its Chrome **Site access** allowing\n`zillow.com`. (ContextMint Bridge is the renamed fetchproxy extension from the\nsame maintainer; build it from source or verify the release zip with\n`shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`.) For the saved-searches/saved-homes calls, that tab must\nalso be **signed in**. Pairing persists — after the first approval every\nlater `fpx` call reuses it.\n\n## Core call\n\nEvery endpoint here is a GET of a server-rendered HTML page (Zillow is a\nNext.js app; the whole page state is embedded as JSON in a\n`<script id=\"__NEXT_DATA__\">` tag) — there is no JSON API to hit\ndirectly. Fetch, then pull the JSON out of the HTML:\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow > /tmp/page.html\npython3 -c '\nimport re, sys, json\nhtml = open(\"/tmp/page.html\").read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n' | jq '.'\n```\n\n`references/pages.md` has the extractor as a reusable one-liner plus the\nper-page `pageProps` field paths (search results, property detail,\nphotos, price/tax/Zestimate history, saved searches/homes, market\nreport) and the address-autocomplete GraphQL call, all transcribed from\nthe MCP's `src/tools/*.ts` (which parse the exact same pages).\n\n## The one rule: resolve the location first (search only)\n\n`zillow_search_properties`'s two-step dance is exactly what\n`/homes/<slug>_rb/` needs: fetch the bare slug path first to get Zillow's\nresolved `regionSelection` + `mapBounds`, THEN re-fetch with those pinned\ninto a `searchQueryState` query param alongside your filters — a filtered\nfetch without the pinned region silently falls back to the user's last\nsearch region instead of honoring the slug. A full-address query can\nresolve straight to a `homedetails` page (no region at all) — see\n`references/pages.md` §1 for both shapes. Property lookups by `zpid`\nneed no resolve step — `/homedetails/<zpid>_zpid/` is direct.\n\n## Auth\n\nNo login is stored or passed by `fpx` — the saved-searches\n(`/myzillow/SavedSearches`) and saved-homes (`/myzillow/favorites`) pages\nsimply render your saved data (or redirect to `/user/login`) depending on\nwhether the tab riding the bridge is signed in. Everything else is\nanonymous.\n\n## Exit codes (fetch verbs)\n\n- `0` — success. A signed-out redirect (`/user/login`, `?login=true`) or\n  a captcha interstitial (body contains `captcha-delivery`, small body)\n  can still ride in a `0` response — check the fetched HTML, `fpx`\n  doesn't know Zillow's sign-in/bot-wall markers.\n- `2` — bridge unavailable: extension not connected or pairing pending →\n  run `fpx pair -p zillow`, confirm a zillow.com tab is open.\n- `3` — bot wall: the tab hasn't cleared PerimeterX → open/refresh a\n  `www.zillow.com` tab and retry.\n- `4` — upstream non-2xx from Zillow.\n\n## Notes\n\n- `fpx health -p zillow` shows bridge connection state when a call fails.\n- Zillow publishes no consumer API — these are the same private\n  server-rendered pages the zillow.com web app itself loads, reached\n  through your own signed-in tab.\n- This project is developed and maintained by AI (Claude).\n\nFile v1.2.2:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"zillow-fpx\",\n  \"version\": \"1.2.2\",\n  \"publishedAt\": 1791588505699\n}\n\nFile v1.2.2:references/pages.md\n\n# Zillow pages for fpx\n\nAll paths below are fetched with `fpx get 'https://www.zillow.com<path>' -p zillow`.\nEvery page is server-rendered Next.js — the data lives in\n`__NEXT_DATA__.props.pageProps`, never in a separate JSON API. Field\npaths below are transcribed from the MCP's parsers\n(`src/next-data.ts`, `src/tools/*.ts`) — live-verified there, not\nre-captured here.\n\n## 0. The extractor (reuse for every page below)\n\n```sh\nextract_page_props() {\n  python3 -c '\nimport re, sys, json\nhtml = sys.stdin.read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nif not m:\n    sys.exit(\"no __NEXT_DATA__ script tag found — likely a bot-wall or redirect page\")\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n'\n}\n\nfpx get 'https://www.zillow.com/robots.txt' -p zillow  # smoke test, no parsing needed\n```\n\nPipe any fetched HTML through `extract_page_props` to get the page's\n`pageProps` as one JSON line, then `jq` into it per the recipes below.\n\n## 1. Search listings\n\nTwo-step dance — **always resolve before filtering**:\n\n**Step 1 — resolve** (bare slug, no query string):\n\n```sh\nfpx get 'https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '.searchPageState.queryState.regionSelection, .searchPageState.queryState.mapBounds' /tmp/pp.json\n```\n\n- If `searchPageState` is present with a non-empty `regionSelection` +\n  `mapBounds` → you have a **region**; proceed to step 2.\n- If `searchPageState` is **absent** but `pageProps.gdpClientCache` (or\n  `pageProps.componentProps.gdpClientCache`) is present, Zillow resolved\n  the query straight to ONE property (a homedetails page) — see §2, no\n  step 2 needed.\n- If `searchPageState.queryState.regionSelection` is empty AND\n  `cat1.searchResults.listResults` is non-empty, Zillow returned\n  address/street-level listings directly with no region to pin — use\n  those listings as-is (issue #31 in the MCP).\n\n**Step 2 — filtered search** (region pinned + your filters), only when\nstep 1 gave you a region:\n\n```sh\nSQS='{\"usersSearchTerm\":\"Brooklyn, NY\",\"filterState\":{\"price\":{\"max\":900000},\"beds\":{\"min\":2}},\"isListVisible\":true,\"isMapVisible\":false,\"regionSelection\":[{\"regionId\":37607,\"regionType\":17}],\"mapBounds\":{\"north\":40.74,\"south\":40.57,\"east\":-73.83,\"west\":-74.05}}'\nENC=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$SQS\")\nfpx get \"https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/?searchQueryState=${ENC}\" -p zillow \\\n  | extract_page_props | jq '.searchPageState.cat1.searchResults.listResults[] | {zpid: .hdpData.homeInfo.zpid, price: .hdpData.homeInfo.price, address: .hdpData.homeInfo.streetAddress, beds: .hdpData.homeInfo.bedrooms, url: .detailUrl}'\n```\n\n`filterState` keys the MCP sets (mirror these in the JSON above):\n`isForRent`/`isForSaleByAgent`/etc `{value: true|false}` (status\nswitches), `price {min,max}`, `beds {min}`, `baths {min}`, one\n`{value:true}` flag per home type (`isSingleFamily`, `isCondo`,\n`isTownhouse`, `isMultiFamily`, `isManufactured`, `isLotLand`,\n`isApartment`), and `pagination: {currentPage: N}` for page > 1. Zillow\nreturns ~40 listings per page; increment `pagination.currentPage` and\nre-fetch to walk further pages (stop on an empty `listResults`).\n\nPagination example (page 2):\n\n```sh\nSQS='{...same as above..., \"pagination\":{\"currentPage\":2}}'\n```\n\n## 2. Property detail by zpid\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\n# gdpClientCache is a JSON-encoded STRING inside pageProps — parse twice.\njq -r '.gdpClientCache // .componentProps.gdpClientCache' /tmp/pp.json \\\n  | jq '[to_entries[] | select(.key | startswith(\"Property:\")) | select(.value.property) | .value.property][0]\n        // [to_entries[] | select(.value.property) | .value.property][0]'\n```\n\nThat gives the raw `property` object. Useful top-level fields: `zpid`,\n`hdpUrl`, `address {streetAddress,city,state,zipcode,neighborhood}`,\n`mlsStreetAddress` (canonical MLS address — may disagree with `address`,\nprefer it when present), `price`, `zestimate`, `rentZestimate`,\n`bedrooms`, `bathrooms`, `livingArea`, `lotSize` (sqft), `yearBuilt`,\n`homeType`, `homeStatus`, `description`, `latitude`/`longitude`,\n`daysOnZillow`, `taxAssessedValue`/`taxAssessedYear`,\n`taxAnnualAmount` (values < 10 are a not-yet-assessed sentinel, not a\nreal bill), `schools[]`, `resoFacts {yearBuilt, associationFee,\nassociationFeeFrequency, taxAnnualAmount}` (MLS fallback source),\n`priceHistory[]`, `taxHistory[]`.\n\nOnly a URL with a trailing `<zpid>_zpid/` resolves — a slug-only URL\nredirects to the generic search page (no `gdpClientCache`). If you only\nhave an address, resolve to a zpid via §1 or the autocomplete call in §7\nfirst.\n\n## 3. Price / tax history (same property object as §2)\n\n```sh\njq '.priceHistory' /tmp/property.json    # [{date, price, event, source, ...}]\njq '.taxHistory' /tmp/property.json      # [{time or year, value, taxIncreaseRate, ...}]\n```\n\nBoth arrays live inline on the property object fetched in §2 — no\nseparate request. Absent on some (commonly non-Showcase) listings —\nZillow renders the trend client-side for those.\n\n## 4. Zestimate history (same property object as §2)\n\n```sh\njq '(first(.homeValueChartData[] | select(.name==\"This home\")) // .homeValueChartData[0]) | .points' /tmp/property.json\n```\n\nEach point is `{x: <unix ms>, y: <value>}` or `{date, value}` depending\non deploy. Fall back to deriving a series from `priceHistory[].{date,price}`\nwhen `homeValueChartData` is absent. `rentValueChartData` is the parallel\nseries for `rent` when present.\n\n## 5. Photos (same property object as §2)\n\n```sh\njq '[.photos, .responsivePhotos, .originalPhotos] | map(select(type==\"array\" and length>0)) | first // []' /tmp/property.json\n```\n\nEach entry: `{caption, subjectType, url, mixedSources: {jpeg: [{url,width}], webp: [{url,width}]}}`.\nPick the widest `mixedSources.jpeg`/`webp` entry for the largest image;\n`url` alone is the hero/thumbnail. `streetViewImageUrl` and\n`hiResImageLink` sit at the top level of the property object too.\n\n## 6. Saved searches / saved homes (requires a signed-in tab)\n\n```sh\n# Saved searches — path is case-sensitive (capital S)\nfpx get 'https://www.zillow.com/myzillow/SavedSearches' -p zillow \\\n  | extract_page_props | jq '.savedSearches // .userSavedSearches'\n\n# Saved (favorited) homes — flattened across collections\nfpx get 'https://www.zillow.com/myzillow/favorites' -p zillow \\\n  | extract_page_props | jq '[.collectionsResponse[] | (.homes // .properties // .items // [])[]]'\n```\n\nA signed-out tab redirects to `/user/login` instead of rendering these —\ncheck the fetched HTML's final URL / body before trusting an empty\nresult as \"no saves.\"\n\n## 7. Market report for a region\n\n```sh\nfpx get 'https://www.zillow.com/home-values/6181/brooklyn-ny/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '{region: .zhviRegion, analytics: .odpMarketAnalytics}' /tmp/pp.json\n```\n\n`zhviRegion {name, regionTypeName, parentCounty.name, parentState.name}`;\n`odpMarketAnalytics.mrktListingLatest {newListings, forSaleInventory,\nmedianListPrice, medianDaysOnMarket}`; `.mrktSaleLatest\n{medianSalePrice, daysToPending}`; `.zhviLatest {zhvi, zhviYoY,\nasOfDate}` (`zhviYoY` is a fraction — multiply by 100 for a percent).\nThe region id/slug (e.g. `6181/brooklyn-ny`) comes from a Zillow\nhome-values URL; there's no separate region-lookup endpoint documented\nin the MCP.\n\n## 8. Address autocomplete (bonus — resolving a free-text address to a zpid)\n\nZillow's own address typeahead, used internally by the MCP's\n`zillow_get_by_address` resolver ladder before it falls back to §1's\nsearch. Inline GraphQL (no persisted-query hash), POST:\n\n```sh\ncat > /tmp/ac.json <<'JSON'\n{\n  \"operationName\": \"GetAutocompleteResults\",\n  \"query\": \"query GetAutocompleteResults($query: String!, $queryOptions: SearchAssistanceQueryOptions, $resultType: [SearchAssistanceResultType], $shouldRequestSpellCorrectedMetadata: Boolean = false) { searchAssistanceResult: zgsAutocompleteRequest(query: $query, queryOptions: $queryOptions, resultType: $resultType, shouldRequestSpellCorrectedMetadata: $shouldRequestSpellCorrectedMetadata) { requestId results { __typename ... on SearchAssistanceAddressResult { id } } } }\",\n  \"variables\": { \"query\": \"3538 Trent St Charlotte NC\", \"resultType\": [\"REGIONS\",\"FORSALE\",\"RENTALS\",\"SOLD\",\"COMMUNITIES\",\"SCHOOLS\",\"SCHOOL_DISTRICTS\",\"SEMANTIC_REGIONS\",\"BUILDER_COMMUNITIES\"], \"shouldRequestSpellCorrectedMetadata\": false },\n  \"resultType\": [\"REGIONS\",\"FORSALE\",\"RENTALS\",\"SOLD\",\"COMMUNITIES\",\"SCHOOLS\",\"SCHOOL_DISTRICTS\",\"SEMANTIC_REGIONS\",\"BUILDER_COMMUNITIES\"],\n  \"shouldRequestSpellCorrectedMetadata\": false\n}\nJSON\nQS='query=3538%20Trent%20St%20Charlotte%20NC&resultType=REGIONS&resultType=FORSALE&resultType=RENTALS&resultType=SOLD&resultType=COMMUNITIES&resultType=SCHOOLS&resultType=SCHOOL_DISTRICTS&resultType=SEMANTIC_REGIONS&resultType=BUILDER_COMMUNITIES&shouldRequestSpellCorrectedMetadata=false&operationName=GetAutocompleteResults'\nfpx post-json \"https://www.zillow.com/zg-graph?${QS}\" @/tmp/ac.json -p zillow \\\n  -H 'origin: https://www.zillow.com' \\\n  -H 'referer: https://www.zillow.com/homes/for_sale/' \\\n  -H 'x-caller-id: static-search-page-graphql' \\\n  | jq -r '.data.searchAssistanceResult.results[] | select(.__typename==\"SearchAssistanceAddressResult\") | .id'\n```\n\nEach result `.id` is a full canonical address string (e.g.\n`\"3538 Trent St Charlotte, NC 28209\"`) — feed that string into §1's\nresolve step (`/homes/<that-string>_rb/`) to get the zpid. These three\nheaders are cookie-free by design — the bridge supplies the session\nambiently; don't add a `Cookie` header yourself.\n\n## 9. Healthcheck\n\n```sh\nfpx get 'https://www.zillow.com/robots.txt' -p zillow\n```\n\nA 200 with plain-text `robots.txt` content confirms the bridge, the\nextension, and a responsive zillow.com tab — the same probe\n`zillow_healthcheck` runs.\n\nFile v1.2.2:skill-card.md\n\n## Description:\n\nGuides agents in retrieving US Zillow listings, property details, market reports, and signed-in saved data through a browser-backed shell CLI.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and agents use this skill to search US property listings and inspect Zillow property, pricing, tax, photo, and market data without running the Zillow MCP server. Signed-in users can also retrieve their saved searches and homes.\n\n### Deployment Geography for Use:\n\nUnited States\n\n## Known Risks and Mitigations:\n\nRisk: The CLI and browser extension can access Zillow pages through the user's browser session.\n\nMitigation: Install and pair them only if you are comfortable granting that access; review the extension before use.\n\nRisk: Saved searches, saved homes, and exact-address queries can expose account or location data to local scripts and command output.\n\nMitigation: Run those examples only when needed, and avoid sharing captured outputs or temporary files containing sensitive data.\n\n## Reference(s):\n\n- [Zillow pages for fpx](references/pages.md)\n- [ClawHub skill release](https://clawhub.ai/chrischall/skills/zillow-fpx)\n- [ContextMint Bridge releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n\n## Skill Output:\n\n**Output Type(s):** [Shell commands, Code, Guidance]\n\n**Output Format:** [Markdown with shell and JSON examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Retrieved results may contain property addresses or signed-in saved-listing data.]\n\n## Skill Version(s):\n\n1.2.2 (source: server-resolved release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.2.1: 4 files, 8635 bytes\n\nFiles: references/pages.md (10041b), skill-card.md (2250b), SKILL.md (4854b), _meta.json (129b)\n\nFile v1.2.1:SKILL.md\n\n---\nname: zillow-fpx\ndescription: >-\n  Query zillow.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the zillow-mcp server — search\n  listings, pull a full property record by zpid, price/tax/Zestimate\n  history, photos, market reports, and your signed-in saved\n  searches/homes, all via one-shot HTTP calls through a signed-in browser\n  tab. Use when you want Zillow data without the MCP, in a script, or on\n  a machine where the MCP isn't installed.\n---\n\n# Zillow via fpx (no MCP)\n\nZillow fronts `www.zillow.com` with a PerimeterX bot-wall that blocks\nplain `curl`/Node requests, and several tools (saved searches/homes)\nneed an actual signed-in session. `fpx` routes every request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), so the\nsame page loads that a real visit would.\n\nThis is the same data the `zillow_*` MCP tools return — every property\ntool is a scrape of Zillow's server-rendered Next.js pages\n(`__NEXT_DATA__`), not a documented JSON API. No credentials are stored\nanywhere; auth (for the saved-data endpoints) is just \"have a signed-in\nzillow.com tab open.\"\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli             # provides `fpx`\nfpx profile add zillow --domain zillow.com # only the fetch capability is needed\nfpx pair -p zillow                         # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n([releases](https://github.com/nullnet-app/contextmint-bridge/releases)), with an\nopen `www.zillow.com` tab, and its Chrome **Site access** allowing\n`zillow.com`. (ContextMint Bridge is the renamed fetchproxy extension from the\nsame maintainer; build it from source or verify the release zip with\n`shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`.) For the saved-searches/saved-homes calls, that tab must\nalso be **signed in**. Pairing persists — after the first approval every\nlater `fpx` call reuses it.\n\n## Core call\n\nEvery endpoint here is a GET of a server-rendered HTML page (Zillow is a\nNext.js app; the whole page state is embedded as JSON in a\n`<script id=\"__NEXT_DATA__\">` tag) — there is no JSON API to hit\ndirectly. Fetch, then pull the JSON out of the HTML:\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow > /tmp/page.html\npython3 -c '\nimport re, sys, json\nhtml = open(\"/tmp/page.html\").read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n' | jq '.'\n```\n\n`references/pages.md` has the extractor as a reusable one-liner plus the\nper-page `pageProps` field paths (search results, property detail,\nphotos, price/tax/Zestimate history, saved searches/homes, market\nreport) and the address-autocomplete GraphQL call, all transcribed from\nthe MCP's `src/tools/*.ts` (which parse the exact same pages).\n\n## The one rule: resolve the location first (search only)\n\n`zillow_search_properties`'s two-step dance is exactly what\n`/homes/<slug>_rb/` needs: fetch the bare slug path first to get Zillow's\nresolved `regionSelection` + `mapBounds`, THEN re-fetch with those pinned\ninto a `searchQueryState` query param alongside your filters — a filtered\nfetch without the pinned region silently falls back to the user's last\nsearch region instead of honoring the slug. A full-address query can\nresolve straight to a `homedetails` page (no region at all) — see\n`references/pages.md` §1 for both shapes. Property lookups by `zpid`\nneed no resolve step — `/homedetails/<zpid>_zpid/` is direct.\n\n## Auth\n\nNo login is stored or passed by `fpx` — the saved-searches\n(`/myzillow/SavedSearches`) and saved-homes (`/myzillow/favorites`) pages\nsimply render your saved data (or redirect to `/user/login`) depending on\nwhether the tab riding the bridge is signed in. Everything else is\nanonymous.\n\n## Exit codes (fetch verbs)\n\n- `0` — success. A signed-out redirect (`/user/login`, `?login=true`) or\n  a captcha interstitial (body contains `captcha-delivery`, small body)\n  can still ride in a `0` response — check the fetched HTML, `fpx`\n  doesn't know Zillow's sign-in/bot-wall markers.\n- `2` — bridge unavailable: extension not connected or pairing pending →\n  run `fpx pair -p zillow`, confirm a zillow.com tab is open.\n- `3` — bot wall: the tab hasn't cleared PerimeterX → open/refresh a\n  `www.zillow.com` tab and retry.\n- `4` — upstream non-2xx from Zillow.\n\n## Notes\n\n- `fpx health -p zillow` shows bridge connection state when a call fails.\n- Zillow publishes no consumer API — these are the same private\n  server-rendered pages the zillow.com web app itself loads, reached\n  through your own signed-in tab.\n- This project is developed and maintained by AI (Claude).\n\nFile v1.2.1:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"zillow-fpx\",\n  \"version\": \"1.2.1\",\n  \"publishedAt\": 1791380401886\n}\n\nFile v1.2.1:references/pages.md\n\n# Zillow pages for fpx\n\nAll paths below are fetched with `fpx get 'https://www.zillow.com<path>' -p zillow`.\nEvery page is server-rendered Next.js — the data lives in\n`__NEXT_DATA__.props.pageProps`, never in a separate JSON API. Field\npaths below are transcribed from the MCP's parsers\n(`src/next-data.ts`, `src/tools/*.ts`) — live-verified there, not\nre-captured here.\n\n## 0. The extractor (reuse for every page below)\n\n```sh\nextract_page_props() {\n  python3 -c '\nimport re, sys, json\nhtml = sys.stdin.read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nif not m:\n    sys.exit(\"no __NEXT_DATA__ script tag found — likely a bot-wall or redirect page\")\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n'\n}\n\nfpx get 'https://www.zillow.com/robots.txt' -p zillow  # smoke test, no parsing needed\n```\n\nPipe any fetched HTML through `extract_page_props` to get the page's\n`pageProps` as one JSON line, then `jq` into it per the recipes below.\n\n## 1. Search listings\n\nTwo-step dance — **always resolve before filtering**:\n\n**Step 1 — resolve** (bare slug, no query string):\n\n```sh\nfpx get 'https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '.searchPageState.queryState.regionSelection, .searchPageState.queryState.mapBounds' /tmp/pp.json\n```\n\n- If `searchPageState` is present with a non-empty `regionSelection` +\n  `mapBounds` → you have a **region**; proceed to step 2.\n- If `searchPageState` is **absent** but `pageProps.gdpClientCache` (or\n  `pageProps.componentProps.gdpClientCache`) is present, Zillow resolved\n  the query straight to ONE property (a homedetails page) — see §2, no\n  step 2 needed.\n- If `searchPageState.queryState.regionSelection` is empty AND\n  `cat1.searchResults.listResults` is non-empty, Zillow returned\n  address/street-level listings directly with no region to pin — use\n  those listings as-is (issue #31 in the MCP).\n\n**Step 2 — filtered search** (region pinned + your filters), only when\nstep 1 gave you a region:\n\n```sh\nSQS='{\"usersSearchTerm\":\"Brooklyn, NY\",\"filterState\":{\"price\":{\"max\":900000},\"beds\":{\"min\":2}},\"isListVisible\":true,\"isMapVisible\":false,\"regionSelection\":[{\"regionId\":37607,\"regionType\":17}],\"mapBounds\":{\"north\":40.74,\"south\":40.57,\"east\":-73.83,\"west\":-74.05}}'\nENC=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$SQS\")\nfpx get \"https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/?searchQueryState=${ENC}\" -p zillow \\\n  | extract_page_props | jq '.searchPageState.cat1.searchResults.listResults[] | {zpid: .hdpData.homeInfo.zpid, price: .hdpData.homeInfo.price, address: .hdpData.homeInfo.streetAddress, beds: .hdpData.homeInfo.bedrooms, url: .detailUrl}'\n```\n\n`filterState` keys the MCP sets (mirror these in the JSON above):\n`isForRent`/`isForSaleByAgent`/etc `{value: true|false}` (status\nswitches), `price {min,max}`, `beds {min}`, `baths {min}`, one\n`{value:true}` flag per home type (`isSingleFamily`, `isCondo`,\n`isTownhouse`, `isMultiFamily`, `isManufactured`, `isLotLand`,\n`isApartment`), and `pagination: {currentPage: N}` for page > 1. Zillow\nreturns ~40 listings per page; increment `pagination.currentPage` and\nre-fetch to walk further pages (stop on an empty `listResults`).\n\nPagination example (page 2):\n\n```sh\nSQS='{...same as above..., \"pagination\":{\"currentPage\":2}}'\n```\n\n## 2. Property detail by zpid\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\n# gdpClientCache is a JSON-encoded STRING inside pageProps — parse twice.\njq -r '.gdpClientCache // .componentProps.gdpClientCache' /tmp/pp.json \\\n  | jq '[to_entries[] | select(.key | startswith(\"Property:\")) | select(.value.property) | .value.property][0]\n        // [to_entries[] | select(.value.property) | .value.property][0]'\n```\n\nThat gives the raw `property` object. Useful top-level fields: `zpid`,\n`hdpUrl`, `address {streetAddress,city,state,zipcode,neighborhood}`,\n`mlsStreetAddress` (canonical MLS address — may disagree with `address`,\nprefer it when present), `price`, `zestimate`, `rentZestimate`,\n`bedrooms`, `bathrooms`, `livingArea`, `lotSize` (sqft), `yearBuilt`,\n`homeType`, `homeStatus`, `description`, `latitude`/`longitude`,\n`daysOnZillow`, `taxAssessedValue`/`taxAssessedYear`,\n`taxAnnualAmount` (values < 10 are a not-yet-assessed sentinel, not a\nreal bill), `schools[]`, `resoFacts {yearBuilt, associationFee,\nassociationFeeFrequency, taxAnnualAmount}` (MLS fallback source),\n`priceHistory[]`, `taxHistory[]`.\n\nOnly a URL with a trailing `<zpid>_zpid/` resolves — a slug-only URL\nredirects to the generic search page (no `gdpClientCache`). If you only\nhave an address, resolve to a zpid via §1 or the autocomplete call in §7\nfirst.\n\n## 3. Price / tax history (same property object as §2)\n\n```sh\njq '.priceHistory' /tmp/property.json    # [{date, price, event, source, ...}]\njq '.taxHistory' /tmp/property.json      # [{time or year, value, taxIncreaseRate, ...}]\n```\n\nBoth arrays live inline on the property object fetched in §2 — no\nseparate request. Absent on some (commonly non-Showcase) listings —\nZillow renders the trend client-side for those.\n\n## 4. Zestimate history (same property object as §2)\n\n```sh\njq '(first(.homeValueChartData[] | select(.name==\"This home\")) // .homeValueChartData[0]) | .points' /tmp/property.json\n```\n\nEach point is `{x: <unix ms>, y: <value>}` or `{date, value}` depending\non deploy. Fall back to deriving a series from `priceHistory[].{date,price}`\nwhen `homeValueChartData` is absent. `rentValueChartData` is the parallel\nseries for `rent` when present.\n\n## 5. Photos (same property object as §2)\n\n```sh\njq '[.photos, .responsivePhotos, .originalPhotos] | map(select(type==\"array\" and length>0)) | first // []' /tmp/property.json\n```\n\nEach entry: `{caption, subjectType, url, mixedSources: {jpeg: [{url,width}], webp: [{url,width}]}}`.\nPick the widest `mixedSources.jpeg`/`webp` entry for the largest image;\n`url` alone is the hero/thumbnail. `streetViewImageUrl` and\n`hiResImageLink` sit at the top level of the property object too.\n\n## 6. Saved searches / saved homes (requires a signed-in tab)\n\n```sh\n# Saved searches — path is case-sensitive (capital S)\nfpx get 'https://www.zillow.com/myzillow/SavedSearches' -p zillow \\\n  | extract_page_props | jq '.savedSearches // .userSavedSearches'\n\n# Saved (favorited) homes — flattened across collections\nfpx get 'https://www.zillow.com/myzillow/favorites' -p zillow \\\n  | extract_page_props | jq '[.collectionsResponse[] | (.homes // .properties // .items // [])[]]'\n```\n\nA signed-out tab redirects to `/user/login` instead of rendering these —\ncheck the fetched HTML's final URL / body before trusting an empty\nresult as \"no saves.\"\n\n## 7. Market report for a region\n\n```sh\nfpx get 'https://www.zillow.com/home-values/6181/brooklyn-ny/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '{region: .zhviRegion, analytics: .odpMarketAnalytics}' /tmp/pp.json\n```\n\n`zhviRegion {name, regionTypeName, parentCounty.name, parentState.name}`;\n`odpMarketAnalytics.mrktListingLatest {newListings, forSaleInventory,\nmedianListPrice, medianDaysOnMarket}`; `.mrktSaleLatest\n{medianSalePrice, daysToPending}`; `.zhviLatest {zhvi, zhviYoY,\nasOfDate}` (`zhviYoY` is a fraction — multiply by 100 for a percent).\nThe region id/slug (e.g. `6181/brooklyn-ny`) comes from a Zillow\nhome-values URL; there's no separate region-lookup endpoint documented\nin the MCP.\n\n## 8. Address autocomplete (bonus — resolving a free-text address to a zpid)\n\nZillow's own address typeahead, used internally by the MCP's\n`zillow_get_by_address` resolver ladder before it falls back to §1's\nsearch. Inline GraphQL (no persisted-query hash), POST:\n\n```sh\ncat > /tmp/ac.json <<'JSON'\n{\n  \"operationName\": \"GetAutocompleteResults\",\n  \"query\": \"query GetAutocompleteResults($query: String!, $queryOptions: SearchAssistanceQueryOptions, $resultType: [SearchAssistanceResultType], $shouldRequestSpellCorrectedMetadata: Boolean = false) { searchAssistanceResult: zgsAutocompleteRequest(query: $query, queryOptions: $queryOptions, resultType: $resultType, shouldRequestSpellCorrectedMetadata: $shouldRequestSpellCorrectedMetadata) { requestId results { __typename ... on SearchAssistanceAddressResult { id } } } }\",\n  \"variables\": { \"query\": \"3538 Trent St Charlotte NC\", \"resultType\": [\"REGIONS\",\"FORSALE\",\"RENTALS\",\"SOLD\",\"COMMUNITIES\",\"SCHOOLS\",\"SCHOOL_DISTRICTS\",\"SEMANTIC_REGIONS\",\"BUILDER_COMMUNITIES\"], \"shouldRequestSpellCorrectedMetadata\": false },\n  \"resultType\": [\"REGIONS\",\"FORSALE\",\"RENTALS\",\"SOLD\",\"COMMUNITIES\",\"SCHOOLS\",\"SCHOOL_DISTRICTS\",\"SEMANTIC_REGIONS\",\"BUILDER_COMMUNITIES\"],\n  \"shouldRequestSpellCorrectedMetadata\": false\n}\nJSON\nQS='query=3538%20Trent%20St%20Charlotte%20NC&resultType=REGIONS&resultType=FORSALE&resultType=RENTALS&resultType=SOLD&resultType=COMMUNITIES&resultType=SCHOOLS&resultType=SCHOOL_DISTRICTS&resultType=SEMANTIC_REGIONS&resultType=BUILDER_COMMUNITIES&shouldRequestSpellCorrectedMetadata=false&operationName=GetAutocompleteResults'\nfpx post-json \"https://www.zillow.com/zg-graph?${QS}\" @/tmp/ac.json -p zillow \\\n  -H 'origin: https://www.zillow.com' \\\n  -H 'referer: https://www.zillow.com/homes/for_sale/' \\\n  -H 'x-caller-id: static-search-page-graphql' \\\n  | jq -r '.data.searchAssistanceResult.results[] | select(.__typename==\"SearchAssistanceAddressResult\") | .id'\n```\n\nEach result `.id` is a full canonical address string (e.g.\n`\"3538 Trent St Charlotte, NC 28209\"`) — feed that string into §1's\nresolve step (`/homes/<that-string>_rb/`) to get the zpid. These three\nheaders are cookie-free by design — the bridge supplies the session\nambiently; don't add a `Cookie` header yourself.\n\n## 9. Healthcheck\n\n```sh\nfpx get 'https://www.zillow.com/robots.txt' -p zillow\n```\n\nA 200 with plain-text `robots.txt` content confirms the bridge, the\nextension, and a responsive zillow.com tab — the same probe\n`zillow_healthcheck` runs.\n\nFile v1.2.1:skill-card.md\n\n## Description:\n\nHelps agents query Zillow listings, property details, market reports, and optionally saved homes and searches through the user's browser session using fpx.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and agents use this skill to search US Zillow listings and retrieve property, price history, photo, and market information without the Zillow MCP server. With an intentionally signed-in browser tab, they can also retrieve their saved searches and homes.\n\n### Deployment Geography for Use:\n\nUnited States\n\n## Known Risks and Mitigations:\n\nRisk: The browser bridge and fpx can access Zillow pages through the user's browser session.\n\nMitigation: Install and pair them only if comfortable granting access to zillow.com; review the extension and its site access before use.\n\nRisk: Saved-search and saved-home requests can disclose private Zillow data to the agent.\n\nMitigation: Use those requests only when intentionally sharing saved data; remove temporary files that contain sensitive addresses.\n\nRisk: A successful fetch may return a sign-in redirect or bot challenge instead of property data.\n\nMitigation: Check the fetched page for login or challenge markers before using extracted results.\n\n## Reference(s):\n\n- [zillow-fpx ClawHub release](https://clawhub.ai/chrischall/skills/zillow-fpx)\n- [Zillow page recipes](references/pages.md)\n- [ContextMint Bridge releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Shell commands, Configuration guidance]\n\n**Output Format:** [Markdown with shell snippets and JSON extraction examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Property and saved-data results depend on Zillow page availability and the user's browser session.]\n\n## Skill Version(s):\n\n1.2.1 (source: ClawHub release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.2.0: 4 files, 8572 bytes\n\nFiles: references/pages.md (10041b), skill-card.md (2112b), SKILL.md (4854b), _meta.json (129b)\n\nFile v1.2.0:SKILL.md\n\n---\nname: zillow-fpx\ndescription: >-\n  Query zillow.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the zillow-mcp server — search\n  listings, pull a full property record by zpid, price/tax/Zestimate\n  history, photos, market reports, and your signed-in saved\n  searches/homes, all via one-shot HTTP calls through a signed-in browser\n  tab. Use when you want Zillow data without the MCP, in a script, or on\n  a machine where the MCP isn't installed.\n---\n\n# Zillow via fpx (no MCP)\n\nZillow fronts `www.zillow.com` with a PerimeterX bot-wall that blocks\nplain `curl`/Node requests, and several tools (saved searches/homes)\nneed an actual signed-in session. `fpx` routes every request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), so the\nsame page loads that a real visit would.\n\nThis is the same data the `zillow_*` MCP tools return — every property\ntool is a scrape of Zillow's server-rendered Next.js pages\n(`__NEXT_DATA__`), not a documented JSON API. No credentials are stored\nanywhere; auth (for the saved-data endpoints) is just \"have a signed-in\nzillow.com tab open.\"\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli             # provides `fpx`\nfpx profile add zillow --domain zillow.com # only the fetch capability is needed\nfpx pair -p zillow                         # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n([releases](https://github.com/nullnet-app/contextmint-bridge/releases)), with an\nopen `www.zillow.com` tab, and its Chrome **Site access** allowing\n`zillow.com`. (ContextMint Bridge is the renamed fetchproxy extension from the\nsame maintainer; build it from source or verify the release zip with\n`shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`.) For the saved-searches/saved-homes calls, that tab must\nalso be **signed in**. Pairing persists — after the first approval every\nlater `fpx` call reuses it.\n\n## Core call\n\nEvery endpoint here is a GET of a server-rendered HTML page (Zillow is a\nNext.js app; the whole page state is embedded as JSON in a\n`<script id=\"__NEXT_DATA__\">` tag) — there is no JSON API to hit\ndirectly. Fetch, then pull the JSON out of the HTML:\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow > /tmp/page.html\npython3 -c '\nimport re, sys, json\nhtml = open(\"/tmp/page.html\").read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n' | jq '.'\n```\n\n`references/pages.md` has the extractor as a reusable one-liner plus the\nper-page `pageProps` field paths (search results, property detail,\nphotos, price/tax/Zestimate history, saved searches/homes, market\nreport) and the address-autocomplete GraphQL call, all transcribed from\nthe MCP's `src/tools/*.ts` (which parse the exact same pages).\n\n## The one rule: resolve the location first (search only)\n\n`zillow_search_properties`'s two-step dance is exactly what\n`/homes/<slug>_rb/` needs: fetch the bare slug path first to get Zillow's\nresolved `regionSelection` + `mapBounds`, THEN re-fetch with those pinned\ninto a `searchQueryState` query param alongside your filters — a filtered\nfetch without the pinned region silently falls back to the user's last\nsearch region instead of honoring the slug. A full-address query can\nresolve straight to a `homedetails` page (no region at all) — see\n`references/pages.md` §1 for both shapes. Property lookups by `zpid`\nneed no resolve step — `/homedetails/<zpid>_zpid/` is direct.\n\n## Auth\n\nNo login is stored or passed by `fpx` — the saved-searches\n(`/myzillow/SavedSearches`) and saved-homes (`/myzillow/favorites`) pages\nsimply render your saved data (or redirect to `/user/login`) depending on\nwhether the tab riding the bridge is signed in. Everything else is\nanonymous.\n\n## Exit codes (fetch verbs)\n\n- `0` — success. A signed-out redirect (`/user/login`, `?login=true`) or\n  a captcha interstitial (body contains `captcha-delivery`, small body)\n  can still ride in a `0` response — check the fetched HTML, `fpx`\n  doesn't know Zillow's sign-in/bot-wall markers.\n- `2` — bridge unavailable: extension not connected or pairing pending →\n  run `fpx pair -p zillow`, confirm a zillow.com tab is open.\n- `3` — bot wall: the tab hasn't cleared PerimeterX → open/refresh a\n  `www.zillow.com` tab and retry.\n- `4` — upstream non-2xx from Zillow.\n\n## Notes\n\n- `fpx health -p zillow` shows bridge connection state when a call fails.\n- Zillow publishes no consumer API — these are the same private\n  server-rendered pages the zillow.com web app itself loads, reached\n  through your own signed-in tab.\n- This project is developed and maintained by AI (Claude).\n\nFile v1.2.0:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"zillow-fpx\",\n  \"version\": \"1.2.0\",\n  \"publishedAt\": 1791293027473\n}\n\nFile v1.2.0:references/pages.md\n\n# Zillow pages for fpx\n\nAll paths below are fetched with `fpx get 'https://www.zillow.com<path>' -p zillow`.\nEvery page is server-rendered Next.js — the data lives in\n`__NEXT_DATA__.props.pageProps`, never in a separate JSON API. Field\npaths below are transcribed from the MCP's parsers\n(`src/next-data.ts`, `src/tools/*.ts`) — live-verified there, not\nre-captured here.\n\n## 0. The extractor (reuse for every page below)\n\n```sh\nextract_page_props() {\n  python3 -c '\nimport re, sys, json\nhtml = sys.stdin.read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nif not m:\n    sys.exit(\"no __NEXT_DATA__ script tag found — likely a bot-wall or redirect page\")\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n'\n}\n\nfpx get 'https://www.zillow.com/robots.txt' -p zillow  # smoke test, no parsing needed\n```\n\nPipe any fetched HTML through `extract_page_props` to get the page's\n`pageProps` as one JSON line, then `jq` into it per the recipes below.\n\n## 1. Search listings\n\nTwo-step dance — **always resolve before filtering**:\n\n**Step 1 — resolve** (bare slug, no query string):\n\n```sh\nfpx get 'https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '.searchPageState.queryState.regionSelection, .searchPageState.queryState.mapBounds' /tmp/pp.json\n```\n\n- If `searchPageState` is present with a non-empty `regionSelection` +\n  `mapBounds` → you have a **region**; proceed to step 2.\n- If `searchPageState` is **absent** but `pageProps.gdpClientCache` (or\n  `pageProps.componentProps.gdpClientCache`) is present, Zillow resolved\n  the query straight to ONE property (a homedetails page) — see §2, no\n  step 2 needed.\n- If `searchPageState.queryState.regionSelection` is empty AND\n  `cat1.searchResults.listResults` is non-empty, Zillow returned\n  address/street-level listings directly with no region to pin — use\n  those listings as-is (issue #31 in the MCP).\n\n**Step 2 — filtered search** (region pinned + your filters), only when\nstep 1 gave you a region:\n\n```sh\nSQS='{\"usersSearchTerm\":\"Brooklyn, NY\",\"filterState\":{\"price\":{\"max\":900000},\"beds\":{\"min\":2}},\"isListVisible\":true,\"isMapVisible\":false,\"regionSelection\":[{\"regionId\":37607,\"regionType\":17}],\"mapBounds\":{\"north\":40.74,\"south\":40.57,\"east\":-73.83,\"west\":-74.05}}'\nENC=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$SQS\")\nfpx get \"https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/?searchQueryState=${ENC}\" -p zillow \\\n  | extract_page_props | jq '.searchPageState.cat1.searchResults.listResults[] | {zpid: .hdpData.homeInfo.zpid, price: .hdpData.homeInfo.price, address: .hdpData.homeInfo.streetAddress, beds: .hdpData.homeInfo.bedrooms, url: .detailUrl}'\n```\n\n`filterState` keys the MCP sets (mirror these in the JSON above):\n`isForRent`/`isForSaleByAgent`/etc `{value: true|false}` (status\nswitches), `price {min,max}`, `beds {min}`, `baths {min}`, one\n`{value:true}` flag per home type (`isSingleFamily`, `isCondo`,\n`isTownhouse`, `isMultiFamily`, `isManufactured`, `isLotLand`,\n`isApartment`), and `pagination: {currentPage: N}` for page > 1. Zillow\nreturns ~40 listings per page; increment `pagination.currentPage` and\nre-fetch to walk further pages (stop on an empty `listResults`).\n\nPagination example (page 2):\n\n```sh\nSQS='{...same as above..., \"pagination\":{\"currentPage\":2}}'\n```\n\n## 2. Property detail by zpid\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\n# gdpClientCache is a JSON-encoded STRING inside pageProps — parse twice.\njq -r '.gdpClientCache // .componentProps.gdpClientCache' /tmp/pp.json \\\n  | jq '[to_entries[] | select(.key | startswith(\"Property:\")) | select(.value.property) | .value.property][0]\n        // [to_entries[] | select(.value.property) | .value.property][0]'\n```\n\nThat gives the raw `property` object. Useful top-level fields: `zpid`,\n`hdpUrl`, `address {streetAddress,city,state,zipcode,neighborhood}`,\n`mlsStreetAddress` (canonical MLS address — may disagree with `address`,\nprefer it when present), `price`, `zestimate`, `rentZestimate`,\n`bedrooms`, `bathrooms`, `livingArea`, `lotSize` (sqft), `yearBuilt`,\n`homeType`, `homeStatus`, `description`, `latitude`/`longitude`,\n`daysOnZillow`, `taxAssessedValue`/`taxAssessedYear`,\n`taxAnnualAmount` (values < 10 are a not-yet-assessed sentinel, not a\nreal bill), `schools[]`, `resoFacts {yearBuilt, associationFee,\nassociationFeeFrequency, taxAnnualAmount}` (MLS fallback source),\n`priceHistory[]`, `taxHistory[]`.\n\nOnly a URL with a trailing `<zpid>_zpid/` resolves — a slug-only URL\nredirects to the generic search page (no `gdpClientCache`). If you only\nhave an address, resolve to a zpid via §1 or the autocomplete call in §7\nfirst.\n\n## 3. Price / tax history (same property object as §2)\n\n```sh\njq '.priceHistory' /tmp/property.json    # [{date, price, event, source, ...}]\njq '.taxHistory' /tmp/property.json      # [{time or year, value, taxIncreaseRate, ...}]\n```\n\nBoth arrays live inline on the property object fetched in §2 — no\nseparate request. Absent on some (commonly non-Showcase) listings —\nZillow renders the trend client-side for those.\n\n## 4. Zestimate history (same property object as §2)\n\n```sh\njq '(first(.homeValueChartData[] | select(.name==\"This home\")) // .homeValueChartData[0]) | .points' /tmp/property.json\n```\n\nEach point is `{x: <unix ms>, y: <value>}` or `{date, value}` depending\non deploy. Fall back to deriving a series from `priceHistory[].{date,price}`\nwhen `homeValueChartData` is absent. `rentValueChartData` is the parallel\nseries for `rent` when present.\n\n## 5. Photos (same property object as §2)\n\n```sh\njq '[.photos, .responsivePhotos, .originalPhotos] | map(select(type==\"array\" and length>0)) | first // []' /tmp/property.json\n```\n\nEach entry: `{caption, subjectType, url, mixedSources: {jpeg: [{url,width}], webp: [{url,width}]}}`.\nPick the widest `mixedSources.jpeg`/`webp` entry for the largest image;\n`url` alone is the hero/thumbnail. `streetViewImageUrl` and\n`hiResImageLink` sit at the top level of the property object too.\n\n## 6. Saved searches / saved homes (requires a signed-in tab)\n\n```sh\n# Saved searches — path is case-sensitive (capital S)\nfpx get 'https://www.zillow.com/myzillow/SavedSearches' -p zillow \\\n  | extract_page_props | jq '.savedSearches // .userSavedSearches'\n\n# Saved (favorited) homes — flattened across collections\nfpx get 'https://www.zillow.com/myzillow/favorites' -p zillow \\\n  | extract_page_props | jq '[.collectionsResponse[] | (.homes // .properties // .items // [])[]]'\n```\n\nA signed-out tab redirects to `/user/login` instead of rendering these —\ncheck the fetched HTML's final URL / body before trusting an empty\nresult as \"no saves.\"\n\n## 7. Market report for a region\n\n```sh\nfpx get 'https://www.zillow.com/home-values/6181/brooklyn-ny/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '{region: .zhviRegion, analytics: .odpMarketAnalytics}' /tmp/pp.json\n```\n\n`zhviRegion {name, regionTypeName, parentCounty.name, parentState.name}`;\n`odpMarketAnalytics.mrktListingLatest {newListings, forSaleInventory,\nmedianListPrice, medianDaysOnMarket}`; `.mrktSaleLatest\n{medianSalePrice, daysToPending}`; `.zhviLatest {zhvi, zhviYoY,\nasOfDate}` (`zhviYoY` is a fraction — multiply by 100 for a percent).\nThe region id/slug (e.g. `6181/brooklyn-ny`) comes from a Zillow\nhome-values URL; there's no separate region-lookup endpoint documented\nin the MCP.\n\n## 8. Address autocomplete (bonus — resolving a free-text address to a zpid)\n\nZillow's own address typeahead, used internally by the MCP's\n`zillow_get_by_address` resolver ladder before it falls back to §1's\nsearch. Inline GraphQL (no persisted-query hash), POST:\n\n```sh\ncat > /tmp/ac.json <<'JSON'\n{\n  \"operationName\": \"GetAutocompleteResults\",\n  \"query\": \"query GetAutocompleteResults($query: String!, $queryOptions: SearchAssistanceQueryOptions, $resultType: [SearchAssistanceResultType], $shouldRequestSpellCorrectedMetadata: Boolean = false) { searchAssistanceResult: zgsAutocompleteRequest(query: $query, queryOptions: $queryOptions, resultType: $resultType, shouldRequestSpellCorrectedMetadata: $shouldRequestSpellCorrectedMetadata) { requestId results { __typename ... on SearchAssistanceAddressResult { id } } } }\",\n  \"variables\": { \"query\": \"3538 Trent St Charlotte NC\", \"resultType\": [\"REGIONS\",\"FORSALE\",\"RENTALS\",\"SOLD\",\"COMMUNITIES\",\"SCHOOLS\",\"SCHOOL_DISTRICTS\",\"SEMANTIC_REGIONS\",\"BUILDER_COMMUNITIES\"], \"shouldRequestSpellCorrectedMetadata\": false },\n  \"resultType\": [\"REGIONS\",\"FORSALE\",\"RENTALS\",\"SOLD\",\"COMMUNITIES\",\"SCHOOLS\",\"SCHOOL_DISTRICTS\",\"SEMANTIC_REGIONS\",\"BUILDER_COMMUNITIES\"],\n  \"shouldRequestSpellCorrectedMetadata\": false\n}\nJSON\nQS='query=3538%20Trent%20St%20Charlotte%20NC&resultType=REGIONS&resultType=FORSALE&resultType=RENTALS&resultType=SOLD&resultType=COMMUNITIES&resultType=SCHOOLS&resultType=SCHOOL_DISTRICTS&resultType=SEMANTIC_REGIONS&resultType=BUILDER_COMMUNITIES&shouldRequestSpellCorrectedMetadata=false&operationName=GetAutocompleteResults'\nfpx post-json \"https://www.zillow.com/zg-graph?${QS}\" @/tmp/ac.json -p zillow \\\n  -H 'origin: https://www.zillow.com' \\\n  -H 'referer: https://www.zillow.com/homes/for_sale/' \\\n  -H 'x-caller-id: static-search-page-graphql' \\\n  | jq -r '.data.searchAssistanceResult.results[] | select(.__typename==\"SearchAssistanceAddressResult\") | .id'\n```\n\nEach result `.id` is a full canonical address string (e.g.\n`\"3538 Trent St Charlotte, NC 28209\"`) — feed that string into §1's\nresolve step (`/homes/<that-string>_rb/`) to get the zpid. These three\nheaders are cookie-free by design — the bridge supplies the session\nambiently; don't add a `Cookie` header yourself.\n\n## 9. Healthcheck\n\n```sh\nfpx get 'https://www.zillow.com/robots.txt' -p zillow\n```\n\nA 200 with plain-text `robots.txt` content confirms the bridge, the\nextension, and a responsive zillow.com tab — the same probe\n`zillow_healthcheck` runs.\n\nFile v1.2.0:skill-card.md\n\n## Description:\n\nHelps agents search U.S. Zillow listings, inspect properties and market data, and access saved searches or homes through a browser-connected command-line tool.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and other Zillow users can guide an agent to find U.S. property listings, retrieve property details and market reports, or view their own saved searches and homes without a Zillow MCP server.\n\n### Deployment Geography for Use:\n\nGlobal (U.S. real-estate data)\n\n## Known Risks and Mitigations:\n\nRisk: Browser-connected requests can access Zillow data available in the user's signed-in tab, including saved searches and homes.\n\nMitigation: Use a signed-in Zillow tab only when saved data is intentionally needed, and approve browser pairing deliberately.\n\nRisk: Address autocomplete sends the entered address to Zillow.\n\nMitigation: Enter addresses only when sharing them with Zillow is acceptable.\n\nRisk: A successful fetch can still return a sign-in redirect or bot-check page instead of property data.\n\nMitigation: Check the returned page before extracting or relying on its results.\n\n## Reference(s):\n\n- [Zillow page recipes](references/pages.md)\n- [ContextMint Bridge extension releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n- [ClawHub skill release](https://clawhub.ai/chrischall/skills/zillow-fpx)\n\n## Skill Output:\n\n**Output Type(s):** [Guidance, Shell commands, Code]\n\n**Output Format:** [Markdown with shell and data-extraction examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Can guide retrieval of listing, property, market, and user-saved data from Zillow.]\n\n## Skill Version(s):\n\n1.2.0 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.1.8: 4 files, 8455 bytes\n\nFiles: references/pages.md (10041b), skill-card.md (1806b), SKILL.md (4854b), _meta.json (129b)\n\nFile v1.1.8:SKILL.md\n\n---\nname: zillow-fpx\ndescription: >-\n  Query zillow.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the zillow-mcp server — search\n  listings, pull a full property record by zpid, price/tax/Zestimate\n  history, photos, market reports, and your signed-in saved\n  searches/homes, all via one-shot HTTP calls through a signed-in browser\n  tab. Use when you want Zillow data without the MCP, in a script, or on\n  a machine where the MCP isn't installed.\n---\n\n# Zillow via fpx (no MCP)\n\nZillow fronts `www.zillow.com` with a PerimeterX bot-wall that blocks\nplain `curl`/Node requests, and several tools (saved searches/homes)\nneed an actual signed-in session. `fpx` routes every request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), so the\nsame page loads that a real visit would.\n\nThis is the same data the `zillow_*` MCP tools return — every property\ntool is a scrape of Zillow's server-rendered Next.js pages\n(`__NEXT_DATA__`), not a documented JSON API. No credentials are stored\nanywhere; auth (for the saved-data endpoints) is just \"have a signed-in\nzillow.com tab open.\"\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli             # provides `fpx`\nfpx profile add zillow --domain zillow.com # only the fetch capability is needed\nfpx pair -p zillow                         # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n([releases](https://github.com/nullnet-app/contextmint-bridge/releases)), with an\nopen `www.zillow.com` tab, and its Chrome **Site access** allowing\n`zillow.com`. (ContextMint Bridge is the renamed fetchproxy extension from the\nsame maintainer; build it from source or verify the release zip with\n`shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`.) For the saved-searches/saved-homes calls, that tab must\nalso be **signed in**. Pairing persists — after the first approval every\nlater `fpx` call reuses it.\n\n## Core call\n\nEvery endpoint here is a GET of a server-rendered HTML page (Zillow is a\nNext.js app; the whole page state is embedded as JSON in a\n`<script id=\"__NEXT_DATA__\">` tag) — there is no JSON API to hit\ndirectly. Fetch, then pull the JSON out of the HTML:\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow > /tmp/page.html\npython3 -c '\nimport re, sys, json\nhtml = open(\"/tmp/page.html\").read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n' | jq '.'\n```\n\n`references/pages.md` has the extractor as a reusable one-liner plus the\nper-page `pageProps` field paths (search results, property detail,\nphotos, price/tax/Zestimate history, saved searches/homes, market\nreport) and the address-autocomplete GraphQL call, all transcribed from\nthe MCP's `src/tools/*.ts` (which parse the exact same pages).\n\n## The one rule: resolve the location first (search only)\n\n`zillow_search_properties`'s two-step dance is exactly what\n`/homes/<slug>_rb/` needs: fetch the bare slug path first to get Zillow's\nresolved `regionSelection` + `mapBounds`, THEN re-fetch with those pinned\ninto a `searchQueryState` query param alongside your filters — a filtered\nfetch without the pinned region silently falls back to the user's last\nsearch region instead of honoring the slug. A full-address query can\nresolve straight to a `homedetails` page (no region at all) — see\n`references/pages.md` §1 for both shapes. Property lookups by `zpid`\nneed no resolve step — `/homedetails/<zpid>_zpid/` is direct.\n\n## Auth\n\nNo login is stored or passed by `fpx` — the saved-searches\n(`/myzillow/SavedSearches`) and saved-homes (`/myzillow/favorites`) pages\nsimply render your saved data (or redirect to `/user/login`) depending on\nwhether the tab riding the bridge is signed in. Everything else is\nanonymous.\n\n## Exit codes (fetch verbs)\n\n- `0` — success. A signed-out redirect (`/user/login`, `?login=true`) or\n  a captcha interstitial (body contains `captcha-delivery`, small body)\n  can still ride in a `0` response — check the fetched HTML, `fpx`\n  doesn't know Zillow's sign-in/bot-wall markers.\n- `2` — bridge unavailable: extension not connected or pairing pending →\n  run `fpx pair -p zillow`, confirm a zillow.com tab is open.\n- `3` — bot wall: the tab hasn't cleared PerimeterX → open/refresh a\n  `www.zillow.com` tab and retry.\n- `4` — upstream non-2xx from Zillow.\n\n## Notes\n\n- `fpx health -p zillow` shows bridge connection state when a call fails.\n- Zillow publishes no consumer API — these are the same private\n  server-rendered pages the zillow.com web app itself loads, reached\n  through your own signed-in tab.\n- This project is developed and maintained by AI (Claude).\n\nFile v1.1.8:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"zillow-fpx\",\n  \"version\": \"1.1.8\",\n  \"publishedAt\": 1791220104387\n}\n\nFile v1.1.8:references/pages.md\n\n# Zillow pages for fpx\n\nAll paths below are fetched with `fpx get 'https://www.zillow.com<path>' -p zillow`.\nEvery page is server-rendered Next.js — the data lives in\n`__NEXT_DATA__.props.pageProps`, never in a separate JSON API. Field\npaths below are transcribed from the MCP's parsers\n(`src/next-data.ts`, `src/tools/*.ts`) — live-verified there, not\nre-captured here.\n\n## 0. The extractor (reuse for every page below)\n\n```sh\nextract_page_props() {\n  python3 -c '\nimport re, sys, json\nhtml = sys.stdin.read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nif not m:\n    sys.exit(\"no __NEXT_DATA__ script tag found — likely a bot-wall or redirect page\")\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n'\n}\n\nfpx get 'https://www.zillow.com/robots.txt' -p zillow  # smoke test, no parsing needed\n```\n\nPipe any fetched HTML through `extract_page_props` to get the page's\n`pageProps` as one JSON line, then `jq` into it per the recipes below.\n\n## 1. Search listings\n\nTwo-step dance — **always resolve before filtering**:\n\n**Step 1 — resolve** (bare slug, no query string):\n\n```sh\nfpx get 'https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '.searchPageState.queryState.regionSelection, .searchPageState.queryState.mapBounds' /tmp/pp.json\n```\n\n- If `searchPageState` is present with a non-empty `regionSelection` +\n  `mapBounds` → you have a **region**; proceed to step 2.\n- If `searchPageState` is **absent** but `pageProps.gdpClientCache` (or\n  `pageProps.componentProps.gdpClientCache`) is present, Zillow resolved\n  the query straight to ONE property (a homedetails page) — see §2, no\n  step 2 needed.\n- If `searchPageState.queryState.regionSelection` is empty AND\n  `cat1.searchResults.listResults` is non-empty, Zillow returned\n  address/street-level listings directly with no region to pin — use\n  those listings as-is (issue #31 in the MCP).\n\n**Step 2 — filtered search** (region pinned + your filters), only when\nstep 1 gave you a region:\n\n```sh\nSQS='{\"usersSearchTerm\":\"Brooklyn, NY\",\"filterState\":{\"price\":{\"max\":900000},\"beds\":{\"min\":2}},\"isListVisible\":true,\"isMapVisible\":false,\"regionSelection\":[{\"regionId\":37607,\"regionType\":17}],\"mapBounds\":{\"north\":40.74,\"south\":40.57,\"east\":-73.83,\"west\":-74.05}}'\nENC=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$SQS\")\nfpx get \"https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/?searchQueryState=${ENC}\" -p zillow \\\n  | extract_page_props | jq '.searchPageState.cat1.searchResults.listResults[] | {zpid: .hdpData.homeInfo.zpid, price: .hdpData.homeInfo.price, address: .hdpData.homeInfo.streetAddress, beds: .hdpData.homeInfo.bedrooms, url: .detailUrl}'\n```\n\n`filterState` keys the MCP sets (mirror these in the JSON above):\n`isForRent`/`isForSaleByAgent`/etc `{value: true|false}` (status\nswitches), `price {min,max}`, `beds {min}`, `baths {min}`, one\n`{value:true}` flag per home type (`isSingleFamily`, `isCondo`,\n`isTownhouse`, `isMultiFamily`, `isManufactured`, `isLotLand`,\n`isApartment`), and `pagination: {currentPage: N}` for page > 1. Zillow\nreturns ~40 listings per page; increment `pagination.currentPage` and\nre-fetch to walk further pages (stop on an empty `listResults`).\n\nPagination example (page 2):\n\n```sh\nSQS='{...same as above..., \"pagination\":{\"currentPage\":2}}'\n```\n\n## 2. Property detail by zpid\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\n# gdpClientCache is a JSON-encoded STRING inside pageProps — parse twice.\njq -r '.gdpClientCache // .componentProps.gdpClientCache' /tmp/pp.json \\\n  | jq '[to_entries[] | select(.key | startswith(\"Property:\")) | select(.value.property) | .value.property][0]\n        // [to_entries[] | select(.value.property) | .value.property][0]'\n```\n\nThat gives the raw `property` object. Useful top-level fields: `zpid`,\n`hdpUrl`, `address {streetAddress,city,state,zipcode,neighborhood}`,\n`mlsStreetAddress` (canonical MLS address — may disagree with `address`,\nprefer it when present), `price`, `zestimate`, `rentZestimate`,\n`bedrooms`, `bathrooms`, `livingArea`, `lotSize` (sqft), `yearBuilt`,\n`homeType`, `homeStatus`, `description`, `latitude`/`longitude`,\n`daysOnZillow`, `taxAssessedValue`/`taxAssessedYear`,\n`taxAnnualAmount` (values < 10 are a not-yet-assessed sentinel, not a\nreal bill), `schools[]`, `resoFacts {yearBuilt, associationFee,\nassociationFeeFrequency, taxAnnualAmount}` (MLS fallback source),\n`priceHistory[]`, `taxHistory[]`.\n\nOnly a URL with a trailing `<zpid>_zpid/` resolves — a slug-only URL\nredirects to the generic search page (no `gdpClientCache`). If you only\nhave an address, resolve to a zpid via §1 or the autocomplete call in §7\nfirst.\n\n## 3. Price / tax history (same property object as §2)\n\n```sh\njq '.priceHistory' /tmp/property.json    # [{date, price, event, source, ...}]\njq '.taxHistory' /tmp/property.json      # [{time or year, value, taxIncreaseRate, ...}]\n```\n\nBoth arrays live inline on the property object fetched in §2 — no\nseparate request. Absent on some (commonly non-Showcase) listings —\nZillow renders the trend client-side for those.\n\n## 4. Zestimate history (same property object as §2)\n\n```sh\njq '(first(.homeValueChartData[] | select(.name==\"This home\")) // .homeValueChartData[0]) | .points' /tmp/property.json\n```\n\nEach point is `{x: <unix ms>, y: <value>}` or `{date, value}` depending\non deploy. Fall back to deriving a series from `priceHistory[].{date,price}`\nwhen `homeValueChartData` is absent. `rentValueChartData` is the parallel\nseries for `rent` when present.\n\n## 5. Photos (same property object as §2)\n\n```sh\njq '[.photos, .responsivePhotos, .originalPhotos] | map(select(type==\"array\" and length>0)) | first // []' /tmp/property.json\n```\n\nEach entry: `{caption, subjectType, url, mixedSources: {jpeg: [{url,width}], webp: [{url,width}]}}`.\nPick the widest `mixedSources.jpeg`/`webp` entry for the largest image;\n`url` alone is the hero/thumbnail. `streetViewImageUrl` and\n`hiResImageLink` sit at the top level of the property object too.\n\n## 6. Saved searches / saved homes (requires a signed-in tab)\n\n```sh\n# Saved searches — path is case-sensitive (capital S)\nfpx get 'https://www.zillow.com/myzillow/SavedSearches' -p zillow \\\n  | extract_page_props | jq '.savedSearches // .userSavedSearches'\n\n# Saved (favorited) homes — flattened across collections\nfpx get 'https://www.zillow.com/myzillow/favorites' -p zillow \\\n  | extract_page_props | jq '[.collectionsResponse[] | (.homes // .properties // .items // [])[]]'\n```\n\nA signed-out tab redirects to `/user/login` instead of rendering these —\ncheck the fetched HTML's final URL / body before trusting an empty\nresult as \"no saves.\"\n\n## 7. Market report for a region\n\n```sh\nfpx get 'https://www.zillow.com/home-values/6181/brooklyn-ny/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '{region: .zhviRegion, analytics: .odpMarketAnalytics}' /tmp/pp.json\n```\n\n`zhviRegion {name, regionTypeName, parentCounty.name, parentState.name}`;\n`odpMarketAnalytics.mrktListingLatest {newListings, forSaleInventory,\nmedianListPrice, medianDaysOnMarket}`; `.mrktSaleLatest\n{medianSalePrice, daysToPending}`; `.zhviLatest {zhvi, zhviYoY,\nasOfDate}` (`zhviYoY` is a fraction — multiply by 100 for a percent).\nThe region id/slug (e.g. `6181/brooklyn-ny`) comes from a Zillow\nhome-values URL; there's no separate region-lookup endpoint documented\nin the MCP.\n\n## 8. Address autocomplete (bonus — resolving a free-text address to a zpid)\n\nZillow's own address typeahead, used internally by the MCP's\n`zillow_get_by_address` resolver ladder before it falls back to §1's\nsearch. Inline GraphQL (no persisted-query hash), POST:\n\n```sh\ncat > /tmp/ac.json <<'JSON'\n{\n  \"operationName\": \"GetAutocompleteResults\",\n  \"query\": \"query GetAutocompleteResults($query: String!, $queryOptions: SearchAssistanceQueryOptions, $resultType: [SearchAssistanceResultType], $shouldRequestSpellCorrectedMetadata: Boolean = false) { searchAssistanceResult: zgsAutocompleteRequest(query: $query, queryOptions: $queryOptions, resultType: $resultType, shouldRequestSpellCorrectedMetadata: $shouldRequestSpellCorrectedMetadata) { requestId results { __typename ... on SearchAssistanceAddressResult { id } } } }\",\n  \"variables\": { \"query\": \"3538 Trent St Charlotte NC\", \"resultType\": [\"REGIONS\",\"FORSALE\",\"RENTALS\",\"SOLD\",\"COMMUNITIES\",\"SCHOOLS\",\"SCHOOL_DISTRICTS\",\"SEMANTIC_REGIONS\",\"BUILDER_COMMUNITIES\"], \"shouldRequestSpellCorrectedMetadata\": false },\n  \"resultType\": [\"REGIONS\",\"FORSALE\",\"RENTALS\",\"SOLD\",\"COMMUNITIES\",\"SCHOOLS\",\"SCHOOL_DISTRICTS\",\"SEMANTIC_REGIONS\",\"BUILDER_COMMUNITIES\"],\n  \"shouldRequestSpellCorrectedMetadata\": false\n}\nJSON\nQS='query=3538%20Trent%20St%20Charlotte%20NC&resultType=REGIONS&resultType=FORSALE&resultType=RENTALS&resultType=SOLD&resultType=COMMUNITIES&resultType=SCHOOLS&resultType=SCHOOL_DISTRICTS&resultType=SEMANTIC_REGIONS&resultType=BUILDER_COMMUNITIES&shouldRequestSpellCorrectedMetadata=false&operationName=GetAutocompleteResults'\nfpx post-json \"https://www.zillow.com/zg-graph?${QS}\" @/tmp/ac.json -p zillow \\\n  -H 'origin: https://www.zillow.com' \\\n  -H 'referer: https://www.zillow.com/homes/for_sale/' \\\n  -H 'x-caller-id: static-search-page-graphql' \\\n  | jq -r '.data.searchAssistanceResult.results[] | select(.__typename==\"SearchAssistanceAddressResult\") | .id'\n```\n\nEach result `.id` is a full canonical address string (e.g.\n`\"3538 Trent St Charlotte, NC 28209\"`) — feed that string into §1's\nresolve step (`/homes/<that-string>_rb/`) to get the zpid. These three\nheaders are cookie-free by design — the bridge supplies the session\nambiently; don't add a `Cookie` header yourself.\n\n## 9. Healthcheck\n\n```sh\nfpx get 'https://www.zillow.com/robots.txt' -p zillow\n```\n\nA 200 with plain-text `robots.txt` content confirms the bridge, the\nextension, and a responsive zillow.com tab — the same probe\n`zillow_healthcheck` runs.\n\nFile v1.1.8:skill-card.md\n\n## Description:\n\nGuides agents in retrieving Zillow listings, property details, valuation history, market reports, and user-authorized saved data through a paired browser tab.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and agents use this skill to search US real-estate listings and inspect Zillow property and market data without an MCP server. With the user's authorization and signed-in session, they can also retrieve saved searches and homes.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The workflow depends on a paired browser extension and CLI.\n\nMitigation: Install only if you trust the fpx CLI and ContextMint Bridge extension.\n\nRisk: Saved searches and favorited homes expose private account data from a signed-in Zillow session.\n\nMitigation: Use saved-data recipes only when the user explicitly authorizes access to their signed-in account.\n\n## Reference(s):\n\n- [Zillow fpx page recipes](references/pages.md)\n- [ContextMint Bridge releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n- [ClawHub skill listing](https://clawhub.ai/chrischall/skills/zillow-fpx)\n\n## Skill Output:\n\n**Output Type(s):** [Guidance, Shell commands, Code]\n\n**Output Format:** [Markdown with shell and Python examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [None]\n\n## Skill Version(s):\n\n1.1.8 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.1.7: 4 files, 8529 bytes\n\nFiles: references/pages.md (10041b), skill-card.md (1961b), SKILL.md (4854b), _meta.json (129b)\n\nFile v1.1.7:SKILL.md\n\n---\nname: zillow-fpx\ndescription: >-\n  Query zillow.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the zillow-mcp server — search\n  listings, pull a full property record by zpid, price/tax/Zestimate\n  history, photos, market reports, and your signed-in saved\n  searches/homes, all via one-shot HTTP calls through a signed-in browser\n  tab. Use when you want Zillow data without the MCP, in a script, or on\n  a machine where the MCP isn't installed.\n---\n\n# Zillow via fpx (no MCP)\n\nZillow fronts `www.zillow.com` with a PerimeterX bot-wall that blocks\nplain `curl`/Node requests, and several tools (saved searches/homes)\nneed an actual signed-in session. `fpx` routes every request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), so the\nsame page loads that a real visit would.\n\nThis is the same data the `zillow_*` MCP tools return — every property\ntool is a scrape of Zillow's server-rendered Next.js pages\n(`__NEXT_DATA__`), not a documented JSON API. No credentials are stored\nanywhere; auth (for the saved-data endpoints) is just \"have a signed-in\nzillow.com tab open.\"\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli             # provides `fpx`\nfpx profile add zillow --domain zillow.com # only the fetch capability is needed\nfpx pair -p zillow                         # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n([releases](https://github.com/nullnet-app/contextmint-bridge/releases)), with an\nopen `www.zillow.com` tab, and its Chrome **Site access** allowing\n`zillow.com`. (ContextMint Bridge is the renamed fetchproxy extension from the\nsame maintainer; build it from source or verify the release zip with\n`shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`.) For the saved-searches/saved-homes calls, that tab must\nalso be **signed in**. Pairing persists — after the first approval every\nlater `fpx` call reuses it.\n\n## Core call\n\nEvery endpoint here is a GET of a server-rendered HTML page (Zillow is a\nNext.js app; the whole page state is embedded as JSON in a\n`<script id=\"__NEXT_DATA__\">` tag) — there is no JSON API to hit\ndirectly. Fetch, then pull the JSON out of the HTML:\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow > /tmp/page.html\npython3 -c '\nimport re, sys, json\nhtml = open(\"/tmp/page.html\").read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n' | jq '.'\n```\n\n`references/pages.md` has the extractor as a reusable one-liner plus the\nper-page `pageProps` field paths (search results, property detail,\nphotos, price/tax/Zestimate history, saved searches/homes, market\nreport) and the address-autocomplete GraphQL call, all transcribed from\nthe MCP's `src/tools/*.ts` (which parse the exact same pages).\n\n## The one rule: resolve the location first (search only)\n\n`zillow_search_properties`'s two-step dance is exactly what\n`/homes/<slug>_rb/` needs: fetch the bare slug path first to get Zillow's\nresolved `regionSelection` + `mapBounds`, THEN re-fetch with those pinned\ninto a `searchQueryState` query param alongside your filters — a filtered\nfetch without the pinned region silently falls back to the user's last\nsearch region instead of honoring the slug. A full-address query can\nresolve straight to a `homedetails` page (no region at all) — see\n`references/pages.md` §1 for both shapes. Property lookups by `zpid`\nneed no resolve step — `/homedetails/<zpid>_zpid/` is direct.\n\n## Auth\n\nNo login is stored or passed by `fpx` — the saved-searches\n(`/myzillow/SavedSearches`) and saved-homes (`/myzillow/favorites`) pages\nsimply render your saved data (or redirect to `/user/login`) depending on\nwhether the tab riding the bridge is signed in. Everything else is\nanonymous.\n\n## Exit codes (fetch verbs)\n\n- `0` — success. A signed-out redirect (`/user/login`, `?login=true`) or\n  a captcha interstitial (body contains `captcha-delivery`, small body)\n  can still ride in a `0` response — check the fetched HTML, `fpx`\n  doesn't know Zillow's sign-in/bot-wall markers.\n- `2` — bridge unavailable: extension not connected or pairing pending →\n  run `fpx pair -p zillow`, confirm a zillow.com tab is open.\n- `3` — bot wall: the tab hasn't cleared PerimeterX → open/refresh a\n  `www.zillow.com` tab and retry.\n- `4` — upstream non-2xx from Zillow.\n\n## Notes\n\n- `fpx health -p zillow` shows bridge connection state when a call fails.\n- Zillow publishes no consumer API — these are the same private\n  server-rendered pages the zillow.com web app itself loads, reached\n  through your own signed-in tab.\n- This project is developed and maintained by AI (Claude).\n\nFile v1.1.7:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"zillow-fpx\",\n  \"version\": \"1.1.7\",\n  \"publishedAt\": 1791168741264\n}\n\nFile v1.1.7:references/pages.md\n\n# Zillow pages for fpx\n\nAll paths below are fetched with `fpx get 'https://www.zillow.com<path>' -p zillow`.\nEvery page is server-rendered Next.js — the data lives in\n`__NEXT_DATA__.props.pageProps`, never in a separate JSON API. Field\npaths below are transcribed from the MCP's parsers\n(`src/next-data.ts`, `src/tools/*.ts`) — live-verified there, not\nre-captured here.\n\n## 0. The extractor (reuse for every page below)\n\n```sh\nextract_page_props() {\n  python3 -c '\nimport re, sys, json\nhtml = sys.stdin.read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nif not m:\n    sys.exit(\"no __NEXT_DATA__ script tag found — likely a bot-wall or redirect page\")\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n'\n}\n\nfpx get 'https://www.zillow.com/robots.txt' -p zillow  # smoke test, no parsing needed\n```\n\nPipe any fetched HTML through `extract_page_props` to get the page's\n`pageProps` as one JSON line, then `jq` into it per the recipes below.\n\n## 1. Search listings\n\nTwo-step dance — **always resolve before filtering**:\n\n**Step 1 — resolve** (bare slug, no query string):\n\n```sh\nfpx get 'https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '.searchPageState.queryState.regionSelection, .searchPageState.queryState.mapBounds' /tmp/pp.json\n```\n\n- If `searchPageState` is present with a non-empty `regionSelection` +\n  `mapBounds` → you have a **region**; proceed to step 2.\n- If `searchPageState` is **absent** but `pageProps.gdpClientCache` (or\n  `pageProps.componentProps.gdpClientCache`) is present, Zillow resolved\n  the query straight to ONE property (a homedetails page) — see §2, no\n  step 2 needed.\n- If `searchPageState.queryState.regionSelection` is empty AND\n  `cat1.searchResults.listResults` is non-empty, Zillow returned\n  address/street-level listings directly with no region to pin — use\n  those listings as-is (issue #31 in the MCP).\n\n**Step 2 — filtered search** (region pinned + your filters), only when\nstep 1 gave you a region:\n\n```sh\nSQS='{\"usersSearchTerm\":\"Brooklyn, NY\",\"filterState\":{\"price\":{\"max\":900000},\"beds\":{\"min\":2}},\"isListVisible\":true,\"isMapVisible\":false,\"regionSelection\":[{\"regionId\":37607,\"regionType\":17}],\"mapBounds\":{\"north\":40.74,\"south\":40.57,\"east\":-73.83,\"west\":-74.05}}'\nENC=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$SQS\")\nfpx get \"https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/?searchQueryState=${ENC}\" -p zillow \\\n  | extract_page_props | jq '.searchPageState.cat1.searchResults.listResults[] | {zpid: .hdpData.homeInfo.zpid, price: .hdpData.homeInfo.price, address: .hdpData.homeInfo.streetAddress, beds: .hdpData.homeInfo.bedrooms, url: .detailUrl}'\n```\n\n`filterState` keys the MCP sets (mirror these in the JSON above):\n`isForRent`/`isForSaleByAgent`/etc `{value: true|false}` (status\nswitches), `price {min,max}`, `beds {min}`, `baths {min}`, one\n`{value:true}` flag per home type (`isSingleFamily`, `isCondo`,\n`isTownhouse`, `isMultiFamily`, `isManufactured`, `isLotLand`,\n`isApartment`), and `pagination: {currentPage: N}` for page > 1. Zillow\nreturns ~40 listings per page; increment `pagination.currentPage` and\nre-fetch to walk further pages (stop on an empty `listResults`).\n\nPagination example (page 2):\n\n```sh\nSQS='{...same as above..., \"pagination\":{\"currentPage\":2}}'\n```\n\n## 2. Property detail by zpid\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\n# gdpClientCache is a JSON-encoded STRING inside pageProps — parse twice.\njq -r '.gdpClientCache // .componentProps.gdpClientCache' /tmp/pp.json \\\n  | jq '[to_entries[] | select(.key | startswith(\"Property:\")) | select(.value.property) | .value.property][0]\n        // [to_entries[] | select(.value.property) | .value.property][0]'\n```\n\nThat gives the raw `property` object. Useful top-level fields: `zpid`,\n`hdpUrl`, `address {streetAddress,city,state,zipcode,neighborhood}`,\n`mlsStreetAddress` (canonical MLS address — may disagree with `address`,\nprefer it when present), `price`, `zestimate`, `rentZestimate`,\n`bedrooms`, `bathrooms`, `livingArea`, `lotSize` (sqft), `yearBuilt`,\n`homeType`, `homeStatus`, `description`, `latitude`/`longitude`,\n`daysOnZillow`, `taxAssessedValue`/`taxAssessedYear`,\n`taxAnnualAmount` (values < 10 are a not-yet-assessed sentinel, not a\nreal bill), `schools[]`, `resoFacts {yearBuilt, associationFee,\nassociationFeeFrequency, taxAnnualAmount}` (MLS fallback source),\n`priceHistory[]`, `taxHistory[]`.\n\nOnly a URL with a trailing `<zpid>_zpid/` resolves — a slug-only URL\nredirects to the generic search page (no `gdpClientCache`). If you only\nhave an address, resolve to a zpid via §1 or the autocomplete call in §7\nfirst.\n\n## 3. Price / tax history (same property object as §2)\n\n```sh\njq '.priceHistory' /tmp/property.json    # [{date, price, event, source, ...}]\njq '.taxHistory' /tmp/property.json      # [{time or year, value, taxIncreaseRate, ...}]\n```\n\nBoth arrays live inline on the property object fetched in §2 — no\nseparate request. Absent on some (commonly non-Showcase) listings —\nZillow renders the trend client-side for those.\n\n## 4. Zestimate history (same property object as §2)\n\n```sh\njq '(first(.homeValueChartData[] | select(.name==\"This home\")) // .homeValueChartData[0]) | .points' /tmp/property.json\n```\n\nEach point is `{x: <unix ms>, y: <value>}` or `{date, value}` depending\non deploy. Fall back to deriving a series from `priceHistory[].{date,price}`\nwhen `homeValueChartData` is absent. `rentValueChartData` is the parallel\nseries for `rent` when present.\n\n## 5. Photos (same property object as §2)\n\n```sh\njq '[.photos, .responsivePhotos, .originalPhotos] | map(select(type==\"array\" and length>0)) | first // []' /tmp/property.json\n```\n\nEach entry: `{caption, subjectType, url, mixedSources: {jpeg: [{url,width}], webp: [{url,width}]}}`.\nPick the widest `mixedSources.jpeg`/`webp` entry for the largest image;\n`url` alone is the hero/thumbnail. `streetViewImageUrl` and\n`hiResImageLink` sit at the top level of the property object too.\n\n## 6. Saved searches / saved homes (requires a signed-in tab)\n\n```sh\n# Saved searches — path is case-sensitive (capital S)\nfpx get 'https://www.zillow.com/myzillow/SavedSearches' -p zillow \\\n  | extract_page_props | jq '.savedSearches // .userSavedSearches'\n\n# Saved (favorited) homes — flattened across collections\nfpx get 'https://www.zillow.com/myzillow/favorites' -p zillow \\\n  | extract_page_props | jq '[.collectionsResponse[] | (.homes // .properties // .items // [])[]]'\n```\n\nA signed-out tab redirects to `/user/login` instead of rendering these —\ncheck the fetched HTML's final URL / body before trusting an empty\nresult as \"no saves.\"\n\n## 7. Market report for a region\n\n```sh\nfpx get 'https://www.zillow.com/home-values/6181/brooklyn-ny/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '{region: .zhviRegion, analytics: .odpMarketAnalytics}' /tmp/pp.json\n```\n\n`zhviRegion {name, regionTypeName, parentCounty.name, parentState.name}`;\n`odpMarketAnalytics.mrktListingLatest {newListings, forSaleInventory,\nmedianListPrice, medianDaysOnMarket}`; `.mrktSaleLatest\n{medianSalePrice, daysToPending}`; `.zhviLatest {zhvi, zhviYoY,\nasOfDate}` (`zhviYoY` is a fraction — multiply by 100 for a percent).\nThe region id/slug (e.g. `6181/brooklyn-ny`) comes from a Zillow\nhome-values URL; there's no separate region-lookup endpoint documented\nin the MCP.\n\n## 8. Address autocomplete (bonus — resolving a free-text address to a zpid)\n\nZillow's own address typeahead, used internally by the MCP's\n`zillow_get_by_address` resolver ladder before it falls back to §1's\nsearch. Inline GraphQL (no persisted-query hash), POST:\n\n```sh\ncat > /tmp/ac.json <<'JSON'\n{\n  \"operationName\": \"GetAutocompleteResults\",\n  \"query\": \"query GetAutocompleteResults($query: String!, $queryOptions: SearchAssistanceQueryOptions, $resultType: [SearchAssistanceResultType], $shouldRequestSpellCorrectedMetadata: Boolean = false) { searchAssistanceResult: zgsAutocompleteRequest(query: $query, queryOptions: $queryOptions, resultType: $resultType, shouldRequestSpellCorrectedMetadata: $shouldRequestSpellCorrectedMetadata) { requestId results { __typename ... on SearchAssistanceAddressResult { id } } } }\",\n  \"variables\": { \"query\": \"3538 Trent St Charlotte NC\", \"resultType\": [\"REGIONS\",\"FORSALE\",\"RENTALS\",\"SOLD\",\"COMMUNITIES\",\"SCHOOLS\",\"SCHOOL_DISTRICTS\",\"SEMANTIC_REGIONS\",\"BUILDER_COMMUNITIES\"], \"shouldRequestSpellCorrectedMetadata\": false },\n  \"resultType\": [\"REGIONS\",\"FORSALE\",\"RENTALS\",\"SOLD\",\"COMMUNITIES\",\"SCHOOLS\",\"SCHOOL_DISTRICTS\",\"SEMANTIC_REGIONS\",\"BUILDER_COMMUNITIES\"],\n  \"shouldRequestSpellCorrectedMetadata\": false\n}\nJSON\nQS='query=3538%20Trent%20St%20Charlotte%20NC&resultType=REGIONS&resultType=FORSALE&resultType=RENTALS&resultType=SOLD&resultType=COMMUNITIES&resultType=SCHOOLS&resultType=SCHOOL_DISTRICTS&resultType=SEMANTIC_REGIONS&resultType=BUILDER_COMMUNITIES&shouldRequestSpellCorrectedMetadata=false&operationName=GetAutocompleteResults'\nfpx post-json \"https://www.zillow.com/zg-graph?${QS}\" @/tmp/ac.json -p zillow \\\n  -H 'origin: https://www.zillow.com' \\\n  -H 'referer: https://www.zillow.com/homes/for_sale/' \\\n  -H 'x-caller-id: static-search-page-graphql' \\\n  | jq -r '.data.searchAssistanceResult.results[] | select(.__typename==\"SearchAssistanceAddressResult\") | .id'\n```\n\nEach result `.id` is a full canonical address string (e.g.\n`\"3538 Trent St Charlotte, NC 28209\"`) — feed that string into §1's\nresolve step (`/homes/<that-string>_rb/`) to get the zpid. These three\nheaders are cookie-free by design — the bridge supplies the session\nambiently; don't add a `Cookie` header yourself.\n\n## 9. Healthcheck\n\n```sh\nfpx get 'https://www.zillow.com/robots.txt' -p zillow\n```\n\nA 200 with plain-text `robots.txt` content confirms the bridge, the\nextension, and a responsive zillow.com tab — the same probe\n`zillow_healthcheck` runs.\n\nFile v1.1.7:skill-card.md\n\n## Description:\n\nGuides agents in querying Zillow listings, property details, market reports, and signed-in saved items through the fpx CLI and a browser tab.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nAgents and developers use this skill to retrieve Zillow property and market information from a shell, including saved searches and homes when the user is signed in, without a Zillow MCP server.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Saved searches and homes expose private account data through a signed-in Zillow tab.\n\nMitigation: Use saved-data commands only when explicitly requested and treat results as private.\n\nRisk: Address autocomplete may transmit sensitive personal addresses.\n\nMitigation: Avoid sending sensitive addresses to autocomplete unless necessary.\n\nRisk: The workflow depends on a third-party CLI and browser extension with access to a Zillow tab.\n\nMitigation: Install only if comfortable with both tools and limit extension site access to Zillow.\n\n## Reference(s):\n\n- [Zillow page and extraction recipes](artifact/references/pages.md)\n- [ContextMint Bridge releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n\n## Skill Output:\n\n**Output Type(s):** [Shell commands, Code, Guidance]\n\n**Output Format:** [Markdown with shell, Python, and jq examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Returns instructions for extracting listing, property, and account-scoped data from Zillow pages.]\n\n## Skill Version(s):\n\n1.1.7 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.1.6: 4 files, 8423 bytes\n\nFiles: references/pages.md (10041b), skill-card.md (1739b), SKILL.md (4854b), _meta.json (129b)\n\nFile v1.1.6:SKILL.md\n\n---\nname: zillow-fpx\ndescription: >-\n  Query zillow.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the zillow-mcp server — search\n  listings, pull a full property record by zpid, price/tax/Zestimate\n  history, photos, market reports, and your signed-in saved\n  searches/homes, all via one-shot HTTP calls through a signed-in browser\n  tab. Use when you want Zillow data without the MCP, in a script, or on\n  a machine where the MCP isn't installed.\n---\n\n# Zillow via fpx (no MCP)\n\nZillow fronts `www.zillow.com` with a PerimeterX bot-wall that blocks\nplain `curl`/Node requests, and several tools (saved searches/homes)\nneed an actual signed-in session. `fpx` routes every request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), so the\nsame page loads that a real visit would.\n\nThis is the same data the `zillow_*` MCP tools return — every property\ntool is a scrape of Zillow's server-rendered Next.js pages\n(`__NEXT_DATA__`), not a documented JSON API. No credentials are stored\nanywhere; auth (for the saved-data endpoints) is just \"have a signed-in\nzillow.com tab open.\"\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli             # provides `fpx`\nfpx profile add zillow --domain zillow.com # only the fetch capability is needed\nfpx pair -p zillow                         # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n([releases](https://github.com/nullnet-app/contextmint-bridge/releases)), with an\nopen `www.zillow.com` tab, and its Chrome **Site access** allowing\n`zillow.com`. (ContextMint Bridge is the renamed fetchproxy extension from the\nsame maintainer; build it from source or verify the release zip with\n`shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`.) For the saved-searches/saved-homes calls, that tab must\nalso be **signed in**. Pairing persists — after the first approval every\nlater `fpx` call reuses it.\n\n## Core call\n\nEvery endpoint here is a GET of a server-rendered HTML page (Zillow is a\nNext.js app; the whole page state is embedded as JSON in a\n`<script id=\"__NEXT_DATA__\">` tag) — there is no JSON API to hit\ndirectly. Fetch, then pull the JSON out of the HTML:\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow > /tmp/page.html\npython3 -c '\nimport re, sys, json\nhtml = open(\"/tmp/page.html\").read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n' | jq '.'\n```\n\n`references/pages.md` has the extractor as a reusable one-liner plus the\nper-page `pageProps` field paths (search results, property detail,\nphotos, price/tax/Zestimate history, saved searches/homes, market\nreport) and the address-autocomplete GraphQL call, all transcribed from\nthe MCP's `src/tools/*.ts` (which parse the exact same pages).\n\n## The one rule: resolve the location first (search only)\n\n`zillow_search_properties`'s two-step dance is exactly what\n`/homes/<slug>_rb/` needs: fetch the bare slug path first to get Zillow's\nresolved `regionSelection` + `mapBounds`, THEN re-fetch with those pinned\ninto a `searchQueryState` query param alongside your filters — a filtered\nfetch without the pinned region silently falls back to the user's last\nsearch region instead of honoring the slug. A full-address query can\nresolve straight to a `homedetails` page (no region at all) — see\n`references/pages.md` §1 for both shapes. Property lookups by `zpid`\nneed no resolve step — `/homedetails/<zpid>_zpid/` is direct.\n\n## Auth\n\nNo login is stored or passed by `fpx` — the saved-searches\n(`/myzillow/SavedSearches`) and saved-homes (`/myzillow/favorites`) pages\nsimply render your saved data (or redirect to `/user/login`) depending on\nwhether the tab riding the bridge is signed in. Everything else is\nanonymous.\n\n## Exit codes (fetch verbs)\n\n- `0` — success. A signed-out redirect (`/user/login`, `?login=true`) or\n  a captcha interstitial (body contains `captcha-delivery`, small body)\n  can still ride in a `0` response — check the fetched HTML, `fpx`\n  doesn't know Zillow's sign-in/bot-wall markers.\n- `2` — bridge unavailable: extension not connected or pairing pending →\n  run `fpx pair -p zillow`, confirm a zillow.com tab is open.\n- `3` — bot wall: the tab hasn't cleared PerimeterX → open/refresh a\n  `www.zillow.com` tab and retry.\n- `4` — upstream non-2xx from Zillow.\n\n## Notes\n\n- `fpx health -p zillow` shows bridge connection state when a call fails.\n- Zillow publishes no consumer API — these are the same private\n  server-rendered pages the zillow.com web app itself loads, reached\n  through your own signed-in tab.\n- This project is developed and maintained by AI (Claude).\n\nFile v1.1.6:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"zillow-fpx\",\n  \"version\": \"1.1.6\",\n  \"publishedAt\": 1791036071414\n}\n\nFile v1.1.6:references/pages.md\n\n# Zillow pages for fpx\n\nAll paths below are fetched with `fpx get 'https://www.zillow.com<path>' -p zillow`.\nEvery page is server-rendered Next.js — the data lives in\n`__NEXT_DATA__.props.pageProps`, never in a separate JSON API. Field\npaths below are transcribed from the MCP's parsers\n(`src/next-data.ts`, `src/tools/*.ts`) — live-verified there, not\nre-captured here.\n\n## 0. The extractor (reuse for every page below)\n\n```sh\nextract_page_props() {\n  python3 -c '\nimport re, sys, json\nhtml = sys.stdin.read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nif not m:\n    sys.exit(\"no __NEXT_DATA__ script tag found — likely a bot-wall or redirect page\")\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n'\n}\n\nfpx get 'https://www.zillow.com/robots.txt' -p zillow  # smoke test, no parsing needed\n```\n\nPipe any fetched HTML through `extract_page_props` to get the page's\n`pageProps` as one JSON line, then `jq` into it per the recipes below.\n\n## 1. Search listings\n\nTwo-step dance — **always resolve before filtering**:\n\n**Step 1 — resolve** (bare slug, no query string):\n\n```sh\nfpx get 'https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '.searchPageState.queryState.regionSelection, .searchPageState.queryState.mapBounds' /tmp/pp.json\n```\n\n- If `searchPageState` is present with a non-empty `regionSelection` +\n  `mapBounds` → you have a **region**; proceed to step 2.\n- If `searchPageState` is **absent** but `pageProps.gdpClientCache` (or\n  `pageProps.componentProps.gdpClientCache`) is present, Zillow resolved\n  the query straight to ONE property (a homedetails page) — see §2, no\n  step 2 needed.\n- If `searchPageState.queryState.regionSelection` is empty AND\n  `cat1.searchResults.listResults` is non-empty, Zillow returned\n  address/street-level listings directly with no region to pin — use\n  those listings as-is (issue #31 in the MCP).\n\n**Step 2 — filtered search** (region pinned + your filters), only when\nstep 1 gave you a region:\n\n```sh\nSQS='{\"usersSearchTerm\":\"Brooklyn, NY\",\"filterState\":{\"price\":{\"max\":900000},\"beds\":{\"min\":2}},\"isListVisible\":true,\"isMapVisible\":false,\"regionSelection\":[{\"regionId\":37607,\"regionType\":17}],\"mapBounds\":{\"north\":40.74,\"south\":40.57,\"east\":-73.83,\"west\":-74.05}}'\nENC=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$SQS\")\nfpx get \"https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/?searchQueryState=${ENC}\" -p zillow \\\n  | extract_page_props | jq '.searchPageState.cat1.searchResults.listResults[] | {zpid: .hdpData.homeInfo.zpid, price: .hdpData.homeInfo.price, address: .hdpData.homeInfo.streetAddress, beds: .hdpData.homeInfo.bedrooms, url: .detailUrl}'\n```\n\n`filterState` keys the MCP sets (mirror these in the JSON above):\n`isForRent`/`isForSaleByAgent`/etc `{value: true|false}` (status\nswitches), `price {min,max}`, `beds {min}`, `baths {min}`, one\n`{value:true}` flag per home type (`isSingleFamily`, `isCondo`,\n`isTownhouse`, `isMultiFamily`, `isManufactured`, `isLotLand`,\n`isApartment`), and `pagination: {currentPage: N}` for page > 1. Zillow\nreturns ~40 listings per page; increment `pagination.currentPage` and\nre-fetch to walk further pages (stop on an empty `listResults`).\n\nPagination example (page 2):\n\n```sh\nSQS='{...same as above..., \"pagination\":{\"currentPage\":2}}'\n```\n\n## 2. Property detail by zpid\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\n# gdpClientCache is a JSON-encoded STRING inside pageProps — parse twice.\njq -r '.gdpClientCache // .componentProps.gdpClientCache' /tmp/pp.json \\\n  | jq '[to_entries[] | select(.key | startswith(\"Property:\")) | select(.value.property) | .value.property][0]\n        // [to_entries[] | select(.value.property) | .value.property][0]'\n```\n\nThat gives the raw `property` object. Useful top-level fields: `zpid`,\n`hdpUrl`, `address {streetAddress,city,state,zipcode,neighborhood}`,\n`mlsStreetAddress` (canonical MLS address — may disagree with `address`,\nprefer it when present), `price`, `zestimate`, `rentZestimate`,\n`bedrooms`, `bathrooms`, `livingArea`, `lotSize` (sqft), `yearBuilt`,\n`homeType`, `homeStatus`, `description`, `latitude`/`longitude`,\n`daysOnZillow`, `taxAssessedValue`/`taxAssessedYear`,\n`taxAnnualAmount` (values < 10 are a not-yet-assessed sentinel, not a\nreal bill), `schools[]`, `resoFacts {yearBuilt, associationFee,\nassociationFeeFrequency, taxAnnualAmount}` (MLS fallback source),\n`priceHistory[]`, `taxHistory[]`.\n\nOnly a URL with a trailing `<zpid>_zpid/` resolves — a slug-only URL\nredirects to the generic search page (no `gdpClientCache`). If you only\nhave an address, resolve to a zpid via §1 or the autocomplete call in §7\nfirst.\n\n## 3. Price / tax history (same property object as §2)\n\n```sh\njq '.priceHistory' /tmp/property.json    # [{date, price, event, source, ...}]\njq '.taxHistory' /tmp/property.json      # [{time or year, value, taxIncreaseRate, ...}]\n```\n\nBoth arrays live inline on the property object fetched in §2 — no\nseparate request. Absent on some (commonly non-Showcase) listings —\nZillow renders the trend client-side for those.\n\n## 4. Zestimate history (same property object as §2)\n\n```sh\njq '(first(.homeValueChartData[] | select(.name==\"This home\")) // .homeValueChartData[0]) | .points' /tmp/property.json\n```\n\nEach point is `{x: <unix ms>, y: <value>}` or `{date, value}` depending\non deploy. Fall back to deriving a series from `priceHistory[].{date,price}`\nwhen `homeValueChartData` is absent. `rentValueChartData` is the parallel\nseries for `rent` when present.\n\n## 5. Photos (same property object as §2)\n\n```sh\njq '[.photos, .responsivePhotos, .originalPhotos] | map(select(type==\"array\" and length>0)) | first // []' /tmp/property.json\n```\n\nEach entry: `{caption, subjectType, url, mixedSources: {jpeg: [{url,width}], webp: [{url,width}]}}`.\nPick the widest `mixedSources.jpeg`/`webp` entry for the largest image;\n`url` alone is the hero/thumbnail. `streetViewImageUrl` and\n`hiResImageLink` sit at the top level of the property object too.\n\n## 6. Saved searches / saved homes (requires a signed-in tab)\n\n```sh\n# Saved searches — path is case-sensitive (capital S)\nfpx get 'https://www.zillow.com/myzillow/SavedSearches' -p zillow \\\n  | extract_page_props | jq '.savedSearches // .userSavedSearches'\n\n# Saved (favorited) homes — flattened across collections\nfpx get 'https://www.zillow.com/myzillow/favorites' -p zillow \\\n  | extract_page_props | jq '[.collectionsResponse[] | (.homes // .properties // .items // [])[]]'\n```\n\nA signed-out tab redirects to `/user/login` instead of rendering these —\ncheck the fetched HTML's final URL / body before trusting an empty\nresult as \"no saves.\"\n\n## 7. Market report for a region\n\n```sh\nfpx get 'https://www.zillow.com/home-values/6181/brooklyn-ny/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '{region: .zhviRegion, analytics: .odpMarketAnalytics}' /tmp/pp.json\n```\n\n`zhviRegion {name, regionTypeName, parentCounty.name, parentState.name}`;\n`odpMarketAnalytics.mrktListingLatest {newListings, forSaleInventory,\nmedianListPrice, medianDaysOnMarket}`; `.mrktSaleLatest\n{medianSalePrice, daysToPending}`; `.zhviLatest {zhvi, zhviYoY,\nasOfDate}` (`zhviYoY` is a fraction — multiply by 100 for a percent).\nThe region id/slug (e.g. `6181/brooklyn-ny`) comes from a Zillow\nhome-values URL; there's no separate region-lookup endpoint documented\nin the MCP.\n\n## 8. Address autocomplete (bonus — resolving a free-text address to a zpid)\n\nZillow's own address typeahead, used internally by the MCP's\n`zillow_get_by_address` resolver ladder before it falls back to §1's\nsearch. Inline GraphQL (no persisted-query hash), POST:\n\n```sh\ncat > /tmp/ac.json <<'JSON'\n{\n  \"operationName\": \"GetAutocompleteResults\",\n  \"query\": \"query GetAutocompleteResults($query: String!, $queryOptions: SearchAssistanceQueryOptions, $resultType: [SearchAssistanceResultType], $shouldRequestSpellCorrectedMetadata: Boolean = false) { searchAssistanceResult: zgsAutocompleteRequest(query: $query, queryOptions: $queryOptions, resultType: $resultType, shouldRequestSpellCorrectedMetadata: $shouldRequestSpellCorrectedMetadata) { requestId results { __typename ... on SearchAssistanceAddressResult { id } } } }\",\n  \"variables\": { \"query\": \"3538 Trent St Charlotte NC\", \"resultType\": [\"REGIONS\",\"FORSALE\",\"RENTALS\",\"SOLD\",\"COMMUNITIES\",\"SCHOOLS\",\"SCHOOL_DISTRICTS\",\"SEMANTIC_REGIONS\",\"BUILDER_COMMUNITIES\"], \"shouldRequestSpellCorrectedMetadata\": false },\n  \"resultType\": [\"REGIONS\",\"FORSALE\",\"RENTALS\",\"SOLD\",\"COMMUNITIES\",\"SCHOOLS\",\"SCHOOL_DISTRICTS\",\"SEMANTIC_REGIONS\",\"BUILDER_COMMUNITIES\"],\n  \"shouldRequestSpellCorrectedMetadata\": false\n}\nJSON\nQS='query=3538%20Trent%20St%20Charlotte%20NC&resultType=REGIONS&resultType=FORSALE&resultType=RENTALS&resultType=SOLD&resultType=COMMUNITIES&resultType=SCHOOLS&resultType=SCHOOL_DISTRICTS&resultType=SEMANTIC_REGIONS&resultType=BUILDER_COMMUNITIES&shouldRequestSpellCorrectedMetadata=false&operationName=GetAutocompleteResults'\nfpx post-json \"https://www.zillow.com/zg-graph?${QS}\" @/tmp/ac.json -p zillow \\\n  -H 'origin: https://www.zillow.com' \\\n  -H 'referer: https://www.zillow.com/homes/for_sale/' \\\n  -H 'x-caller-id: static-search-page-graphql' \\\n  | jq -r '.data.searchAssistanceResult.results[] | select(.__typename==\"SearchAssistanceAddressResult\") | .id'\n```\n\nEach result `.id` is a full canonical address string (e.g.\n`\"3538 Trent St Charlotte, NC 28209\"`) — feed that string into §1's\nresolve step (`/homes/<that-string>_rb/`) to get the zpid. These three\nheaders are cookie-free by design — the bridge supplies the session\nambiently; don't add a `Cookie` header yourself.\n\n## 9. Healthcheck\n\n```sh\nfpx get 'https://www.zillow.com/robots.txt' -p zillow\n```\n\nA 200 with plain-text `robots.txt` content confirms the bridge, the\nextension, and a responsive zillow.com tab — the same probe\n`zillow_healthcheck` runs.\n\nFile v1.1.6:skill-card.md\n\n## Description:\n\nGuides agents in using fpx and a browser tab to retrieve Zillow listings, property details, market reports, and signed-in saved items without an MCP server.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and other agents use this skill to search US real-estate listings and retrieve property details, price history, photos, market data, or their own saved Zillow items through a browser tab.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: A paired browser tab can expose account-specific saved searches and homes, and pairing persists until revoked.\n\nMitigation: Use a dedicated browser profile or sign out for public lookups; remove or revoke pairing when finished.\n\n## Reference(s):\n\n- [Zillow fpx on ClawHub](https://clawhub.ai/chrischall/skills/zillow-fpx)\n- [Zillow page recipes](artifact/references/pages.md)\n- [ContextMint Bridge releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n\n## Skill Output:\n\n**Output Type(s):** [Shell commands, Code, Guidance]\n\n**Output Format:** [Markdown with shell and JSON examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Commands retrieve Zillow page data, including account-specific saved items when the browser tab is signed in.]\n\n## Skill Version(s):\n\n1.1.6 (source: ClawHub release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.1.5: 4 files, 8574 bytes\n\nFiles: references/pages.md (10041b), skill-card.md (2123b), SKILL.md (4854b), _meta.json (129b)\n\nFile v1.1.5:SKILL.md\n\n---\nname: zillow-fpx\ndescription: >-\n  Query zillow.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the zillow-mcp server — search\n  listings, pull a full property record by zpid, price/tax/Zestimate\n  history, photos, market reports, and your signed-in saved\n  searches/homes, all via one-shot HTTP calls through a signed-in browser\n  tab. Use when you want Zillow data without the MCP, in a script, or on\n  a machine where the MCP isn't installed.\n---\n\n# Zillow via fpx (no MCP)\n\nZillow fronts `www.zillow.com` with a PerimeterX bot-wall that blocks\nplain `curl`/Node requests, and several tools (saved searches/homes)\nneed an actual signed-in session. `fpx` routes every request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), so the\nsame page loads that a real visit would.\n\nThis is the same data the `zillow_*` MCP tools return — every property\ntool is a scrape of Zillow's server-rendered Next.js pages\n(`__NEXT_DATA__`), not a documented JSON API. No credentials are stored\nanywhere; auth (for the saved-data endpoints) is just \"have a signed-in\nzillow.com tab open.\"\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli             # provides `fpx`\nfpx profile add zillow --domain zillow.com # only the fetch capability is needed\nfpx pair -p zillow                         # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n([releases](https://github.com/nullnet-app/contextmint-bridge/releases)), with an\nopen `www.zillow.com` tab, and its Chrome **Site access** allowing\n`zillow.com`. (ContextMint Bridge is the renamed fetchproxy extension from the\nsame maintainer; build it from source or verify the release zip with\n`shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`.) For the saved-searches/saved-homes calls, that tab must\nalso be **signed in**. Pairing persists — after the first approval every\nlater `fpx` call reuses it.\n\n## Core call\n\nEvery endpoint here is a GET of a server-rendered HTML page (Zillow is a\nNext.js app; the whole page state is embedded as JSON in a\n`<script id=\"__NEXT_DATA__\">` tag) — there is no JSON API to hit\ndirectly. Fetch, then pull the JSON out of the HTML:\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow > /tmp/page.html\npython3 -c '\nimport re, sys, json\nhtml = open(\"/tmp/page.html\").read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n' | jq '.'\n```\n\n`references/pages.md` has the extractor as a reusable one-liner plus the\nper-page `pageProps` field paths (search results, property detail,\nphotos, price/tax/Zestimate history, saved searches/homes, market\nreport) and the address-autocomplete GraphQL call, all transcribed from\nthe MCP's `src/tools/*.ts` (which parse the exact same pages).\n\n## The one rule: resolve the location first (search only)\n\n`zillow_search_properties`'s two-step dance is exactly what\n`/homes/<slug>_rb/` needs: fetch the bare slug path first to get Zillow's\nresolved `regionSelection` + `mapBounds`, THEN re-fetch with those pinned\ninto a `searchQueryState` query param alongside your filters — a filtered\nfetch without the pinned region silently falls back to the user's last\nsearch region instead of honoring the slug. A full-address query can\nresolve straight to a `homedetails` page (no region at all) — see\n`references/pages.md` §1 for both shapes. Property lookups by `zpid`\nneed no resolve step — `/homedetails/<zpid>_zpid/` is direct.\n\n## Auth\n\nNo login is stored or passed by `fpx` — the saved-searches\n(`/myzillow/SavedSearches`) and saved-homes (`/myzillow/favorites`) pages\nsimply render your saved data (or redirect to `/user/login`) depending on\nwhether the tab riding the bridge is signed in. Everything else is\nanonymous.\n\n## Exit codes (fetch verbs)\n\n- `0` — success. A signed-out redirect (`/user/login`, `?login=true`) or\n  a captcha interstitial (body contains `captcha-delivery`, small body)\n  can still ride in a `0` response — check the fetched HTML, `fpx`\n  doesn't know Zillow's sign-in/bot-wall markers.\n- `2` — bridge unavailable: extension not connected or pairing pending →\n  run `fpx pair -p zillow`, confirm a zillow.com tab is open.\n- `3` — bot wall: the tab hasn't cleared PerimeterX → open/refresh a\n  `www.zillow.com` tab and retry.\n- `4` — upstream non-2xx from Zillow.\n\n## Notes\n\n- `fpx health -p zillow` shows bridge connection state when a call fails.\n- Zillow publishes no consumer API — these are the same private\n  server-rendered pages the zillow.com web app itself loads, reached\n  through your own signed-in tab.\n- This project is developed and maintained by AI (Claude).\n\nFile v1.1.5:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"zillow-fpx\",\n  \"version\": \"1.1.5\",\n  \"publishedAt\": 1790992040414\n}\n\nFile v1.1.5:references/pages.md\n\n# Zillow pages for fpx\n\nAll paths below are fetched with `fpx get 'https://www.zillow.com<path>' -p zillow`.\nEvery page is server-rendered Next.js — the data lives in\n`__NEXT_DATA__.props.pageProps`, never in a separate JSON API. Field\npaths below are transcribed from the MCP's parsers\n(`src/next-data.ts`, `src/tools/*.ts`) — live-verified there, not\nre-captured here.\n\n## 0. The extractor (reuse for every page below)\n\n```sh\nextract_page_props() {\n  python3 -c '\nimport re, sys, json\nhtml = sys.stdin.read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nif not m:\n    sys.exit(\"no __NEXT_DATA__ script tag found — likely a bot-wall or redirect page\")\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n'\n}\n\nfpx get 'https://www.zillow.com/robots.txt' -p zillow  # smoke test, no parsing needed\n```\n\nPipe any fetched HTML through `extract_page_props` to get the page's\n`pageProps` as one JSON line, then `jq` into it per the recipes below.\n\n## 1. Search listings\n\nTwo-step dance — **always resolve before filtering**:\n\n**Step 1 — resolve** (bare slug, no query string):\n\n```sh\nfpx get 'https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '.searchPageState.queryState.regionSelection, .searchPageState.queryState.mapBounds' /tmp/pp.json\n```\n\n- If `searchPageState` is present with a non-empty `regionSelection` +\n  `mapBounds` → you have a **region**; proceed to step 2.\n- If `searchPageState` is **absent** but `pageProps.gdpClientCache` (or\n  `pageProps.componentProps.gdpClientCache`) is present, Zillow resolved\n  the query straight to ONE property (a homedetails page) — see §2, no\n  step 2 needed.\n- If `searchPageState.queryState.regionSelection` is empty AND\n  `cat1.searchResults.listResults` is non-empty, Zillow returned\n  address/street-level listings directly with no region to pin — use\n  those listings as-is (issue #31 in the MCP).\n\n**Step 2 — filtered search** (region pinned + your filters), only when\nstep 1 gave you a region:\n\n```sh\nSQS='{\"usersSearchTerm\":\"Brooklyn, NY\",\"filterState\":{\"price\":{\"max\":900000},\"beds\":{\"min\":2}},\"isListVisible\":true,\"isMapVisible\":false,\"regionSelection\":[{\"regionId\":37607,\"regionType\":17}],\"mapBounds\":{\"north\":40.74,\"south\":40.57,\"east\":-73.83,\"west\":-74.05}}'\nENC=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$SQS\")\nfpx get \"https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/?searchQueryState=${ENC}\" -p zillow \\\n  | extract_page_props | jq '.searchPageState.cat1.searchResults.listResults[] | {zpid: .hdpData.homeInfo.zpid, price: .hdpData.homeInfo.price, address: .hdpData.homeInfo.streetAddress, beds: .hdpData.homeInfo.bedrooms, url: .detailUrl}'\n```\n\n`filterState` keys the MCP sets (mirror these in the JSON above):\n`isForRent`/`isForSaleByAgent`/etc `{value: true|false}` (status\nswitches), `price {min,max}`, `beds {min}`, `baths {min}`, one\n`{value:true}` flag per home type (`isSingleFamily`, `isCondo`,\n`isTownhouse`, `isMultiFamily`, `isManufactured`, `isLotLand`,\n`isApartment`), and `pagination: {currentPage: N}` for page > 1. Zillow\nreturns ~40 listings per page; increment `pagination.currentPage` and\nre-fetch to walk further pages (stop on an empty `listResults`).\n\nPagination example (page 2):\n\n```sh\nSQS='{...same as above..., \"pagination\":{\"currentPage\":2}}'\n```\n\n## 2. Property detail by zpid\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\n# gdpClientCache is a JSON-encoded STRING inside pageProps — parse twice.\njq -r '.gdpClientCache // .componentProps.gdpClientCache' /tmp/pp.json \\\n  | jq '[to_entries[] | select(.key | startswith(\"Property:\")) | select(.value.property) | .value.property][0]\n        // [to_entries[] | select(.value.property) | .value.property][0]'\n```\n\nThat gives the raw `property` object. Useful top-level fields: `zpid`,\n`hdpUrl`, `address {streetAddress,city,state,zipcode,neighborhood}`,\n`mlsStreetAddress` (canonical MLS address — may disagree with `address`,\nprefer it when present), `price`, `zestimate`, `rentZestimate`,\n`bedrooms`, `bathrooms`, `livingArea`, `lotSize` (sqft), `yearBuilt`,\n`homeType`, `homeStatus`, `description`, `latitude`/`longitude`,\n`daysOnZillow`, `taxAssessedValue`/`taxAssessedYear`,\n`taxAnnualAmount` (values < 10 are a not-yet-assessed sentinel, not a\nreal bill), `schools[]`, `resoFacts {yearBuilt, associationFee,\nassociationFeeFrequency, taxAnnualAmount}` (MLS fallback source),\n`priceHistory[]`, `taxHistory[]`.\n\nOnly a URL with a trailing `<zpid>_zpid/` resolves — a slug-only URL\nredirects to the generic search page (no `gdpClientCache`). If you only\nhave an address, resolve to a zpid via §1 or the autocomplete call in §7\nfirst.\n\n## 3. Price / tax history (same property object as §2)\n\n```sh\njq '.priceHistory' /tmp/property.json    # [{date, price, event, source, ...}]\njq '.taxHistory' /tmp/property.json      # [{time or year, value, taxIncreaseRate, ...}]\n```\n\nBoth arrays live inline on the property object fetched in §2 — no\nseparate request. Absent on some (commonly non-Showcase) listings —\nZillow renders the trend client-side for those.\n\n## 4. Zestimate history (same property object as §2)\n\n```sh\njq '(first(.homeValueChartData[] | select(.name==\"This home\")) // .homeValueChartData[0]) | .points' /tmp/property.json\n```\n\nEach point is `{x: <unix ms>, y: <value>}` or `{date, value}` depending\non deploy. Fall back to deriving a series from `priceHistory[].{date,price}`\nwhen `homeValueChartData` is absent. `rentValueChartData` is the parallel\nseries for `rent` when present.\n\n## 5. Photos (same property object as §2)\n\n```sh\njq '[.photos, .responsivePhotos, .originalPhotos] | map(select(type==\"array\" and length>0)) | first // []' /tmp/property.json\n```\n\nEach entry: `{caption, subjectType, url, mixedSources: {jpeg: [{url,width}], webp: [{url,width}]}}`.\nPick the widest `mixedSources.jpeg`/`webp` entry for the largest image;\n`url` alone is the hero/thumbnail. `streetViewImageUrl` and\n`hiResImageLink` sit at the top level of the property object too.\n\n## 6. Saved searches / saved homes (requires a signed-in tab)\n\n```sh\n# Saved searches — path is case-sensitive (capital S)\nfpx get 'https://www.zillow.com/myzillow/SavedSearches' -p zillow \\\n  | extract_page_props | jq '.savedSearches // .userSavedSearches'\n\n# Saved (favorited) homes — flattened across collections\nfpx get 'https://www.zillow.com/myzillow/favorites' -p zillow \\\n  | extract_page_props | jq '[.collectionsResponse[] | (.homes // .properties // .items // [])[]]'\n```\n\nA signed-out tab redirects to `/user/login` instead of rendering these —\ncheck the fetched HTML's final URL / body before trusting an empty\nresult as \"no saves.\"\n\n## 7. Market report for a region\n\n```sh\nfpx get 'https://www.zillow.com/home-values/6181/brooklyn-ny/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '{region: .zhviRegion, analytics: .odpMarketAnalytics}' /tmp/pp.json\n```\n\n`zhviRegion {name, regionTypeName, parentCounty.name, parentState.name}`;\n`odpMarketAnalytics.mrktListingLatest {newListings, forSaleInventory,\nmedianListPrice, medianDaysOnMarket}`; `.mrktSaleLatest\n{medianSalePrice, daysToPending}`; `.zhviLatest {zhvi, zhviYoY,\nasOfDate}` (`zhviYoY` is a fraction — multiply by 100 for a percent).\nThe region id/slug (e.g. `6181/brooklyn-ny`) comes from a Zillow\nhome-values URL; there's no separate region-lookup endpoint documented\nin the MCP.\n\n## 8. Address autocomplete (bonus — resolving a free-text address to a zpid)\n\nZillow's own address typeahead, used internally by the MCP's\n`zillow_get_by_address` resolver ladder before it falls back to §1's\nsearch. Inline GraphQL (no persisted-query hash), POST:\n\n```sh\ncat > /tmp/ac.json <<'JSON'\n{\n  \"operationName\": \"GetAutocompleteResults\",\n  \"query\": \"query GetAutocompleteResults($query: String!, $queryOptions: SearchAssistanceQueryOptions, $resultType: [SearchAssistanceResultType], $shouldRequestSpellCorrectedMetadata: Boolean = false) { searchAssistanceResult: zgsAutocompleteRequest(query: $query, queryOptions: $queryOptions, resultType: $resultType, shouldRequestSpellCorrectedMetadata: $shouldRequestSpellCorrectedMetadata) { requestId results { __typename ... on SearchAssistanceAddressResult { id } } } }\",\n  \"variables\": { \"query\": \"3538 Trent St Charlotte NC\", \"resultType\": [\"REGIONS\",\"FORSALE\",\"RENTALS\",\"SOLD\",\"COMMUNITIES\",\"SCHOOLS\",\"SCHOOL_DISTRICTS\",\"SEMANTIC_REGIONS\",\"BUILDER_COMMUNITIES\"], \"shouldRequestSpellCorrectedMetadata\": false },\n  \"resultType\": [\"REGIONS\",\"FORSALE\",\"RENTALS\",\"SOLD\",\"COMMUNITIES\",\"SCHOOLS\",\"SCHOOL_DISTRICTS\",\"SEMANTIC_REGIONS\",\"BUILDER_COMMUNITIES\"],\n  \"shouldRequestSpellCorrectedMetadata\": false\n}\nJSON\nQS='query=3538%20Trent%20St%20Charlotte%20NC&resultType=REGIONS&resultType=FORSALE&resultType=RENTALS&resultType=SOLD&resultType=COMMUNITIES&resultType=SCHOOLS&resultType=SCHOOL_DISTRICTS&resultType=SEMANTIC_REGIONS&resultType=BUILDER_COMMUNITIES&shouldRequestSpellCorrectedMetadata=false&operationName=GetAutocompleteResults'\nfpx post-json \"https://www.zillow.com/zg-graph?${QS}\" @/tmp/ac.json -p zillow \\\n  -H 'origin: https://www.zillow.com' \\\n  -H 'referer: https://www.zillow.com/homes/for_sale/' \\\n  -H 'x-caller-id: static-search-page-graphql' \\\n  | jq -r '.data.searchAssistanceResult.results[] | select(.__typename==\"SearchAssistanceAddressResult\") | .id'\n```\n\nEach result `.id` is a full canonical address string (e.g.\n`\"3538 Trent St Charlotte, NC 28209\"`) — feed that string into §1's\nresolve step (`/homes/<that-string>_rb/`) to get the zpid. These three\nheaders are cookie-free by design — the bridge supplies the session\nambiently; don't add a `Cookie` header yourself.\n\n## 9. Healthcheck\n\n```sh\nfpx get 'https://www.zillow.com/robots.txt' -p zillow\n```\n\nA 200 with plain-text `robots.txt` content confirms the bridge, the\nextension, and a responsive zillow.com tab — the same probe\n`zillow_healthcheck` runs.\n\nFile v1.1.5:skill-card.md\n\n## Description:\n\nGuides agents in using the fpx CLI and a paired browser tab to retrieve Zillow listings, property details, market reports, and authorized saved items without a Zillow MCP server.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and agents use this skill to search US property listings and inspect property records, histories, and market reports through a user's browser tab. With explicit authorization, they can also retrieve the user's saved searches and homes.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Pairing the CLI and browser extension gives the skill access to a Zillow browser tab.\n\nMitigation: Verify the extension and package source before installing, and pair only if comfortable granting that access.\n\nRisk: A signed-in tab can expose personal saved searches and homes.\n\nMitigation: Fetch saved account data only when the user explicitly requests it.\n\nRisk: Zillow sign-in redirects or bot checks may be mistaken for successful page results.\n\nMitigation: Check returned pages for sign-in or bot-check content before using extracted results.\n\n## Reference(s):\n\n- [Zillow fpx skill release](https://clawhub.ai/chrischall/skills/zillow-fpx)\n- [Zillow page and field reference](references/pages.md)\n- [ContextMint Bridge releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n\n## Skill Output:\n\n**Output Type(s):** [Shell commands, Code, Guidance]\n\n**Output Format:** [Markdown with shell and Python snippets]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Retrieved results can include personal saved items when the user explicitly authorizes access.]\n\n## Skill Version(s):\n\n1.1.5 (source: ClawHub release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.1.4: 4 files, 8466 bytes\n\nFiles: references/pages.md (10041b), skill-card.md (1885b), SKILL.md (4854b), _meta.json (129b)\n\nFile v1.1.4:SKILL.md\n\n---\nname: zillow-fpx\ndescription: >-\n  Query zillow.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the zillow-mcp server — search\n  listings, pull a full property record by zpid, price/tax/Zestimate\n  history, photos, market reports, and your signed-in saved\n  searches/homes, all via one-shot HTTP calls through a signed-in browser\n  tab. Use when you want Zillow data without the MCP, in a script, or on\n  a machine where the MCP isn't installed.\n---\n\n# Zillow via fpx (no MCP)\n\nZillow fronts `www.zillow.com` with a PerimeterX bot-wall that blocks\nplain `curl`/Node requests, and several tools (saved searches/homes)\nneed an actual signed-in session. `fpx` routes every request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), so the\nsame page loads that a real visit would.\n\nThis is the same data the `zillow_*` MCP tools return — every property\ntool is a scrape of Zillow's server-rendered Next.js pages\n(`__NEXT_DATA__`), not a documented JSON API. No credentials are stored\nanywhere; auth (for the saved-data endpoints) is just \"have a signed-in\nzillow.com tab open.\"\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli             # provides `fpx`\nfpx profile add zillow --domain zillow.com # only the fetch capability is needed\nfpx pair -p zillow                         # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n([releases](https://github.com/nullnet-app/contextmint-bridge/releases)), with an\nopen `www.zillow.com` tab, and its Chrome **Site access** allowing\n`zillow.com`. (ContextMint Bridge is the renamed fetchproxy extension from the\nsame maintainer; build it from source or verify the release zip with\n`shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`.) For the saved-searches/saved-homes calls, that tab must\nalso be **signed in**. Pairing persists — after the first approval every\nlater `fpx` call reuses it.\n\n## Core call\n\nEvery endpoint here is a GET of a server-rendered HTML page (Zillow is a\nNext.js app; the whole page state is embedded as JSON in a\n`<script id=\"__NEXT_DATA__\">` tag) — there is no JSON API to hit\ndirectly. Fetch, then pull the JSON out of the HTML:\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow > /tmp/page.html\npython3 -c '\nimport re, sys, json\nhtml = open(\"/tmp/page.html\").read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n' | jq '.'\n```\n\n`references/pages.md` has the extractor as a reusable one-liner plus the\nper-page `pageProps` field paths (search results, property detail,\nphotos, price/tax/Zestimate history, saved searches/homes, market\nreport) and the address-autocomplete GraphQL call, all transcribed from\nthe MCP's `src/tools/*.ts` (which parse the exact same pages).\n\n## The one rule: resolve the location first (search only)\n\n`zillow_search_properties`'s two-step dance is exactly what\n`/homes/<slug>_rb/` needs: fetch the bare slug path first to get Zillow's\nresolved `regionSelection` + `mapBounds`, THEN re-fetch with those pinned\ninto a `searchQueryState` query param alongside your filters — a filtered\nfetch without the pinned region silently falls back to the user's last\nsearch region instead of honoring the slug. A full-address query can\nresolve straight to a `homedetails` page (no region at all) — see\n`references/pages.md` §1 for both shapes. Property lookups by `zpid`\nneed no resolve step — `/homedetails/<zpid>_zpid/` is direct.\n\n## Auth\n\nNo login is stored or passed by `fpx` — the saved-searches\n(`/myzillow/SavedSearches`) and saved-homes (`/myzillow/favorites`) pages\nsimply render your saved data (or redirect to `/user/login`) depending on\nwhether the tab riding the bridge is signed in. Everything else is\nanonymous.\n\n## Exit codes (fetch verbs)\n\n- `0` — success. A signed-out redirect (`/user/login`, `?login=true`) or\n  a captcha interstitial (body contains `captcha-delivery`, small body)\n  can still ride in a `0` response — check the fetched HTML, `fpx`\n  doesn't know Zillow's sign-in/bot-wall markers.\n- `2` — bridge unavailable: extension not connected or pairing pending →\n  run `fpx pair -p zillow`, confirm a zillow.com tab is open.\n- `3` — bot wall: the tab hasn't cleared PerimeterX → open/refresh a\n  `www.zillow.com` tab and retry.\n- `4` — upstream non-2xx from Zillow.\n\n## Notes\n\n- `fpx health -p zillow` shows bridge connection state when a call fails.\n- Zillow publishes no consumer API — these are the same private\n  server-rendered pages the zillow.com web app itself loads, reached\n  through your own signed-in tab.\n- This project is developed and maintained by AI (Claude).\n\nFile v1.1.4:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"zillow-fpx\",\n  \"version\": \"1.1.4\",\n  \"publishedAt\": 1790603730603\n}\n\nFile v1.1.4:references/pages.md\n\n# Zillow pages for fpx\n\nAll paths below are fetched with `fpx get 'https://www.zillow.com<path>' -p zillow`.\nEvery page is server-rendered Next.js — the data lives in\n`__NEXT_DATA__.props.pageProps`, never in a separate JSON API. Field\npaths below are transcribed from the MCP's parsers\n(`src/next-data.ts`, `src/tools/*.ts`) — live-verified there, not\nre-captured here.\n\n## 0. The extractor (reuse for every page below)\n\n```sh\nextract_page_props() {\n  python3 -c '\nimport re, sys, json\nhtml = sys.stdin.read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nif not m:\n    sys.exit(\"no __NEXT_DATA__ script tag found — likely a bot-wall or redirect page\")\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n'\n}\n\nfpx get 'https://www.zillow.com/robots.txt' -p zillow  # smoke test, no parsing needed\n```\n\nPipe any fetched HTML through `extract_page_props` to get the page's\n`pageProps` as one JSON line, then `jq` into it per the recipes below.\n\n## 1. Search listings\n\nTwo-step dance — **always resolve before filtering**:\n\n**Step 1 — resolve** (bare slug, no query string):\n\n```sh\nfpx get 'https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '.searchPageState.queryState.regionSelection, .searchPageState.queryState.mapBounds' /tmp/pp.json\n```\n\n- If `searchPageState` is present with a non-empty `regionSelection` +\n  `mapBounds` → you have a **region**; proceed to step 2.\n- If `searchPageState` is **absent** but `pageProps.gdpClientCache` (or\n  `pageProps.componentProps.gdpClientCache`) is present, Zillow resolved\n  the query straight to ONE property (a homedetails page) — see §2, no\n  step 2 needed.\n- If `searchPageState.queryState.regionSelection` is empty AND\n  `cat1.searchResults.listResults` is non-empty, Zillow returned\n  address/street-level listings directly with no region to pin — use\n  those listings as-is (issue #31 in the MCP).\n\n**Step 2 — filtered search** (region pinned + your filters), only when\nstep 1 gave you a region:\n\n```sh\nSQS='{\"usersSearchTerm\":\"Brooklyn, NY\",\"filterState\":{\"price\":{\"max\":900000},\"beds\":{\"min\":2}},\"isListVisible\":true,\"isMapVisible\":false,\"regionSelection\":[{\"regionId\":37607,\"regionType\":17}],\"mapBounds\":{\"north\":40.74,\"south\":40.57,\"east\":-73.83,\"west\":-74.05}}'\nENC=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$SQS\")\nfpx get \"https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/?searchQueryState=${ENC}\" -p zillow \\\n  | extract_page_props | jq '.searchPageState.cat1.searchResults.listResults[] | {zpid: .hdpData.homeInfo.zpid, price: .hdpData.homeInfo.price, address: .hdpData.homeInfo.streetAddress, beds: .hdpData.homeInfo.bedrooms, url: .detailUrl}'\n```\n\n`filterState` keys the MCP sets (mirror these in the JSON above):\n`isForRent`/`isForSaleByAgent`/etc `{value: true|false}` (status\nswitches), `price {min,max}`, `beds {min}`, `baths {min}`, one\n`{value:true}` flag per home type (`isSingleFamily`, `isCondo`,\n`isTownhouse`, `isMultiFamily`, `isManufactured`, `isLotLand`,\n`isApartment`), and `pagination: {currentPage: N}` for page > 1. Zillow\nreturns ~40 listings per page; increment `pagination.currentPage` and\nre-fetch to walk further pages (stop on an empty `listResults`).\n\nPagination example (page 2):\n\n```sh\nSQS='{...same as above..., \"pagination\":{\"currentPage\":2}}'\n```\n\n## 2. Property detail by zpid\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\n# gdpClientCache is a JSON-encoded STRING inside pageProps — parse twice.\njq -r '.gdpClientCache // .componentProps.gdpClientCache' /tmp/pp.json \\\n  | jq '[to_entries[] | select(.key | startswith(\"Property:\")) | select(.value.property) | .value.property][0]\n        // [to_entries[] | select(.value.property) | .value.property][0]'\n```\n\nThat gives the raw `property` object. Useful top-level fields: `zpid`,\n`hdpUrl`, `address {streetAddress,city,state,zipcode,neighborhood}`,\n`mlsStreetAddress` (canonical MLS address — may disagree with `address`,\nprefer it when present), `price`, `zestimate`, `rentZestimate`,\n`bedrooms`, `bathrooms`, `livingArea`, `lotSize` (sqft), `yearBuilt`,\n`homeType`, `homeStatus`, `description`, `latitude`/`longitude`,\n`daysOnZillow`, `taxAssessedValue`/`taxAssessedYear`,\n`taxAnnualAmount` (values < 10 are a not-yet-assessed sentinel, not a\nreal bill), `schools[]`, `resoFacts {yearBuilt, associationFee,\nassociationFeeFrequency, taxAnnualAmount}` (MLS fallback source),\n`priceHistory[]`, `taxHistory[]`.\n\nOnly a URL with a trailing `<zpid>_zpid/` resolves — a slug-only URL\nredirects to the generic search page (no `gdpClientCache`). If you only\nhave an address, resolve to a zpid via §1 or the autocomplete call in §7\nfirst.\n\n## 3. Price / tax history (same property object as §2)\n\n```sh\njq '.priceHistory' /tmp/property.json    # [{date, price, event, source, ...}]\njq '.taxHistory' /tmp/property.json      # [{time or year, value, taxIncreaseRate, ...}]\n```\n\nBoth arrays live inline on the property object fetched in §2 — no\nseparate request. Absent on some (commonly non-Showcase) listings —\nZillow renders the trend client-side for those.\n\n## 4. Zestimate history (same property object as §2)\n\n```sh\njq '(first(.homeValueChartData[] | select(.name==\"This home\")) // .homeValueChartData[0]) | .points' /tmp/property.json\n```\n\nEach point is `{x: <unix ms>, y: <value>}` or `{date, value}` depending\non deploy. Fall back to deriving a series from `priceHistory[].{date,price}`\nwhen `homeValueChartData` is absent. `rentValueChartData` is the parallel\nseries for `rent` when present.\n\n## 5. Photos (same property object as §2)\n\n```sh\njq '[.photos, .responsivePhotos, .originalPhotos] | map(select(type==\"array\" and length>0)) | first // []' /tmp/property.json\n```\n\nEach entry: `{caption, subjectType, url, mixedSources: {jpeg: [{url,width}], webp: [{url,width}]}}`.\nPick the widest `mixedSources.jpeg`/`webp` entry for the largest image;\n`url` alone is the hero/thumbnail. `streetViewImageUrl` and\n`hiResImageLink` sit at the top level of the property object too.\n\n## 6. Saved searches / saved homes (requires a signed-in tab)\n\n```sh\n# Saved searches — path is case-sensitive (capital S)\nfpx get 'https://www.zillow.com/myzillow/SavedSearches' -p zillow \\\n  | extract_page_props | jq '.savedSearches // .userSavedSearches'\n\n# Saved (favorited) homes — flattened across collections\nfpx get 'https://www.zillow.com/myzillow/favorites' -p zillow \\\n  | extract_page_props | jq '[.collectionsResponse[] | (.homes // .properties // .items // [])[]]'\n```\n\nA signed-out tab redirects to `/user/login` instead of rendering these —\ncheck the fetched HTML's final URL / body before trusting an empty\nresult as \"no saves.\"\n\n## 7. Market report for a region\n\n```sh\nfpx get 'https://www.zillow.com/home-values/6181/brooklyn-ny/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '{region: .zhviRegion, analytics: .odpMarketAnalytics}' /tmp/pp.json\n```\n\n`zhviRegion {name, regionTypeName, parentCounty.name, parentState.name}`;\n`odpMarketAnalytics.mrktListingLatest {newListings, forSaleInventory,\nmedianListPrice, medianDaysOnMarket}`; `.mrktSaleLatest\n{medianSalePrice, daysToPending}`; `.zhviLatest {zhvi, zhviYoY,\nasOfDate}` (`zhviYoY` is a fraction — multiply by 100 for a percent).\nThe region id/slug (e.g. `6181/brooklyn-ny`) comes from a Zillow\nhome-values URL; there's no separate region-lookup endpoint documented\nin the MCP.\n\n## 8. Address autocomplete (bonus — resolving a free-text address to a zpid)\n\nZillow's own address typeahead, used internally by the MCP's\n`zillow_get_by_address` resolver ladder before it falls back to §1's\nsearch. Inline GraphQL (no persisted-query hash), POST:\n\n```sh\ncat > /tmp/ac.json <<'JSON'\n{\n  \"operationName\": \"GetAutocompleteResults\",\n  \"query\": \"query GetAutocompleteResults($query: String!, $queryOptions: SearchAssistanceQueryOptions, $resultType: [SearchAssistanceResultType], $shouldRequestSpellCorrectedMetadata: Boolean = false) { searchAssistanceResult: zgsAutocompleteRequest(query: $query, queryOptions: $queryOptions, resultType: $resultType, shouldRequestSpellCorrectedMetadata: $shouldRequestSpellCorrectedMetadata) { requestId results { __typename ... on SearchAssistanceAddressResult { id } } } }\",\n  \"variables\": { \"query\": \"3538 Trent St Charlotte NC\", \"resultType\": [\"REGIONS\",\"FORSALE\",\"RENTALS\",\"SOLD\",\"COMMUNITIES\",\"SCHOOLS\",\"SCHOOL_DISTRICTS\",\"SEMANTIC_REGIONS\",\"BUILDER_COMMUNITIES\"], \"shouldRequestSpellCorrectedMetadata\": false },\n  \"resultType\": [\"REGIONS\",\"FORSALE\",\"RENTALS\",\"SOLD\",\"COMMUNITIES\",\"SCHOOLS\",\"SCHOOL_DISTRICTS\",\"SEMANTIC_REGIONS\",\"BUILDER_COMMUNITIES\"],\n  \"shouldRequestSpellCorrectedMetadata\": false\n}\nJSON\nQS='query=3538%20Trent%20St%20Charlotte%20NC&resultType=REGIONS&resultType=FORSALE&resultType=RENTALS&resultType=SOLD&resultType=COMMUNITIES&resultType=SCHOOLS&resultType=SCHOOL_DISTRICTS&resultType=SEMANTIC_REGIONS&resultType=BUILDER_COMMUNITIES&shouldRequestSpellCorrectedMetadata=false&operationName=GetAutocompleteResults'\nfpx post-json \"https://www.zillow.com/zg-graph?${QS}\" @/tmp/ac.json -p zillow \\\n  -H 'origin: https://www.zillow.com' \\\n  -H 'referer: https://www.zillow.com/homes/for_sale/' \\\n  -H 'x-caller-id: static-search-page-graphql' \\\n  | jq -r '.data.searchAssistanceResult.results[] | select(.__typename==\"SearchAssistanceAddressResult\") | .id'\n```\n\nEach result `.id` is a full canonical address string (e.g.\n`\"3538 Trent St Charlotte, NC 28209\"`) — feed that string into §1's\nresolve step (`/homes/<that-string>_rb/`) to get the zpid. These three\nheaders are cookie-free by design — the bridge supplies the session\nambiently; don't add a `Cookie` header yourself.\n\n## 9. Healthcheck\n\n```sh\nfpx get 'https://www.zillow.com/robots.txt' -p zillow\n```\n\nA 200 with plain-text `robots.txt` content confirms the bridge, the\nextension, and a responsive zillow.com tab — the same probe\n`zillow_healthcheck` runs.\n\nFile v1.1.4:skill-card.md\n\n## Description:\n\nHelps agents query Zillow listings, property details, market reports, and signed-in saved items through a browser-connected command-line workflow without the Zillow MCP server.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nHomebuyers, real-estate researchers, and developers can ask an agent to search US Zillow listings, inspect property and market information, or retrieve their saved homes and searches when explicitly requested.\n\n### Deployment Geography for Use:\n\nUnited States\n\n## Known Risks and Mitigations:\n\nRisk: Zillow requests pass through fpx and the ContextMint Bridge browser extension.\n\nMitigation: Install only if comfortable routing Zillow requests through that browser connection.\n\nRisk: Fetching saved homes or searches can reveal personal account information.\n\nMitigation: Request signed-in saved data only when you intend to share it with the agent for the current task.\n\n## Reference(s):\n\n- [Zillow via fpx release](https://clawhub.ai/chrischall/skills/zillow-fpx)\n- [Zillow page recipes](references/pages.md)\n- [ContextMint Bridge releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Shell commands, Guidance]\n\n**Output Format:** [Markdown with shell commands and Zillow data summaries]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Saved homes and searches may contain personal Zillow account data.]\n\n## Skill Version(s):\n\n1.1.4 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.1.3: 4 files, 8242 bytes\n\nFiles: references/pages.md (10041b), skill-card.md (1677b), SKILL.md (4569b), _meta.json (129b)\n\nFile v1.1.3:SKILL.md\n\n---\nname: zillow-fpx\ndescription: >-\n  Query zillow.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the zillow-mcp server — search\n  listings, pull a full property record by zpid, price/tax/Zestimate\n  history, photos, market reports, and your signed-in saved\n  searches/homes, all via one-shot HTTP calls through a signed-in browser\n  tab. Use when you want Zillow data without the MCP, in a script, or on\n  a machine where the MCP isn't installed.\n---\n\n# Zillow via fpx (no MCP)\n\nZillow fronts `www.zillow.com` with a PerimeterX bot-wall that blocks\nplain `curl`/Node requests, and several tools (saved searches/homes)\nneed an actual signed-in session. `fpx` routes every request through the\nuser's own signed-in browser tab (the fetchproxy extension), so the\nsame page loads that a real visit would.\n\nThis is the same data the `zillow_*` MCP tools return — every property\ntool is a scrape of Zillow's server-rendered Next.js pages\n(`__NEXT_DATA__`), not a documented JSON API. No credentials are stored\nanywhere; auth (for the saved-data endpoints) is just \"have a signed-in\nzillow.com tab open.\"\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli             # provides `fpx`\nfpx profile add zillow --domain zillow.com # only the fetch capability is needed\nfpx pair -p zillow                         # prints a pair code → approve in the fetchproxy extension\n```\n\nRequirements: the **fetchproxy** browser extension installed, with an\nopen `www.zillow.com` tab, and its Chrome **Site access** allowing\n`zillow.com`. For the saved-searches/saved-homes calls, that tab must\nalso be **signed in**. Pairing persists — after the first approval every\nlater `fpx` call reuses it.\n\n## Core call\n\nEvery endpoint here is a GET of a server-rendered HTML page (Zillow is a\nNext.js app; the whole page state is embedded as JSON in a\n`<script id=\"__NEXT_DATA__\">` tag) — there is no JSON API to hit\ndirectly. Fetch, then pull the JSON out of the HTML:\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow > /tmp/page.html\npython3 -c '\nimport re, sys, json\nhtml = open(\"/tmp/page.html\").read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n' | jq '.'\n```\n\n`references/pages.md` has the extractor as a reusable one-liner plus the\nper-page `pageProps` field paths (search results, property detail,\nphotos, price/tax/Zestimate history, saved searches/homes, market\nreport) and the address-autocomplete GraphQL call, all transcribed from\nthe MCP's `src/tools/*.ts` (which parse the exact same pages).\n\n## The one rule: resolve the location first (search only)\n\n`zillow_search_properties`'s two-step dance is exactly what\n`/homes/<slug>_rb/` needs: fetch the bare slug path first to get Zillow's\nresolved `regionSelection` + `mapBounds`, THEN re-fetch with those pinned\ninto a `searchQueryState` query param alongside your filters — a filtered\nfetch without the pinned region silently falls back to the user's last\nsearch region instead of honoring the slug. A full-address query can\nresolve straight to a `homedetails` page (no region at all) — see\n`references/pages.md` §1 for both shapes. Property lookups by `zpid`\nneed no resolve step — `/homedetails/<zpid>_zpid/` is direct.\n\n## Auth\n\nNo login is stored or passed by `fpx` — the saved-searches\n(`/myzillow/SavedSearches`) and saved-homes (`/myzillow/favorites`) pages\nsimply render your saved data (or redirect to `/user/login`) depending on\nwhether the tab riding the bridge is signed in. Everything else is\nanonymous.\n\n## Exit codes (fetch verbs)\n\n- `0` — success. A signed-out redirect (`/user/login`, `?login=true`) or\n  a captcha interstitial (body contains `captcha-delivery`, small body)\n  can still ride in a `0` response — check the fetched HTML, `fpx`\n  doesn't know Zillow's sign-in/bot-wall markers.\n- `2` — bridge unavailable: extension not connected or pairing pending →\n  run `fpx pair -p zillow`, confirm a zillow.com tab is open.\n- `3` — bot wall: the tab hasn't cleared PerimeterX → open/refresh a\n  `www.zillow.com` tab and retry.\n- `4` — upstream non-2xx from Zillow.\n\n## Notes\n\n- `fpx health -p zillow` shows bridge connection state when a call fails.\n- Zillow publishes no consumer API — these are the same private\n  server-rendered pages the zillow.com web app itself loads, reached\n  through your own signed-in tab.\n- This project is developed and maintained by AI (Claude).\n\nFile v1.1.3:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"zillow-fpx\",\n  \"version\": \"1.1.3\",\n  \"publishedAt\": 1790351596945\n}\n\nFile v1.1.3:references/pages.md\n\n# Zillow\n\nArchive v1.1.2: 4 files, 8507 bytes\n\nFiles: references/pages.md (10041b), skill-card.md (2220b), SKILL.md (4569b), _meta.json (129b)","readmeExcerpt":"Skill: zillow-fpx Owner: chrischall Summary: Query zillow.com (US real-estate portal) from a shell with the fpx CLI (@fetchproxy/cli) instead of running the zillow-mcp server — search listings, pull a full property record by zpid, price/tax/Zestimate history, photos, market reports, and your signed-in saved searches/homes, all via one-shot HTTP calls through a signed-in browser tab. Use when you want Zillow data with","codeSnippets":[],"executableExamples":[{"language":"sh","snippet":"npm install -g @fetchproxy/cli             # provides `fpx`\nfpx profile add zillow --domain zillow.com # only the fetch capability is needed\nfpx pair -p zillow                         # prints a pair code → approve in ContextMint Bridge"},{"language":"sh","snippet":"fpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow > /tmp/page.html\npython3 -c '\nimport re, sys, json\nhtml = open(\"/tmp/page.html\").read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n' | jq '.'"},{"language":"sh","snippet":"extract_page_props() {\n  python3 -c '\nimport re, sys, json\nhtml = sys.stdin.read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nif not m:\n    sys.exit(\"no __NEXT_DATA__ script tag found — likely a bot-wall or redirect page\")\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n'\n}\n\nfpx get 'https://www.zillow.com/robots.txt' -p zillow  # smoke test, no parsing needed"},{"language":"sh","snippet":"fpx get 'https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '.searchPageState.queryState.regionSelection, .searchPageState.queryState.mapBounds' /tmp/pp.json"},{"language":"sh","snippet":"SQS='{\"usersSearchTerm\":\"Brooklyn, NY\",\"filterState\":{\"price\":{\"max\":900000},\"beds\":{\"min\":2}},\"isListVisible\":true,\"isMapVisible\":false,\"regionSelection\":[{\"regionId\":37607,\"regionType\":17}],\"mapBounds\":{\"north\":40.74,\"south\":40.57,\"east\":-73.83,\"west\":-74.05}}'\nENC=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$SQS\")\nfpx get \"https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/?searchQueryState=${ENC}\" -p zillow \\\n  | extract_page_props | jq '.searchPageState.cat1.searchResults.listResults[] | {zpid: .hdpData.homeInfo.zpid, price: .hdpData.homeInfo.price, address: .hdpData.homeInfo.streetAddress, beds: .hdpData.homeInfo.bedrooms, url: .detailUrl}'"},{"language":"sh","snippet":"SQS='{...same as above..., \"pagination\":{\"currentPage\":2}}'"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: zillow-fpx\ndescription: >-\n  Query zillow.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the zillow-mcp server — search\n  listings, pull a full property record by zpid, price/tax/Zestimate\n  history, photos, market reports, and your signed-in saved\n  searches/homes, all via one-shot HTTP calls through a signed-in browser\n  tab. Use when you want Zillow data without the MCP, in a script, or on\n  a machine where the MCP isn't installed.\n---\n\n# Zillow via fpx (no MCP)\n\nZillow fronts `www.zillow.com` with a PerimeterX bot-wall that blocks\nplain `curl`/Node requests, and several tools (saved searches/homes)\nneed an actual signed-in session. `fpx` routes every request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), so the\nsame page loads that a real visit would.\n\nThis is the same data the `zillow_*` MCP tools return — every property\ntool is a scrape of Zillow's server-rendered Next.js pages\n(`__NEXT_DATA__`), not a documented JSON API. No credentials are stored\nanywhere; auth (for the saved-data endpoints) is just \"have a signed-in\nzillow.com tab open.\"\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli             # provides `fpx`\nfpx profile add zillow --domain zillow.com # only the fetch capability is needed\nfpx pair -p zillow                         # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n([releases](https://github.com/nullnet-app/contextmint-bridge/releases)), with an\nopen `www.zillow.com` tab, and its Chrome **Site access** allowing\n`zillow.com`. (ContextMint Bridge is the renamed fetchproxy extension from the\nsame maintainer; build it from source or verify the release zip with\n`shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`.) For the saved-searches/saved-homes calls, that tab must\nalso be **signed in**. Pairing persists — after the first approval every\nlater `fpx` call reuses it.\n\n## Core call\n\nEvery endpoint here is a GET of a server-rendered HTML page (Zillow is a\nNext.js app; the whole page state is embedded as JSON in a\n`<script id=\"__NEXT_DATA__\">` tag) — there is no JSON API to hit\ndirectly. Fetch, then pull the JSON out of the HTML:\n\n```sh\nfpx get 'https://www.zillow.com/homedetails/12345_zpid/' -p zillow > /tmp/page.html\npython3 -c '\nimport re, sys, json\nhtml = open(\"/tmp/page.html\").read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n' | jq '.'\n```\n\n`references/pages.md` has the extractor as a reusable one-liner plus the\nper-page `pageProps` field paths (search results, property detail,\nphotos, price/tax/Zestimate history, saved searches/homes, market\nreport) and the address-autocomplete GraphQL call, all transcribed from\nthe MCP's `src/tools/*.ts` (which parse the exact same pages).\n\n## The one rule: resolve the loca"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"zillow-fpx\",\n  \"version\": \"1.2.2\",\n  \"publishedAt\": 1791588505699\n}"},{"path":"references/pages.md","content":"# Zillow pages for fpx\n\nAll paths below are fetched with `fpx get 'https://www.zillow.com<path>' -p zillow`.\nEvery page is server-rendered Next.js — the data lives in\n`__NEXT_DATA__.props.pageProps`, never in a separate JSON API. Field\npaths below are transcribed from the MCP's parsers\n(`src/next-data.ts`, `src/tools/*.ts`) — live-verified there, not\nre-captured here.\n\n## 0. The extractor (reuse for every page below)\n\n```sh\nextract_page_props() {\n  python3 -c '\nimport re, sys, json\nhtml = sys.stdin.read()\nm = re.search(r\"<script[^>]*id=[\\\"\\x27]__NEXT_DATA__[\\\"\\x27][^>]*>(.*?)</script>\", html, re.S | re.I)\nif not m:\n    sys.exit(\"no __NEXT_DATA__ script tag found — likely a bot-wall or redirect page\")\nprint(json.dumps(json.loads(m.group(1))[\"props\"][\"pageProps\"]))\n'\n}\n\nfpx get 'https://www.zillow.com/robots.txt' -p zillow  # smoke test, no parsing needed\n```\n\nPipe any fetched HTML through `extract_page_props` to get the page's\n`pageProps` as one JSON line, then `jq` into it per the recipes below.\n\n## 1. Search listings\n\nTwo-step dance — **always resolve before filtering**:\n\n**Step 1 — resolve** (bare slug, no query string):\n\n```sh\nfpx get 'https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/' -p zillow \\\n  | extract_page_props > /tmp/pp.json\njq '.searchPageState.queryState.regionSelection, .searchPageState.queryState.mapBounds' /tmp/pp.json\n```\n\n- If `searchPageState` is present with a non-empty `regionSelection` +\n  `mapBounds` → you have a **region**; proceed to step 2.\n- If `searchPageState` is **absent** but `pageProps.gdpClientCache` (or\n  `pageProps.componentProps.gdpClientCache`) is present, Zillow resolved\n  the query straight to ONE property (a homedetails page) — see §2, no\n  step 2 needed.\n- If `searchPageState.queryState.regionSelection` is empty AND\n  `cat1.searchResults.listResults` is non-empty, Zillow returned\n  address/street-level listings directly with no region to pin — use\n  those listings as-is (issue #31 in the MCP).\n\n**Step 2 — filtered search** (region pinned + your filters), only when\nstep 1 gave you a region:\n\n```sh\nSQS='{\"usersSearchTerm\":\"Brooklyn, NY\",\"filterState\":{\"price\":{\"max\":900000},\"beds\":{\"min\":2}},\"isListVisible\":true,\"isMapVisible\":false,\"regionSelection\":[{\"regionId\":37607,\"regionType\":17}],\"mapBounds\":{\"north\":40.74,\"south\":40.57,\"east\":-73.83,\"west\":-74.05}}'\nENC=$(python3 -c \"import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1]))\" \"$SQS\")\nfpx get \"https://www.zillow.com/homes/Brooklyn%2C%20NY_rb/?searchQueryState=${ENC}\" -p zillow \\\n  | extract_page_props | jq '.searchPageState.cat1.searchResults.listResults[] | {zpid: .hdpData.homeInfo.zpid, price: .hdpData.homeInfo.price, address: .hdpData.homeInfo.streetAddress, beds: .hdpData.homeInfo.bedrooms, url: .detailUrl}'\n```\n\n`filterState` keys the MCP sets (mirror these in the JSON above):\n`isForRent`/`isForSaleByAgent`/etc `{value: true|false}` (status\nswitches), `price {min,max}`, `beds {min}`, `baths {min}`, one\n`{value:true}` flag per home type (`i"},{"path":"skill-card.md","content":"## Description:\n\nGuides agents in retrieving US Zillow listings, property details, market reports, and signed-in saved data through a browser-backed shell CLI.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[chrischall](https://clawhub.ai/user/chrischall)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and agents use this skill to search US property listings and inspect Zillow property, pricing, tax, photo, and market data without running the Zillow MCP server. Signed-in users can also retrieve their saved searches and homes.\n\n### Deployment Geography for Use:\n\nUnited States\n\n## Known Risks and Mitigations:\n\nRisk: The CLI and browser extension can access Zillow pages through the user's browser session.\n\nMitigation: Install and pair them only if you are comfortable granting that access; review the extension before use.\n\nRisk: Saved searches, saved homes, and exact-address queries can expose account or location data to local scripts and command output.\n\nMitigation: Run those examples only when needed, and avoid sharing captured outputs or temporary files containing sensitive data.\n\n## Reference(s):\n\n- [Zillow pages for fpx](references/pages.md)\n- [ClawHub skill release](https://clawhub.ai/chrischall/skills/zillow-fpx)\n- [ContextMint Bridge releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n\n## Skill Output:\n\n**Output Type(s):** [Shell commands, Code, Guidance]\n\n**Output Format:** [Markdown with shell and JSON examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Retrieved results may contain property addresses or signed-in saved-listing data.]\n\n## Skill Version(s):\n\n1.2.2 (source: server-resolved release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1462,"uniquenessScore":43,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T11:28:07.451Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-10T11:28:07.451Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T13:33:25.951Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}