Redfin 會在新上架的美國 MLS 房源進入系統後的五分鐘內更新其中 。這種即時性,對任何想打造房地產資料管線的人來說都很有吸引力——也正因如此,很多爬蟲都會盯上 Redfin,然後在幾分鐘內就被封鎖。
我在 從事資料擷取工具開發很多年,可以很直接地說:從「抓取 Redfin」到「抓取 Redfin 又不被封鎖」之間的落差,正是大多數教學翻車的地方。它們只會秀 BeautifulSoup 程式碼,卻跳過 Cloudflare 把請求擋下來的關鍵步驟,最後讓你盯著 403 頁面一頭霧水。這篇指南不一樣。我會帶你走過三種實戰路線——HTML 解析、Redfin 隱藏 API,以及使用 Thunderbit 的無程式碼方案——並且重點說明真正重要的反機器人防護。讀完後,你會很清楚哪種方法最適合你的技術背景、資料規模,以及你能接受多少維護成本。
Redfin 是什麼?為什麼它的資料這麼重要?
Redfin 是一家以技術驅動的房地產經紀公司,旗下是領薪制經紀人,直接從 MLS 資料源取得房源。它涵蓋 ,每月服務接近 5,000 萬名訪客。和只做資料彙整的入口網站不同,Redfin 的資料經過經紀人驗證,而且它自家的 Redfin Estimate AVM 覆蓋了 ,對在售物件的中位誤差僅 1.96%。

