← back to Commercialrealestate
CRE: reroute fetch-sfr-redfin off Browserbase to local Chrome ($0)
98859708651f58d6e13f1fe71aba504af2ded64b · 2026-08-18 12:03:23 -0700 · Steve Abrams
TK-10655 follow-up (Steve approved the residual). Same one-line default flip as
its condo sibling: LOCAL is now the default (CC_LOCAL=0 opts back into paid
Browserbase); SDK + creds lazy-loaded only on the paid path. Residential IP
clears Redfin's gis-csv wall. Completes the Browserbase->local reroute across
all CRE Redfin scrapers.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M scripts/fetch-sfr-redfin.js
Diff
commit 98859708651f58d6e13f1fe71aba504af2ded64b
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Tue Aug 18 12:03:23 2026 -0700
CRE: reroute fetch-sfr-redfin off Browserbase to local Chrome ($0)
TK-10655 follow-up (Steve approved the residual). Same one-line default flip as
its condo sibling: LOCAL is now the default (CC_LOCAL=0 opts back into paid
Browserbase); SDK + creds lazy-loaded only on the paid path. Residential IP
clears Redfin's gis-csv wall. Completes the Browserbase->local reroute across
all CRE Redfin scrapers.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
scripts/fetch-sfr-redfin.js | 25 +++++++++++++++++--------
1 file changed, 17 insertions(+), 8 deletions(-)
diff --git a/scripts/fetch-sfr-redfin.js b/scripts/fetch-sfr-redfin.js
index 415368b..9415034 100644
--- a/scripts/fetch-sfr-redfin.js
+++ b/scripts/fetch-sfr-redfin.js
@@ -3,7 +3,8 @@
// Same gis-csv feed that cracked the condo sweep (fetch-condos-redfin.js) but uipt=1 (single-family
// detached) instead of uipt=3 (condo). status=9 = active for-sale. For each resolved LA region
// (data/redfin-regions.json cities + redfin-neighborhoods.json hoods, 229 region_ids) we warm ONE
-// Browserbase session and fetch the gis-csv feed in-page, then upsert each SFR into cre.sfr.
+// LOCAL real-Chrome session (default; residential IP, $0 — TK-10655) and fetch the gis-csv feed
+// in-page, then upsert each SFR into cre.sfr. CC_LOCAL=0 opts back into paid Browserbase.
//
// /stingray/api/gis-csv?al=1®ion_id=<id>®ion_type=<6 city|1 hood>&uipt=1&num_homes=350&status=9
//
@@ -25,18 +26,22 @@
const fs = require('fs');
const path = require('path');
const { chromium } = require('playwright-core');
-const Browserbase = require('@browserbasehq/sdk').default;
const { Pool } = require('pg');
const { inLACounty } = require('./sources/la-county');
-const bbEnv = fs.readFileSync(process.env.HOME + '/.claude/skills/browserbase/.env', 'utf8');
const get = (t, k) => (t.match(new RegExp('^' + k + '=(.*)$', 'm')) || [])[1]?.replace(/['"]/g, '').trim();
const ROOT = path.join(__dirname, '..');
const pool = new Pool({ host: '/tmp', port: 5432, database: 'cre', user: process.env.USER || 'stevestudio2' });
-// CC_LOCAL=1 launches local Chrome (residential IP clears Redfin) instead of a paid Browserbase
-// session — $0/run. Same in-page gis-csv fetch; only the browser transport differs.
-const LOCAL = process.env.CC_LOCAL === '1';
+// LOCAL is now the DEFAULT (TK-10655, prefer-local rule): drive the local Google Chrome (residential
+// IP clears Redfin's bot wall) at $0/run. Opt back into paid Browserbase ONLY with CC_LOCAL=0.
+// Same in-page gis-csv fetch; only the browser transport differs. Browserbase creds/SDK are loaded
+// lazily below and ONLY when CC_LOCAL=0, so a default local run needs no browserbase .env present.
+const LOCAL = process.env.CC_LOCAL !== '0';
+function bbCreds() {
+ const bbEnv = fs.readFileSync(process.env.HOME + '/.claude/skills/browserbase/.env', 'utf8');
+ return { KEY: get(bbEnv, 'BROWSERBASE_API_KEY'), PROJECT: get(bbEnv, 'BROWSERBASE_PROJECT_ID') };
+}
const CHROME_PATH = process.env.CHROME_PATH || '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';
const SESSION_COST = LOCAL ? 0 : 0.04;
const MAX_SESSIONS = +(process.env.CC_MAX_SESSIONS || (LOCAL ? 999 : 30));
@@ -187,8 +192,12 @@ function loadRegions() {
if (LOCAL) {
browser = await chromium.launch({ executablePath: CHROME_PATH, args: ['--disable-blink-features=AutomationControlled'] });
} else {
- const bb = new Browserbase({ apiKey: get(bbEnv, 'BROWSERBASE_API_KEY') });
- session = await bb.sessions.create({ projectId: get(bbEnv, 'BROWSERBASE_PROJECT_ID'), browserSettings: { solveCaptchas: true, viewport: { width: 1440, height: 1000 } } });
+ // Paid fallback, opt-in only (CC_LOCAL=0). SDK + creds loaded lazily so a default local run
+ // never touches Browserbase.
+ const Browserbase = require('@browserbasehq/sdk').default;
+ const { KEY, PROJECT } = bbCreds();
+ const bb = new Browserbase({ apiKey: KEY });
+ session = await bb.sessions.create({ projectId: PROJECT, browserSettings: { solveCaptchas: true, viewport: { width: 1440, height: 1000 } } });
browser = await chromium.connectOverCDP(session.connectUrl);
}
const ctx = browser.contexts()[0] || await browser.newContext({ userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', viewport: { width: 1440, height: 1000 } });
← 9ac1e11 Fix mls.html empty grid: relative fetch() threw on credentia
·
back to Commercialrealestate
·
Apply credential-safe fetch wrapper fleet-wide (22 CRCP page d6f3dbf →