{"id":"0dfb0b80-45d8-4b8b-b7a6-093e18d18ad8","entityType":"agent","slug":"clawhub-chrischall-redfin-fpx","name":"redfin-fpx","canonicalUrl":"https://www.xpersona.co/agent/clawhub-chrischall-redfin-fpx","canonicalPath":"/agent/clawhub-chrischall-redfin-fpx","generatedAt":"2026-10-10T11:53:35.961Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T09:16:01.253Z","emptyReason":null},"description":"Query redfin.com (US real-estate portal) from a shell with the fpx CLI (@fetchproxy/cli) instead of running the redfin-mcp server — resolve locations/addresses, search for-sale listings, read property detail (price, beds/baths, price history, tax history), market trends, comparable rentals, climate risk, photos, and (signed-in) saved homes and saved searches, via one-shot calls through a signed-in browser tab. Use when you want Redfin 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:redfin-fpx","sourceUrl":"https://clawhub.ai/chrischall/redfin-fpx","homepage":"https://clawhub.ai/chrischall/skills/redfin-fpx","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/chrischall/redfin-fpx","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/chrischall/skills/redfin-fpx","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":64,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"redfin-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-10T09:16:01.253Z","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-10T09:16:01.253Z","emptyReason":null},"stars":null,"forks":null,"downloads":1531,"packageName":null,"latestVersion":"1.2.3","tractionLabel":"1.5K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T09:16:01.253Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T09:16:01.253Z","lastCrawledAt":"2026-10-10T09:16:01.253Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T09:16:01.253Z","lastVerifiedAt":null,"highlights":[{"version":"1.2.3","createdAt":"2026-10-09T23:28:28.798Z","changelog":"- Reference documentation updated: endpoints overview in references/stingray-endpoints.md was changed. - The skill card documentation file (skill-card.md) was removed. - No functional or interface changes to CLI or key flows.","fileCount":4,"zipByteSize":9222},{"version":"1.2.2","createdAt":"2026-10-07T13:38:28.667Z","changelog":"- Removed the documentation file skill-card.md. - No changes to functionality or user-facing features.","fileCount":4,"zipByteSize":9270},{"version":"1.2.1","createdAt":"2026-10-06T15:38:50.732Z","changelog":"- Removed the file skill-card.md. - No user-facing functional or documentation changes.","fileCount":4,"zipByteSize":9296},{"version":"1.2.0","createdAt":"2026-10-06T13:24:16.453Z","changelog":"- Removed sample file skill-card.md. - No functional or documentation changes to the skill's usage or description.","fileCount":4,"zipByteSize":9273},{"version":"1.1.8","createdAt":"2026-10-05T17:09:13.557Z","changelog":"- Removed the file: skill-card.md - No other feature or documentation changes included in this version.","fileCount":4,"zipByteSize":9173},{"version":"1.1.7","createdAt":"2026-10-05T02:50:34.567Z","changelog":"- Removed the sample file skill-card.md. - No functional or user-facing changes.","fileCount":4,"zipByteSize":9305},{"version":"1.1.6","createdAt":"2026-10-03T13:58:31.564Z","changelog":"- Removed the skill-card.md file. - No functional or documentation changes to the skill itself.","fileCount":4,"zipByteSize":9199},{"version":"1.1.5","createdAt":"2026-10-03T01:47:03.374Z","changelog":"- Removed the skill documentation file skill-card.md. - No changes to code or user-facing functionality.","fileCount":4,"zipByteSize":9191}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17cjx1a349nz5apaqp02vgz4h85728z:redfin-fpx","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s17cjx1a349nz5apaqp02vgz4h85728z:redfin-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/redfin-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-redfin-fpx/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-redfin-fpx/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-redfin-fpx/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-redfin-fpx/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-redfin-fpx/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-redfin-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-10T11:53:35.957Z"}},"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-redfin-fpx/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-redfin-fpx/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-redfin-fpx/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-chrischall-redfin-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-10T09:16:01.253Z","emptyReason":null},"readme":"Skill: redfin-fpx\n\nOwner: chrischall\n\nSummary: Query redfin.com (US real-estate portal) from a shell with the fpx CLI (@fetchproxy/cli) instead of running the redfin-mcp server — resolve locations/addresses, search for-sale listings, read property detail (price, beds/baths, price history, tax history), market trends, comparable rentals, climate risk, photos, and (signed-in) saved homes and saved searches, via one-shot calls through a signed-in browser tab. Use when you want Redfin data without the MCP, in a script, or on a machine where the MCP isn't installed.\n\nTags: latest:1.2.3\n\nVersion history:\n\nv1.2.3 | 2026-10-09T23:28:28.798Z | auto\n\n- Reference documentation updated: endpoints overview in references/stingray-endpoints.md was changed.\n- The skill card documentation file (skill-card.md) was removed.\n- No functional or interface changes to CLI or key flows.\n\nv1.2.2 | 2026-10-07T13:38:28.667Z | auto\n\n- Removed the documentation file skill-card.md.\n- No changes to functionality or user-facing features.\n\nv1.2.1 | 2026-10-06T15:38:50.732Z | auto\n\n- Removed the file skill-card.md.\n- No user-facing functional or documentation changes.\n\nv1.2.0 | 2026-10-06T13:24:16.453Z | auto\n\n- Removed sample file skill-card.md.\n- No functional or documentation changes to the skill's usage or description.\n\nv1.1.8 | 2026-10-05T17:09:13.557Z | auto\n\n- Removed the file: skill-card.md\n- No other feature or documentation changes included in this version.\n\nv1.1.7 | 2026-10-05T02:50:34.567Z | auto\n\n- Removed the sample file skill-card.md.\n- No functional or user-facing changes.\n\nv1.1.6 | 2026-10-03T13:58:31.564Z | auto\n\n- Removed the skill-card.md file.\n- No functional or documentation changes to the skill itself.\n\nv1.1.5 | 2026-10-03T01:47:03.374Z | auto\n\n- Removed the skill documentation file skill-card.md.\n- No changes to code or user-facing functionality.\n\nv1.1.4 | 2026-09-28T13:56:04.136Z | auto\n\n- Updated documentation to refer to the \"ContextMint Bridge\" extension instead of \"Transporter\"/\"fetchproxy\" extension, reflecting the extension's rename.\n- Added details and instructions for installing/verifying the ContextMint Bridge extension, including relevant GitHub links and shasum verification guidance.\n- Clarified that ContextMint Bridge is not yet available for Safari.\n- Removed the file skill-card.md.\n\nv1.1.3 | 2026-09-25T15:50:31.337Z | auto\n\nredfin-fpx 1.1.3\n\n- Removed the skill-card.md file. \n- No user-facing changes; documentation and functionality remain unchanged.\n\nv1.1.2 | 2026-09-23T21:43:25.712Z | auto\n\n- Removed the file: skill-card.md\n- No functional changes to the skill's behavior or usage.\n\nv1.1.1 | 2026-09-23T15:39:33.094Z | auto\n\n- Removed the skill-card.md file.\n- No changes to functionality or documentation content.\n\nv1.1.0 | 2026-09-20T02:53:47.478Z | auto\n\n- Removed the file skill-card.md.  \n- No functional or user-facing changes; documentation and usage remain the same.\n\nv1.0.0 | 2026-09-19T13:00:48.518Z | auto\n\n- Removed the file: skill-card.md.\n- No user-facing or functional changes; documentation and main usage remain unchanged.\n\nv0.13.5 | 2026-09-15T19:25:18.493Z | auto\n\n- Removed the skill-card.md file.\n- No changes to functionality or behavior in this release.\n- Documentation remains up to date; no user-facing impact.\n\nv0.13.4 | 2026-09-14T14:07:27.792Z | auto\n\n- Removed the skill-card.md file.\n- No user-facing functionality or documentation changes in this release.\n\nv0.13.3 | 2026-09-10T17:51:49.524Z | auto\n\n- Removed the skill-card.md file.\n- No user-facing changes to functionality or documentation.\n\nv0.13.2 | 2026-09-09T21:16:25.313Z | auto\n\n- Removed the skill-card.md file.\n- No other user-facing changes.\n\nv0.13.1 | 2026-09-05T00:51:09.950Z | auto\n\n- Removed the skill-card.md file.\n- No changes to functionality or user-facing documentation.\n\nv0.13.0 | 2026-09-04T22:22:35.489Z | auto\n\n- Removed the file skill-card.md.\n- No user-facing functionality changes.\n\nv0.12.0 | 2026-09-02T23:20:27.951Z | auto\n\n- Removed the file skill-card.md.\n- No changes to functionality or documentation beyond file cleanup.\n\nv0.11.0 | 2026-08-29T13:54:23.188Z | auto\n\n- Removed the skill-card.md file from the project.\n- No changes to functionality or documentation in SKILL.md.\n\nv0.10.5 | 2026-08-28T21:07:28.518Z | auto\n\n- Removed the skill-card.md file.\n- No user-facing functionality changes; documentation and core usage remain the same.\n\nv0.10.4 | 2026-08-28T11:34:53.983Z | auto\n\n- Removed the file skill-card.md.\n- No functional or user-facing changes; this is a documentation/file cleanup release.\n\nv0.10.3 | 2026-08-06T00:43:36.556Z | auto\n\n- Removed the file skill-card.md.\n- No other user-facing changes.\n\nv0.10.2 | 2026-07-30T12:54:01.579Z | auto\n\n- Added detailed usage instructions and core concepts to SKILL.md, documenting how to use redfin-fpx with the fpx CLI.\n- Explained the need to use the Transporter browser extension to bypass Redfin's bot protection.\n- Described endpoint usage patterns, request formatting, and two-step property detail retrieval.\n- Included troubleshooting tips (exit codes) and special notes for climate risk and authentication requirements.\n- Clarified when signed-in access is required for certain endpoints.\n\nArchive index:\n\nArchive v1.2.3: 4 files, 9222 bytes\n\nFiles: references/stingray-endpoints.md (11233b), skill-card.md (1948b), SKILL.md (5445b), _meta.json (129b)\n\nFile v1.2.3:SKILL.md\n\n---\nname: redfin-fpx\ndescription: >-\n  Query redfin.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the redfin-mcp server — resolve\n  locations/addresses, search for-sale listings, read property detail\n  (price, beds/baths, price history, tax history), market trends,\n  comparable rentals, climate risk, photos, and (signed-in) saved homes\n  and saved searches, via one-shot calls through a signed-in browser tab.\n  Use when you want Redfin data without the MCP, in a script, or on a\n  machine where the MCP isn't installed.\n---\n\n# Redfin via fpx (no MCP)\n\nRedfin fronts `www.redfin.com` — including every `/stingray/...` JSON\nendpoint — with an AWS WAF challenge that blocks plain `curl`/Node\nrequests regardless of headers. `fpx` routes the request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), which has\nalready cleared the challenge, so the same request succeeds. Most reads\nare anonymous (no Redfin login needed — just an open tab); the saved-homes\nand saved-searches endpoints additionally require the tab to be signed in\nto redfin.com.\n\nThis is the same data the `redfin_*` MCP tools return, reached with one\nCLI call instead of a running server. Every call rides through the bridge\n(no bootstrap-then-direct-fetch shortcut) — Redfin validates each request\nat the session level.\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli              # provides `fpx`\nfpx profile add redfin --domain redfin.com  # only the fetch capability is needed\nfpx pair -p redfin                          # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n(from https://github.com/nullnet-app/contextmint-bridge/releases), with an\nopen `www.redfin.com` tab, and its Chrome **Site access** allowing\n`redfin.com`. Pairing persists — after the first approval every later\n`fpx` call reuses it.\n\nContextMint Bridge is the fetchproxy extension renamed, same maintainer (see https://github.com/chrischall/fetchproxy#extension); source at https://github.com/nullnet-app/contextmint-bridge — build it yourself or verify a release zip with `shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`. Safari isn't available yet — use Chrome.\n\n## Core call\n\nAlmost every endpoint is a GET to a `/stingray/...` path. Redfin prefixes\nevery stingray JSON body with a literal anti-CSRF `{}&&`, so strip that\nbefore piping to `jq`:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin \\\n  | sed -E 's/^\\{\\}&&//' \\\n  | jq '.payload.homes'\n```\n\nEvery stripped body is an envelope `{ version, errorMessage, resultCode,\npayload }` — check `resultCode == 0` before trusting `payload` (a nonzero\ncode means Redfin rejected the request; `errorMessage` explains why).\n\nReady-to-run request paths (autocomplete, search, property detail, price\nhistory, market trends, comparable rentals, climate risk, saved homes)\nare in `references/stingray-endpoints.md`. Exhaustive field lists live in\nthe repo at `src/tools/*.ts` — the endpoints here are compact,\nlive-verified subsets.\n\n## The one rule: resolve the location/address first\n\nRedfin search takes numeric **region_id + region_type**, never place\nnames, and property detail wants a **propertyId + listingId** pair.\nAlways autocomplete first:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Seattle&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | sed -E 's/^\\{\\}&&//' \\\n  | jq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0] | \"\\(.id)\\t\\(.name)\"'\n# 2_16163  Seattle\n```\n\n`id` is formatted `\"<region_type>_<region_id>\"`. An `Addresses` section\n(instead of/alongside `Places`) means autocomplete resolved a specific\nhome rather than a region — its `url` embeds the home's canonical\n`/home/<id>` path (use that with the property-detail calls instead of a\nregion search).\n\n## Two-step property detail\n\nA homedetails URL only gets you `propertyId`/`listingId` via one extra\nround trip:\n\n1. `GET /stingray/api/home/details/initialInfo?path=<url-path>` → `{propertyId, listingId, ...}`\n2. `GET /stingray/api/home/details/aboveTheFold?propertyId=…&listingId=…&accessLevel=1` → the actual detail\n\nIf you already have `property_id` + `listing_id` (e.g. from a search\nresult), skip step 1 and go straight to `aboveTheFold` (and\n`belowTheFold` for price/tax history).\n\n## Exit codes (fetch verbs)\n\n- `0` — success (still check the stripped envelope's `resultCode`).\n- `2` — bridge unavailable: extension not connected or pairing pending → run `fpx pair -p redfin`, confirm a redfin.com tab is open.\n- `3` — bot wall: the tab hasn't cleared the AWS WAF challenge → open/refresh a `www.redfin.com` tab and retry.\n- `4` — upstream non-2xx from Redfin.\n\n## Notes\n\n- Anonymous reads only work for search/property/market/history/rentals;\n  `redfin_get_saved_homes` / `redfin_get_saved_searches` need the bridged\n  tab signed in to redfin.com.\n- Climate-risk data is **not** a JSON endpoint — it's regex-extracted\n  from the server-rendered homedetails HTML (`fpx get` the page, then\n  grep/extract; see `references/stingray-endpoints.md` §7 for the field\n  names to look for). There's no clean stingray path for it.\n- `fpx health -p redfin` shows bridge connection state when a call fails.\n- This project is developed and maintained by AI (Claude).\n\nFile v1.2.3:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"redfin-fpx\",\n  \"version\": \"1.2.3\",\n  \"publishedAt\": 1791588508798\n}\n\nFile v1.2.3:references/stingray-endpoints.md\n\n# Redfin stingray endpoints for fpx\n\nReady-to-run requests for `fpx get '<url>' -p redfin`. All paths and\nparams are transcribed from the live-verified request builders in\n`src/tools/*.ts` / `src/autocomplete.ts` in this repo — see the header\ncomment of each source file for verification dates and any known quirks.\n\nBase origin: `https://www.redfin.com`. Every `/stingray/...` response\ncarries a literal `{}&&` anti-CSRF prefix — strip it before parsing:\n\n```sh\nSTRIP='sed -E s/^\\{\\}\\&\\&//'\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin | $STRIP | jq '.payload'\n```\n\nThe stripped body is `{ version, errorMessage, resultCode, payload }`;\n`resultCode !== 0` means Redfin rejected the request (`errorMessage` has\nwhy).\n\n---\n\n## 1. Autocomplete — resolve a location or address (do this first)\n\n`GET /stingray/do/location-autocomplete`\n\nParams: `location` (free text), `start=0`, `count=1` (only the first row\nof each section is ever needed), `v=2`, `iss=false`, `ooa=true`,\n`mrs=false`.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Brooklyn%2C%20NY&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.sections[] | {name, rows: [.rows[0]]}'\n```\n\nResponse: `payload.sections[]`, each `{ name: \"Places\"|\"Addresses\"|\"Schools\"|\"Agents\"|…, rows: [...] }`.\n\n- **Places** rows: `id` formatted `\"<region_type>_<region_id>\"` (e.g.\n  `\"6_30749\"` → region_type 6, region_id 30749), `name`, `subName`, `url`.\n- **Addresses** rows: no `id` — `url` is the canonical home path, e.g.\n  `/NC/Lake-Lure/158-Raven-Blvd-28746/home/112653221`. Parse\n  `/<STATE>/<City>/<Street>-<ZIP>(/unit-<U>)?/home/<home_id>`. A full\n  street address typically returns an Addresses row instead of/alongside\n  Places — that's Redfin telling you it resolved a specific home, not a\n  searchable region.\n\n```sh\n# Region id for a search:\njq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0].id'\n# Home id + canonical url for an address:\njq -r '.payload.sections[] | select(.name==\"Addresses\") | .rows[0].url'\n```\n\n## 2. Search for-sale listings — `/stingray/api/gis`\n\nRequires a resolved `region_id` + `region_type` from §1. Query params\n(all strings/CSVs):\n\n| param | meaning |\n|---|---|\n| `al=1` | always 1 |\n| `num_homes` | result limit (Redfin web app default 40) |\n| `region_id`, `region_type` | from autocomplete |\n| `sf=1,2,3,5,6,7` | static — result fields to include |\n| `start=0` | pagination offset |\n| `status` | `1` = active for sale; `9` = active+coming-soon+contingent+pending (broader — what redfin-mcp uses as its default \"everything for sale\" view) |\n| `uipt` | CSV of property-type bitmap: house=1, condo=2, townhouse=3, multi_family=4, land=5, other=6, manufactured=7, co-op=8 (omit/`1,2,3,4,5,6,7,8` for all) |\n| `v=8` | static |\n| `min_price`, `max_price` | optional, USD |\n| `num_beds`, `num_baths` | optional, minimums |\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?al=1&num_homes=40&region_id=30749&region_type=6&sf=1,2,3,5,6,7&start=0&status=9&uipt=1,2,3,4,5,6,7,8&v=8&max_price=1500000' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.homes[] | {propertyId, price, streetLine, city, state, zip, beds, baths, sqFt, url}'\n```\n\nNotes:\n- Redfin's gis API has an undocumented **~350-result hard cap** per call\n  — if `payload.homes | length` hits ~350, more listings likely exist\n  server-side (narrow with price/bed filters; there's no server-side\n  pagination here).\n- Redfin's gis API can silently substitute a region it *does* index for\n  one it doesn't. Check `payload.serviceRegionName` against the region\n  you asked for; if it names a different place (or `homes[].city/state`\n  don't match the requested region), don't trust the results for\n  small/rural markets — try a nearby larger city/county instead.\n- `sqFt`/`price`/`lotSize`/etc. may ride as either a bare number or\n  `{value: number}` — unwrap defensively.\n\n## 3. Property detail (two round trips)\n\n### 3a. Resolve propertyId + listingId — `/stingray/api/home/details/initialInfo`\n\nOnly needed when you have a URL, not IDs. `path` is the URL-encoded\n`/<STATE>/<City>/<Street>-<ZIP>/home/<id>` path (no origin).\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/initialInfo?path=%2FNY%2FBrooklyn%2F42-Monroe-St-11238%2Fhome%2F40732555' \\\n  -p redfin | $STRIP | jq '.payload | {propertyId, listingId, marketId, marketName}'\n```\n\nA bare `/home/<id>` URL (no full slug) will NOT resolve here — Redfin's\nown site 301s `/home/<id>` to the full slug first. If you only have a\nnumeric property_id, `GET /home/<id>` (no `/stingray` prefix) and read\nthe bridge's followed redirect target/final URL, then feed that path to\n`initialInfo`.\n\n### 3b. Detail — `/stingray/api/home/details/aboveTheFold`\n\nParams: `propertyId`, `listingId`, `accessLevel=1`.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/aboveTheFold?propertyId=40732555&listingId=123456789&accessLevel=1' \\\n  -p redfin | $STRIP \\\n  | jq '.payload | {\n      addr: .addressSectionInfo.streetAddress,\n      price: (.addressSectionInfo.latestPriceInfo.amount // .addressSectionInfo.priceInfo.amount),\n      beds: .addressSectionInfo.beds, baths: .addressSectionInfo.baths,\n      sqft: .addressSectionInfo.sqFt,\n      remarks: .mainHouseInfo.publicRemarksParagraph,\n      photo: .mediaBrowserInfo.photos[0].photoUrls.fullScreenPhotoUrl\n    }'\n```\n\n`addressSectionInfo` carries price/beds/baths/sqft/status/dates;\n`mainHouseInfo` carries the marketing description + HOA dues;\n`mediaBrowserInfo.photos[]` carries the gallery (see §8).\n\n### 3c. Price + tax history — `/stingray/api/home/details/belowTheFold`\n\nSame `propertyId`/`listingId`/`accessLevel=1` params, different path:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/belowTheFold?propertyId=40732555&listingId=123456789&accessLevel=1' \\\n  -p redfin | $STRIP \\\n  | jq '{\n      price_events: [.payload.propertyHistoryInfo.events[] | {date: .eventDate, event: .eventDescription, price}],\n      tax_events: [.payload.publicRecordsInfo.allTaxInfo[] | {year: .rollYear, taxesDue}],\n      lot_sqft: .payload.publicRecordsInfo.basicInfo.lotSqFt\n    }'\n```\n\nField gotchas: `event.price` is a bare number (not `{amount}`); the\ntax-history array is `allTaxInfo` (current-year-only is `taxInfo`); tax\nrecords use `taxesDue`, not `taxesPaid`.\n\n## 4. Market trends — `/stingray/api/region/<region_type>/<region_id>/<property_type>/market-trends`\n\n`property_type`: `1`=all (default), `2`=house, `3`=condo, `4`=townhouse,\n`5`=multi-family, `6`=land.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/region/2/16163/1/market-trends' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.tableData | {for_sale: .homesForSaleCurMonth, sold: .homesSoldCurMonth, homesForSale, homesSold}'\n```\n\nEach row: `label`, `currentHouseAndCondoValue` (scale depends on\n`valueType`: `LONG`=count, `CURRENCY`=USD, `CURRENCY_THOUSANDS`=USD/1000,\n`PERCENT`=fraction), plus `houseAndCondoYoy{Up,ValueProportionalChange}`\nand the `Mom` equivalents. Neighborhood-typed regions (type 6) often\nreturn empty tables — prefer city-level regions for this endpoint.\n\n## 5. Comparable rentals — `/stingray/api/home/comparable-rentals`\n\nParams: `rentEstimateLow`, `rentEstimateHigh`, `latitude`, `longitude`,\n`propertyId` — the rent-estimate range and lat/lng come from the\nproperty's own page (not derivable independently; read them off\n`aboveTheFold`/the live homedetails page first).\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/comparable-rentals?rentEstimateLow=2200&rentEstimateHigh=2600&latitude=40.679&longitude=-73.958&propertyId=40732555' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.comparableRentals[] | {streetAddress, monthlyRent: .monthlyRent.amount, beds, baths, distance: .distance.value}'\n```\n\n## 6. Address resolution notes\n\n`/stingray/do/location-autocomplete` (§1) is also the address resolver —\nthere's no separate endpoint. For a fuzzy street address, retry with\ncommon suffix swaps (Rd↔Road, Ln↔Lane, St↔Street, Ave↔Avenue, …) if the\nfirst call's Addresses row doesn't come back, and verify the returned\nstreet genuinely matches what you asked for (Redfin's autocomplete is\nfuzzy and can return a neighboring house number).\n\n## 7. Climate risk — HTML extraction (no JSON endpoint)\n\nRedfin server-renders First Street Foundation climate data directly into\nthe homedetails page HTML — there is no stingray path for it (probed\nURLs 404). `fpx get` the page itself and grep/parse the embedded blocks:\n\n```sh\nfpx get 'https://www.redfin.com/NY/Brooklyn/42-Monroe-St-11238/home/40732555' -p redfin > /tmp/page.html\ngrep -o '\\\\\"floodData\\\\\":{[^}]*}' /tmp/page.html   # also try unescaped \"floodData\":{...}\ngrep -o '\\\\\"fireData\\\\\":{[^}]*}'  /tmp/page.html\ngrep -o '\\\\\"heatData\\\\\":{[^}]*}'  /tmp/page.html\n```\n\nEach block is a JSON object (possibly double-escaped — un-escape `\\\"`→`\"`\nand `\\\\`→`\\` if the naive extraction above doesn't parse). Key fields:\n`floodFactor`/`fireFactor`/`heatFactor` (1–10), `femaZones[]`,\n`chance[]` (30-yr flood-chance series), `lowInsurancePrice`/\n`highInsurancePrice`, `cumulativeRiskYear{0,5,10,15,20}`. First Street\ndoes **not** cover landslide risk. A shared `fsid`/census-tract value\nacross nearby properties usually means identical scores — cheap to\ngroup instead of re-fetching every address in a cluster.\n\n## 8. Photos\n\nAlready embedded in `aboveTheFold.mediaBrowserInfo.photos[]` (§3b) — no\nseparate endpoint. Each photo: `photoUrls.{fullScreenPhotoUrl,\nnonFullScreenPhotoUrl, nonFullScreenPhotoUrlCompressed, lightboxListUrl}`,\n`thumbnailData.thumbnailUrl`, `photoText` (caption).\n\n```sh\njq '.payload.mediaBrowserInfo.photos[] | .photoUrls.fullScreenPhotoUrl'\n```\n\nFor saved-home cards (§9), the homecards endpoint omits `photoUrls`\nentirely — construct the CDN URL yourself from `mlsId` + `dataSourceId`:\n\n```\nhttps://ssl.cdn-redfin.com/photo/<dataSourceId>/bigphoto/<last3-of-mlsId-zero-padded>/<mlsId>_0.jpg\n```\n\n(index 0 → `_0.jpg`; index N>0 → `_<N>_0.jpg`; `mbphotov3/` + `genMid.`\nprefix instead of `bigphoto/` for the mid-size variant.)\n\n## 9. Saved homes / saved searches — requires a SIGNED-IN tab\n\nThese need the bridged `www.redfin.com` tab to be logged in (not just\nbot-wall-cleared).\n\n```sh\n# 1. Favorited property IDs are embedded as /home/<id> links in the page HTML:\nfpx get 'https://www.redfin.com/myredfin/favorites' -p redfin > /tmp/favs.html\ngrep -oE '/home/[0-9]+' /tmp/favs.html | grep -oE '[0-9]+' | sort -u\n\n# 2. Fetch the home-card details for those IDs (comma-separated):\nfpx get 'https://www.redfin.com/stingray/do/api/v3/favorites/homecards?b=40732555,18659204&r=' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.homecards[] | {propertyId, isFavorite, addr: .commonHomeData.entireAddressString, price: .commonHomeData.priceInfo.amount}'\n\n# Saved searches: no JSON endpoint — region URLs are regex-extracted from the page HTML.\nfpx get 'https://www.redfin.com/myredfin/saved-searches' -p redfin \\\n  | grep -oE '\"(/(city|zipcode|neighborhood|county|state)/[^\"<>?#]+)\"'\n```\n\n## 10. Bridge healthcheck\n\n```sh\nfpx get 'https://www.redfin.com/robots.txt' -p redfin >/dev/null && echo ok\nfpx health -p redfin\n```\n\nFile v1.2.3:skill-card.md\n\n## Description:\n\nHelps agents query U.S. Redfin listings, property details, market data, and, with a signed-in browser, saved homes and searches 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 retrieve Redfin property and market information from a shell without running an MCP server. Saved homes and searches require an explicitly paired, signed-in browser session.\n\n### Deployment Geography for Use:\n\nUnited States (Redfin property data)\n\n## Known Risks and Mitigations:\n\nRisk: Saved homes and searches may expose private account data.\n\nMitigation: Ask before accessing signed-in saved items; avoid logging or sharing raw results unnecessarily.\n\nRisk: Browser pairing connects requests to the user's Redfin session.\n\nMitigation: Pair the bridge only with the user's explicit approval.\n\n## Reference(s):\n\n- [Redfin fpx skill release](https://clawhub.ai/chrischall/skills/redfin-fpx)\n- [Redfin endpoint reference](references/stingray-endpoints.md)\n- [ContextMint Bridge releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n- [Fetchproxy extension information](https://github.com/chrischall/fetchproxy#extension)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Shell commands, Configuration instructions, Guidance]\n\n**Output Format:** [Markdown with shell examples and summaries of retrieved Redfin data]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Saved-item results may contain private account data.]\n\n## Skill Version(s):\n\n1.2.3 (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.2.2: 4 files, 9270 bytes\n\nFiles: references/stingray-endpoints.md (11215b), skill-card.md (2001b), SKILL.md (5445b), _meta.json (129b)\n\nFile v1.2.2:SKILL.md\n\n---\nname: redfin-fpx\ndescription: >-\n  Query redfin.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the redfin-mcp server — resolve\n  locations/addresses, search for-sale listings, read property detail\n  (price, beds/baths, price history, tax history), market trends,\n  comparable rentals, climate risk, photos, and (signed-in) saved homes\n  and saved searches, via one-shot calls through a signed-in browser tab.\n  Use when you want Redfin data without the MCP, in a script, or on a\n  machine where the MCP isn't installed.\n---\n\n# Redfin via fpx (no MCP)\n\nRedfin fronts `www.redfin.com` — including every `/stingray/...` JSON\nendpoint — with an AWS WAF challenge that blocks plain `curl`/Node\nrequests regardless of headers. `fpx` routes the request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), which has\nalready cleared the challenge, so the same request succeeds. Most reads\nare anonymous (no Redfin login needed — just an open tab); the saved-homes\nand saved-searches endpoints additionally require the tab to be signed in\nto redfin.com.\n\nThis is the same data the `redfin_*` MCP tools return, reached with one\nCLI call instead of a running server. Every call rides through the bridge\n(no bootstrap-then-direct-fetch shortcut) — Redfin validates each request\nat the session level.\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli              # provides `fpx`\nfpx profile add redfin --domain redfin.com  # only the fetch capability is needed\nfpx pair -p redfin                          # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n(from https://github.com/nullnet-app/contextmint-bridge/releases), with an\nopen `www.redfin.com` tab, and its Chrome **Site access** allowing\n`redfin.com`. Pairing persists — after the first approval every later\n`fpx` call reuses it.\n\nContextMint Bridge is the fetchproxy extension renamed, same maintainer (see https://github.com/chrischall/fetchproxy#extension); source at https://github.com/nullnet-app/contextmint-bridge — build it yourself or verify a release zip with `shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`. Safari isn't available yet — use Chrome.\n\n## Core call\n\nAlmost every endpoint is a GET to a `/stingray/...` path. Redfin prefixes\nevery stingray JSON body with a literal anti-CSRF `{}&&`, so strip that\nbefore piping to `jq`:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin \\\n  | sed -E 's/^\\{\\}&&//' \\\n  | jq '.payload.homes'\n```\n\nEvery stripped body is an envelope `{ version, errorMessage, resultCode,\npayload }` — check `resultCode == 0` before trusting `payload` (a nonzero\ncode means Redfin rejected the request; `errorMessage` explains why).\n\nReady-to-run request paths (autocomplete, search, property detail, price\nhistory, market trends, comparable rentals, climate risk, saved homes)\nare in `references/stingray-endpoints.md`. Exhaustive field lists live in\nthe repo at `src/tools/*.ts` — the endpoints here are compact,\nlive-verified subsets.\n\n## The one rule: resolve the location/address first\n\nRedfin search takes numeric **region_id + region_type**, never place\nnames, and property detail wants a **propertyId + listingId** pair.\nAlways autocomplete first:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Seattle&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | sed -E 's/^\\{\\}&&//' \\\n  | jq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0] | \"\\(.id)\\t\\(.name)\"'\n# 2_16163  Seattle\n```\n\n`id` is formatted `\"<region_type>_<region_id>\"`. An `Addresses` section\n(instead of/alongside `Places`) means autocomplete resolved a specific\nhome rather than a region — its `url` embeds the home's canonical\n`/home/<id>` path (use that with the property-detail calls instead of a\nregion search).\n\n## Two-step property detail\n\nA homedetails URL only gets you `propertyId`/`listingId` via one extra\nround trip:\n\n1. `GET /stingray/api/home/details/initialInfo?path=<url-path>` → `{propertyId, listingId, ...}`\n2. `GET /stingray/api/home/details/aboveTheFold?propertyId=…&listingId=…&accessLevel=1` → the actual detail\n\nIf you already have `property_id` + `listing_id` (e.g. from a search\nresult), skip step 1 and go straight to `aboveTheFold` (and\n`belowTheFold` for price/tax history).\n\n## Exit codes (fetch verbs)\n\n- `0` — success (still check the stripped envelope's `resultCode`).\n- `2` — bridge unavailable: extension not connected or pairing pending → run `fpx pair -p redfin`, confirm a redfin.com tab is open.\n- `3` — bot wall: the tab hasn't cleared the AWS WAF challenge → open/refresh a `www.redfin.com` tab and retry.\n- `4` — upstream non-2xx from Redfin.\n\n## Notes\n\n- Anonymous reads only work for search/property/market/history/rentals;\n  `redfin_get_saved_homes` / `redfin_get_saved_searches` need the bridged\n  tab signed in to redfin.com.\n- Climate-risk data is **not** a JSON endpoint — it's regex-extracted\n  from the server-rendered homedetails HTML (`fpx get` the page, then\n  grep/extract; see `references/stingray-endpoints.md` §7 for the field\n  names to look for). There's no clean stingray path for it.\n- `fpx health -p redfin` shows bridge connection state when a call fails.\n- This project is developed and maintained by AI (Claude).\n\nFile v1.2.2:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"redfin-fpx\",\n  \"version\": \"1.2.2\",\n  \"publishedAt\": 1791380308667\n}\n\nFile v1.2.2:references/stingray-endpoints.md\n\n# Redfin stingray endpoints for fpx\n\nReady-to-run requests for `fpx get '<url>' -p redfin`. All paths and\nparams are transcribed from the live-verified request builders in\n`src/tools/*.ts` / `src/autocomplete.ts` in this repo — see the header\ncomment of each source file for verification dates and any known quirks.\n\nBase origin: `https://www.redfin.com`. Every `/stingray/...` response\ncarries a literal `{}&&` anti-CSRF prefix — strip it before parsing:\n\n```sh\nSTRIP='sed -E s/^\\{\\}\\&\\&//'\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin | $STRIP | jq '.payload'\n```\n\nThe stripped body is `{ version, errorMessage, resultCode, payload }`;\n`resultCode !== 0` means Redfin rejected the request (`errorMessage` has\nwhy).\n\n---\n\n## 1. Autocomplete — resolve a location or address (do this first)\n\n`GET /stingray/do/location-autocomplete`\n\nParams: `location` (free text), `start=0`, `count=1` (only the first row\nof each section is ever needed), `v=2`, `iss=false`, `ooa=true`,\n`mrs=false`.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Brooklyn%2C%20NY&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.sections[] | {name, rows: [.rows[0]]}'\n```\n\nResponse: `payload.sections[]`, each `{ name: \"Places\"|\"Addresses\"|\"Schools\"|\"Agents\"|…, rows: [...] }`.\n\n- **Places** rows: `id` formatted `\"<region_type>_<region_id>\"` (e.g.\n  `\"6_30749\"` → region_type 6, region_id 30749), `name`, `subName`, `url`.\n- **Addresses** rows: no `id` — `url` is the canonical home path, e.g.\n  `/NC/Lake-Lure/158-Raven-Blvd-28746/home/112653221`. Parse\n  `/<STATE>/<City>/<Street>-<ZIP>(/unit-<U>)?/home/<home_id>`. A full\n  street address typically returns an Addresses row instead of/alongside\n  Places — that's Redfin telling you it resolved a specific home, not a\n  searchable region.\n\n```sh\n# Region id for a search:\njq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0].id'\n# Home id + canonical url for an address:\njq -r '.payload.sections[] | select(.name==\"Addresses\") | .rows[0].url'\n```\n\n## 2. Search for-sale listings — `/stingray/api/gis`\n\nRequires a resolved `region_id` + `region_type` from §1. Query params\n(all strings/CSVs):\n\n| param | meaning |\n|---|---|\n| `al=1` | always 1 |\n| `num_homes` | result limit (Redfin web app default 40) |\n| `region_id`, `region_type` | from autocomplete |\n| `sf=1,2,3,5,6,7` | static — result fields to include |\n| `start=0` | pagination offset |\n| `status` | `1` = active for sale; `9` = active+coming-soon+contingent+pending (broader — what redfin-mcp uses as its default \"everything for sale\" view) |\n| `uipt` | CSV of property-type bitmap: house=1, condo=2, townhouse=3, multi_family=4, land=5, manufactured=6 (omit/`1,2,3,4,5,6,7,8` for all) |\n| `v=8` | static |\n| `min_price`, `max_price` | optional, USD |\n| `num_beds`, `num_baths` | optional, minimums |\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?al=1&num_homes=40&region_id=30749&region_type=6&sf=1,2,3,5,6,7&start=0&status=9&uipt=1,2,3,4,5,6,7,8&v=8&max_price=1500000' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.homes[] | {propertyId, price, streetLine, city, state, zip, beds, baths, sqFt, url}'\n```\n\nNotes:\n- Redfin's gis API has an undocumented **~350-result hard cap** per call\n  — if `payload.homes | length` hits ~350, more listings likely exist\n  server-side (narrow with price/bed filters; there's no server-side\n  pagination here).\n- Redfin's gis API can silently substitute a region it *does* index for\n  one it doesn't. Check `payload.serviceRegionName` against the region\n  you asked for; if it names a different place (or `homes[].city/state`\n  don't match the requested region), don't trust the results for\n  small/rural markets — try a nearby larger city/county instead.\n- `sqFt`/`price`/`lotSize`/etc. may ride as either a bare number or\n  `{value: number}` — unwrap defensively.\n\n## 3. Property detail (two round trips)\n\n### 3a. Resolve propertyId + listingId — `/stingray/api/home/details/initialInfo`\n\nOnly needed when you have a URL, not IDs. `path` is the URL-encoded\n`/<STATE>/<City>/<Street>-<ZIP>/home/<id>` path (no origin).\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/initialInfo?path=%2FNY%2FBrooklyn%2F42-Monroe-St-11238%2Fhome%2F40732555' \\\n  -p redfin | $STRIP | jq '.payload | {propertyId, listingId, marketId, marketName}'\n```\n\nA bare `/home/<id>` URL (no full slug) will NOT resolve here — Redfin's\nown site 301s `/home/<id>` to the full slug first. If you only have a\nnumeric property_id, `GET /home/<id>` (no `/stingray` prefix) and read\nthe bridge's followed redirect target/final URL, then feed that path to\n`initialInfo`.\n\n### 3b. Detail — `/stingray/api/home/details/aboveTheFold`\n\nParams: `propertyId`, `listingId`, `accessLevel=1`.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/aboveTheFold?propertyId=40732555&listingId=123456789&accessLevel=1' \\\n  -p redfin | $STRIP \\\n  | jq '.payload | {\n      addr: .addressSectionInfo.streetAddress,\n      price: (.addressSectionInfo.latestPriceInfo.amount // .addressSectionInfo.priceInfo.amount),\n      beds: .addressSectionInfo.beds, baths: .addressSectionInfo.baths,\n      sqft: .addressSectionInfo.sqFt,\n      remarks: .mainHouseInfo.publicRemarksParagraph,\n      photo: .mediaBrowserInfo.photos[0].photoUrls.fullScreenPhotoUrl\n    }'\n```\n\n`addressSectionInfo` carries price/beds/baths/sqft/status/dates;\n`mainHouseInfo` carries the marketing description + HOA dues;\n`mediaBrowserInfo.photos[]` carries the gallery (see §8).\n\n### 3c. Price + tax history — `/stingray/api/home/details/belowTheFold`\n\nSame `propertyId`/`listingId`/`accessLevel=1` params, different path:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/belowTheFold?propertyId=40732555&listingId=123456789&accessLevel=1' \\\n  -p redfin | $STRIP \\\n  | jq '{\n      price_events: [.payload.propertyHistoryInfo.events[] | {date: .eventDate, event: .eventDescription, price}],\n      tax_events: [.payload.publicRecordsInfo.allTaxInfo[] | {year: .rollYear, taxesDue}],\n      lot_sqft: .payload.publicRecordsInfo.basicInfo.lotSqFt\n    }'\n```\n\nField gotchas: `event.price` is a bare number (not `{amount}`); the\ntax-history array is `allTaxInfo` (current-year-only is `taxInfo`); tax\nrecords use `taxesDue`, not `taxesPaid`.\n\n## 4. Market trends — `/stingray/api/region/<region_type>/<region_id>/<property_type>/market-trends`\n\n`property_type`: `1`=all (default), `2`=house, `3`=condo, `4`=townhouse,\n`5`=multi-family, `6`=land.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/region/2/16163/1/market-trends' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.tableData | {for_sale: .homesForSaleCurMonth, sold: .homesSoldCurMonth, homesForSale, homesSold}'\n```\n\nEach row: `label`, `currentHouseAndCondoValue` (scale depends on\n`valueType`: `LONG`=count, `CURRENCY`=USD, `CURRENCY_THOUSANDS`=USD/1000,\n`PERCENT`=fraction), plus `houseAndCondoYoy{Up,ValueProportionalChange}`\nand the `Mom` equivalents. Neighborhood-typed regions (type 6) often\nreturn empty tables — prefer city-level regions for this endpoint.\n\n## 5. Comparable rentals — `/stingray/api/home/comparable-rentals`\n\nParams: `rentEstimateLow`, `rentEstimateHigh`, `latitude`, `longitude`,\n`propertyId` — the rent-estimate range and lat/lng come from the\nproperty's own page (not derivable independently; read them off\n`aboveTheFold`/the live homedetails page first).\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/comparable-rentals?rentEstimateLow=2200&rentEstimateHigh=2600&latitude=40.679&longitude=-73.958&propertyId=40732555' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.comparableRentals[] | {streetAddress, monthlyRent: .monthlyRent.amount, beds, baths, distance: .distance.value}'\n```\n\n## 6. Address resolution notes\n\n`/stingray/do/location-autocomplete` (§1) is also the address resolver —\nthere's no separate endpoint. For a fuzzy street address, retry with\ncommon suffix swaps (Rd↔Road, Ln↔Lane, St↔Street, Ave↔Avenue, …) if the\nfirst call's Addresses row doesn't come back, and verify the returned\nstreet genuinely matches what you asked for (Redfin's autocomplete is\nfuzzy and can return a neighboring house number).\n\n## 7. Climate risk — HTML extraction (no JSON endpoint)\n\nRedfin server-renders First Street Foundation climate data directly into\nthe homedetails page HTML — there is no stingray path for it (probed\nURLs 404). `fpx get` the page itself and grep/parse the embedded blocks:\n\n```sh\nfpx get 'https://www.redfin.com/NY/Brooklyn/42-Monroe-St-11238/home/40732555' -p redfin > /tmp/page.html\ngrep -o '\\\\\"floodData\\\\\":{[^}]*}' /tmp/page.html   # also try unescaped \"floodData\":{...}\ngrep -o '\\\\\"fireData\\\\\":{[^}]*}'  /tmp/page.html\ngrep -o '\\\\\"heatData\\\\\":{[^}]*}'  /tmp/page.html\n```\n\nEach block is a JSON object (possibly double-escaped — un-escape `\\\"`→`\"`\nand `\\\\`→`\\` if the naive extraction above doesn't parse). Key fields:\n`floodFactor`/`fireFactor`/`heatFactor` (1–10), `femaZones[]`,\n`chance[]` (30-yr flood-chance series), `lowInsurancePrice`/\n`highInsurancePrice`, `cumulativeRiskYear{0,5,10,15,20}`. First Street\ndoes **not** cover landslide risk. A shared `fsid`/census-tract value\nacross nearby properties usually means identical scores — cheap to\ngroup instead of re-fetching every address in a cluster.\n\n## 8. Photos\n\nAlready embedded in `aboveTheFold.mediaBrowserInfo.photos[]` (§3b) — no\nseparate endpoint. Each photo: `photoUrls.{fullScreenPhotoUrl,\nnonFullScreenPhotoUrl, nonFullScreenPhotoUrlCompressed, lightboxListUrl}`,\n`thumbnailData.thumbnailUrl`, `photoText` (caption).\n\n```sh\njq '.payload.mediaBrowserInfo.photos[] | .photoUrls.fullScreenPhotoUrl'\n```\n\nFor saved-home cards (§9), the homecards endpoint omits `photoUrls`\nentirely — construct the CDN URL yourself from `mlsId` + `dataSourceId`:\n\n```\nhttps://ssl.cdn-redfin.com/photo/<dataSourceId>/bigphoto/<last3-of-mlsId-zero-padded>/<mlsId>_0.jpg\n```\n\n(index 0 → `_0.jpg`; index N>0 → `_<N>_0.jpg`; `mbphotov3/` + `genMid.`\nprefix instead of `bigphoto/` for the mid-size variant.)\n\n## 9. Saved homes / saved searches — requires a SIGNED-IN tab\n\nThese need the bridged `www.redfin.com` tab to be logged in (not just\nbot-wall-cleared).\n\n```sh\n# 1. Favorited property IDs are embedded as /home/<id> links in the page HTML:\nfpx get 'https://www.redfin.com/myredfin/favorites' -p redfin > /tmp/favs.html\ngrep -oE '/home/[0-9]+' /tmp/favs.html | grep -oE '[0-9]+' | sort -u\n\n# 2. Fetch the home-card details for those IDs (comma-separated):\nfpx get 'https://www.redfin.com/stingray/do/api/v3/favorites/homecards?b=40732555,18659204&r=' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.homecards[] | {propertyId, isFavorite, addr: .commonHomeData.entireAddressString, price: .commonHomeData.priceInfo.amount}'\n\n# Saved searches: no JSON endpoint — region URLs are regex-extracted from the page HTML.\nfpx get 'https://www.redfin.com/myredfin/saved-searches' -p redfin \\\n  | grep -oE '\"(/(city|zipcode|neighborhood|county|state)/[^\"<>?#]+)\"'\n```\n\n## 10. Bridge healthcheck\n\n```sh\nfpx get 'https://www.redfin.com/robots.txt' -p redfin >/dev/null && echo ok\nfpx health -p redfin\n```\n\nFile v1.2.2:skill-card.md\n\n## Description:\n\nGuides agents in querying US Redfin listings, property details, market data, and optional signed-in saved items through the fpx CLI and a paired browser extension.\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 look up US homes, listings, prices, market trends, rentals, and climate risk from Redfin without running an MCP server. With explicit user intent, they can also retrieve saved homes and searches from a signed-in account.\n\n### Deployment Geography for Use:\n\nUnited States\n\n## Known Risks and Mitigations:\n\nRisk: Signed-in saved homes and searches can expose private account data to the agent.\n\nMitigation: Use saved-item endpoints only when the user specifically requests them; treat returned items as private.\n\nRisk: Requests run through a paired extension using the user's browser session.\n\nMitigation: Install and pair the fpx CLI and ContextMint Bridge only if the user accepts browser-session Redfin access.\n\n## Reference(s):\n\n- [Redfin FPX ClawHub release](https://clawhub.ai/chrischall/skills/redfin-fpx)\n- [Stingray endpoint examples](artifact/references/stingray-endpoints.md)\n- [ContextMint Bridge extension](https://github.com/nullnet-app/contextmint-bridge)\n\n## Skill Output:\n\n**Output Type(s):** [Guidance, Shell commands, Configuration instructions]\n\n**Output Format:** [Markdown with shell examples and JSON response guidance]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Redfin responses require prefix removal and result-code checking.]\n\n## Skill Version(s):\n\n1.2.2 (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.2.1: 4 files, 9296 bytes\n\nFiles: references/stingray-endpoints.md (11215b), skill-card.md (2190b), SKILL.md (5445b), _meta.json (129b)\n\nFile v1.2.1:SKILL.md\n\n---\nname: redfin-fpx\ndescription: >-\n  Query redfin.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the redfin-mcp server — resolve\n  locations/addresses, search for-sale listings, read property detail\n  (price, beds/baths, price history, tax history), market trends,\n  comparable rentals, climate risk, photos, and (signed-in) saved homes\n  and saved searches, via one-shot calls through a signed-in browser tab.\n  Use when you want Redfin data without the MCP, in a script, or on a\n  machine where the MCP isn't installed.\n---\n\n# Redfin via fpx (no MCP)\n\nRedfin fronts `www.redfin.com` — including every `/stingray/...` JSON\nendpoint — with an AWS WAF challenge that blocks plain `curl`/Node\nrequests regardless of headers. `fpx` routes the request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), which has\nalready cleared the challenge, so the same request succeeds. Most reads\nare anonymous (no Redfin login needed — just an open tab); the saved-homes\nand saved-searches endpoints additionally require the tab to be signed in\nto redfin.com.\n\nThis is the same data the `redfin_*` MCP tools return, reached with one\nCLI call instead of a running server. Every call rides through the bridge\n(no bootstrap-then-direct-fetch shortcut) — Redfin validates each request\nat the session level.\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli              # provides `fpx`\nfpx profile add redfin --domain redfin.com  # only the fetch capability is needed\nfpx pair -p redfin                          # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n(from https://github.com/nullnet-app/contextmint-bridge/releases), with an\nopen `www.redfin.com` tab, and its Chrome **Site access** allowing\n`redfin.com`. Pairing persists — after the first approval every later\n`fpx` call reuses it.\n\nContextMint Bridge is the fetchproxy extension renamed, same maintainer (see https://github.com/chrischall/fetchproxy#extension); source at https://github.com/nullnet-app/contextmint-bridge — build it yourself or verify a release zip with `shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`. Safari isn't available yet — use Chrome.\n\n## Core call\n\nAlmost every endpoint is a GET to a `/stingray/...` path. Redfin prefixes\nevery stingray JSON body with a literal anti-CSRF `{}&&`, so strip that\nbefore piping to `jq`:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin \\\n  | sed -E 's/^\\{\\}&&//' \\\n  | jq '.payload.homes'\n```\n\nEvery stripped body is an envelope `{ version, errorMessage, resultCode,\npayload }` — check `resultCode == 0` before trusting `payload` (a nonzero\ncode means Redfin rejected the request; `errorMessage` explains why).\n\nReady-to-run request paths (autocomplete, search, property detail, price\nhistory, market trends, comparable rentals, climate risk, saved homes)\nare in `references/stingray-endpoints.md`. Exhaustive field lists live in\nthe repo at `src/tools/*.ts` — the endpoints here are compact,\nlive-verified subsets.\n\n## The one rule: resolve the location/address first\n\nRedfin search takes numeric **region_id + region_type**, never place\nnames, and property detail wants a **propertyId + listingId** pair.\nAlways autocomplete first:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Seattle&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | sed -E 's/^\\{\\}&&//' \\\n  | jq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0] | \"\\(.id)\\t\\(.name)\"'\n# 2_16163  Seattle\n```\n\n`id` is formatted `\"<region_type>_<region_id>\"`. An `Addresses` section\n(instead of/alongside `Places`) means autocomplete resolved a specific\nhome rather than a region — its `url` embeds the home's canonical\n`/home/<id>` path (use that with the property-detail calls instead of a\nregion search).\n\n## Two-step property detail\n\nA homedetails URL only gets you `propertyId`/`listingId` via one extra\nround trip:\n\n1. `GET /stingray/api/home/details/initialInfo?path=<url-path>` → `{propertyId, listingId, ...}`\n2. `GET /stingray/api/home/details/aboveTheFold?propertyId=…&listingId=…&accessLevel=1` → the actual detail\n\nIf you already have `property_id` + `listing_id` (e.g. from a search\nresult), skip step 1 and go straight to `aboveTheFold` (and\n`belowTheFold` for price/tax history).\n\n## Exit codes (fetch verbs)\n\n- `0` — success (still check the stripped envelope's `resultCode`).\n- `2` — bridge unavailable: extension not connected or pairing pending → run `fpx pair -p redfin`, confirm a redfin.com tab is open.\n- `3` — bot wall: the tab hasn't cleared the AWS WAF challenge → open/refresh a `www.redfin.com` tab and retry.\n- `4` — upstream non-2xx from Redfin.\n\n## Notes\n\n- Anonymous reads only work for search/property/market/history/rentals;\n  `redfin_get_saved_homes` / `redfin_get_saved_searches` need the bridged\n  tab signed in to redfin.com.\n- Climate-risk data is **not** a JSON endpoint — it's regex-extracted\n  from the server-rendered homedetails HTML (`fpx get` the page, then\n  grep/extract; see `references/stingray-endpoints.md` §7 for the field\n  names to look for). There's no clean stingray path for it.\n- `fpx health -p redfin` shows bridge connection state when a call fails.\n- This project is developed and maintained by AI (Claude).\n\nFile v1.2.1:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"redfin-fpx\",\n  \"version\": \"1.2.1\",\n  \"publishedAt\": 1791301130732\n}\n\nFile v1.2.1:references/stingray-endpoints.md\n\n# Redfin stingray endpoints for fpx\n\nReady-to-run requests for `fpx get '<url>' -p redfin`. All paths and\nparams are transcribed from the live-verified request builders in\n`src/tools/*.ts` / `src/autocomplete.ts` in this repo — see the header\ncomment of each source file for verification dates and any known quirks.\n\nBase origin: `https://www.redfin.com`. Every `/stingray/...` response\ncarries a literal `{}&&` anti-CSRF prefix — strip it before parsing:\n\n```sh\nSTRIP='sed -E s/^\\{\\}\\&\\&//'\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin | $STRIP | jq '.payload'\n```\n\nThe stripped body is `{ version, errorMessage, resultCode, payload }`;\n`resultCode !== 0` means Redfin rejected the request (`errorMessage` has\nwhy).\n\n---\n\n## 1. Autocomplete — resolve a location or address (do this first)\n\n`GET /stingray/do/location-autocomplete`\n\nParams: `location` (free text), `start=0`, `count=1` (only the first row\nof each section is ever needed), `v=2`, `iss=false`, `ooa=true`,\n`mrs=false`.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Brooklyn%2C%20NY&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.sections[] | {name, rows: [.rows[0]]}'\n```\n\nResponse: `payload.sections[]`, each `{ name: \"Places\"|\"Addresses\"|\"Schools\"|\"Agents\"|…, rows: [...] }`.\n\n- **Places** rows: `id` formatted `\"<region_type>_<region_id>\"` (e.g.\n  `\"6_30749\"` → region_type 6, region_id 30749), `name`, `subName`, `url`.\n- **Addresses** rows: no `id` — `url` is the canonical home path, e.g.\n  `/NC/Lake-Lure/158-Raven-Blvd-28746/home/112653221`. Parse\n  `/<STATE>/<City>/<Street>-<ZIP>(/unit-<U>)?/home/<home_id>`. A full\n  street address typically returns an Addresses row instead of/alongside\n  Places — that's Redfin telling you it resolved a specific home, not a\n  searchable region.\n\n```sh\n# Region id for a search:\njq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0].id'\n# Home id + canonical url for an address:\njq -r '.payload.sections[] | select(.name==\"Addresses\") | .rows[0].url'\n```\n\n## 2. Search for-sale listings — `/stingray/api/gis`\n\nRequires a resolved `region_id` + `region_type` from §1. Query params\n(all strings/CSVs):\n\n| param | meaning |\n|---|---|\n| `al=1` | always 1 |\n| `num_homes` | result limit (Redfin web app default 40) |\n| `region_id`, `region_type` | from autocomplete |\n| `sf=1,2,3,5,6,7` | static — result fields to include |\n| `start=0` | pagination offset |\n| `status` | `1` = active for sale; `9` = active+coming-soon+contingent+pending (broader — what redfin-mcp uses as its default \"everything for sale\" view) |\n| `uipt` | CSV of property-type bitmap: house=1, condo=2, townhouse=3, multi_family=4, land=5, manufactured=6 (omit/`1,2,3,4,5,6,7,8` for all) |\n| `v=8` | static |\n| `min_price`, `max_price` | optional, USD |\n| `num_beds`, `num_baths` | optional, minimums |\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?al=1&num_homes=40&region_id=30749&region_type=6&sf=1,2,3,5,6,7&start=0&status=9&uipt=1,2,3,4,5,6,7,8&v=8&max_price=1500000' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.homes[] | {propertyId, price, streetLine, city, state, zip, beds, baths, sqFt, url}'\n```\n\nNotes:\n- Redfin's gis API has an undocumented **~350-result hard cap** per call\n  — if `payload.homes | length` hits ~350, more listings likely exist\n  server-side (narrow with price/bed filters; there's no server-side\n  pagination here).\n- Redfin's gis API can silently substitute a region it *does* index for\n  one it doesn't. Check `payload.serviceRegionName` against the region\n  you asked for; if it names a different place (or `homes[].city/state`\n  don't match the requested region), don't trust the results for\n  small/rural markets — try a nearby larger city/county instead.\n- `sqFt`/`price`/`lotSize`/etc. may ride as either a bare number or\n  `{value: number}` — unwrap defensively.\n\n## 3. Property detail (two round trips)\n\n### 3a. Resolve propertyId + listingId — `/stingray/api/home/details/initialInfo`\n\nOnly needed when you have a URL, not IDs. `path` is the URL-encoded\n`/<STATE>/<City>/<Street>-<ZIP>/home/<id>` path (no origin).\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/initialInfo?path=%2FNY%2FBrooklyn%2F42-Monroe-St-11238%2Fhome%2F40732555' \\\n  -p redfin | $STRIP | jq '.payload | {propertyId, listingId, marketId, marketName}'\n```\n\nA bare `/home/<id>` URL (no full slug) will NOT resolve here — Redfin's\nown site 301s `/home/<id>` to the full slug first. If you only have a\nnumeric property_id, `GET /home/<id>` (no `/stingray` prefix) and read\nthe bridge's followed redirect target/final URL, then feed that path to\n`initialInfo`.\n\n### 3b. Detail — `/stingray/api/home/details/aboveTheFold`\n\nParams: `propertyId`, `listingId`, `accessLevel=1`.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/aboveTheFold?propertyId=40732555&listingId=123456789&accessLevel=1' \\\n  -p redfin | $STRIP \\\n  | jq '.payload | {\n      addr: .addressSectionInfo.streetAddress,\n      price: (.addressSectionInfo.latestPriceInfo.amount // .addressSectionInfo.priceInfo.amount),\n      beds: .addressSectionInfo.beds, baths: .addressSectionInfo.baths,\n      sqft: .addressSectionInfo.sqFt,\n      remarks: .mainHouseInfo.publicRemarksParagraph,\n      photo: .mediaBrowserInfo.photos[0].photoUrls.fullScreenPhotoUrl\n    }'\n```\n\n`addressSectionInfo` carries price/beds/baths/sqft/status/dates;\n`mainHouseInfo` carries the marketing description + HOA dues;\n`mediaBrowserInfo.photos[]` carries the gallery (see §8).\n\n### 3c. Price + tax history — `/stingray/api/home/details/belowTheFold`\n\nSame `propertyId`/`listingId`/`accessLevel=1` params, different path:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/belowTheFold?propertyId=40732555&listingId=123456789&accessLevel=1' \\\n  -p redfin | $STRIP \\\n  | jq '{\n      price_events: [.payload.propertyHistoryInfo.events[] | {date: .eventDate, event: .eventDescription, price}],\n      tax_events: [.payload.publicRecordsInfo.allTaxInfo[] | {year: .rollYear, taxesDue}],\n      lot_sqft: .payload.publicRecordsInfo.basicInfo.lotSqFt\n    }'\n```\n\nField gotchas: `event.price` is a bare number (not `{amount}`); the\ntax-history array is `allTaxInfo` (current-year-only is `taxInfo`); tax\nrecords use `taxesDue`, not `taxesPaid`.\n\n## 4. Market trends — `/stingray/api/region/<region_type>/<region_id>/<property_type>/market-trends`\n\n`property_type`: `1`=all (default), `2`=house, `3`=condo, `4`=townhouse,\n`5`=multi-family, `6`=land.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/region/2/16163/1/market-trends' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.tableData | {for_sale: .homesForSaleCurMonth, sold: .homesSoldCurMonth, homesForSale, homesSold}'\n```\n\nEach row: `label`, `currentHouseAndCondoValue` (scale depends on\n`valueType`: `LONG`=count, `CURRENCY`=USD, `CURRENCY_THOUSANDS`=USD/1000,\n`PERCENT`=fraction), plus `houseAndCondoYoy{Up,ValueProportionalChange}`\nand the `Mom` equivalents. Neighborhood-typed regions (type 6) often\nreturn empty tables — prefer city-level regions for this endpoint.\n\n## 5. Comparable rentals — `/stingray/api/home/comparable-rentals`\n\nParams: `rentEstimateLow`, `rentEstimateHigh`, `latitude`, `longitude`,\n`propertyId` — the rent-estimate range and lat/lng come from the\nproperty's own page (not derivable independently; read them off\n`aboveTheFold`/the live homedetails page first).\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/comparable-rentals?rentEstimateLow=2200&rentEstimateHigh=2600&latitude=40.679&longitude=-73.958&propertyId=40732555' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.comparableRentals[] | {streetAddress, monthlyRent: .monthlyRent.amount, beds, baths, distance: .distance.value}'\n```\n\n## 6. Address resolution notes\n\n`/stingray/do/location-autocomplete` (§1) is also the address resolver —\nthere's no separate endpoint. For a fuzzy street address, retry with\ncommon suffix swaps (Rd↔Road, Ln↔Lane, St↔Street, Ave↔Avenue, …) if the\nfirst call's Addresses row doesn't come back, and verify the returned\nstreet genuinely matches what you asked for (Redfin's autocomplete is\nfuzzy and can return a neighboring house number).\n\n## 7. Climate risk — HTML extraction (no JSON endpoint)\n\nRedfin server-renders First Street Foundation climate data directly into\nthe homedetails page HTML — there is no stingray path for it (probed\nURLs 404). `fpx get` the page itself and grep/parse the embedded blocks:\n\n```sh\nfpx get 'https://www.redfin.com/NY/Brooklyn/42-Monroe-St-11238/home/40732555' -p redfin > /tmp/page.html\ngrep -o '\\\\\"floodData\\\\\":{[^}]*}' /tmp/page.html   # also try unescaped \"floodData\":{...}\ngrep -o '\\\\\"fireData\\\\\":{[^}]*}'  /tmp/page.html\ngrep -o '\\\\\"heatData\\\\\":{[^}]*}'  /tmp/page.html\n```\n\nEach block is a JSON object (possibly double-escaped — un-escape `\\\"`→`\"`\nand `\\\\`→`\\` if the naive extraction above doesn't parse). Key fields:\n`floodFactor`/`fireFactor`/`heatFactor` (1–10), `femaZones[]`,\n`chance[]` (30-yr flood-chance series), `lowInsurancePrice`/\n`highInsurancePrice`, `cumulativeRiskYear{0,5,10,15,20}`. First Street\ndoes **not** cover landslide risk. A shared `fsid`/census-tract value\nacross nearby properties usually means identical scores — cheap to\ngroup instead of re-fetching every address in a cluster.\n\n## 8. Photos\n\nAlready embedded in `aboveTheFold.mediaBrowserInfo.photos[]` (§3b) — no\nseparate endpoint. Each photo: `photoUrls.{fullScreenPhotoUrl,\nnonFullScreenPhotoUrl, nonFullScreenPhotoUrlCompressed, lightboxListUrl}`,\n`thumbnailData.thumbnailUrl`, `photoText` (caption).\n\n```sh\njq '.payload.mediaBrowserInfo.photos[] | .photoUrls.fullScreenPhotoUrl'\n```\n\nFor saved-home cards (§9), the homecards endpoint omits `photoUrls`\nentirely — construct the CDN URL yourself from `mlsId` + `dataSourceId`:\n\n```\nhttps://ssl.cdn-redfin.com/photo/<dataSourceId>/bigphoto/<last3-of-mlsId-zero-padded>/<mlsId>_0.jpg\n```\n\n(index 0 → `_0.jpg`; index N>0 → `_<N>_0.jpg`; `mbphotov3/` + `genMid.`\nprefix instead of `bigphoto/` for the mid-size variant.)\n\n## 9. Saved homes / saved searches — requires a SIGNED-IN tab\n\nThese need the bridged `www.redfin.com` tab to be logged in (not just\nbot-wall-cleared).\n\n```sh\n# 1. Favorited property IDs are embedded as /home/<id> links in the page HTML:\nfpx get 'https://www.redfin.com/myredfin/favorites' -p redfin > /tmp/favs.html\ngrep -oE '/home/[0-9]+' /tmp/favs.html | grep -oE '[0-9]+' | sort -u\n\n# 2. Fetch the home-card details for those IDs (comma-separated):\nfpx get 'https://www.redfin.com/stingray/do/api/v3/favorites/homecards?b=40732555,18659204&r=' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.homecards[] | {propertyId, isFavorite, addr: .commonHomeData.entireAddressString, price: .commonHomeData.priceInfo.amount}'\n\n# Saved searches: no JSON endpoint — region URLs are regex-extracted from the page HTML.\nfpx get 'https://www.redfin.com/myredfin/saved-searches' -p redfin \\\n  | grep -oE '\"(/(city|zipcode|neighborhood|county|state)/[^\"<>?#]+)\"'\n```\n\n## 10. Bridge healthcheck\n\n```sh\nfpx get 'https://www.redfin.com/robots.txt' -p redfin >/dev/null && echo ok\nfpx health -p redfin\n```\n\nFile v1.2.1:skill-card.md\n\n## Description:\n\nProvides shell commands for querying Redfin listings, property details, market data, climate risk, and optional signed-in saved homes and searches through the fpx browser bridge.\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 retrieve US real-estate listings and property information from a shell without running a Redfin MCP server. Signed-in users can also query their saved homes and searches.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The approved browser bridge can fetch Redfin data through an active browser session.\n\nMitigation: Pair the browser extension only if comfortable with that access, and limit its site access to redfin.com.\n\nRisk: Saved-home and saved-search examples can expose signed-in account data in shell output or temporary HTML files.\n\nMitigation: Run account-data examples only when intended; use restrictive permissions for temporary files and delete them after use.\n\n## Reference(s):\n\n- [Redfin FPX release on ClawHub](https://clawhub.ai/chrischall/skills/redfin-fpx)\n- [Redfin endpoint examples](references/stingray-endpoints.md)\n- [ContextMint Bridge source](https://github.com/nullnet-app/contextmint-bridge)\n- [ContextMint Bridge releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n- [Fetchproxy CLI and extension notes](https://github.com/chrischall/fetchproxy#extension)\n\n## Skill Output:\n\n**Output Type(s):** [Shell commands, Guidance]\n\n**Output Format:** [Markdown with shell commands and JSON query examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Requires an approved browser bridge and a Redfin tab; saved-account queries require a signed-in tab.]\n\n## Skill Version(s):\n\n1.2.1 (source: server-resolved release)\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, 9273 bytes\n\nFiles: references/stingray-endpoints.md (11215b), skill-card.md (2061b), SKILL.md (5445b), _meta.json (129b)\n\nFile v1.2.0:SKILL.md\n\n---\nname: redfin-fpx\ndescription: >-\n  Query redfin.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the redfin-mcp server — resolve\n  locations/addresses, search for-sale listings, read property detail\n  (price, beds/baths, price history, tax history), market trends,\n  comparable rentals, climate risk, photos, and (signed-in) saved homes\n  and saved searches, via one-shot calls through a signed-in browser tab.\n  Use when you want Redfin data without the MCP, in a script, or on a\n  machine where the MCP isn't installed.\n---\n\n# Redfin via fpx (no MCP)\n\nRedfin fronts `www.redfin.com` — including every `/stingray/...` JSON\nendpoint — with an AWS WAF challenge that blocks plain `curl`/Node\nrequests regardless of headers. `fpx` routes the request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), which has\nalready cleared the challenge, so the same request succeeds. Most reads\nare anonymous (no Redfin login needed — just an open tab); the saved-homes\nand saved-searches endpoints additionally require the tab to be signed in\nto redfin.com.\n\nThis is the same data the `redfin_*` MCP tools return, reached with one\nCLI call instead of a running server. Every call rides through the bridge\n(no bootstrap-then-direct-fetch shortcut) — Redfin validates each request\nat the session level.\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli              # provides `fpx`\nfpx profile add redfin --domain redfin.com  # only the fetch capability is needed\nfpx pair -p redfin                          # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n(from https://github.com/nullnet-app/contextmint-bridge/releases), with an\nopen `www.redfin.com` tab, and its Chrome **Site access** allowing\n`redfin.com`. Pairing persists — after the first approval every later\n`fpx` call reuses it.\n\nContextMint Bridge is the fetchproxy extension renamed, same maintainer (see https://github.com/chrischall/fetchproxy#extension); source at https://github.com/nullnet-app/contextmint-bridge — build it yourself or verify a release zip with `shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`. Safari isn't available yet — use Chrome.\n\n## Core call\n\nAlmost every endpoint is a GET to a `/stingray/...` path. Redfin prefixes\nevery stingray JSON body with a literal anti-CSRF `{}&&`, so strip that\nbefore piping to `jq`:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin \\\n  | sed -E 's/^\\{\\}&&//' \\\n  | jq '.payload.homes'\n```\n\nEvery stripped body is an envelope `{ version, errorMessage, resultCode,\npayload }` — check `resultCode == 0` before trusting `payload` (a nonzero\ncode means Redfin rejected the request; `errorMessage` explains why).\n\nReady-to-run request paths (autocomplete, search, property detail, price\nhistory, market trends, comparable rentals, climate risk, saved homes)\nare in `references/stingray-endpoints.md`. Exhaustive field lists live in\nthe repo at `src/tools/*.ts` — the endpoints here are compact,\nlive-verified subsets.\n\n## The one rule: resolve the location/address first\n\nRedfin search takes numeric **region_id + region_type**, never place\nnames, and property detail wants a **propertyId + listingId** pair.\nAlways autocomplete first:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Seattle&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | sed -E 's/^\\{\\}&&//' \\\n  | jq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0] | \"\\(.id)\\t\\(.name)\"'\n# 2_16163  Seattle\n```\n\n`id` is formatted `\"<region_type>_<region_id>\"`. An `Addresses` section\n(instead of/alongside `Places`) means autocomplete resolved a specific\nhome rather than a region — its `url` embeds the home's canonical\n`/home/<id>` path (use that with the property-detail calls instead of a\nregion search).\n\n## Two-step property detail\n\nA homedetails URL only gets you `propertyId`/`listingId` via one extra\nround trip:\n\n1. `GET /stingray/api/home/details/initialInfo?path=<url-path>` → `{propertyId, listingId, ...}`\n2. `GET /stingray/api/home/details/aboveTheFold?propertyId=…&listingId=…&accessLevel=1` → the actual detail\n\nIf you already have `property_id` + `listing_id` (e.g. from a search\nresult), skip step 1 and go straight to `aboveTheFold` (and\n`belowTheFold` for price/tax history).\n\n## Exit codes (fetch verbs)\n\n- `0` — success (still check the stripped envelope's `resultCode`).\n- `2` — bridge unavailable: extension not connected or pairing pending → run `fpx pair -p redfin`, confirm a redfin.com tab is open.\n- `3` — bot wall: the tab hasn't cleared the AWS WAF challenge → open/refresh a `www.redfin.com` tab and retry.\n- `4` — upstream non-2xx from Redfin.\n\n## Notes\n\n- Anonymous reads only work for search/property/market/history/rentals;\n  `redfin_get_saved_homes` / `redfin_get_saved_searches` need the bridged\n  tab signed in to redfin.com.\n- Climate-risk data is **not** a JSON endpoint — it's regex-extracted\n  from the server-rendered homedetails HTML (`fpx get` the page, then\n  grep/extract; see `references/stingray-endpoints.md` §7 for the field\n  names to look for). There's no clean stingray path for it.\n- `fpx health -p redfin` shows bridge connection state when a call fails.\n- This project is developed and maintained by AI (Claude).\n\nFile v1.2.0:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"redfin-fpx\",\n  \"version\": \"1.2.0\",\n  \"publishedAt\": 1791293056453\n}\n\nFile v1.2.0:references/stingray-endpoints.md\n\n# Redfin stingray endpoints for fpx\n\nReady-to-run requests for `fpx get '<url>' -p redfin`. All paths and\nparams are transcribed from the live-verified request builders in\n`src/tools/*.ts` / `src/autocomplete.ts` in this repo — see the header\ncomment of each source file for verification dates and any known quirks.\n\nBase origin: `https://www.redfin.com`. Every `/stingray/...` response\ncarries a literal `{}&&` anti-CSRF prefix — strip it before parsing:\n\n```sh\nSTRIP='sed -E s/^\\{\\}\\&\\&//'\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin | $STRIP | jq '.payload'\n```\n\nThe stripped body is `{ version, errorMessage, resultCode, payload }`;\n`resultCode !== 0` means Redfin rejected the request (`errorMessage` has\nwhy).\n\n---\n\n## 1. Autocomplete — resolve a location or address (do this first)\n\n`GET /stingray/do/location-autocomplete`\n\nParams: `location` (free text), `start=0`, `count=1` (only the first row\nof each section is ever needed), `v=2`, `iss=false`, `ooa=true`,\n`mrs=false`.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Brooklyn%2C%20NY&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.sections[] | {name, rows: [.rows[0]]}'\n```\n\nResponse: `payload.sections[]`, each `{ name: \"Places\"|\"Addresses\"|\"Schools\"|\"Agents\"|…, rows: [...] }`.\n\n- **Places** rows: `id` formatted `\"<region_type>_<region_id>\"` (e.g.\n  `\"6_30749\"` → region_type 6, region_id 30749), `name`, `subName`, `url`.\n- **Addresses** rows: no `id` — `url` is the canonical home path, e.g.\n  `/NC/Lake-Lure/158-Raven-Blvd-28746/home/112653221`. Parse\n  `/<STATE>/<City>/<Street>-<ZIP>(/unit-<U>)?/home/<home_id>`. A full\n  street address typically returns an Addresses row instead of/alongside\n  Places — that's Redfin telling you it resolved a specific home, not a\n  searchable region.\n\n```sh\n# Region id for a search:\njq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0].id'\n# Home id + canonical url for an address:\njq -r '.payload.sections[] | select(.name==\"Addresses\") | .rows[0].url'\n```\n\n## 2. Search for-sale listings — `/stingray/api/gis`\n\nRequires a resolved `region_id` + `region_type` from §1. Query params\n(all strings/CSVs):\n\n| param | meaning |\n|---|---|\n| `al=1` | always 1 |\n| `num_homes` | result limit (Redfin web app default 40) |\n| `region_id`, `region_type` | from autocomplete |\n| `sf=1,2,3,5,6,7` | static — result fields to include |\n| `start=0` | pagination offset |\n| `status` | `1` = active for sale; `9` = active+coming-soon+contingent+pending (broader — what redfin-mcp uses as its default \"everything for sale\" view) |\n| `uipt` | CSV of property-type bitmap: house=1, condo=2, townhouse=3, multi_family=4, land=5, manufactured=6 (omit/`1,2,3,4,5,6,7,8` for all) |\n| `v=8` | static |\n| `min_price`, `max_price` | optional, USD |\n| `num_beds`, `num_baths` | optional, minimums |\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?al=1&num_homes=40&region_id=30749&region_type=6&sf=1,2,3,5,6,7&start=0&status=9&uipt=1,2,3,4,5,6,7,8&v=8&max_price=1500000' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.homes[] | {propertyId, price, streetLine, city, state, zip, beds, baths, sqFt, url}'\n```\n\nNotes:\n- Redfin's gis API has an undocumented **~350-result hard cap** per call\n  — if `payload.homes | length` hits ~350, more listings likely exist\n  server-side (narrow with price/bed filters; there's no server-side\n  pagination here).\n- Redfin's gis API can silently substitute a region it *does* index for\n  one it doesn't. Check `payload.serviceRegionName` against the region\n  you asked for; if it names a different place (or `homes[].city/state`\n  don't match the requested region), don't trust the results for\n  small/rural markets — try a nearby larger city/county instead.\n- `sqFt`/`price`/`lotSize`/etc. may ride as either a bare number or\n  `{value: number}` — unwrap defensively.\n\n## 3. Property detail (two round trips)\n\n### 3a. Resolve propertyId + listingId — `/stingray/api/home/details/initialInfo`\n\nOnly needed when you have a URL, not IDs. `path` is the URL-encoded\n`/<STATE>/<City>/<Street>-<ZIP>/home/<id>` path (no origin).\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/initialInfo?path=%2FNY%2FBrooklyn%2F42-Monroe-St-11238%2Fhome%2F40732555' \\\n  -p redfin | $STRIP | jq '.payload | {propertyId, listingId, marketId, marketName}'\n```\n\nA bare `/home/<id>` URL (no full slug) will NOT resolve here — Redfin's\nown site 301s `/home/<id>` to the full slug first. If you only have a\nnumeric property_id, `GET /home/<id>` (no `/stingray` prefix) and read\nthe bridge's followed redirect target/final URL, then feed that path to\n`initialInfo`.\n\n### 3b. Detail — `/stingray/api/home/details/aboveTheFold`\n\nParams: `propertyId`, `listingId`, `accessLevel=1`.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/aboveTheFold?propertyId=40732555&listingId=123456789&accessLevel=1' \\\n  -p redfin | $STRIP \\\n  | jq '.payload | {\n      addr: .addressSectionInfo.streetAddress,\n      price: (.addressSectionInfo.latestPriceInfo.amount // .addressSectionInfo.priceInfo.amount),\n      beds: .addressSectionInfo.beds, baths: .addressSectionInfo.baths,\n      sqft: .addressSectionInfo.sqFt,\n      remarks: .mainHouseInfo.publicRemarksParagraph,\n      photo: .mediaBrowserInfo.photos[0].photoUrls.fullScreenPhotoUrl\n    }'\n```\n\n`addressSectionInfo` carries price/beds/baths/sqft/status/dates;\n`mainHouseInfo` carries the marketing description + HOA dues;\n`mediaBrowserInfo.photos[]` carries the gallery (see §8).\n\n### 3c. Price + tax history — `/stingray/api/home/details/belowTheFold`\n\nSame `propertyId`/`listingId`/`accessLevel=1` params, different path:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/belowTheFold?propertyId=40732555&listingId=123456789&accessLevel=1' \\\n  -p redfin | $STRIP \\\n  | jq '{\n      price_events: [.payload.propertyHistoryInfo.events[] | {date: .eventDate, event: .eventDescription, price}],\n      tax_events: [.payload.publicRecordsInfo.allTaxInfo[] | {year: .rollYear, taxesDue}],\n      lot_sqft: .payload.publicRecordsInfo.basicInfo.lotSqFt\n    }'\n```\n\nField gotchas: `event.price` is a bare number (not `{amount}`); the\ntax-history array is `allTaxInfo` (current-year-only is `taxInfo`); tax\nrecords use `taxesDue`, not `taxesPaid`.\n\n## 4. Market trends — `/stingray/api/region/<region_type>/<region_id>/<property_type>/market-trends`\n\n`property_type`: `1`=all (default), `2`=house, `3`=condo, `4`=townhouse,\n`5`=multi-family, `6`=land.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/region/2/16163/1/market-trends' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.tableData | {for_sale: .homesForSaleCurMonth, sold: .homesSoldCurMonth, homesForSale, homesSold}'\n```\n\nEach row: `label`, `currentHouseAndCondoValue` (scale depends on\n`valueType`: `LONG`=count, `CURRENCY`=USD, `CURRENCY_THOUSANDS`=USD/1000,\n`PERCENT`=fraction), plus `houseAndCondoYoy{Up,ValueProportionalChange}`\nand the `Mom` equivalents. Neighborhood-typed regions (type 6) often\nreturn empty tables — prefer city-level regions for this endpoint.\n\n## 5. Comparable rentals — `/stingray/api/home/comparable-rentals`\n\nParams: `rentEstimateLow`, `rentEstimateHigh`, `latitude`, `longitude`,\n`propertyId` — the rent-estimate range and lat/lng come from the\nproperty's own page (not derivable independently; read them off\n`aboveTheFold`/the live homedetails page first).\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/comparable-rentals?rentEstimateLow=2200&rentEstimateHigh=2600&latitude=40.679&longitude=-73.958&propertyId=40732555' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.comparableRentals[] | {streetAddress, monthlyRent: .monthlyRent.amount, beds, baths, distance: .distance.value}'\n```\n\n## 6. Address resolution notes\n\n`/stingray/do/location-autocomplete` (§1) is also the address resolver —\nthere's no separate endpoint. For a fuzzy street address, retry with\ncommon suffix swaps (Rd↔Road, Ln↔Lane, St↔Street, Ave↔Avenue, …) if the\nfirst call's Addresses row doesn't come back, and verify the returned\nstreet genuinely matches what you asked for (Redfin's autocomplete is\nfuzzy and can return a neighboring house number).\n\n## 7. Climate risk — HTML extraction (no JSON endpoint)\n\nRedfin server-renders First Street Foundation climate data directly into\nthe homedetails page HTML — there is no stingray path for it (probed\nURLs 404). `fpx get` the page itself and grep/parse the embedded blocks:\n\n```sh\nfpx get 'https://www.redfin.com/NY/Brooklyn/42-Monroe-St-11238/home/40732555' -p redfin > /tmp/page.html\ngrep -o '\\\\\"floodData\\\\\":{[^}]*}' /tmp/page.html   # also try unescaped \"floodData\":{...}\ngrep -o '\\\\\"fireData\\\\\":{[^}]*}'  /tmp/page.html\ngrep -o '\\\\\"heatData\\\\\":{[^}]*}'  /tmp/page.html\n```\n\nEach block is a JSON object (possibly double-escaped — un-escape `\\\"`→`\"`\nand `\\\\`→`\\` if the naive extraction above doesn't parse). Key fields:\n`floodFactor`/`fireFactor`/`heatFactor` (1–10), `femaZones[]`,\n`chance[]` (30-yr flood-chance series), `lowInsurancePrice`/\n`highInsurancePrice`, `cumulativeRiskYear{0,5,10,15,20}`. First Street\ndoes **not** cover landslide risk. A shared `fsid`/census-tract value\nacross nearby properties usually means identical scores — cheap to\ngroup instead of re-fetching every address in a cluster.\n\n## 8. Photos\n\nAlready embedded in `aboveTheFold.mediaBrowserInfo.photos[]` (§3b) — no\nseparate endpoint. Each photo: `photoUrls.{fullScreenPhotoUrl,\nnonFullScreenPhotoUrl, nonFullScreenPhotoUrlCompressed, lightboxListUrl}`,\n`thumbnailData.thumbnailUrl`, `photoText` (caption).\n\n```sh\njq '.payload.mediaBrowserInfo.photos[] | .photoUrls.fullScreenPhotoUrl'\n```\n\nFor saved-home cards (§9), the homecards endpoint omits `photoUrls`\nentirely — construct the CDN URL yourself from `mlsId` + `dataSourceId`:\n\n```\nhttps://ssl.cdn-redfin.com/photo/<dataSourceId>/bigphoto/<last3-of-mlsId-zero-padded>/<mlsId>_0.jpg\n```\n\n(index 0 → `_0.jpg`; index N>0 → `_<N>_0.jpg`; `mbphotov3/` + `genMid.`\nprefix instead of `bigphoto/` for the mid-size variant.)\n\n## 9. Saved homes / saved searches — requires a SIGNED-IN tab\n\nThese need the bridged `www.redfin.com` tab to be logged in (not just\nbot-wall-cleared).\n\n```sh\n# 1. Favorited property IDs are embedded as /home/<id> links in the page HTML:\nfpx get 'https://www.redfin.com/myredfin/favorites' -p redfin > /tmp/favs.html\ngrep -oE '/home/[0-9]+' /tmp/favs.html | grep -oE '[0-9]+' | sort -u\n\n# 2. Fetch the home-card details for those IDs (comma-separated):\nfpx get 'https://www.redfin.com/stingray/do/api/v3/favorites/homecards?b=40732555,18659204&r=' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.homecards[] | {propertyId, isFavorite, addr: .commonHomeData.entireAddressString, price: .commonHomeData.priceInfo.amount}'\n\n# Saved searches: no JSON endpoint — region URLs are regex-extracted from the page HTML.\nfpx get 'https://www.redfin.com/myredfin/saved-searches' -p redfin \\\n  | grep -oE '\"(/(city|zipcode|neighborhood|county|state)/[^\"<>?#]+)\"'\n```\n\n## 10. Bridge healthcheck\n\n```sh\nfpx get 'https://www.redfin.com/robots.txt' -p redfin >/dev/null && echo ok\nfpx health -p redfin\n```\n\nFile v1.2.0:skill-card.md\n\n## Description:\n\nGuides agents in looking up US Redfin listings, property details, market trends, rentals, climate risk, and optionally saved homes and searches 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 agents use this skill to retrieve US real-estate information from Redfin in shell workflows without running an MCP server; account-linked saved items are optional.\n\n### Deployment Geography for Use:\n\nUnited States\n\n## Known Risks and Mitigations:\n\nRisk: Redfin requests run through the user's browser session.\n\nMitigation: Use a separate or signed-out browser profile for public listing lookups.\n\nRisk: Saved-home and saved-search lookups can expose account-linked Redfin data to the agent and shell output.\n\nMitigation: Run those lookups only when you intend to share the saved data.\n\nRisk: Some listing searches may return a substituted region or incomplete result set.\n\nMitigation: Check the returned region and narrow broad searches before relying on results.\n\n## Reference(s):\n\n- [Redfin fpx skill release](https://clawhub.ai/chrischall/skills/redfin-fpx)\n- [Redfin endpoint guide](references/stingray-endpoints.md)\n- [ContextMint Bridge source and releases](https://github.com/nullnet-app/contextmint-bridge)\n\n## Skill Output:\n\n**Output Type(s):** [Shell commands, Guidance]\n\n**Output Format:** [Markdown with shell examples and structured lookup results]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include property details, market data, and, when explicitly requested, account-linked saved items.]\n\n## Skill Version(s):\n\n1.2.0 (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.8: 4 files, 9173 bytes\n\nFiles: references/stingray-endpoints.md (11215b), skill-card.md (1842b), SKILL.md (5445b), _meta.json (129b)\n\nFile v1.1.8:SKILL.md\n\n---\nname: redfin-fpx\ndescription: >-\n  Query redfin.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the redfin-mcp server — resolve\n  locations/addresses, search for-sale listings, read property detail\n  (price, beds/baths, price history, tax history), market trends,\n  comparable rentals, climate risk, photos, and (signed-in) saved homes\n  and saved searches, via one-shot calls through a signed-in browser tab.\n  Use when you want Redfin data without the MCP, in a script, or on a\n  machine where the MCP isn't installed.\n---\n\n# Redfin via fpx (no MCP)\n\nRedfin fronts `www.redfin.com` — including every `/stingray/...` JSON\nendpoint — with an AWS WAF challenge that blocks plain `curl`/Node\nrequests regardless of headers. `fpx` routes the request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), which has\nalready cleared the challenge, so the same request succeeds. Most reads\nare anonymous (no Redfin login needed — just an open tab); the saved-homes\nand saved-searches endpoints additionally require the tab to be signed in\nto redfin.com.\n\nThis is the same data the `redfin_*` MCP tools return, reached with one\nCLI call instead of a running server. Every call rides through the bridge\n(no bootstrap-then-direct-fetch shortcut) — Redfin validates each request\nat the session level.\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli              # provides `fpx`\nfpx profile add redfin --domain redfin.com  # only the fetch capability is needed\nfpx pair -p redfin                          # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n(from https://github.com/nullnet-app/contextmint-bridge/releases), with an\nopen `www.redfin.com` tab, and its Chrome **Site access** allowing\n`redfin.com`. Pairing persists — after the first approval every later\n`fpx` call reuses it.\n\nContextMint Bridge is the fetchproxy extension renamed, same maintainer (see https://github.com/chrischall/fetchproxy#extension); source at https://github.com/nullnet-app/contextmint-bridge — build it yourself or verify a release zip with `shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`. Safari isn't available yet — use Chrome.\n\n## Core call\n\nAlmost every endpoint is a GET to a `/stingray/...` path. Redfin prefixes\nevery stingray JSON body with a literal anti-CSRF `{}&&`, so strip that\nbefore piping to `jq`:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin \\\n  | sed -E 's/^\\{\\}&&//' \\\n  | jq '.payload.homes'\n```\n\nEvery stripped body is an envelope `{ version, errorMessage, resultCode,\npayload }` — check `resultCode == 0` before trusting `payload` (a nonzero\ncode means Redfin rejected the request; `errorMessage` explains why).\n\nReady-to-run request paths (autocomplete, search, property detail, price\nhistory, market trends, comparable rentals, climate risk, saved homes)\nare in `references/stingray-endpoints.md`. Exhaustive field lists live in\nthe repo at `src/tools/*.ts` — the endpoints here are compact,\nlive-verified subsets.\n\n## The one rule: resolve the location/address first\n\nRedfin search takes numeric **region_id + region_type**, never place\nnames, and property detail wants a **propertyId + listingId** pair.\nAlways autocomplete first:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Seattle&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | sed -E 's/^\\{\\}&&//' \\\n  | jq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0] | \"\\(.id)\\t\\(.name)\"'\n# 2_16163  Seattle\n```\n\n`id` is formatted `\"<region_type>_<region_id>\"`. An `Addresses` section\n(instead of/alongside `Places`) means autocomplete resolved a specific\nhome rather than a region — its `url` embeds the home's canonical\n`/home/<id>` path (use that with the property-detail calls instead of a\nregion search).\n\n## Two-step property detail\n\nA homedetails URL only gets you `propertyId`/`listingId` via one extra\nround trip:\n\n1. `GET /stingray/api/home/details/initialInfo?path=<url-path>` → `{propertyId, listingId, ...}`\n2. `GET /stingray/api/home/details/aboveTheFold?propertyId=…&listingId=…&accessLevel=1` → the actual detail\n\nIf you already have `property_id` + `listing_id` (e.g. from a search\nresult), skip step 1 and go straight to `aboveTheFold` (and\n`belowTheFold` for price/tax history).\n\n## Exit codes (fetch verbs)\n\n- `0` — success (still check the stripped envelope's `resultCode`).\n- `2` — bridge unavailable: extension not connected or pairing pending → run `fpx pair -p redfin`, confirm a redfin.com tab is open.\n- `3` — bot wall: the tab hasn't cleared the AWS WAF challenge → open/refresh a `www.redfin.com` tab and retry.\n- `4` — upstream non-2xx from Redfin.\n\n## Notes\n\n- Anonymous reads only work for search/property/market/history/rentals;\n  `redfin_get_saved_homes` / `redfin_get_saved_searches` need the bridged\n  tab signed in to redfin.com.\n- Climate-risk data is **not** a JSON endpoint — it's regex-extracted\n  from the server-rendered homedetails HTML (`fpx get` the page, then\n  grep/extract; see `references/stingray-endpoints.md` §7 for the field\n  names to look for). There's no clean stingray path for it.\n- `fpx health -p redfin` shows bridge connection state when a call fails.\n- This project is developed and maintained by AI (Claude).\n\nFile v1.1.8:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"redfin-fpx\",\n  \"version\": \"1.1.8\",\n  \"publishedAt\": 1791220153557\n}\n\nFile v1.1.8:references/stingray-endpoints.md\n\n# Redfin stingray endpoints for fpx\n\nReady-to-run requests for `fpx get '<url>' -p redfin`. All paths and\nparams are transcribed from the live-verified request builders in\n`src/tools/*.ts` / `src/autocomplete.ts` in this repo — see the header\ncomment of each source file for verification dates and any known quirks.\n\nBase origin: `https://www.redfin.com`. Every `/stingray/...` response\ncarries a literal `{}&&` anti-CSRF prefix — strip it before parsing:\n\n```sh\nSTRIP='sed -E s/^\\{\\}\\&\\&//'\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin | $STRIP | jq '.payload'\n```\n\nThe stripped body is `{ version, errorMessage, resultCode, payload }`;\n`resultCode !== 0` means Redfin rejected the request (`errorMessage` has\nwhy).\n\n---\n\n## 1. Autocomplete — resolve a location or address (do this first)\n\n`GET /stingray/do/location-autocomplete`\n\nParams: `location` (free text), `start=0`, `count=1` (only the first row\nof each section is ever needed), `v=2`, `iss=false`, `ooa=true`,\n`mrs=false`.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Brooklyn%2C%20NY&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.sections[] | {name, rows: [.rows[0]]}'\n```\n\nResponse: `payload.sections[]`, each `{ name: \"Places\"|\"Addresses\"|\"Schools\"|\"Agents\"|…, rows: [...] }`.\n\n- **Places** rows: `id` formatted `\"<region_type>_<region_id>\"` (e.g.\n  `\"6_30749\"` → region_type 6, region_id 30749), `name`, `subName`, `url`.\n- **Addresses** rows: no `id` — `url` is the canonical home path, e.g.\n  `/NC/Lake-Lure/158-Raven-Blvd-28746/home/112653221`. Parse\n  `/<STATE>/<City>/<Street>-<ZIP>(/unit-<U>)?/home/<home_id>`. A full\n  street address typically returns an Addresses row instead of/alongside\n  Places — that's Redfin telling you it resolved a specific home, not a\n  searchable region.\n\n```sh\n# Region id for a search:\njq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0].id'\n# Home id + canonical url for an address:\njq -r '.payload.sections[] | select(.name==\"Addresses\") | .rows[0].url'\n```\n\n## 2. Search for-sale listings — `/stingray/api/gis`\n\nRequires a resolved `region_id` + `region_type` from §1. Query params\n(all strings/CSVs):\n\n| param | meaning |\n|---|---|\n| `al=1` | always 1 |\n| `num_homes` | result limit (Redfin web app default 40) |\n| `region_id`, `region_type` | from autocomplete |\n| `sf=1,2,3,5,6,7` | static — result fields to include |\n| `start=0` | pagination offset |\n| `status` | `1` = active for sale; `9` = active+coming-soon+contingent+pending (broader — what redfin-mcp uses as its default \"everything for sale\" view) |\n| `uipt` | CSV of property-type bitmap: house=1, condo=2, townhouse=3, multi_family=4, land=5, manufactured=6 (omit/`1,2,3,4,5,6,7,8` for all) |\n| `v=8` | static |\n| `min_price`, `max_price` | optional, USD |\n| `num_beds`, `num_baths` | optional, minimums |\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?al=1&num_homes=40&region_id=30749&region_type=6&sf=1,2,3,5,6,7&start=0&status=9&uipt=1,2,3,4,5,6,7,8&v=8&max_price=1500000' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.homes[] | {propertyId, price, streetLine, city, state, zip, beds, baths, sqFt, url}'\n```\n\nNotes:\n- Redfin's gis API has an undocumented **~350-result hard cap** per call\n  — if `payload.homes | length` hits ~350, more listings likely exist\n  server-side (narrow with price/bed filters; there's no server-side\n  pagination here).\n- Redfin's gis API can silently substitute a region it *does* index for\n  one it doesn't. Check `payload.serviceRegionName` against the region\n  you asked for; if it names a different place (or `homes[].city/state`\n  don't match the requested region), don't trust the results for\n  small/rural markets — try a nearby larger city/county instead.\n- `sqFt`/`price`/`lotSize`/etc. may ride as either a bare number or\n  `{value: number}` — unwrap defensively.\n\n## 3. Property detail (two round trips)\n\n### 3a. Resolve propertyId + listingId — `/stingray/api/home/details/initialInfo`\n\nOnly needed when you have a URL, not IDs. `path` is the URL-encoded\n`/<STATE>/<City>/<Street>-<ZIP>/home/<id>` path (no origin).\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/initialInfo?path=%2FNY%2FBrooklyn%2F42-Monroe-St-11238%2Fhome%2F40732555' \\\n  -p redfin | $STRIP | jq '.payload | {propertyId, listingId, marketId, marketName}'\n```\n\nA bare `/home/<id>` URL (no full slug) will NOT resolve here — Redfin's\nown site 301s `/home/<id>` to the full slug first. If you only have a\nnumeric property_id, `GET /home/<id>` (no `/stingray` prefix) and read\nthe bridge's followed redirect target/final URL, then feed that path to\n`initialInfo`.\n\n### 3b. Detail — `/stingray/api/home/details/aboveTheFold`\n\nParams: `propertyId`, `listingId`, `accessLevel=1`.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/aboveTheFold?propertyId=40732555&listingId=123456789&accessLevel=1' \\\n  -p redfin | $STRIP \\\n  | jq '.payload | {\n      addr: .addressSectionInfo.streetAddress,\n      price: (.addressSectionInfo.latestPriceInfo.amount // .addressSectionInfo.priceInfo.amount),\n      beds: .addressSectionInfo.beds, baths: .addressSectionInfo.baths,\n      sqft: .addressSectionInfo.sqFt,\n      remarks: .mainHouseInfo.publicRemarksParagraph,\n      photo: .mediaBrowserInfo.photos[0].photoUrls.fullScreenPhotoUrl\n    }'\n```\n\n`addressSectionInfo` carries price/beds/baths/sqft/status/dates;\n`mainHouseInfo` carries the marketing description + HOA dues;\n`mediaBrowserInfo.photos[]` carries the gallery (see §8).\n\n### 3c. Price + tax history — `/stingray/api/home/details/belowTheFold`\n\nSame `propertyId`/`listingId`/`accessLevel=1` params, different path:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/belowTheFold?propertyId=40732555&listingId=123456789&accessLevel=1' \\\n  -p redfin | $STRIP \\\n  | jq '{\n      price_events: [.payload.propertyHistoryInfo.events[] | {date: .eventDate, event: .eventDescription, price}],\n      tax_events: [.payload.publicRecordsInfo.allTaxInfo[] | {year: .rollYear, taxesDue}],\n      lot_sqft: .payload.publicRecordsInfo.basicInfo.lotSqFt\n    }'\n```\n\nField gotchas: `event.price` is a bare number (not `{amount}`); the\ntax-history array is `allTaxInfo` (current-year-only is `taxInfo`); tax\nrecords use `taxesDue`, not `taxesPaid`.\n\n## 4. Market trends — `/stingray/api/region/<region_type>/<region_id>/<property_type>/market-trends`\n\n`property_type`: `1`=all (default), `2`=house, `3`=condo, `4`=townhouse,\n`5`=multi-family, `6`=land.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/region/2/16163/1/market-trends' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.tableData | {for_sale: .homesForSaleCurMonth, sold: .homesSoldCurMonth, homesForSale, homesSold}'\n```\n\nEach row: `label`, `currentHouseAndCondoValue` (scale depends on\n`valueType`: `LONG`=count, `CURRENCY`=USD, `CURRENCY_THOUSANDS`=USD/1000,\n`PERCENT`=fraction), plus `houseAndCondoYoy{Up,ValueProportionalChange}`\nand the `Mom` equivalents. Neighborhood-typed regions (type 6) often\nreturn empty tables — prefer city-level regions for this endpoint.\n\n## 5. Comparable rentals — `/stingray/api/home/comparable-rentals`\n\nParams: `rentEstimateLow`, `rentEstimateHigh`, `latitude`, `longitude`,\n`propertyId` — the rent-estimate range and lat/lng come from the\nproperty's own page (not derivable independently; read them off\n`aboveTheFold`/the live homedetails page first).\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/comparable-rentals?rentEstimateLow=2200&rentEstimateHigh=2600&latitude=40.679&longitude=-73.958&propertyId=40732555' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.comparableRentals[] | {streetAddress, monthlyRent: .monthlyRent.amount, beds, baths, distance: .distance.value}'\n```\n\n## 6. Address resolution notes\n\n`/stingray/do/location-autocomplete` (§1) is also the address resolver —\nthere's no separate endpoint. For a fuzzy street address, retry with\ncommon suffix swaps (Rd↔Road, Ln↔Lane, St↔Street, Ave↔Avenue, …) if the\nfirst call's Addresses row doesn't come back, and verify the returned\nstreet genuinely matches what you asked for (Redfin's autocomplete is\nfuzzy and can return a neighboring house number).\n\n## 7. Climate risk — HTML extraction (no JSON endpoint)\n\nRedfin server-renders First Street Foundation climate data directly into\nthe homedetails page HTML — there is no stingray path for it (probed\nURLs 404). `fpx get` the page itself and grep/parse the embedded blocks:\n\n```sh\nfpx get 'https://www.redfin.com/NY/Brooklyn/42-Monroe-St-11238/home/40732555' -p redfin > /tmp/page.html\ngrep -o '\\\\\"floodData\\\\\":{[^}]*}' /tmp/page.html   # also try unescaped \"floodData\":{...}\ngrep -o '\\\\\"fireData\\\\\":{[^}]*}'  /tmp/page.html\ngrep -o '\\\\\"heatData\\\\\":{[^}]*}'  /tmp/page.html\n```\n\nEach block is a JSON object (possibly double-escaped — un-escape `\\\"`→`\"`\nand `\\\\`→`\\` if the naive extraction above doesn't parse). Key fields:\n`floodFactor`/`fireFactor`/`heatFactor` (1–10), `femaZones[]`,\n`chance[]` (30-yr flood-chance series), `lowInsurancePrice`/\n`highInsurancePrice`, `cumulativeRiskYear{0,5,10,15,20}`. First Street\ndoes **not** cover landslide risk. A shared `fsid`/census-tract value\nacross nearby properties usually means identical scores — cheap to\ngroup instead of re-fetching every address in a cluster.\n\n## 8. Photos\n\nAlready embedded in `aboveTheFold.mediaBrowserInfo.photos[]` (§3b) — no\nseparate endpoint. Each photo: `photoUrls.{fullScreenPhotoUrl,\nnonFullScreenPhotoUrl, nonFullScreenPhotoUrlCompressed, lightboxListUrl}`,\n`thumbnailData.thumbnailUrl`, `photoText` (caption).\n\n```sh\njq '.payload.mediaBrowserInfo.photos[] | .photoUrls.fullScreenPhotoUrl'\n```\n\nFor saved-home cards (§9), the homecards endpoint omits `photoUrls`\nentirely — construct the CDN URL yourself from `mlsId` + `dataSourceId`:\n\n```\nhttps://ssl.cdn-redfin.com/photo/<dataSourceId>/bigphoto/<last3-of-mlsId-zero-padded>/<mlsId>_0.jpg\n```\n\n(index 0 → `_0.jpg`; index N>0 → `_<N>_0.jpg`; `mbphotov3/` + `genMid.`\nprefix instead of `bigphoto/` for the mid-size variant.)\n\n## 9. Saved homes / saved searches — requires a SIGNED-IN tab\n\nThese need the bridged `www.redfin.com` tab to be logged in (not just\nbot-wall-cleared).\n\n```sh\n# 1. Favorited property IDs are embedded as /home/<id> links in the page HTML:\nfpx get 'https://www.redfin.com/myredfin/favorites' -p redfin > /tmp/favs.html\ngrep -oE '/home/[0-9]+' /tmp/favs.html | grep -oE '[0-9]+' | sort -u\n\n# 2. Fetch the home-card details for those IDs (comma-separated):\nfpx get 'https://www.redfin.com/stingray/do/api/v3/favorites/homecards?b=40732555,18659204&r=' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.homecards[] | {propertyId, isFavorite, addr: .commonHomeData.entireAddressString, price: .commonHomeData.priceInfo.amount}'\n\n# Saved searches: no JSON endpoint — region URLs are regex-extracted from the page HTML.\nfpx get 'https://www.redfin.com/myredfin/saved-searches' -p redfin \\\n  | grep -oE '\"(/(city|zipcode|neighborhood|county|state)/[^\"<>?#]+)\"'\n```\n\n## 10. Bridge healthcheck\n\n```sh\nfpx get 'https://www.redfin.com/robots.txt' -p redfin >/dev/null && echo ok\nfpx health -p redfin\n```\n\nFile v1.1.8:skill-card.md\n\n## Description:\n\nHelps agents query US Redfin listings, property details, market trends, and, when authorized, saved homes and searches using the fpx command-line tool and an open 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 look up US real-estate listings, property information, local trends, rentals, and climate data without running a separate Redfin MCP server. Signed-in users can also request their saved homes and searches.\n\n### Deployment Geography for Use:\n\nUnited States\n\n## Known Risks and Mitigations:\n\nRisk: Access through an open browser tab may expose saved homes and searches associated with a signed-in Redfin account.\n\nMitigation: Grant the browser bridge access to redfin.com only if comfortable doing so, and request saved homes or searches only when explicitly intended.\n\n## Reference(s):\n\n- [Redfin endpoint reference](references/stingray-endpoints.md)\n- [ClawHub skill release](https://clawhub.ai/chrischall/skills/redfin-fpx)\n- [ContextMint Bridge source and setup](https://github.com/nullnet-app/contextmint-bridge)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Shell commands, Guidance]\n\n**Output Format:** [Markdown with shell commands and summarized Redfin results]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Some saved-account results require a signed-in Redfin browser tab.]\n\n## Skill Version(s):\n\n1.1.8 (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.7: 4 files, 9305 bytes\n\nFiles: references/stingray-endpoints.md (11215b), skill-card.md (2116b), SKILL.md (5445b), _meta.json (129b)\n\nFile v1.1.7:SKILL.md\n\n---\nname: redfin-fpx\ndescription: >-\n  Query redfin.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the redfin-mcp server — resolve\n  locations/addresses, search for-sale listings, read property detail\n  (price, beds/baths, price history, tax history), market trends,\n  comparable rentals, climate risk, photos, and (signed-in) saved homes\n  and saved searches, via one-shot calls through a signed-in browser tab.\n  Use when you want Redfin data without the MCP, in a script, or on a\n  machine where the MCP isn't installed.\n---\n\n# Redfin via fpx (no MCP)\n\nRedfin fronts `www.redfin.com` — including every `/stingray/...` JSON\nendpoint — with an AWS WAF challenge that blocks plain `curl`/Node\nrequests regardless of headers. `fpx` routes the request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), which has\nalready cleared the challenge, so the same request succeeds. Most reads\nare anonymous (no Redfin login needed — just an open tab); the saved-homes\nand saved-searches endpoints additionally require the tab to be signed in\nto redfin.com.\n\nThis is the same data the `redfin_*` MCP tools return, reached with one\nCLI call instead of a running server. Every call rides through the bridge\n(no bootstrap-then-direct-fetch shortcut) — Redfin validates each request\nat the session level.\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli              # provides `fpx`\nfpx profile add redfin --domain redfin.com  # only the fetch capability is needed\nfpx pair -p redfin                          # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n(from https://github.com/nullnet-app/contextmint-bridge/releases), with an\nopen `www.redfin.com` tab, and its Chrome **Site access** allowing\n`redfin.com`. Pairing persists — after the first approval every later\n`fpx` call reuses it.\n\nContextMint Bridge is the fetchproxy extension renamed, same maintainer (see https://github.com/chrischall/fetchproxy#extension); source at https://github.com/nullnet-app/contextmint-bridge — build it yourself or verify a release zip with `shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`. Safari isn't available yet — use Chrome.\n\n## Core call\n\nAlmost every endpoint is a GET to a `/stingray/...` path. Redfin prefixes\nevery stingray JSON body with a literal anti-CSRF `{}&&`, so strip that\nbefore piping to `jq`:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin \\\n  | sed -E 's/^\\{\\}&&//' \\\n  | jq '.payload.homes'\n```\n\nEvery stripped body is an envelope `{ version, errorMessage, resultCode,\npayload }` — check `resultCode == 0` before trusting `payload` (a nonzero\ncode means Redfin rejected the request; `errorMessage` explains why).\n\nReady-to-run request paths (autocomplete, search, property detail, price\nhistory, market trends, comparable rentals, climate risk, saved homes)\nare in `references/stingray-endpoints.md`. Exhaustive field lists live in\nthe repo at `src/tools/*.ts` — the endpoints here are compact,\nlive-verified subsets.\n\n## The one rule: resolve the location/address first\n\nRedfin search takes numeric **region_id + region_type**, never place\nnames, and property detail wants a **propertyId + listingId** pair.\nAlways autocomplete first:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Seattle&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | sed -E 's/^\\{\\}&&//' \\\n  | jq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0] | \"\\(.id)\\t\\(.name)\"'\n# 2_16163  Seattle\n```\n\n`id` is formatted `\"<region_type>_<region_id>\"`. An `Addresses` section\n(instead of/alongside `Places`) means autocomplete resolved a specific\nhome rather than a region — its `url` embeds the home's canonical\n`/home/<id>` path (use that with the property-detail calls instead of a\nregion search).\n\n## Two-step property detail\n\nA homedetails URL only gets you `propertyId`/`listingId` via one extra\nround trip:\n\n1. `GET /stingray/api/home/details/initialInfo?path=<url-path>` → `{propertyId, listingId, ...}`\n2. `GET /stingray/api/home/details/aboveTheFold?propertyId=…&listingId=…&accessLevel=1` → the actual detail\n\nIf you already have `property_id` + `listing_id` (e.g. from a search\nresult), skip step 1 and go straight to `aboveTheFold` (and\n`belowTheFold` for price/tax history).\n\n## Exit codes (fetch verbs)\n\n- `0` — success (still check the stripped envelope's `resultCode`).\n- `2` — bridge unavailable: extension not connected or pairing pending → run `fpx pair -p redfin`, confirm a redfin.com tab is open.\n- `3` — bot wall: the tab hasn't cleared the AWS WAF challenge → open/refresh a `www.redfin.com` tab and retry.\n- `4` — upstream non-2xx from Redfin.\n\n## Notes\n\n- Anonymous reads only work for search/property/market/history/rentals;\n  `redfin_get_saved_homes` / `redfin_get_saved_searches` need the bridged\n  tab signed in to redfin.com.\n- Climate-risk data is **not** a JSON endpoint — it's regex-extracted\n  from the server-rendered homedetails HTML (`fpx get` the page, then\n  grep/extract; see `references/stingray-endpoints.md` §7 for the field\n  names to look for). There's no clean stingray path for it.\n- `fpx health -p redfin` shows bridge connection state when a call fails.\n- This project is developed and maintained by AI (Claude).\n\nFile v1.1.7:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"redfin-fpx\",\n  \"version\": \"1.1.7\",\n  \"publishedAt\": 1791168634567\n}\n\nFile v1.1.7:references/stingray-endpoints.md\n\n# Redfin stingray endpoints for fpx\n\nReady-to-run requests for `fpx get '<url>' -p redfin`. All paths and\nparams are transcribed from the live-verified request builders in\n`src/tools/*.ts` / `src/autocomplete.ts` in this repo — see the header\ncomment of each source file for verification dates and any known quirks.\n\nBase origin: `https://www.redfin.com`. Every `/stingray/...` response\ncarries a literal `{}&&` anti-CSRF prefix — strip it before parsing:\n\n```sh\nSTRIP='sed -E s/^\\{\\}\\&\\&//'\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin | $STRIP | jq '.payload'\n```\n\nThe stripped body is `{ version, errorMessage, resultCode, payload }`;\n`resultCode !== 0` means Redfin rejected the request (`errorMessage` has\nwhy).\n\n---\n\n## 1. Autocomplete — resolve a location or address (do this first)\n\n`GET /stingray/do/location-autocomplete`\n\nParams: `location` (free text), `start=0`, `count=1` (only the first row\nof each section is ever needed), `v=2`, `iss=false`, `ooa=true`,\n`mrs=false`.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Brooklyn%2C%20NY&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.sections[] | {name, rows: [.rows[0]]}'\n```\n\nResponse: `payload.sections[]`, each `{ name: \"Places\"|\"Addresses\"|\"Schools\"|\"Agents\"|…, rows: [...] }`.\n\n- **Places** rows: `id` formatted `\"<region_type>_<region_id>\"` (e.g.\n  `\"6_30749\"` → region_type 6, region_id 30749), `name`, `subName`, `url`.\n- **Addresses** rows: no `id` — `url` is the canonical home path, e.g.\n  `/NC/Lake-Lure/158-Raven-Blvd-28746/home/112653221`. Parse\n  `/<STATE>/<City>/<Street>-<ZIP>(/unit-<U>)?/home/<home_id>`. A full\n  street address typically returns an Addresses row instead of/alongside\n  Places — that's Redfin telling you it resolved a specific home, not a\n  searchable region.\n\n```sh\n# Region id for a search:\njq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0].id'\n# Home id + canonical url for an address:\njq -r '.payload.sections[] | select(.name==\"Addresses\") | .rows[0].url'\n```\n\n## 2. Search for-sale listings — `/stingray/api/gis`\n\nRequires a resolved `region_id` + `region_type` from §1. Query params\n(all strings/CSVs):\n\n| param | meaning |\n|---|---|\n| `al=1` | always 1 |\n| `num_homes` | result limit (Redfin web app default 40) |\n| `region_id`, `region_type` | from autocomplete |\n| `sf=1,2,3,5,6,7` | static — result fields to include |\n| `start=0` | pagination offset |\n| `status` | `1` = active for sale; `9` = active+coming-soon+contingent+pending (broader — what redfin-mcp uses as its default \"everything for sale\" view) |\n| `uipt` | CSV of property-type bitmap: house=1, condo=2, townhouse=3, multi_family=4, land=5, manufactured=6 (omit/`1,2,3,4,5,6,7,8` for all) |\n| `v=8` | static |\n| `min_price`, `max_price` | optional, USD |\n| `num_beds`, `num_baths` | optional, minimums |\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?al=1&num_homes=40&region_id=30749&region_type=6&sf=1,2,3,5,6,7&start=0&status=9&uipt=1,2,3,4,5,6,7,8&v=8&max_price=1500000' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.homes[] | {propertyId, price, streetLine, city, state, zip, beds, baths, sqFt, url}'\n```\n\nNotes:\n- Redfin's gis API has an undocumented **~350-result hard cap** per call\n  — if `payload.homes | length` hits ~350, more listings likely exist\n  server-side (narrow with price/bed filters; there's no server-side\n  pagination here).\n- Redfin's gis API can silently substitute a region it *does* index for\n  one it doesn't. Check `payload.serviceRegionName` against the region\n  you asked for; if it names a different place (or `homes[].city/state`\n  don't match the requested region), don't trust the results for\n  small/rural markets — try a nearby larger city/county instead.\n- `sqFt`/`price`/`lotSize`/etc. may ride as either a bare number or\n  `{value: number}` — unwrap defensively.\n\n## 3. Property detail (two round trips)\n\n### 3a. Resolve propertyId + listingId — `/stingray/api/home/details/initialInfo`\n\nOnly needed when you have a URL, not IDs. `path` is the URL-encoded\n`/<STATE>/<City>/<Street>-<ZIP>/home/<id>` path (no origin).\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/initialInfo?path=%2FNY%2FBrooklyn%2F42-Monroe-St-11238%2Fhome%2F40732555' \\\n  -p redfin | $STRIP | jq '.payload | {propertyId, listingId, marketId, marketName}'\n```\n\nA bare `/home/<id>` URL (no full slug) will NOT resolve here — Redfin's\nown site 301s `/home/<id>` to the full slug first. If you only have a\nnumeric property_id, `GET /home/<id>` (no `/stingray` prefix) and read\nthe bridge's followed redirect target/final URL, then feed that path to\n`initialInfo`.\n\n### 3b. Detail — `/stingray/api/home/details/aboveTheFold`\n\nParams: `propertyId`, `listingId`, `accessLevel=1`.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/aboveTheFold?propertyId=40732555&listingId=123456789&accessLevel=1' \\\n  -p redfin | $STRIP \\\n  | jq '.payload | {\n      addr: .addressSectionInfo.streetAddress,\n      price: (.addressSectionInfo.latestPriceInfo.amount // .addressSectionInfo.priceInfo.amount),\n      beds: .addressSectionInfo.beds, baths: .addressSectionInfo.baths,\n      sqft: .addressSectionInfo.sqFt,\n      remarks: .mainHouseInfo.publicRemarksParagraph,\n      photo: .mediaBrowserInfo.photos[0].photoUrls.fullScreenPhotoUrl\n    }'\n```\n\n`addressSectionInfo` carries price/beds/baths/sqft/status/dates;\n`mainHouseInfo` carries the marketing description + HOA dues;\n`mediaBrowserInfo.photos[]` carries the gallery (see §8).\n\n### 3c. Price + tax history — `/stingray/api/home/details/belowTheFold`\n\nSame `propertyId`/`listingId`/`accessLevel=1` params, different path:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/belowTheFold?propertyId=40732555&listingId=123456789&accessLevel=1' \\\n  -p redfin | $STRIP \\\n  | jq '{\n      price_events: [.payload.propertyHistoryInfo.events[] | {date: .eventDate, event: .eventDescription, price}],\n      tax_events: [.payload.publicRecordsInfo.allTaxInfo[] | {year: .rollYear, taxesDue}],\n      lot_sqft: .payload.publicRecordsInfo.basicInfo.lotSqFt\n    }'\n```\n\nField gotchas: `event.price` is a bare number (not `{amount}`); the\ntax-history array is `allTaxInfo` (current-year-only is `taxInfo`); tax\nrecords use `taxesDue`, not `taxesPaid`.\n\n## 4. Market trends — `/stingray/api/region/<region_type>/<region_id>/<property_type>/market-trends`\n\n`property_type`: `1`=all (default), `2`=house, `3`=condo, `4`=townhouse,\n`5`=multi-family, `6`=land.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/region/2/16163/1/market-trends' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.tableData | {for_sale: .homesForSaleCurMonth, sold: .homesSoldCurMonth, homesForSale, homesSold}'\n```\n\nEach row: `label`, `currentHouseAndCondoValue` (scale depends on\n`valueType`: `LONG`=count, `CURRENCY`=USD, `CURRENCY_THOUSANDS`=USD/1000,\n`PERCENT`=fraction), plus `houseAndCondoYoy{Up,ValueProportionalChange}`\nand the `Mom` equivalents. Neighborhood-typed regions (type 6) often\nreturn empty tables — prefer city-level regions for this endpoint.\n\n## 5. Comparable rentals — `/stingray/api/home/comparable-rentals`\n\nParams: `rentEstimateLow`, `rentEstimateHigh`, `latitude`, `longitude`,\n`propertyId` — the rent-estimate range and lat/lng come from the\nproperty's own page (not derivable independently; read them off\n`aboveTheFold`/the live homedetails page first).\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/comparable-rentals?rentEstimateLow=2200&rentEstimateHigh=2600&latitude=40.679&longitude=-73.958&propertyId=40732555' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.comparableRentals[] | {streetAddress, monthlyRent: .monthlyRent.amount, beds, baths, distance: .distance.value}'\n```\n\n## 6. Address resolution notes\n\n`/stingray/do/location-autocomplete` (§1) is also the address resolver —\nthere's no separate endpoint. For a fuzzy street address, retry with\ncommon suffix swaps (Rd↔Road, Ln↔Lane, St↔Street, Ave↔Avenue, …) if the\nfirst call's Addresses row doesn't come back, and verify the returned\nstreet genuinely matches what you asked for (Redfin's autocomplete is\nfuzzy and can return a neighboring house number).\n\n## 7. Climate risk — HTML extraction (no JSON endpoint)\n\nRedfin server-renders First Street Foundation climate data directly into\nthe homedetails page HTML — there is no stingray path for it (probed\nURLs 404). `fpx get` the page itself and grep/parse the embedded blocks:\n\n```sh\nfpx get 'https://www.redfin.com/NY/Brooklyn/42-Monroe-St-11238/home/40732555' -p redfin > /tmp/page.html\ngrep -o '\\\\\"floodData\\\\\":{[^}]*}' /tmp/page.html   # also try unescaped \"floodData\":{...}\ngrep -o '\\\\\"fireData\\\\\":{[^}]*}'  /tmp/page.html\ngrep -o '\\\\\"heatData\\\\\":{[^}]*}'  /tmp/page.html\n```\n\nEach block is a JSON object (possibly double-escaped — un-escape `\\\"`→`\"`\nand `\\\\`→`\\` if the naive extraction above doesn't parse). Key fields:\n`floodFactor`/`fireFactor`/`heatFactor` (1–10), `femaZones[]`,\n`chance[]` (30-yr flood-chance series), `lowInsurancePrice`/\n`highInsurancePrice`, `cumulativeRiskYear{0,5,10,15,20}`. First Street\ndoes **not** cover landslide risk. A shared `fsid`/census-tract value\nacross nearby properties usually means identical scores — cheap to\ngroup instead of re-fetching every address in a cluster.\n\n## 8. Photos\n\nAlready embedded in `aboveTheFold.mediaBrowserInfo.photos[]` (§3b) — no\nseparate endpoint. Each photo: `photoUrls.{fullScreenPhotoUrl,\nnonFullScreenPhotoUrl, nonFullScreenPhotoUrlCompressed, lightboxListUrl}`,\n`thumbnailData.thumbnailUrl`, `photoText` (caption).\n\n```sh\njq '.payload.mediaBrowserInfo.photos[] | .photoUrls.fullScreenPhotoUrl'\n```\n\nFor saved-home cards (§9), the homecards endpoint omits `photoUrls`\nentirely — construct the CDN URL yourself from `mlsId` + `dataSourceId`:\n\n```\nhttps://ssl.cdn-redfin.com/photo/<dataSourceId>/bigphoto/<last3-of-mlsId-zero-padded>/<mlsId>_0.jpg\n```\n\n(index 0 → `_0.jpg`; index N>0 → `_<N>_0.jpg`; `mbphotov3/` + `genMid.`\nprefix instead of `bigphoto/` for the mid-size variant.)\n\n## 9. Saved homes / saved searches — requires a SIGNED-IN tab\n\nThese need the bridged `www.redfin.com` tab to be logged in (not just\nbot-wall-cleared).\n\n```sh\n# 1. Favorited property IDs are embedded as /home/<id> links in the page HTML:\nfpx get 'https://www.redfin.com/myredfin/favorites' -p redfin > /tmp/favs.html\ngrep -oE '/home/[0-9]+' /tmp/favs.html | grep -oE '[0-9]+' | sort -u\n\n# 2. Fetch the home-card details for those IDs (comma-separated):\nfpx get 'https://www.redfin.com/stingray/do/api/v3/favorites/homecards?b=40732555,18659204&r=' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.homecards[] | {propertyId, isFavorite, addr: .commonHomeData.entireAddressString, price: .commonHomeData.priceInfo.amount}'\n\n# Saved searches: no JSON endpoint — region URLs are regex-extracted from the page HTML.\nfpx get 'https://www.redfin.com/myredfin/saved-searches' -p redfin \\\n  | grep -oE '\"(/(city|zipcode|neighborhood|county|state)/[^\"<>?#]+)\"'\n```\n\n## 10. Bridge healthcheck\n\n```sh\nfpx get 'https://www.redfin.com/robots.txt' -p redfin >/dev/null && echo ok\nfpx health -p redfin\n```\n\nFile v1.1.7:skill-card.md\n\n## Description:\n\nHelps agents query U.S. Redfin listings, property details, market data, and optionally saved account 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 look up U.S. homes, listing details, prices, rental comparisons, and market trends from Redfin without a running MCP server. Signed-in users can also query their saved homes and searches.\n\n### Deployment Geography for Use:\n\nUnited States\n\n## Known Risks and Mitigations:\n\nRisk: Requests through the paired browser tab may expose signed-in Redfin saved homes and searches to the local agent workflow.\n\nMitigation: Use a signed-out or dedicated browser profile for public listings; access saved account data only when comfortable sharing it with the local agent.\n\nRisk: Searches may omit listings or return a substituted region in small markets.\n\nMitigation: Check the returned region and location against the request, and narrow broad searches to avoid result caps.\n\n## Reference(s):\n\n- [Redfin endpoint examples](references/stingray-endpoints.md)\n- [ContextMint Bridge extension and releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n- [Fetchproxy CLI and extension background](https://github.com/chrischall/fetchproxy#extension)\n- [Redfin](https://www.redfin.com)\n\n## Skill Output:\n\n**Output Type(s):** [Shell commands, Guidance, Text]\n\n**Output Format:** [Markdown with shell examples and structured Redfin data excerpts]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Public data is available with an open Redfin tab; saved homes and searches require a signed-in tab.]\n\n## Skill Version(s):\n\n1.1.7 (source: server-resolved ClawHub release)\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, 9199 bytes\n\nFiles: references/stingray-endpoints.md (11215b), skill-card.md (1902b), SKILL.md (5445b), _meta.json (129b)\n\nFile v1.1.6:SKILL.md\n\n---\nname: redfin-fpx\ndescription: >-\n  Query redfin.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the redfin-mcp server — resolve\n  locations/addresses, search for-sale listings, read property detail\n  (price, beds/baths, price history, tax history), market trends,\n  comparable rentals, climate risk, photos, and (signed-in) saved homes\n  and saved searches, via one-shot calls through a signed-in browser tab.\n  Use when you want Redfin data without the MCP, in a script, or on a\n  machine where the MCP isn't installed.\n---\n\n# Redfin via fpx (no MCP)\n\nRedfin fronts `www.redfin.com` — including every `/stingray/...` JSON\nendpoint — with an AWS WAF challenge that blocks plain `curl`/Node\nrequests regardless of headers. `fpx` routes the request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), which has\nalready cleared the challenge, so the same request succeeds. Most reads\nare anonymous (no Redfin login needed — just an open tab); the saved-homes\nand saved-searches endpoints additionally require the tab to be signed in\nto redfin.com.\n\nThis is the same data the `redfin_*` MCP tools return, reached with one\nCLI call instead of a running server. Every call rides through the bridge\n(no bootstrap-then-direct-fetch shortcut) — Redfin validates each request\nat the session level.\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli              # provides `fpx`\nfpx profile add redfin --domain redfin.com  # only the fetch capability is needed\nfpx pair -p redfin                          # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n(from https://github.com/nullnet-app/contextmint-bridge/releases), with an\nopen `www.redfin.com` tab, and its Chrome **Site access** allowing\n`redfin.com`. Pairing persists — after the first approval every later\n`fpx` call reuses it.\n\nContextMint Bridge is the fetchproxy extension renamed, same maintainer (see https://github.com/chrischall/fetchproxy#extension); source at https://github.com/nullnet-app/contextmint-bridge — build it yourself or verify a release zip with `shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`. Safari isn't available yet — use Chrome.\n\n## Core call\n\nAlmost every endpoint is a GET to a `/stingray/...` path. Redfin prefixes\nevery stingray JSON body with a literal anti-CSRF `{}&&`, so strip that\nbefore piping to `jq`:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin \\\n  | sed -E 's/^\\{\\}&&//' \\\n  | jq '.payload.homes'\n```\n\nEvery stripped body is an envelope `{ version, errorMessage, resultCode,\npayload }` — check `resultCode == 0` before trusting `payload` (a nonzero\ncode means Redfin rejected the request; `errorMessage` explains why).\n\nReady-to-run request paths (autocomplete, search, property detail, price\nhistory, market trends, comparable rentals, climate risk, saved homes)\nare in `references/stingray-endpoints.md`. Exhaustive field lists live in\nthe repo at `src/tools/*.ts` — the endpoints here are compact,\nlive-verified subsets.\n\n## The one rule: resolve the location/address first\n\nRedfin search takes numeric **region_id + region_type**, never place\nnames, and property detail wants a **propertyId + listingId** pair.\nAlways autocomplete first:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Seattle&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | sed -E 's/^\\{\\}&&//' \\\n  | jq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0] | \"\\(.id)\\t\\(.name)\"'\n# 2_16163  Seattle\n```\n\n`id` is formatted `\"<region_type>_<region_id>\"`. An `Addresses` section\n(instead of/alongside `Places`) means autocomplete resolved a specific\nhome rather than a region — its `url` embeds the home's canonical\n`/home/<id>` path (use that with the property-detail calls instead of a\nregion search).\n\n## Two-step property detail\n\nA homedetails URL only gets you `propertyId`/`listingId` via one extra\nround trip:\n\n1. `GET /stingray/api/home/details/initialInfo?path=<url-path>` → `{propertyId, listingId, ...}`\n2. `GET /stingray/api/home/details/aboveTheFold?propertyId=…&listingId=…&accessLevel=1` → the actual detail\n\nIf you already have `property_id` + `listing_id` (e.g. from a search\nresult), skip step 1 and go straight to `aboveTheFold` (and\n`belowTheFold` for price/tax history).\n\n## Exit codes (fetch verbs)\n\n- `0` — success (still check the stripped envelope's `resultCode`).\n- `2` — bridge unavailable: extension not connected or pairing pending → run `fpx pair -p redfin`, confirm a redfin.com tab is open.\n- `3` — bot wall: the tab hasn't cleared the AWS WAF challenge → open/refresh a `www.redfin.com` tab and retry.\n- `4` — upstream non-2xx from Redfin.\n\n## Notes\n\n- Anonymous reads only work for search/property/market/history/rentals;\n  `redfin_get_saved_homes` / `redfin_get_saved_searches` need the bridged\n  tab signed in to redfin.com.\n- Climate-risk data is **not** a JSON endpoint — it's regex-extracted\n  from the server-rendered homedetails HTML (`fpx get` the page, then\n  grep/extract; see `references/stingray-endpoints.md` §7 for the field\n  names to look for). There's no clean stingray path for it.\n- `fpx health -p redfin` shows bridge connection state when a call fails.\n- This project is developed and maintained by AI (Claude).\n\nFile v1.1.6:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"redfin-fpx\",\n  \"version\": \"1.1.6\",\n  \"publishedAt\": 1791035911564\n}\n\nFile v1.1.6:references/stingray-endpoints.md\n\n# Redfin stingray endpoints for fpx\n\nReady-to-run requests for `fpx get '<url>' -p redfin`. All paths and\nparams are transcribed from the live-verified request builders in\n`src/tools/*.ts` / `src/autocomplete.ts` in this repo — see the header\ncomment of each source file for verification dates and any known quirks.\n\nBase origin: `https://www.redfin.com`. Every `/stingray/...` response\ncarries a literal `{}&&` anti-CSRF prefix — strip it before parsing:\n\n```sh\nSTRIP='sed -E s/^\\{\\}\\&\\&//'\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin | $STRIP | jq '.payload'\n```\n\nThe stripped body is `{ version, errorMessage, resultCode, payload }`;\n`resultCode !== 0` means Redfin rejected the request (`errorMessage` has\nwhy).\n\n---\n\n## 1. Autocomplete — resolve a location or address (do this first)\n\n`GET /stingray/do/location-autocomplete`\n\nParams: `location` (free text), `start=0`, `count=1` (only the first row\nof each section is ever needed), `v=2`, `iss=false`, `ooa=true`,\n`mrs=false`.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Brooklyn%2C%20NY&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.sections[] | {name, rows: [.rows[0]]}'\n```\n\nResponse: `payload.sections[]`, each `{ name: \"Places\"|\"Addresses\"|\"Schools\"|\"Agents\"|…, rows: [...] }`.\n\n- **Places** rows: `id` formatted `\"<region_type>_<region_id>\"` (e.g.\n  `\"6_30749\"` → region_type 6, region_id 30749), `name`, `subName`, `url`.\n- **Addresses** rows: no `id` — `url` is the canonical home path, e.g.\n  `/NC/Lake-Lure/158-Raven-Blvd-28746/home/112653221`. Parse\n  `/<STATE>/<City>/<Street>-<ZIP>(/unit-<U>)?/home/<home_id>`. A full\n  street address typically returns an Addresses row instead of/alongside\n  Places — that's Redfin telling you it resolved a specific home, not a\n  searchable region.\n\n```sh\n# Region id for a search:\njq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0].id'\n# Home id + canonical url for an address:\njq -r '.payload.sections[] | select(.name==\"Addresses\") | .rows[0].url'\n```\n\n## 2. Search for-sale listings — `/stingray/api/gis`\n\nRequires a resolved `region_id` + `region_type` from §1. Query params\n(all strings/CSVs):\n\n| param | meaning |\n|---|---|\n| `al=1` | always 1 |\n| `num_homes` | result limit (Redfin web app default 40) |\n| `region_id`, `region_type` | from autocomplete |\n| `sf=1,2,3,5,6,7` | static — result fields to include |\n| `start=0` | pagination offset |\n| `status` | `1` = active for sale; `9` = active+coming-soon+contingent+pending (broader — what redfin-mcp uses as its default \"everything for sale\" view) |\n| `uipt` | CSV of property-type bitmap: house=1, condo=2, townhouse=3, multi_family=4, land=5, manufactured=6 (omit/`1,2,3,4,5,6,7,8` for all) |\n| `v=8` | static |\n| `min_price`, `max_price` | optional, USD |\n| `num_beds`, `num_baths` | optional, minimums |\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?al=1&num_homes=40&region_id=30749&region_type=6&sf=1,2,3,5,6,7&start=0&status=9&uipt=1,2,3,4,5,6,7,8&v=8&max_price=1500000' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.homes[] | {propertyId, price, streetLine, city, state, zip, beds, baths, sqFt, url}'\n```\n\nNotes:\n- Redfin's gis API has an undocumented **~350-result hard cap** per call\n  — if `payload.homes | length` hits ~350, more listings likely exist\n  server-side (narrow with price/bed filters; there's no server-side\n  pagination here).\n- Redfin's gis API can silently substitute a region it *does* index for\n  one it doesn't. Check `payload.serviceRegionName` against the region\n  you asked for; if it names a different place (or `homes[].city/state`\n  don't match the requested region), don't trust the results for\n  small/rural markets — try a nearby larger city/county instead.\n- `sqFt`/`price`/`lotSize`/etc. may ride as either a bare number or\n  `{value: number}` — unwrap defensively.\n\n## 3. Property detail (two round trips)\n\n### 3a. Resolve propertyId + listingId — `/stingray/api/home/details/initialInfo`\n\nOnly needed when you have a URL, not IDs. `path` is the URL-encoded\n`/<STATE>/<City>/<Street>-<ZIP>/home/<id>` path (no origin).\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/initialInfo?path=%2FNY%2FBrooklyn%2F42-Monroe-St-11238%2Fhome%2F40732555' \\\n  -p redfin | $STRIP | jq '.payload | {propertyId, listingId, marketId, marketName}'\n```\n\nA bare `/home/<id>` URL (no full slug) will NOT resolve here — Redfin's\nown site 301s `/home/<id>` to the full slug first. If you only have a\nnumeric property_id, `GET /home/<id>` (no `/stingray` prefix) and read\nthe bridge's followed redirect target/final URL, then feed that path to\n`initialInfo`.\n\n### 3b. Detail — `/stingray/api/home/details/aboveTheFold`\n\nParams: `propertyId`, `listingId`, `accessLevel=1`.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/aboveTheFold?propertyId=40732555&listingId=123456789&accessLevel=1' \\\n  -p redfin | $STRIP \\\n  | jq '.payload | {\n      addr: .addressSectionInfo.streetAddress,\n      price: (.addressSectionInfo.latestPriceInfo.amount // .addressSectionInfo.priceInfo.amount),\n      beds: .addressSectionInfo.beds, baths: .addressSectionInfo.baths,\n      sqft: .addressSectionInfo.sqFt,\n      remarks: .mainHouseInfo.publicRemarksParagraph,\n      photo: .mediaBrowserInfo.photos[0].photoUrls.fullScreenPhotoUrl\n    }'\n```\n\n`addressSectionInfo` carries price/beds/baths/sqft/status/dates;\n`mainHouseInfo` carries the marketing description + HOA dues;\n`mediaBrowserInfo.photos[]` carries the gallery (see §8).\n\n### 3c. Price + tax history — `/stingray/api/home/details/belowTheFold`\n\nSame `propertyId`/`listingId`/`accessLevel=1` params, different path:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/details/belowTheFold?propertyId=40732555&listingId=123456789&accessLevel=1' \\\n  -p redfin | $STRIP \\\n  | jq '{\n      price_events: [.payload.propertyHistoryInfo.events[] | {date: .eventDate, event: .eventDescription, price}],\n      tax_events: [.payload.publicRecordsInfo.allTaxInfo[] | {year: .rollYear, taxesDue}],\n      lot_sqft: .payload.publicRecordsInfo.basicInfo.lotSqFt\n    }'\n```\n\nField gotchas: `event.price` is a bare number (not `{amount}`); the\ntax-history array is `allTaxInfo` (current-year-only is `taxInfo`); tax\nrecords use `taxesDue`, not `taxesPaid`.\n\n## 4. Market trends — `/stingray/api/region/<region_type>/<region_id>/<property_type>/market-trends`\n\n`property_type`: `1`=all (default), `2`=house, `3`=condo, `4`=townhouse,\n`5`=multi-family, `6`=land.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/region/2/16163/1/market-trends' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.tableData | {for_sale: .homesForSaleCurMonth, sold: .homesSoldCurMonth, homesForSale, homesSold}'\n```\n\nEach row: `label`, `currentHouseAndCondoValue` (scale depends on\n`valueType`: `LONG`=count, `CURRENCY`=USD, `CURRENCY_THOUSANDS`=USD/1000,\n`PERCENT`=fraction), plus `houseAndCondoYoy{Up,ValueProportionalChange}`\nand the `Mom` equivalents. Neighborhood-typed regions (type 6) often\nreturn empty tables — prefer city-level regions for this endpoint.\n\n## 5. Comparable rentals — `/stingray/api/home/comparable-rentals`\n\nParams: `rentEstimateLow`, `rentEstimateHigh`, `latitude`, `longitude`,\n`propertyId` — the rent-estimate range and lat/lng come from the\nproperty's own page (not derivable independently; read them off\n`aboveTheFold`/the live homedetails page first).\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/home/comparable-rentals?rentEstimateLow=2200&rentEstimateHigh=2600&latitude=40.679&longitude=-73.958&propertyId=40732555' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.comparableRentals[] | {streetAddress, monthlyRent: .monthlyRent.amount, beds, baths, distance: .distance.value}'\n```\n\n## 6. Address resolution notes\n\n`/stingray/do/location-autocomplete` (§1) is also the address resolver —\nthere's no separate endpoint. For a fuzzy street address, retry with\ncommon suffix swaps (Rd↔Road, Ln↔Lane, St↔Street, Ave↔Avenue, …) if the\nfirst call's Addresses row doesn't come back, and verify the returned\nstreet genuinely matches what you asked for (Redfin's autocomplete is\nfuzzy and can return a neighboring house number).\n\n## 7. Climate risk — HTML extraction (no JSON endpoint)\n\nRedfin server-renders First Street Foundation climate data directly into\nthe homedetails page HTML — there is no stingray path for it (probed\nURLs 404). `fpx get` the page itself and grep/parse the embedded blocks:\n\n```sh\nfpx get 'https://www.redfin.com/NY/Brooklyn/42-Monroe-St-11238/home/40732555' -p redfin > /tmp/page.html\ngrep -o '\\\\\"floodData\\\\\":{[^}]*}' /tmp/page.html   # also try unescaped \"floodData\":{...}\ngrep -o '\\\\\"fireData\\\\\":{[^}]*}'  /tmp/page.html\ngrep -o '\\\\\"heatData\\\\\":{[^}]*}'  /tmp/page.html\n```\n\nEach block is a JSON object (possibly double-escaped — un-escape `\\\"`→`\"`\nand `\\\\`→`\\` if the naive extraction above doesn't parse). Key fields:\n`floodFactor`/`fireFactor`/`heatFactor` (1–10), `femaZones[]`,\n`chance[]` (30-yr flood-chance series), `lowInsurancePrice`/\n`highInsurancePrice`, `cumulativeRiskYear{0,5,10,15,20}`. First Street\ndoes **not** cover landslide risk. A shared `fsid`/census-tract value\nacross nearby properties usually means identical scores — cheap to\ngroup instead of re-fetching every address in a cluster.\n\n## 8. Photos\n\nAlready embedded in `aboveTheFold.mediaBrowserInfo.photos[]` (§3b) — no\nseparate endpoint. Each photo: `photoUrls.{fullScreenPhotoUrl,\nnonFullScreenPhotoUrl, nonFullScreenPhotoUrlCompressed, lightboxListUrl}`,\n`thumbnailData.thumbnailUrl`, `photoText` (caption).\n\n```sh\njq '.payload.mediaBrowserInfo.photos[] | .photoUrls.fullScreenPhotoUrl'\n```\n\nFor saved-home cards (§9), the homecards endpoint omits `photoUrls`\nentirely — construct the CDN URL yourself from `mlsId` + `dataSourceId`:\n\n```\nhttps://ssl.cdn-redfin.com/photo/<dataSourceId>/bigphoto/<last3-of-mlsId-zero-padded>/<mlsId>_0.jpg\n```\n\n(index 0 → `_0.jpg`; index N>0 → `_<N>_0.jpg`; `mbphotov3/` + `genMid.`\nprefix instead of `bigphoto/` for the mid-size variant.)\n\n## 9. Saved homes / saved searches — requires a SIGNED-IN tab\n\nThese need the bridged `www.redfin.com` tab to be logged in (not just\nbot-wall-cleared).\n\n```sh\n# 1. Favorited property IDs are embedded as /home/<id> links in the page HTML:\nfpx get 'https://www.redfin.com/myredfin/favorites' -p redfin > /tmp/favs.html\ngrep -oE '/home/[0-9]+' /tmp/favs.html | grep -oE '[0-9]+' | sort -u\n\n# 2. Fetch the home-card details for those IDs (comma-separated):\nfpx get 'https://www.redfin.com/stingray/do/api/v3/favorites/homecards?b=40732555,18659204&r=' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.homecards[] | {propertyId, isFavorite, addr: .commonHomeData.entireAddressString, price: .commonHomeData.priceInfo.amount}'\n\n# Saved searches: no JSON endpoint — region URLs are regex-extracted from the page HTML.\nfpx get 'https://www.redfin.com/myredfin/saved-searches' -p redfin \\\n  | grep -oE '\"(/(city|zipcode|neighborhood|county|state)/[^\"<>?#]+)\"'\n```\n\n## 10. Bridge healthcheck\n\n```sh\nfpx get 'https://www.redfin.com/robots.txt' -p redfin >/dev/null && echo ok\nfpx health -p redfin\n```\n\nFile v1.1.6:skill-card.md\n\n## Description:\n\nGuides agents to query Redfin listings, property details, market data, and signed-in saved items using fpx 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 other agents use this skill to retrieve US real-estate listings, home details, market trends, and, with permission, saved homes or searches without running a separate MCP server.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Saved homes and saved searches can expose private account data.\n\nMitigation: Request explicit permission before fetching these endpoints and avoid logging their responses.\n\nRisk: Requests use a paired browser tab with access to the Redfin session.\n\nMitigation: Install and pair the browser bridge only if comfortable granting it access to that tab.\n\n## Reference(s):\n\n- [Redfin stingray endpoint guide](references/stingray-endpoints.md)\n- [ClawHub skill release](https://clawhub.ai/chrischall/skills/redfin-fpx)\n- [ContextMint Bridge source](https://github.com/nullnet-app/contextmint-bridge)\n- [fpx CLI and extension guidance](https://github.com/chrischall/fetchproxy#extension)\n\n## Skill Output:\n\n**Output Type(s):** [Shell commands, Guidance]\n\n**Output Format:** [Markdown with shell examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Includes examples for parsing Redfin responses; signed-in account data requires explicit permission.]\n\n## Skill Version(s):\n\n1.1.6 (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.5: 4 files, 9191 bytes\n\nFiles: references/stingray-endpoints.md (11215b), skill-card.md (1932b), SKILL.md (5445b), _meta.json (129b)\n\nFile v1.1.5:SKILL.md\n\n---\nname: redfin-fpx\ndescription: >-\n  Query redfin.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the redfin-mcp server — resolve\n  locations/addresses, search for-sale listings, read property detail\n  (price, beds/baths, price history, tax history), market trends,\n  comparable rentals, climate risk, photos, and (signed-in) saved homes\n  and saved searches, via one-shot calls through a signed-in browser tab.\n  Use when you want Redfin data without the MCP, in a script, or on a\n  machine where the MCP isn't installed.\n---\n\n# Redfin via fpx (no MCP)\n\nRedfin fronts `www.redfin.com` — including every `/stingray/...` JSON\nendpoint — with an AWS WAF challenge that blocks plain `curl`/Node\nrequests regardless of headers. `fpx` routes the request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), which has\nalready cleared the challenge, so the same request succeeds. Most reads\nare anonymous (no Redfin login needed — just an open tab); the saved-homes\nand saved-searches endpoints additionally require the tab to be signed in\nto redfin.com.\n\nThis is the same data the `redfin_*` MCP tools return, reached with one\nCLI call instead of a running server. Every call rides through the bridge\n(no bootstrap-then-direct-fetch shortcut) — Redfin validates each request\nat the session level.\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli              # provides `fpx`\nfpx profile add redfin --domain redfin.com  # only the fetch capability is needed\nfpx pair -p redfin                          # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n(from https://github.com/nullnet-app/contextmint-bridge/releases), with an\nopen `www.redfin.com` tab, and its Chrome **Site access** allowing\n`redfin.com`. Pairing persists — after the first approval every later\n`fpx` call reuses it.\n\nContextMint Bridge is the fetchproxy extension renamed, same maintainer (see https://github.com/chrischall/fetchproxy#extension); source at https://github.com/nullnet-app/contextmint-bridge — build it yourself or verify a release zip with `shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`. Safari isn't available yet — use Chrome.\n\n## Core call\n\nAlmost every endpoint is a GET to a `/stingray/...` path. Redfin prefixes\nevery stingray JSON body with a literal anti-CSRF `{}&&`, so strip that\nbefore piping to `jq`:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin \\\n  | sed -E 's/^\\{\\}&&//' \\\n  | jq '.payload.homes'\n```\n\nEvery stripped body is an envelope `{ version, errorMessage, resultCode,\npayload }` — check `resultCode == 0` before trusting `payload` (a nonzero\ncode means Redfin rejected the request; `errorMessage` explains why).\n\nReady-to-run request paths (autocomplete, search, property detail, price\nhistory, market trends, comparable rentals, climate risk, saved homes)\nare in `references/stingray-endpoints.md`. Exhaustive field lists live in\nthe repo at `src/tools/*.ts` — the endpoints here are compact,\nlive-verified subsets.\n\n## The one rule: resolve the location/address first\n\nRedfin search takes numeric **region_id + region_type**, never place\nnames, and property detail wants a **propertyId + listingId** pair.\nAlways autocomplete first:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Seattle&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | sed -E 's/^\\{\\}&&//' \\\n  | jq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0] | \"\\(.id)\\t\\(.name)\"'\n# 2_16163  Seattle\n```\n\n`id` is formatted `\"<region_type>_<region_id>\"`. An `Addresses` section\n(instead of/alongside `Places`) means autocomplete resolved a specific\nhome rather than a region — its `url` embeds the home's canonical\n`/home/<id>` path (use that with the property-detail calls instead of a\nregion search).\n\n## Two-step property detail\n\nA homedetails URL only gets you `propertyId`/`listingId` via one extra\nround trip:\n\n1. `GET /stingray/api/home/details/initialInfo?path=<url-path>` → `{propertyId, listingId, ...}`\n2. `GET /stingray/api/home/details/aboveTheFold?propertyId=…&listingId=…&accessLevel=1` → the actual detail\n\nIf you already have `property_id` + `listing_id` (e.g. from a search\nresult), skip step 1 and go straight to `aboveTheFold` (and\n`belowTheFold` for price/tax history).\n\n## Exit codes (fetch verbs)\n\n- `0` — success (still check the stripped envelope's `resultCode`).\n- `2` — bridge unavailable: extension not connected or pairing pending → run `fpx pair -p redfin`, confirm a redfin.com tab is open.\n- `3` — bot wall: the tab hasn't cleared the AWS WAF challenge → open/refresh a `www.redfin.com` tab and retry.\n- `4` — upstream non-2xx from Redfin.\n\n## Notes\n\n- Anonymous reads only work for search/property/market/history/rentals;\n  `redfin_get_saved_homes` / `redfin_get_saved_searches` need the bridged\n  tab signed in to redfin.com.\n- Climate-risk data is **not** a JSON endpoint — it's regex-extracted\n  from the server-rendered homedetails HTML (`fpx get` the page, then\n  grep/extract; see `references/stingray-endpoints.md` §7 for the field\n  names to look for). There's no clean stingray path for it.\n- `fpx health -p redfin` shows bridge connection state when a call fails.\n- This project is developed and maintained by AI (Claude).\n\nFile v1.1.5:_meta.json\n\n{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"redfin-fpx\",\n  \"version\": \"1.1.5\",\n  \"publishedAt\": 1790992023374\n}\n\nFile v1.1.5:references/stingray-endpoints.md\n\n# Redfin stingray endpoints for fpx\n\nReady-to-run requests for `fpx get '<url>' -p redfin`. All paths and\nparams are transcribed from the live-verified request builders in\n`src/tools/*.ts` / `src/autocomplete.ts` in this repo — see the header\ncomment of each source file for verification dates and any known quirks.\n\nBase origin: `https://www.redfin.com`. Every `/stingray/...` response\ncarries a literal `{}&&` anti-CSRF prefix — strip it before parsing:\n\n```sh\nSTRIP='sed -E s/^\\{\\}\\&\\&//'\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin | $STRIP | jq '.payload'\n```\n\nThe stripped body is `{ version, errorMessage, resultCode, payload }`;\n`resultCode !== 0` means Redfin rejected the request (`errorMessage` has\nwhy).\n\n---\n\n## 1. Autocomplete — resolve a location or address (do this first)\n\n`GET /stingray/do/location-autocomplete`\n\nParams: `location` (free text), `start=0`, `count=1` (only the first row\nof each section is ever needed), `v=2`, `iss=false`, `ooa=true`,\n`mrs=false`.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Brooklyn%2C%20NY&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.sections[] | {name, rows: [.rows[0]]}'\n```\n\nResponse: `payload.sections[]`, each `{ name: \"Places\"|\"Addresses\"|\"Schools\"|\"Agents\"|…, rows: [...] }`.\n\n- **Places** rows: `id` formatted `\"<region_type>_<region_id>\"` (e.g.\n  `\"6_30749\"` → region_type 6, region_id 30749), `name`, `subName`, `url`.\n- **Addresses** rows: no `id` — `url` is the canonical home path, e.g.\n  `/NC/Lake-Lure/158-Raven-Blvd-28746/home/112653221`. Parse\n  `/<STATE>/<City>/<Street>-<ZIP>(/unit-<U>)?/home/<home_id>`. A full\n  street address typically returns an Addresses row instead of/alongside\n  Places — that's Redfin telling you it resolved a specific home, not a\n  searchable region.\n\n```sh\n# Region id for a search:\njq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0].id'\n# Home id + canonical url for an address:\njq -r '.payload.sections[] | select(.name==\"Addresses\") | .rows[0].url'\n```\n\n## 2. Search for-sale listings — `/stingray/api/gis`\n\nRequires a resolved `region_id` + `region_type` from §1. Query params\n(all strings/CSVs):\n\n| param | meaning |\n|---|---|\n| `al=1` | always 1 |\n| `num_homes` | result limit (Redfin web app default 40) |\n| `region_id`, `region_type` | from autocomplete |\n| `sf=1,2,3,5,6,7` | static — result fields to include |\n| `start=0` | pagination offset |\n| `status` | `1` = active for sale; `9` = active+coming-soon+contingent+pending (broader — what redfin-mcp uses as its default \"everything for sale\" view) |\n| `uipt` | CSV of property-type bitmap: house=1, condo=2, townhouse=3, multi_family=4, land=5, manufactured=6 (omit/`1,2,3,4,5,6,7,8` for all) |\n| `v=8` | static |\n| `min_price`, `max_price` | optional, USD |\n| `num_beds`, `num_baths` | optional, minimums |\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?al=1&num_homes=40&region_id=30749&region_type=6&sf=1,2,3,5,6,7&start=0&status=9&uipt=1,2,3,4,5,6,7,8&v=8&max_price=1500000' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.homes[] | {propertyId, price, streetLine, city, state, zip, beds, baths, sqFt, url}'\n```\n\nNotes:\n- Redfin's gis API has an undocumented **~350-result hard cap** per call\n  — if `payload.homes | length` hits ~350, more listings likely exist\n  server-side (narrow with price/bed filters; there's no server-side\n  pagination here).\n- Redfin's gis API can silently substitute a region it *does* index for\n  one it doesn't. Check `payload.serviceRegionName` against the region\n  you asked for; if it names a different place (or `homes[].city/state`\n  don't match the requested region), don't trust the results for\n  small/rural markets — try a nearby larger city/county instead.\n- `sqFt`/`price`/`lotSize`/etc. \n\nArchive v1.1.4: 4 files, 9369 bytes\n\nFiles: references/stingray-endpoints.md (11215b), skill-card.md (2289b), SKILL.md (5445b), _meta.json (129b)\n\nArchive v1.1.3: 4 files, 8897 bytes\n\nFiles: references/stingray-endpoints.md (11215b), skill-card.md (1615b), SKILL.md (5006b), _meta.json (129b)","readmeExcerpt":"Skill: redfin-fpx Owner: chrischall Summary: Query redfin.com (US real-estate portal) from a shell with the fpx CLI (@fetchproxy/cli) instead of running the redfin-mcp server — resolve locations/addresses, search for-sale listings, read property detail (price, beds/baths, price history, tax history), market trends, comparable rentals, climate risk, photos, and (signed-in) saved homes and saved searches, via one-shot ","codeSnippets":[],"executableExamples":[{"language":"sh","snippet":"npm install -g @fetchproxy/cli              # provides `fpx`\nfpx profile add redfin --domain redfin.com  # only the fetch capability is needed\nfpx pair -p redfin                          # prints a pair code → approve in ContextMint Bridge"},{"language":"sh","snippet":"fpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin \\\n  | sed -E 's/^\\{\\}&&//' \\\n  | jq '.payload.homes'"},{"language":"sh","snippet":"fpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Seattle&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | sed -E 's/^\\{\\}&&//' \\\n  | jq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0] | \"\\(.id)\\t\\(.name)\"'\n# 2_16163  Seattle"},{"language":"sh","snippet":"STRIP='sed -E s/^\\{\\}\\&\\&//'\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin | $STRIP | jq '.payload'"},{"language":"sh","snippet":"fpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Brooklyn%2C%20NY&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.sections[] | {name, rows: [.rows[0]]}'"},{"language":"sh","snippet":"# Region id for a search:\njq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0].id'\n# Home id + canonical url for an address:\njq -r '.payload.sections[] | select(.name==\"Addresses\") | .rows[0].url'"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: redfin-fpx\ndescription: >-\n  Query redfin.com (US real-estate portal) from a shell with the fpx CLI\n  (@fetchproxy/cli) instead of running the redfin-mcp server — resolve\n  locations/addresses, search for-sale listings, read property detail\n  (price, beds/baths, price history, tax history), market trends,\n  comparable rentals, climate risk, photos, and (signed-in) saved homes\n  and saved searches, via one-shot calls through a signed-in browser tab.\n  Use when you want Redfin data without the MCP, in a script, or on a\n  machine where the MCP isn't installed.\n---\n\n# Redfin via fpx (no MCP)\n\nRedfin fronts `www.redfin.com` — including every `/stingray/...` JSON\nendpoint — with an AWS WAF challenge that blocks plain `curl`/Node\nrequests regardless of headers. `fpx` routes the request through the\nuser's own signed-in browser tab (the ContextMint Bridge extension), which has\nalready cleared the challenge, so the same request succeeds. Most reads\nare anonymous (no Redfin login needed — just an open tab); the saved-homes\nand saved-searches endpoints additionally require the tab to be signed in\nto redfin.com.\n\nThis is the same data the `redfin_*` MCP tools return, reached with one\nCLI call instead of a running server. Every call rides through the bridge\n(no bootstrap-then-direct-fetch shortcut) — Redfin validates each request\nat the session level.\n\n## One-time setup\n\n```sh\nnpm install -g @fetchproxy/cli              # provides `fpx`\nfpx profile add redfin --domain redfin.com  # only the fetch capability is needed\nfpx pair -p redfin                          # prints a pair code → approve in ContextMint Bridge\n```\n\nRequirements: the **ContextMint Bridge** browser extension installed\n(from https://github.com/nullnet-app/contextmint-bridge/releases), with an\nopen `www.redfin.com` tab, and its Chrome **Site access** allowing\n`redfin.com`. Pairing persists — after the first approval every later\n`fpx` call reuses it.\n\nContextMint Bridge is the fetchproxy extension renamed, same maintainer (see https://github.com/chrischall/fetchproxy#extension); source at https://github.com/nullnet-app/contextmint-bridge — build it yourself or verify a release zip with `shasum -a 256 -c contextmint-bridge-chrome-<version>.zip.sha256`. Safari isn't available yet — use Chrome.\n\n## Core call\n\nAlmost every endpoint is a GET to a `/stingray/...` path. Redfin prefixes\nevery stingray JSON body with a literal anti-CSRF `{}&&`, so strip that\nbefore piping to `jq`:\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin \\\n  | sed -E 's/^\\{\\}&&//' \\\n  | jq '.payload.homes'\n```\n\nEvery stripped body is an envelope `{ version, errorMessage, resultCode,\npayload }` — check `resultCode == 0` before trusting `payload` (a nonzero\ncode means Redfin rejected the request; `errorMessage` explains why).\n\nReady-to-run request paths (autocomplete, search, property detail, price\nhistory, market trends, comparable rentals, climate risk, saved homes)\nare in `references/stingray-endpo"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn700jq4sjtf2anb0rk3ft4p7n856872\",\n  \"slug\": \"redfin-fpx\",\n  \"version\": \"1.2.3\",\n  \"publishedAt\": 1791588508798\n}"},{"path":"references/stingray-endpoints.md","content":"# Redfin stingray endpoints for fpx\n\nReady-to-run requests for `fpx get '<url>' -p redfin`. All paths and\nparams are transcribed from the live-verified request builders in\n`src/tools/*.ts` / `src/autocomplete.ts` in this repo — see the header\ncomment of each source file for verification dates and any known quirks.\n\nBase origin: `https://www.redfin.com`. Every `/stingray/...` response\ncarries a literal `{}&&` anti-CSRF prefix — strip it before parsing:\n\n```sh\nSTRIP='sed -E s/^\\{\\}\\&\\&//'\nfpx get 'https://www.redfin.com/stingray/api/gis?...' -p redfin | $STRIP | jq '.payload'\n```\n\nThe stripped body is `{ version, errorMessage, resultCode, payload }`;\n`resultCode !== 0` means Redfin rejected the request (`errorMessage` has\nwhy).\n\n---\n\n## 1. Autocomplete — resolve a location or address (do this first)\n\n`GET /stingray/do/location-autocomplete`\n\nParams: `location` (free text), `start=0`, `count=1` (only the first row\nof each section is ever needed), `v=2`, `iss=false`, `ooa=true`,\n`mrs=false`.\n\n```sh\nfpx get 'https://www.redfin.com/stingray/do/location-autocomplete?location=Brooklyn%2C%20NY&start=0&count=1&v=2&iss=false&ooa=true&mrs=false' \\\n  -p redfin | $STRIP \\\n  | jq '.payload.sections[] | {name, rows: [.rows[0]]}'\n```\n\nResponse: `payload.sections[]`, each `{ name: \"Places\"|\"Addresses\"|\"Schools\"|\"Agents\"|…, rows: [...] }`.\n\n- **Places** rows: `id` formatted `\"<region_type>_<region_id>\"` (e.g.\n  `\"6_30749\"` → region_type 6, region_id 30749), `name`, `subName`, `url`.\n- **Addresses** rows: no `id` — `url` is the canonical home path, e.g.\n  `/NC/Lake-Lure/158-Raven-Blvd-28746/home/112653221`. Parse\n  `/<STATE>/<City>/<Street>-<ZIP>(/unit-<U>)?/home/<home_id>`. A full\n  street address typically returns an Addresses row instead of/alongside\n  Places — that's Redfin telling you it resolved a specific home, not a\n  searchable region.\n\n```sh\n# Region id for a search:\njq -r '.payload.sections[] | select(.name==\"Places\") | .rows[0].id'\n# Home id + canonical url for an address:\njq -r '.payload.sections[] | select(.name==\"Addresses\") | .rows[0].url'\n```\n\n## 2. Search for-sale listings — `/stingray/api/gis`\n\nRequires a resolved `region_id` + `region_type` from §1. Query params\n(all strings/CSVs):\n\n| param | meaning |\n|---|---|\n| `al=1` | always 1 |\n| `num_homes` | result limit (Redfin web app default 40) |\n| `region_id`, `region_type` | from autocomplete |\n| `sf=1,2,3,5,6,7` | static — result fields to include |\n| `start=0` | pagination offset |\n| `status` | `1` = active for sale; `9` = active+coming-soon+contingent+pending (broader — what redfin-mcp uses as its default \"everything for sale\" view) |\n| `uipt` | CSV of property-type bitmap: house=1, condo=2, townhouse=3, multi_family=4, land=5, other=6, manufactured=7, co-op=8 (omit/`1,2,3,4,5,6,7,8` for all) |\n| `v=8` | static |\n| `min_price`, `max_price` | optional, USD |\n| `num_beds`, `num_baths` | optional, minimums |\n\n```sh\nfpx get 'https://www.redfin.com/stingray/api/gis?al=1&num_homes=40&region_id=30749&re"},{"path":"skill-card.md","content":"## Description:\n\nHelps agents query U.S. Redfin listings, property details, market data, and, with a signed-in browser, saved homes and searches 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 retrieve Redfin property and market information from a shell without running an MCP server. Saved homes and searches require an explicitly paired, signed-in browser session.\n\n### Deployment Geography for Use:\n\nUnited States (Redfin property data)\n\n## Known Risks and Mitigations:\n\nRisk: Saved homes and searches may expose private account data.\n\nMitigation: Ask before accessing signed-in saved items; avoid logging or sharing raw results unnecessarily.\n\nRisk: Browser pairing connects requests to the user's Redfin session.\n\nMitigation: Pair the bridge only with the user's explicit approval.\n\n## Reference(s):\n\n- [Redfin fpx skill release](https://clawhub.ai/chrischall/skills/redfin-fpx)\n- [Redfin endpoint reference](references/stingray-endpoints.md)\n- [ContextMint Bridge releases](https://github.com/nullnet-app/contextmint-bridge/releases)\n- [Fetchproxy extension information](https://github.com/chrischall/fetchproxy#extension)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Shell commands, Configuration instructions, Guidance]\n\n**Output Format:** [Markdown with shell examples and summaries of retrieved Redfin data]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Saved-item results may contain private account data.]\n\n## Skill Version(s):\n\n1.2.3 (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."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1520,"uniquenessScore":44,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T09:16:01.253Z","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-10T09:16:01.253Z","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-10T11:53:35.961Z","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"}]}}}