正因為它同時具備 MLS 等級的即時性、經紀驗證的品質,以及準確度很高的 AVM,房地產投資人、經紀人、PropTech 新創和資料分析師都希望能程式化地取得 Redfin 資料。Python 自然是最常見的選擇:它的爬取生態系成熟(requests、BeautifulSoup、Selenium、Playwright),社群支援龐大,還能直接接到 pandas 和 Jupyter 做分析。
為什麼要用 Python 抓取 Redfin?
不同的人使用 Redfin 資料的方式也不同。以下是常見的使用情境:
| 受眾 | 主要抓取目的 | 範例用途 |
|---|---|---|
| 房地產經紀人 | 開發潛在客戶、掌握市場情報 | 服務區內的新上架與過期房源;經紀人名錄用於競爭分析 |
| 房地產投資人 | 案源開發、報酬率分析 | 租金收益篩選、低估物件偵測、每日新房源提醒 |
| PropTech 新創 | 產品資料管線 | AVM 訓練資料、市場儀表板、iBuyer 收購引擎 |
| 資料分析師 | 市場研究、商業智慧 | ZIP code 層級的中位價趨勢、在市天數時間序列、售價/掛牌價比率 |
| 批發商 / 翻修轉售者 | 困難房源追蹤 | 降價偵測、法拍屋、非上市比較物件 |
更大的趨勢也支持這個需求:目前 都已使用預測分析來找機會與控風險。PropTech 市場預計在 2025 年達到 ,年複合成長率 16.4%。結構化房地產資料早就不是加分項,而是基本配備。
你能抓到的 Redfin 資料欄位有哪些?(完整參考)
在寫任何一行程式之前,你得先知道實際有哪些資料可拿。我已經針對 Redfin 的搜尋結果頁、物件詳情頁和經紀人檔案頁做過整理,並交叉參考了像 與 這類開源 Stingray API 包裝器。總共可整理出跨頁面類型的 117 個不同欄位。
這張表很值得收藏。先搞懂資料結構再寫程式,可以省下好幾個小時的 selector 除錯時間。
搜尋結果頁欄位
這些是房源卡片上可直接看到的輕量欄位,很多情況下不需要完整 JS 渲染就能擷取:
| 欄位 | 資料類型 | 備註 |
|---|---|---|
| 房源 ID | 數字 | Redfin 內部整數,從 href 裡的 /home/{id} 解析出來 |
| 掛牌價格 | 數字 | |
| 完整地址 | 文字 | |
| 臥室 / 浴室 / 坪數 | 數字 | 依序出現的三個數值 |
| 房產類型 | 單選 | SFH、Condo、Townhouse、Multi |
| 狀態 | 文字 | Active、Pending、Contingent |
| 在市天數 | 數字 | |
| 降價指標 | 數字 | 與原始掛牌價的差額 |
| 主圖 | 圖片網址 | 每張卡一張圖 |
| Hot Home 徽章 | 布林值 | |
| 開放看屋日期/時間 | 文字 | |
| 經紀公司標註 | 文字 |
物件詳情頁欄位
真正有深度的資料都在詳情頁。這些欄位很多都需要 JavaScript 渲染或 Stingray API:
| 欄位 | 資料類型 | 備註 |
|---|---|---|
| Redfin Estimate(在售) | 數字 | 透過 /stingray/api/home/details/avm |
| Redfin Estimate(非在售) | 數字 | 透過 /stingray/api/home/details/owner-estimate;中位誤差 7.52% |
| 建造 / 翻新年份 | 數字 | |
| 土地面積 | 數字 | |
| HOA 管理費 | 數字 | 每月,如適用 |
| 房產稅(年度) | 數字 | |
| 稅務評估價值 | 數字 | |
| 成交歷史表 | 表格 | 價格、日期、事件類型 |
| 房源描述 | 文字 | 行銷文案 |
| 照片網址(輪播) | 圖片網址 | 每個房源 20 張以上 |
| 列表經紀人姓名、電話、Email | 文字 / 電話 / Email | 電話常會被遮蔽 |
| 學校評分(小學 / 國中 / 高中) | 數字 | 另含學區名稱 |
| 步行 / 大眾運輸 / 自行車評分 | 數字 | |
| 氣候風險分數 | 數字 | 洪水、火災、熱浪、風災 |
| 相似在售 / 已售 / 鄰近房源 | 網址 | 輪播資料 |
| 停車、車庫、暖氣、冷氣 | 文字 | 設備群組 |
經紀人檔案欄位
| 欄位 | 資料類型 | 備註 |
|---|---|---|
| 經紀人姓名、照片、經紀公司、自我介紹 | 文字 / 圖片 | |
| 電話、聯絡表單 | 電話 / 文字 | 點擊後顯示 |
| 目前在售房源數 | 數字 | |
| 過去 12 個月成交 / 總成交量 | 數字 | |
| 平均售掛比 | 數字 | |
| 星等評分 / 評論數 | 數字 | |
| 年資 / 執照號碼 | 文字 / 數字 |
當你在 Redfin 頁面上使用 Thunderbit 的 AI Suggest Fields 功能時,它會自動偵測這些欄位,並套用正確的資料型別——不需要手動對 CSS selector。
拆解 Redfin 的反機器人防護(不只是「用代理」這麼簡單)
這裡我要特別劃重點,因為大多數教學都會輕描淡寫地略過封鎖問題,然後直接叫你「去買我們贊助商的代理」。這沒有幫助。如果你不知道 Redfin 到底怎麼辨識爬蟲,就算燒掉再多代理額度,還是會被封鎖。,而 ——「比 Zillow 的企業級 WAF 沒那麼激進,但仍依賴自訂限速與 JavaScript 挑戰」。
Redfin 採用的是多層防護:邊緣層的 Cloudflare(JS challenge、Turnstile、TLS/JA3 指紋辨識)再加上 Redfin 自己的應用層限流器。他們的 robots.txt 裡沒有 Crawl-delay,因為實際執行是在 WAF 層完成。
為什麼單純的 requests + BeautifulSoup 會在 Redfin 失敗
如果你用預設 header,直接對 Redfin 的房源頁發出基本的 requests.get(),通常會發生以下幾種情況:
- HTTP 403 —— Cloudflare 的 JS challenge 沒有通過,你拿到的是挑戰頁,不是房源內容。
- 中間挑戰頁 —— HTML 主體裡只有 Cloudflare 的 Turnstile 元件,沒有房產資料。
- HTTP 200 但 HTML 不完整 —— 你會拿到一個外殼,裡面有一大段嵌入式 JSON,位在
root.__reactServerState.InitialContext,但沒有預渲染的搜尋卡片、沒有價格歷史、也沒有學校評分。
Redfin 使用的是自己的 (不是 Next.js),而 hydration key 也是 Redfin 自家的格式:root.__reactServerState.InitialContext,房源資料會嵌在 ReactServerAgent.cache.dataCache 裡。這不是 __NEXT_DATA__,也不是 window.__INITIAL_STATE__。
最常見、卻又最容易被忽略的 silent 403 原因是什麼?缺少 Sec-Fetch-* headers。 Redfin / Cloudflare 會明確驗證 Sec-Fetch-Site、Sec-Fetch-Mode、Sec-Fetch-Dest 和 Sec-Fetch-User。只要缺少其中幾個,立刻就會被標記。
對策清單:延遲、標頭、代理與 Session
以下是各種防護與對應解法的完整拆解:
| Redfin 防護機制 | 作用 | 偵測訊號 | 緩解策略 |
|---|---|---|---|
| Cloudflare JS challenge | 發出 cf_clearance cookie 的中間頁 | 403 + Cloudflare HTML 主體 | 使用 curl_cffi 並設定 impersonate="chrome120";先用首頁暖機;美國住宅代理 |
| Cloudflare Turnstile | 高風險 session 的互動式 CAPTCHA | 403 + Turnstile 小工具 | 具備 stealth 的無頭瀏覽器 + 住宅代理 |
| Cloudflare 錯誤 1020(ASN 封鎖) | 在 WAF 層封鎖被標記的 IP / ASN | 403 主體顯示 "Error 1020 Access Denied" | 改用住宅 / 行動代理;不要使用資料中心 ASN |
| TLS/JA3 指紋辨識 | 辨識非瀏覽器的 TLS 堆疊 | 即使 header 完整也會 silent 403 | 使用 curl_cffi 模擬或真實瀏覽器 |
| HTTP/2 指紋辨識 | 檢查 HTTP/2 SETTINGS 與 HPACK 順序 | 靜默封鎖 | curl_cffi 可像 Chrome 一樣說 HTTP/2 |
| 標頭驗證(UA、Sec-Fetch-*) | 檢查是否像真實瀏覽器 | 第一個請求就 403 | 使用完整 Chrome header,包括 Sec-Fetch-Site/Mode/Dest/User 與合理的 Referer |
| Cookie / session 連續性 | 追蹤 cf_clearance、RF_BROWSER_ID | 冷啟動直連深層 URL 時觸發挑戰 | 持久化 Session;先從首頁暖機 |
| 應用層限流 | 依 IP 限制請求頻率 | 429 | 每次間隔 2–5 秒並加隨機抖動;指數退避 |
| 資料中心 IP 信譽 | 封鎖已知資料中心 ASN | 立刻 1020 / 403 | 只用美國住宅或行動代理 |
| 並發偵測 | 同一 IP 的多個平行請求 | 迅速升級為 Turnstile 挑戰 | 同一 IP 並發數 ≤2 |
社群測試得到的實務門檻:
- 安全節奏:同一 IP 每 2–3 秒 1 次請求
- 單一資料中心 IP 若持續超過每分鐘 20–30 次,通常幾分鐘內就會觸發挑戰
- 軟性限流通常在流量停止後 5–15 分鐘解除
- 資料中心 IP 封鎖(AWS、GCP、Azure、OVH)可能持續數小時到數天
原生 Python requests(urllib3 + OpenSSL)會產生一個 ——即使 header 完整,也會被靜默封鎖。業界常見的解法是 curl_cffi 搭配 impersonate="chrome120",讓 TLS 與 HTTP/2 表現得像 Chrome。
用 Python 抓取 Redfin 的三種方法(以及該選哪一種)

