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:

  1. workspace/scripts/dispo-propstream-blast.js — production scraping script (code inspection)
  2. .secrets/propstream.json credential structure (keys inspected: email, password, loginUrlNO 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

FieldValue
VendorPropStream
URLhttps://app.propstream.com
KB docSOURCE MISSING — no knowledge-base/propstream/ dir
Auth methodWeb session login (Playwright stealth; email + password via .secrets/propstream.json)
Auth credentialop://Aurora/propstream/email + op://Aurora/propstream/password
Cred-proxy portn/a (until B1-B6 ratified per nemoclaw-audit-2026-05-03)
Webhook portn/a
Webhook handlern/a
Webhook dedup tabledispo_blast_recipients (channel='propstream', 24h dedup)
Tunnel pathn/a
Outbound API basen/a (web scraping only — no documented REST API)
Rate limitsUnknown (NEEDS VERIFICATION) — scraper uses 8s login wait + stealth browser
Rate-limit actionCAPTCHA/2FA detection → warning log + manual intervention flag
Screenshot path/tmp/propstream/ (login-page.png, post-login.png for debugging)
Blast channelChannel 4 — “propstream” in dispo_blast_recipients
CostSubscription (SaaS); contact PropStream for pricing
Backup/recoveryn/a (scraping; no data stored locally beyond blast records)
Discord alert channelops
Drift cadencemanual; scraper breaks on UI changes
Data licensesubscription — active PropStream account required
Statusproduction

Credential structure (no plaintext)

PropStream credentials are stored in .secrets/propstream.json with three keys:

KeyPurpose1Password ref
emailPropStream login emailop://Aurora/propstream/email
passwordPropStream login passwordop://Aurora/propstream/password
loginUrlLogin 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 logs

G-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 in dispo_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 for dispo_blast_recipients dedup 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:
    1. Launch Playwright Chromium with stealth plugin (puppeteer-extra-plugin-stealth)
    2. Login to https://app.propstream.com/login with stored credentials
    3. Search flippers by zip code + surrounding zip prefix (same 3-digit prefix) — “sold as flip in last 24 months”
    4. Extract flipper contact info + flip metrics (up to MAX_PAGES_TO_SCRAPE = 20 pages)
    5. Dedup against HubSpot contacts + SalesMsg conversation history + dispo_blast_recipients
    6. Personalize message per flipper profile (flip count, geography, deal price alignment)
    7. Send via SalesMsg from appropriate inbox (Dispo A: 128279; End Buyer CA: 143887; End Buyer FL: 160031)
    8. Record all sends in dispo_blast_recipients with channel='propstream'
  • 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 / passwordSelectors arrays 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_recipients rows written with channel='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 dedup

PropStream 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

InboxSalesMsg IDUse case
Dispo A128279Default dispo outreach
End Buyer CA143887California-area end buyers
End Buyer FL160031Florida-area end buyers

State is extracted from flipper address to route to correct inbox.


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.md before invoking
  • acquisitions-followup — not directly, but flipper contacts may become ACQ targets after dispo blast

Plans that govern this

Feedback rules

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


PlatformHubRole
CRMLScrmlsMLS listing source (anchor)
PropStream (this hub)propstreamFlipper lead lists, Channel 4 cold blast
OpenToCloseopentocloseTC transaction management
HubSpothubspotCRM — cold blast deals land here
InvestorLiftinvestorliftWholesale marketplace
Buyer blast processbuyer-blastParent process: all 4 blast channels

Open issues / TODOs

  • P0 — SOURCE MISSING: Create workspace/knowledge-base/propstream/API.md documenting 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 / passwordSelectors arrays 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 = 20 is a conservative cap; actual throttle threshold undocumented
  • .secrets/propstream.json is on VPS filesystem (not 1Password) — should migrate to op://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.js script inspection + .secrets/propstream.json key structure only