PropStream Flipper Lead Hub
PropStream is a subscription real estate data platform used at RERI as Channel 4 of the dispo buyer blast: scraping recent property flippers by zip code for cold outreach. This hub covers the credential structure, Playwright-based login flow, flipper extraction pattern, compliance gate integration, and HubSpot/SalesMsg dedup logic. Read before modifying dispo-propstream-blast.js or any PropStream scraping workflow.
⚠️ SOURCE MISSING — No KB directory
workspace/knowledge-base/propstream/ does not exist. Per feedback_kb_sync_with_claude_md (G-KB-SYNC-WITH-CLAUDEMD), a KB directory is required before authoring API code for any platform.
This hub was authored from two secondary sources only:
workspace/scripts/dispo-propstream-blast.js— production scraping script (code inspection).secrets/propstream.jsoncredential structure (keys inspected:email,password,loginUrl— NO VALUES QUOTED)
Action required: Create workspace/knowledge-base/propstream/ with API.md documenting the PropStream web app scraping surface, any available REST/export API, rate limiting behavior, and CAPTCHA/2FA handling before extending this integration. Flag this as a G-KB-SYNC-WITH-CLAUDEMD gap until resolved.
Quick reference
| Field | Value |
|---|---|
| Vendor | PropStream |
| URL | https://app.propstream.com |
| KB doc | SOURCE MISSING — no knowledge-base/propstream/ dir |
| Auth method | Web session login (Playwright stealth; email + password via .secrets/propstream.json) |
| Auth credential | op://Aurora/propstream/email + op://Aurora/propstream/password |
| Cred-proxy port | n/a (until B1-B6 ratified per nemoclaw-audit-2026-05-03) |
| Webhook port | n/a |
| Webhook handler | n/a |
| Webhook dedup table | dispo_blast_recipients (channel='propstream', 24h dedup) |
| Tunnel path | n/a |
| Outbound API base | n/a (web scraping only — no documented REST API) |
| Rate limits | Unknown (NEEDS VERIFICATION) — scraper uses 8s login wait + stealth browser |
| Rate-limit action | CAPTCHA/2FA detection → warning log + manual intervention flag |
| Screenshot path | /tmp/propstream/ (login-page.png, post-login.png for debugging) |
| Blast channel | Channel 4 — “propstream” in dispo_blast_recipients |
| Cost | Subscription (SaaS); contact PropStream for pricing |
| Backup/recovery | n/a (scraping; no data stored locally beyond blast records) |
| Discord alert channel | ops |
| Drift cadence | manual; scraper breaks on UI changes |
| Data license | subscription — active PropStream account required |
| Status | production |
Credential structure (no plaintext)
PropStream credentials are stored in .secrets/propstream.json with three keys:
| Key | Purpose | 1Password ref |
|---|---|---|
email | PropStream login email | op://Aurora/propstream/email |
password | PropStream login password | op://Aurora/propstream/password |
loginUrl | Login URL (defaults to https://app.propstream.com if absent) | hardcoded fallback in script |
The script at workspace/scripts/dispo-propstream-blast.js reads these at startup:
const _psCreds = JSON.parse(fs.readFileSync(PROPSTREAM_CREDS_PATH, 'utf8'));
// PROPSTREAM_EMAIL = _psCreds.email ← never quoted in code or logs
// PROPSTREAM_PASSWORD = _psCreds.password ← never quoted in code or logsG-NO-PLAINTEXT-CREDS: Never quote, log, or commit these values. Reference via op:// only.
Components
workspace/scripts/dispo-propstream-blast.js— Channel 4 dispo blast: login → zip-radius flipper search → HubSpot/SalesMsg dedup → personalized SMS → record indispo_blast_recipients.secrets/propstream.json— Credential file (not committed; chmod 600); keys:email,password,loginUrl/tmp/propstream/— Screenshot debug directory (login-page.png, post-login.png, post-login-wait.png)workspace/lib/db.js— Supabase client (used fordispo_blast_recipientsdedup writes)workspace/scripts/lib/compliance-gate.js— Pre-send compliance check (TCPA, opt-out, 10DLC) invoked before every PropStream flipper send- buyer-blast — Parent process hub; PropStream is Channel 4 of 4
How it’s used
- Trigger: dispo-blast or direct CLI:
node workspace/scripts/dispo-propstream-blast.js <deal_id> [--limit 500] [--dry-run] - Flow:
- Launch Playwright Chromium with stealth plugin (
puppeteer-extra-plugin-stealth) - Login to
https://app.propstream.com/loginwith stored credentials - Search flippers by zip code + surrounding zip prefix (same 3-digit prefix) — “sold as flip in last 24 months”
- Extract flipper contact info + flip metrics (up to
MAX_PAGES_TO_SCRAPE = 20pages) - Dedup against HubSpot contacts + SalesMsg conversation history +
dispo_blast_recipients - Personalize message per flipper profile (flip count, geography, deal price alignment)
- Send via SalesMsg from appropriate inbox (Dispo A:
128279; End Buyer CA:143887; End Buyer FL:160031) - Record all sends in
dispo_blast_recipientswithchannel='propstream'
- Launch Playwright Chromium with stealth plugin (
- Failure modes:
- Login CAPTCHA/2FA detected → script logs warning, exits gracefully; requires manual PropStream login to clear
- “Invalid credentials” in page content → throw error, check
.secrets/propstream.json - UI selector change → email/password input selectors fail; update
emailSelectors/passwordSelectorsarrays in script - Rate throttle (unknown threshold) → 8s post-login wait + stealth browser mitigates but not guaranteed
- Success criteria: Flippers extracted, compliance gate passed, SMS sent,
dispo_blast_recipientsrows written withchannel='propstream'
Compliance gate (mandatory before send)
const { checkCompliance } = require('./lib/compliance-gate');
// Invoked per-recipient before every PropStream SMS send
// Gates: TCPA quiet hours, opt-out list, 10DLC registration, blast-safety dedupPropStream blasts are cold outreach to flippers — TCPA compliance is non-negotiable. The compliance gate at compliance-gates must pass before any send. Do not bypass checkCompliance().
Inbox routing
| Inbox | SalesMsg ID | Use case |
|---|---|---|
| Dispo A | 128279 | Default dispo outreach |
| End Buyer CA | 143887 | California-area end buyers |
| End Buyer FL | 160031 | Florida-area end buyers |
State is extracted from flipper address to route to correct inbox.
Cross-links
Agents that touch this
- _summary — dispo blast coordination; triggers PropStream channel
- _summary — oversees blast authorization and result review
Skills that invoke this
- dispo-blast — 4-channel coordinator; PropStream is Channel 4. READ
~/.claude/skills/dispo-blast/SKILL.mdbefore invoking - acquisitions-followup — not directly, but flipper contacts may become ACQ targets after dispo blast
Plans that govern this
- openclaw-self-improvement-layer-2026-05-03 — OSIL roadmap may add PropStream as an IL alternative data source
- openclaw-fragmentation-fix-2026-05-01 — G-NO-PLAINTEXT-CREDS; G-KB-SYNC-WITH-CLAUDEMD gap (no KB dir)
Feedback rules
- feedback_no_plaintext_creds — credentials in
.secrets/propstream.jsononly; reference viaop://in docs - feedback_kb_sync_with_claude_md — G-KB-SYNC-WITH-CLAUDEMD: create
knowledge-base/propstream/before extending this integration - feedback_never_send_without_auth — PropStream blast requires explicit authorization per feedback_action_gate_violation_repeated
- feedback_probe_before_execute — always run
--dry-runon PropStream blast before live send
KB / source docs
- SOURCE MISSING:
knowledge-base/propstream/does not exist. Hub authored from script inspection only. - API — SMS send API used for PropStream flipper outreach
System maps
- request-lifecycle — dispo blast channel position
- external-integrations — PropStream as external data source
Related: Real estate data platform cluster
| Platform | Hub | Role |
|---|---|---|
| CRMLS | crmls | MLS listing source (anchor) |
| PropStream (this hub) | propstream | Flipper lead lists, Channel 4 cold blast |
| OpenToClose | opentoclose | TC transaction management |
| HubSpot | hubspot | CRM — cold blast deals land here |
| InvestorLift | investorlift | Wholesale marketplace |
| Buyer blast process | buyer-blast | Parent process: all 4 blast channels |
Open issues / TODOs
- P0 — SOURCE MISSING: Create
workspace/knowledge-base/propstream/API.mddocumenting actual PropStream scraping surface, any REST export API, rate limits, and 2FA handling. Required before extending this integration. See G-KB-SYNC-WITH-CLAUDEMD. - Login selector brittle — PropStream is a SPA;
emailSelectors/passwordSelectorsarrays may break on UI update. Add a selector-version comment when updated. - CAPTCHA handling is detection-only (warns, does not solve) — PropStream may increase bot protection; monitor
- Rate limits unknown —
MAX_PAGES_TO_SCRAPE = 20is a conservative cap; actual throttle threshold undocumented .secrets/propstream.jsonis on VPS filesystem (not 1Password) — should migrate toop://Aurora/propstream/as part of next cred-proxy ratification (B1-B6)
Recent activity
- 2026-05-03: hub created (W2-S9); SOURCE MISSING flagged per G-KB-SYNC-WITH-CLAUDEMD; sourced from
dispo-propstream-blast.jsscript inspection +.secrets/propstream.jsonkey structure only