我沒有找到任何競品教學會把這三種方法並排比較。以下是決策表:
| 評估標準 | HTML 解析(BS4 + Selenium) | Stingray 隱藏 API | Thunderbit(無程式碼) |
|---|---|---|---|
| 設定難度 | 中等(Python 環境 + 瀏覽器驅動) | 高(需逆向端點) | 低(安裝 Chrome 擴充功能) |
| 反機器人風險 | 高(DOM 請求最容易被看見) | 中等(API 類請求看起來較自然) | 最低(使用你真實的瀏覽器 session) |
| 資料結構品質 | 中等(非結構化 HTML,需要手動解析) | 極佳(預先結構化 JSON) | 高(AI 自動偵測欄位與資料型別) |
| 維護成本 | 高——版面一改就壞 selector | 中等——端點可能無預警變動 | 最低——AI 會跟著版面變化調整 |
| 規模 | 低到中等(配合代理可到數百頁) | 中到高(數千頁,請求更乾淨) | 中等(雲端抓取每批可處理 50 頁) |
| 最適合 | 想完全掌控的開發者 | 需要乾淨 JSON 的開發者 | 非開發者、快速專案、以及沒有開發資源但需要持續資料的人 |
維護成本這點特別值得強調。Redfin 已經歷經兩代房源卡 DOM:舊版(homecardV2Price)與現行版(span.bp-Homecard__Price--value)。社群 GitHub issue 的歷史顯示,CSS selector 大約每 6–12 個月就會壞一次。這種情況發生時,BeautifulSoup 爬蟲往往一夜之間就失效了。而 AI 欄位偵測則能自我適應。
開始前你需要準備什麼
- 難度: 中階(方法 1 與 2),初階(方法 3)
- 所需時間: 方法 1 或 2 約 30 分鐘;方法 3 約 5 分鐘
- 你需要準備:
- Python 3.8+ 與 pip(方法 1 與 2)
- Chrome 瀏覽器(所有方法都需要)
- (方法 3)
- 大規模抓取時所需的美國住宅代理(方法 1 與 2)
方法 1:使用 HTML 解析用 Python 抓取 Redfin(BeautifulSoup + Selenium)
這是一條「完全掌控」的路線。selector 你自己寫,瀏覽器你自己管,錯誤你自己處理。
這是最有學習價值的方法,同時也是最脆弱的方法。
步驟 1:建立 Python 環境
建立虛擬環境並安裝所需套件:
1python -m venv redfin-scraper
2source redfin-scraper/bin/activate # Windows 請用:redfin-scraper\Scripts\activate
3pip install requests beautifulsoup4 selenium webdriver-manager pandas curl_cffi
這裡 curl_cffi 非常重要——它能讓你的 HTTP 請求偽裝成真實 Chrome 的 TLS 指紋,而不是 Cloudflare 一眼就能識破的原生 Python requests 指紋。
步驟 2:設定瀏覽器標頭與 Session
這是大多數新手會失敗的地方。你需要完整的 Chrome header,包含 Redfin / Cloudflare 會驗證的 Sec-Fetch-*:
1from curl_cffi import requests as curl_requests
2HEADERS = {
3 "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
4 "AppleWebKit/537.36 (KHTML, like Gecko) "
5 "Chrome/120.0.0.0 Safari/537.36",
6 "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
7 "Accept-Language": "en-US,en;q=0.9",
8 "Accept-Encoding": "gzip, deflate, br",
9 "Sec-Fetch-Site": "none",
10 "Sec-Fetch-Mode": "navigate",
11 "Sec-Fetch-Dest": "document",
12 "Sec-Fetch-User": "?1",
13}
14session = curl_requests.Session(impersonate="chrome120")
15session.headers.update(HEADERS)
16# 先把 session 暖起來,取得 cf_clearance 和 RF_BROWSER_ID cookies
17session.get("https://www.redfin.com/")
暖機這一步非常關鍵——如果你直接硬打深層房源頁,沒有先建立 cookie、也沒有 Referer,Cloudflare 會把你判得很低。
一定要先從首頁開始。
步驟 3:抓取 Redfin 搜尋結果
當 session 暖好後,你就可以抓取城市搜尋頁並解析房源卡片。以下是目前這一代常用的 selector(2024–2026):
1import time
2import random
3from bs4 import BeautifulSoup
4base_url = "https://www.redfin.com/city/17151/CA/San-Francisco"
5listings = []
6for page_num in range(1, 6): # 第 1 到第 5 頁
7 url = f"{base_url}/page-{page_num}" if page_num > 1 else base_url
8 resp = session.get(url)
9 if resp.status_code != 200:
10 print(f"第 {page_num} 頁被封鎖:HTTP {resp.status_code}")
11 break
12 soup = BeautifulSoup(resp.text, "html.parser")
13 cards = soup.select("[data-rf-test-id='property-card'], a.bp-Homecard")
14 for card in cards:
15 price_el = card.select_one("span.bp-Homecard__Price--value")
16 addr_el = card.select_one("a.bp-Homecard__Address")
17 stats = card.select("span.bp-Homecard__LockedStat--value")
18 listing = {
19 "price": price_el.text.strip() if price_el else None,
20 "address": addr_el.text.strip() if addr_el else None,
21 "beds": stats[0].text.strip() if len(stats) > 0 else None,
22 "baths": stats[1].text.strip() if len(stats) > 1 else None,
23 "sqft": stats[2].text.strip() if len(stats) > 2 else None,
24 "url": "https://www.redfin.com" + addr_el["href"] if addr_el else None,
25 }
26 listings.append(listing)
27 # 每次隨機等待 2–5 秒
28 time.sleep(random.uniform(2, 5))
29print(f"共抓取 {len(listings)} 筆房源")
你應該會看到一個持續增加的字典列表,每筆都包含舊金山房源的價格、地址、臥室 / 浴室 / 坪數與詳情頁 URL。如果你看到 0 張卡片,先檢查 HTTP 狀態碼——若是 403,代表 Cloudflare 已經攔下你了,這時通常需要住宅代理。
步驟 4:抓取單一房源詳情頁
搜尋結果只能拿到基本資料,詳情頁才有 Redfin Estimate、建造年份、HOA、成交歷史、經紀人資訊與照片。這些頁面需要 JavaScript 渲染,所以改用 Selenium:
1from selenium import webdriver
2from selenium.webdriver.chrome.service import Service
3from webdriver_manager.chrome import ChromeDriverManager
4from selenium.webdriver.common.by import By
5import time
6options = webdriver.ChromeOptions()
7options.add_argument("--headless=new")
8options.add_argument("--disable-blink-features=AutomationControlled")
9options.add_argument("user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
10 "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36")
11driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
12for listing in listings[:10]: # 先補強前 10 筆
13 driver.get(listing["url"])
14 time.sleep(random.uniform(3, 6)) # 等待 JS 渲染
15 try:
16 estimate_el = driver.find_element(By.CSS_SELECTOR, "[data-rf-test-name='avmLdpPrice']")
17 listing["redfin_estimate"] = estimate_el.text.strip()
18 except:
19 listing["redfin_estimate"] = None
20 try:
21 year_built = driver.find_element(By.XPATH, "//span[contains(text(),'Year Built')]/following-sibling::span")
22 listing["year_built"] = year_built.text.strip()
23 except:
24 listing["year_built"] = None
25driver.quit()
完成這一步後,你的前 10 筆房源就應該已經補上 Redfin Estimate 與建造年份資料了。對這些巢狀的設施欄位來說,XPath 通常比 CSS selector 更耐用,但它仍然很脆弱——任何 DOM 重組都可能讓它失效。
步驟 5:處理封鎖與錯誤
加入指數退避的重試邏輯:
1import time
2def fetch_with_retry(session, url, max_retries=3):
3 for attempt in range(max_retries):
4 resp = session.get(url)
5 if resp.status_code == 200:
6 return resp
7 elif resp.status_code in (403, 429, 503):
8 wait = (2 ** attempt) + random.uniform(1, 3)
9 print(f"被封鎖({resp.status_code})。{wait:.1f} 秒後重試...")
10 time.sleep(wait)
11 else:
12 print(f"非預期狀態碼:{resp.status_code}")
13 break
14 return None
你被封鎖時的跡象包括:HTTP 403 且內容是 Cloudflare HTML、HTTP 429(明確限流)、回應 body 為空,或頁面內容中出現 "Error 1020 Access Denied"。如果這些情況持續出現,就該加上住宅代理,或改走 API 方法。
方法 2:使用 Python 與隱藏的 Stingray API 抓取 Redfin
這是我最喜歡的方法。Redfin 前端會對內部 JSON API /stingray/api/home/details/* 發出請求,而回傳的是乾淨、有型別的 JSON——不需要解析 HTML。
如何找出 Redfin 的隱藏 API 端點
打開 Chrome DevTools → Network 分頁 → 過濾 Fetch/XHR → 進入任一個 Redfin 房源頁。你會看到像這些端點的請求:
api/home/details/initialInfo—— 解析 URL → propertyId、listingIdapi/home/details/aboveTheFold—— 價格、臥室、浴室、坪數、照片、狀態、經紀人、MLS 編號api/home/details/belowTheFold—— 設施、HOA、稅金、停車、建造年份、土地、歷史api/home/details/avm—— 在售 Redfin Estimateapi/home/details/owner-estimate—— 非在售 Redfin Estimateapi/home/details/descriptiveParagraph—— 行銷描述
對租賃頁來說,rentalId(36 字元 UUID)會從 <meta property="og:image"> 標籤的網址中擷取出來。
透過 Stingray API 擷取房產資料
有一個很關鍵的小細節:Stingray 的 JSON 回應前面會加上字串 {}&& 作為反 CSRF 措施。解析前一定要先去掉:
1import json
2from curl_cffi import requests as curl_requests
3session = curl_requests.Session(impersonate="chrome120")
4session.headers.update(HEADERS)
5# 先暖機 session
6session.get("https://www.redfin.com/")
7# 先抓一個房源頁,取得 cookies 與 property ID
8property_url = "https://www.redfin.com/CA/San-Francisco/123-Main-St-94102/home/12345678"
9page_resp = session.get(property_url)
10# 接著呼叫 Stingray API
11api_url = "https://www.redfin.com/stingray/api/home/details/aboveTheFold?propertyId=12345678"
12api_resp = session.get(api_url, headers={"Referer": property_url})
13# 移除反 CSRF 前綴
14payload = json.loads(api_resp.text.replace("{}&&", "", 1))
15# 擷取結構化資料
16listing_data = payload.get("payload", {})
17print(json.dumps(listing_data, indent=2))
回應中會包含型別明確的欄位:價格是整數、臥室/浴室是數字、照片網址是陣列、經紀人資訊是巢狀物件。完全不需要 BeautifulSoup、CSS selector,也不用猜。
隱藏 API 方法的優點與限制
優點:
- 原生結構化 JSON——比 HTML 解析乾淨許多
- 每次請求更快(payload 更小,也沒有渲染成本)
- 被封鎖風險較低(搭配正確標頭的 API 類請求看起來更自然)
限制:
- 端點可能無預警變動——沒有官方文件
robots.txt明確禁止 wildcard user-agent 存取/stingray/- 需要逆向工程來找新端點
- 仍然需要 session 暖機與正確標頭,否則還是可能被 Cloudflare 擋下
無程式碼替代方案:用 Thunderbit 抓取 Redfin
如果你需要 Redfin 資料,但不想維護 Python 腳本——或者你只是想在五分鐘內看到結果——那就從這裡開始。我們做 的目的,正是為了這件事:從任何網站擷取結構化資料,完全不需要寫程式。
步驟 1:安裝 Thunderbit 並進入 Redfin
先從 Chrome 線上應用程式商店安裝 。打開 Redfin,進入搜尋結果頁——例如舊金山待售房源頁。
步驟 2:點擊「AI Suggest Fields」
點選瀏覽器工具列中的 Thunderbit 圖示,然後點擊 「AI Suggest Fields」。AI 會讀取 Redfin 頁面,並自動建議像是「地址」、「價格」、「臥室」、「浴室」、「坪數」、「房產類型」和「房源照片」等欄位,而且會自動套用正確的資料型別。
你也可以移除不需要的欄位,或者點擊 「+ Add Column」 自訂欄位,直接用白話描述你想要的資料,例如「列表經紀人姓名」或「在市天數」。
接著你就會看到一個已設定好欄位的表格預覽,準備開始填資料。
步驟 3:點擊「Scrape」並看資料自動匯入
點擊 「Scrape」 按鈕。Thunderbit 會處理目前可見的房源並填入表格。遇到分頁結果時,它也會自動處理 pagination,不需要你寫迴圈。
以我的測試來看,一個 50 列的表格大約 45 秒就能填完。結構化資料,隨時可匯出。
Thunderbit 如何處理 Redfin 的反機器人防護
因為 Thunderbit 是在你自己的瀏覽器裡執行,它會沿用你現有的 Redfin cookies、session 與瀏覽器指紋。對 Cloudflare 來說,它看起來就像是一般使用者在瀏覽 Redfin——因為技術上,它確實就是。沒有無頭瀏覽器、沒有資料中心 IP,也沒有不匹配的 TLS 指紋。對公開頁面來說,Thunderbit 的雲端抓取模式一次可以處理 50 個頁面。
這和在伺服器上用 Python 腳本發 requests 的做法,本質上完全不同。
你的瀏覽器 session 本來就已經是被信任的。
使用 Thunderbit 抓取 Redfin 子頁面
在抓完搜尋結果後,點擊 「Scrape Subpages」,讓 AI 逐一拜訪每個房源詳情頁,並把 Redfin Estimate、建造年份、HOA 費、經紀人資訊、房源照片和成交歷史補進表格裡。
這相當於方法 1 裡那段 40 行的 Selenium 迴圈——但你只需要按一次,而且不用維護。
當 Redfin 把 DOM 從 homecardV2Price 改成 span.bp-Homecard__Price--value 時,AI 會跟著調整;你的 Python selector 不會。
不只 CSV:把 Redfin 資料匯出到 Google Sheets、Airtable 和 Notion
很多教學都停在 df.to_csv()。如果只是做一次性分析,這當然夠用。但如果你在房地產團隊工作,你需要的是可協作、可持續更新的資料,而不是堆在某台電腦桌面上的靜態檔案。
用 Python 匯出(gspread + Airtable API)
透過 gspread 匯出到 Google Sheets:
1import gspread
2import pandas as pd
3from gspread_dataframe import set_with_dataframe
4df = pd.DataFrame(listings)
5gc = gspread.service_account(filename="service_account.json")
6sh = gc.open("Redfin Listings")
7ws = sh.worksheet("Sheet1")
8ws.clear()
9set_with_dataframe(ws, df, include_index=False, resize=True)
10# 用 IMAGE() 公式直接在試算表內顯示房源照片
11image_col = df.columns.get_loc("image_url") + 1
12for row_idx, url in enumerate(df["image_url"], start=2):
13 ws.update_cell(row_idx, image_col, f'=IMAGE("{url}")')
提醒一下:Sheets 每個試算表上限是 1,000 萬個儲存格,而且 API 每個專案每分鐘只允許 。如果超過幾十列,請用 ws.batch_update(),不要每個儲存格逐一更新。
透過 pyairtable 匯出到 Airtable:
2024 年有個重要變更:Airtable 已在 。現在必須使用 Personal Access Token(PAT)——任何還在教你用 api_key=... 的教學都已經過時了。
1from pyairtable import Api
2api = Api("patXXXXXXXXXXXXXX.yyyyyyyyyyyyyyyyyyyy")
3table = api.table("appBaseId123", "Redfin Listings")
4records = [
5 {
6 "Address": row["address"],
7 "Price": row["price"],
8 "Beds": row["beds"],
9 "Photo": [{"url": row["image_url"]}], # Airtable 會自動抓取並重新託管
10 }
11 for row in listings
12]
13created = table.batch_create(records, typecast=True)
Airtable 的速率限制是 ,違規會有 30 秒鎖定。附件欄位可接受 [{"url": ...}] 格式,Airtable 伺服器會抓取該網址、重新託管到他們的 CDN,並自動產生縮圖。
用 Thunderbit 匯出(1 次點擊到 Sheets、Airtable、Notion)
Thunderbit 原生支援一鍵匯出到 Google Sheets、Airtable 和 Notion——而且這裡有一點我真的很自豪:房源照片會上傳,並在 Notion 和 Airtable 中以內嵌圖片方式呈現。沒有 =IMAGE() 公式的變通技巧,也不會有壞掉的 CDN 連結。你只要點一下「Export to Airtable」,你的團隊就能拿到一個能在手機上瀏覽縮圖的視覺化房產資料庫。
對需要做視覺化篩選的房地產團隊來說,這就是「實用工具」和「一堆 CSV 列」之間的差別。
抓取 Redfin 合法嗎?ToS、robots.txt 與判例怎麼說
我不是律師,這也不是法律意見。但在資料擷取領域做了這麼多年,我可以肯定地說:大家最常問的就是「這合法嗎?」——而多數教學都會刻意迴避。
Redfin 的 robots.txt
Redfin 的 寫得很詳細。重點如下:
- 完全封鎖的 bots:
peer39_crawler/1.0、AmazonAdBot、FireCrawlAgent—— Redfin 甚至直接點名了 LLM 時代常見的爬取服務 - wildcard
User-agent: *禁止重點:/stingray/(整個內部 API 命名空間)、/myredfin/、/api/v1/rentals/、/api/v1/properties/、/owner-estimate/ - 沒有
Crawl-delay:指令 - 宣告了 50 多個 sitemap —— sitemap 是最乾淨、也最不會觸發 WAF 的網址列舉方式
Redfin 的使用條款
寫道:「除非您事先取得明確的書面許可,不得以任何目的或任何方式自動爬取或查詢本服務……」
這屬於 browsewrap 協議——是透過持續使用來視為接受,而不是點擊式同意。美國法院過去對於沒有實際通知的使用者,通常對 browsewrap 的可執行性保持懷疑(可參考 Nguyen v. Barnes & Noble,第九巡迴,2014)。
相關判例(簡述)
- Van Buren v. United States(美國最高法院,2021):CFAA 的「超越授權存取」條款採用的是「門是開還是關」的判準。拿開著的門做不受歡迎的用途,不等於聯邦層級的駭客行為。
- hiQ Labs v. LinkedIn(第九巡迴,2022):抓取公開可見資料不構成 CFAA 違反。但 hiQ 最後仍以違約為由支付了 50 萬美元和解金,因為 hiQ 曾註冊 LinkedIn 帳號並點選「I agree」。
- Meta Platforms v. Bright Data(北加州地院,2024 年 1 月):法院對 Bright Data 作出簡易判決——在登入狀態外抓取公開資料,不代表 Bright Data 是受 Meta 條款約束的「使用者」。
- X Corp. v. Bright Data(北加州地院,2024 年 5 月):Alsup 法官駁回了 X 的主張,認為試圖用州法控制公開內容複製的請求,會被著作權法排除。
實務建議
- 只抓公開可見資料——不要先註冊帳號再抓(那會帶來 clickwrap 合約風險)
- 尊重速率限制——過於激進的流量可能支持侵入動產(trespass-to-chattels)主張
- 不要大規模重新發布原始資料或照片—— 訴訟(2025 年 7 月提起,潛在損害賠償超過 10 億美元)提醒我們,照片版權非常嚴肅
- Thunderbit 的瀏覽器式做法——在你自己的已驗證 session 裡執行——比無頭資料中心機器人更接近「人工瀏覽的機器速度」,這是在沒有授權 API 之前最站得住腳的姿態
技巧與常見陷阱
以下是我在開發擷取工具、以及看著成千上萬使用者抓取房地產網站後,累積的一些血淚教訓:
- 一定要先暖機 session。 在任何深層 URL 前先打
redfin.com/。冷啟動直接打深層頁,是觸發 Cloudflare 挑戰的第一名原因。 - 合理輪換 User-Agent。 不要只用一個;可以在 5–10 組當前 Chrome / Firefox UA 間輪換。但也不要太激進(每次請求都換 UA 反而很可疑)。
- 用 property ID 去重。 Redfin 的分頁有時會重疊。從每個房源 URL 解析
/home/{id},在補充資料前先去重。 - 盡量避開尖峰時段。 以我的經驗,美國時間深夜 / 清晨受到的 WAF 審查較少。
- 如果拿到 429,要用指數退避。 不要立刻重試——那只會把軟性限流升級成硬性 IP 封鎖。
- 大規模專案(1,000+ 頁)請預留住宅代理預算。 Cloudflare 的 ASN 信譽系統會把資料中心 IP(AWS、GCP、Azure、OVH)列入黑名單,你幾乎會立刻撞上 Error 1020。
要如何選擇適合你的 Redfin 抓取方式?
那到底該選哪一種方法?答案取決於你是誰,以及你需要什麼。
HTML 解析(BeautifulSoup + Selenium): 最適合想完全掌控、能接受維護 CSS selector、而且不介意 Redfin 改版後重寫程式的開發者。你可以預期每 6–12 個月需要回頭修一次。
隱藏 Stingray API: 最適合需要乾淨、結構化 JSON,且有能力逆向分析未公開端點的開發者。它比 HTML 解析更好維護,但端點可能無預警變動。也別忘了,/stingray/ 在 robots.txt 裡是明確禁止的。
Thunderbit(無程式碼): 最適合非開發者、快速專案、以及需要長期取得 Redfin 資料但沒有開發資源的團隊。AI 能適應版面變化,子頁抓取可一鍵補充資料,還內建匯出到 、Airtable 或 Notion。若你是需要一個「會活著更新」的房產資料庫,而不是一次性的 CSV 倒出,這會是阻力最小的路。
不論你選哪條路:開始之前先理解 Redfin 的反機器人防護、知道自己需要哪些欄位、選一個符合團隊流程的匯出格式,並確保自己站在 允許的範圍內。
想先試試無程式碼路線嗎? 可以讓你先體驗 Redfin 抓取,幾分鐘內就看到結果。若你要走 Python 路線,上面的程式碼就是可直接起跑的基礎——只差代理與耐心。
常見問題
Redfin 有公開 API 嗎?
沒有。Redfin 沒有提供正式的公開 API。隱藏的 Stingray API(/stingray/api/home/details/*)會回傳結構化 JSON,而且是 Redfin 前端自己在使用的,但它不是官方公開服務、沒有文件、可能隨時變動,而且在 Redfin 的 robots.txt 中也被明確禁止。像 這類 PyPI 上的開源封裝可以讓你用 Python 存取,但使用時務必自行評估風險。
可以不用 Python 抓 Redfin 嗎?
可以。 是一個 AI Chrome 擴充功能,會沿用你的瀏覽器 session 來提高反機器人韌性——安裝後進入 Redfin,點擊「AI Suggest Fields」,然後匯出到 Excel、Google Sheets、Airtable 或 Notion。若你想探索替代方案,市面上也有其他無程式碼爬取工具和預建資料集供應商。
Redfin 的網站版面多久會改一次?
社群 GitHub issue 歷史顯示,CSS selector 大約每 6–12 個月就會壞一次。Redfin 已經推出過兩代房源卡 DOM——舊版(homecardV2Price、homeAddressV2)和現行版(bp-Homecard__Price--value、bp-Homecard__Address)。成熟的爬蟲通常會依序測試兩種 selector。
像 Thunderbit 這類 AI 工具則能 ,因為它是根據內容辨識欄位,而不是靠 CSS selector。
抓取 Redfin 最好的代理類型是什麼?
大規模抓取建議使用美國住宅代理——社群基準測試的成功率約 80%。資料中心代理幾乎會立刻碰到 Cloudflare Error 1020;AWS、GCP、Azure 與 OVH 的 IP 段都在黑名單上。行動代理成功率最高,但成本通常高出 5–10 倍。
若是小規模個人抓取(少於 100 頁),只要標頭設定正確、搭配 curl_cffi 模擬,以及 2–5 秒延遲,有時甚至不需要代理也能成功。
可以抓 Redfin 上已售出或非上市的房產資料嗎?
可以。已售房產資料與非在售的 Redfin Estimate(中位誤差 )都能用相同方法從詳情頁取得。只是欄位和在售房源不同:非在售頁會有售出價格、售出日期、房產歷史,以及 owner-estimate 端點,但不會有目前掛牌價、在市天數和開放看屋資訊。非在售估價對應的 Stingray API 端點是 api/home/details/owner-estimate,不是 api/home/details/avm。
延伸閱讀