كيفية استخراج بيانات Redfin باستخدام Python (من دون التعرض للحظر)

آخر تحديث في April 15, 2026
كيفية استخراج بيانات Redfin باستخدام Python (من دون التعرض للحظر)

Redfin은 미국 MLS의 신규 매물 중 약 70%를 등록 후 5분 안에 업데이트합니다. 이 정도 속도는 부동산 데이터 파이프라인을 만드는 사람에게는 정말 귀한 자산이죠. 바로 그 이유 때문에 많은 추출 도구들이 Redfin을 먼저 건드렸다가, 몇 분 만에 차단을 당하곤 합니다.

저는 Thunderbit에서 오랫동안 데이터 추출 도구를 다뤄왔고, 분명히 말할 수 있습니다. “Redfin 데이터를 추출한다”와 “차단 없이 Redfin 데이터를 추출한다” 사이의 간극이야말로 대부분의 설명이 무너지는 지점입니다. 많은 글이 BeautifulSoup 코드만 보여주고, Cloudflare가 요청을 삼켜버리는 부분은 건너뛰며, 결국 403 페이지만 멍하니 보게 만들죠. 이 가이드는 다릅니다. HTML 분석, Redfin의 숨겨진 API, 그리고 Thunderbit를 활용한 노코드 방식까지 세 가지 실전 방법을 다루되, 실제로 중요한 봇 방지 대책에 집중하겠습니다. 끝까지 읽으면, 자신의 실력, 작업 규모, 그리고 유지보수 부담에 맞는 방법이 무엇인지 정확히 알 수 있을 겁니다.

Thunderbit로 Redfin 데이터 추출해 보기

Redfin은 무엇이고, 왜 그 데이터가 중요한가?

Redfin은 기술 기반 부동산 중개 플랫폼으로, 정규 급여를 받는 에이전트들이 MLS 피드에서 직접 매물을 가져옵니다. 미국과 캐나다의 42개 주, 100개 이상의 대도시권을 커버하며, 월간 방문자 수는 약 5천만 명에 이릅니다. 단순히 데이터를 모아 보여주는 포털과 달리, Redfin의 데이터는 에이전트가 검증한 정보이고, 자체 Redfin Estimate AVM은 9,500만 개 이상의 부동산을 커버하면서도 매물 상태의 부동산에 대해 중앙 오차율 1.96%를 유지합니다.

redfin_stats_f3c7fb5cbd.png

이렇게 MLS 수준의 최신성, 중개 기반 검증 품질, 강력한 AVM이 결합되어 있기 때문에 부동산 투자자, 에이전트, PropTech 스타트업, 데이터 분석가 모두 Redfin 데이터에 프로그래밍 방식으로 접근하고 싶어 합니다. 그리고 이 작업에는 Python이 가장 자연스러운 선택입니다. requests, BeautifulSoup, Selenium, Playwright 같은 추출 생태계가 성숙해 있고, 커뮤니티 지원도 풍부하며, pandas와 Jupyter와도 바로 연결되어 분석까지 이어갈 수 있으니까요.

왜 Python으로 Redfin 데이터를 추출할까?

이 데이터를 필요로 하는 사람만큼이나 사용 목적도 다양합니다. 보통은 아래처럼 쓰입니다:

사용자 유형주요 추출 목적사용 예시
부동산 중개인리드 생성, 시장 인사이트서비스 지역의 신규/만료 매물, 경쟁사 비교를 위한 에이전트 디렉터리
부동산 투자자딜 플로우, 수익률 분석임대 수익 필터, 저평가 매물 탐지, 신규 매물 일일 알림
PropTech 스타트업제품용 데이터 파이프라인AVM 학습 데이터, 시장 대시보드, iBuyer 인수 엔진
데이터 분석가시장 조사, 비즈니스 인텔리전스ZIP 코드별 평균 가격 추이, 시장 체류 일수 시계열, 매도/호가 비율
스프레더/플리퍼어려운 매물 추적가격 인하, 압류, 오프마켓 비교 매물 감지

더 큰 흐름도 이를 뒷받침합니다. 부동산 회사의 72% 이상이 이미 예측 분석으로 기회를 찾고 리스크를 관리하고 있습니다. PropTech 시장은 2025년 470억 달러에 이를 것으로 예상되며, 연평균 성장률은 16.4%입니다. 구조화된 부동산 데이터는 이제 “있으면 좋은 것”이 아니라 사실상 필수입니다.

추출 가능한 Redfin 데이터 필드 전체 목록

코드를 한 줄도 쓰기 전에, 실제로 무엇을 얻을 수 있는지부터 알아야 합니다. 저는 Redfin의 검색 결과 페이지, 개별 부동산 상세 페이지, 에이전트 프로필을 검토했고, 오픈소스 래퍼인 reteps/redfinRedfinPlus도 함께 대조했습니다. 그 결과 페이지 유형 전반에서 117개의 고유 필드를 확인했습니다.

이 표는 북마크해 둘 만합니다. 코딩하기 전에 데이터 구조를 파악하면, 셀렉터를 찾느라 시행착오를 겪는 시간을 크게 줄일 수 있습니다.

검색 결과 페이지 필드

이건 매물 카드에 바로 보이는 가벼운 필드들로, 대체로 JavaScript 전체 렌더링 없이도 추출할 수 있습니다:

필드데이터 유형메모
부동산 ID숫자Redfin 내부 ID, URL의 /home/{id}에서 추출
등록 가격숫자
전체 주소텍스트
침실 / 욕실 / 면적숫자세 개의 연속 값
부동산 유형단일 선택단독주택, 콘도, 타운하우스, 다세대
상태텍스트활성, 보류, 조건부
시장 체류 일수숫자
가격 인하 표시숫자원래 가격 대비 차이
대표 이미지이미지 URL카드당 1개
Hot Home 배지불리언
오픈하우스 날짜/시간텍스트
중개인 표시텍스트

부동산 상세 페이지 필드

여기서부터는 더 깊은 정보가 나옵니다. 이 필드들 중 상당수는 JavaScript 렌더링이나 Stingray API 호출이 필요합니다:

필드데이터 유형메모
Redfin Estimate (매물 상태)숫자/stingray/api/home/details/avm 통해 제공
Redfin Estimate (오프마켓)숫자/stingray/api/home/details/owner-estimate 통해 제공; 중앙 오차율 7.52%
건축 / 리모델링 연도숫자
토지 면적숫자
HOA 비용숫자월 단위, 해당 시
연간 재산세숫자
세금 평가액숫자
매매 이력 표가격, 날짜, 이벤트 유형
부동산 설명텍스트마케팅 문단
이미지 링크(Carousel)이미지 URL매물당 20장 이상 가능
등록 에이전트 이름, 전화, 이메일텍스트 / 전화 / 이메일전화는 종종 숨김
학교 평점(초/중/고)숫자학군명 포함
도보 / 대중교통 / 자전거 점수숫자
기후 위험 점수숫자홍수, 화재, 폭염, 바람
인근 활성 / 매도 / 유사 매물링크캐러셀 데이터
주차, 차고, 난방, 냉방텍스트편의시설 묶음

에이전트 프로필 필드

필드데이터 유형메모
에이전트 이름, 사진, 소속 사무실, 소개텍스트 / 이미지
전화, 문의 폼전화 / 텍스트클릭 후 표시
활성 매물 수숫자
최근 12개월 판매 건수 / 총 거래액숫자
평균 매매가 대비 등록가 비율숫자
별점 / 리뷰 수숫자
경력 연수 / 면허 번호텍스트 / 숫자

Thunderbit의 AI Suggest Fields 기능을 Redfin 페이지에서 쓰면, 이런 컬럼 대부분을 자동으로 찾아내고 올바른 데이터 형식까지 맞춰 줍니다. CSS 셀렉터를 일일이 손으로 붙일 필요가 없습니다. 이건 조금 뒤에 다시 다루겠습니다.

Redfin의 봇 방어를 이해하기: “프록시만 쓰세요”로 끝나지 않는 이유

여기서 잠깐 멈추고 싶습니다. 대부분의 설명은 차단 문제를 대충 넘기고 곧바로 “프록시를 사세요”로 넘어가 버립니다. 하지만 그건 해법이 아닙니다. Redfin이 무엇을 기준으로 추출 도구를 감지하는지 이해하지 못하면, 프록시 예산만 태우고 결국 똑같이 막히게 됩니다. ScrapeOps는 Redfin의 봇 방어 난도를 10점 만점에 7.5점으로 평가했고, Scraperly는 중간 수준(3/5)이라고 봅니다. “Zillow급 엔터프라이즈 웹 방화벽보다는 덜 공격적이지만, 요청 속도 제한과 커스텀 JavaScript 챌린지를 사용한다”는 설명도 붙어 있죠.

Redfin은 다층 방어를 씁니다. 엣지의 Cloudflare(JavaScript 챌린지, Turnstile, TLS/JA3 지문)와 Redfin 애플리케이션 수준의 rate limiter가 함께 작동합니다. 그리고 robots.txtCrawl-delay는 없습니다. 차단은 WAF 레벨에서 처리되기 때문입니다.

왜 단순한 requests + BeautifulSoup가 Redfin에서 실패할까?

기본 헤더로 requests.get()을 Redfin의 부동산 페이지에 보내면 보통 아래 셋 중 하나가 발생합니다:

  • HTTP 403 — Cloudflare의 JavaScript 챌린지를 풀지 못해서, 부동산 페이지 대신 챌린지 페이지가 옵니다.
  • 중간 챌린지 페이지 — HTML 안에 부동산 데이터 대신 Cloudflare Turnstile 위젯이 들어 있습니다.
  • HTTP 200이지만 불완전한 HTMLroot.__reactServerState.InitialContext 아래에 큰 JSON 덩어리가 들어간 일반 구조만 받고, 검색 카드, 가격 이력, 학교 평점 같은 핵심 정보는 빠져 있습니다.

Redfin은 자체 React SSR 프레임워크를 사용하며, hydration 키도 Redfin 전용입니다. 즉 root.__reactServerState.InitialContext와 그 안의 ReactServerAgent.cache.dataCache 구조를 씁니다. 이건 __NEXT_DATA__도 아니고 window.__INITIAL_STATE__도 아닙니다.

가장 흔한 조용한 403 원인은? Sec-Fetch-* 헤더 누락입니다. Redfin과 Cloudflare는 Sec-Fetch-Site, Sec-Fetch-Mode, Sec-Fetch-Dest, Sec-Fetch-User를 명시적으로 확인합니다. 이게 없으면 바로 의심받습니다.

대응 전략: 지연, 헤더, 프록시, 세션

각 방어층과 대응 방법을 정리하면 아래와 같습니다:

Redfin 방어동작 방식감지 신호완화 전략
Cloudflare JavaScript 챌린지cf_clearance 쿠키를 발급하는 중간 페이지403 + Cloudflare HTML 본문impersonate="chrome120"를 쓰는 curl_cffi; 홈페이지로 세션 초기화; 미국 리전의 주거용 프록시
Cloudflare Turnstile고위험 세션용 인터랙티브 CAPTCHA403 + Turnstile 요소stealth가 적용된 헤드리스 브라우저 + 주거용 프록시
Cloudflare 1020 오류(ASN 차단)차단된 IP / ASN 거부"Error 1020 Access Denied" 문구가 있는 403주거용 또는 모바일 프록시로 전환; 데이터센터 ASN은 사용 금지
TLS/JA3 지문브라우저가 아닌 TLS 패킷 탐지헤더가 좋아도 조용한 403curl_cffi 또는 실제 브라우저
HTTP/2 지문HTTP/2 설정과 HPACK 순서 확인조용한 차단Chrome처럼 HTTP/2를 말하는 curl_cffi
헤더 검증(UA, Sec-Fetch-*)브라우저와 일치하는 헤더 조합첫 요청부터 403Sec-Fetch-Site/Mode/Dest/User와 현실적인 Referer를 포함한 완전한 Chrome 헤더 세트
쿠키/세션 지속성cf_clearance, RF_BROWSER_ID 추적깊은 링크에서 바로 챌린지지속 세션 사용, 먼저 홈페이지 방문
애플리케이션 레이트 리밋IP당 요청 수 제한4292–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)는 어떤 브라우저와도 맞지 않는 JA3 지문을 남깁니다. 그래서 헤더가 완벽해도 조용히 막힐 수 있죠. 실무에서 많이 쓰는 해법은 curl_cffiimpersonate="chrome120" 조합입니다. TLS와 HTTP/2를 Chrome에 가깝게 말해 주기 때문입니다.

Python으로 Redfin 데이터를 추출하는 3가지 방법과 선택 기준

redfin_methods_dc0828acd4.png

세 가지 방법을 나란히 비교한 자료는 거의 없더군요. 그래서 판단 표를 직접 정리했습니다.

기준HTML 분석(BS4 + Selenium)숨겨진 Stingray APIThunderbit(노코드)
설정 난도중간(Python 환경 + 브라우저/드라이버)높음(엔드포인트 역공학 필요)낮음(Chrome 확장 설치만)
차단 위험높음(DOM 요청이 가장 눈에 띔)중간(API 유사 요청이 더 깔끔함)가장 낮음(실제 브라우저 세션 사용)
데이터 구조 품질중간(HTML이 지저분해 직접 파싱)매우 좋음(처음부터 JSON 구조화)높음(AI가 필드와 타입을 자동 판별)
유지보수 부담높음 — 디자인 변경 시 셀렉터가 깨짐중간 — 엔드포인트가 예고 없이 바뀔 수 있음가장 낮음 — AI가 레이아웃 변화에 적응
확장성낮음~중간(프록시 포함 수백 건 수준)중간~높음(더 깔끔한 요청으로 수천 건 가능)중간(클라우드 배치로 50페이지 단위)
적합 대상완전한 제어가 필요한 개발자깔끔한 JSON이 필요한 개발자비개발자, 빠른 프로젝트, 개발 리소스 없이 지속적 데이터가 필요한 경우

여기서 유지보수도 꼭 짚고 가야 합니다. Redfin은 부동산 카드용 DOM을 두 세대로 바꿔 왔습니다. 예전 방식은 homecardV2Price, 현재 방식은 span.bp-Homecard__Price--value입니다. 공개 GitHub 기록을 보면 CSS 셀렉터가 6~12개월 주기로 깨지는 일이 꽤 흔합니다. 그런 일이 생기면 BeautifulSoup 기반 스크래퍼는 하룻밤 사이에 멈추죠. AI 기반 필드 감지 방식은 이런 변화에 훨씬 잘 적응합니다.

시작하기 전에

  • 난이도: 중간(방법 1, 2), 초급(방법 3)
  • 소요 시간: 방법 1 또는 2는 약 30분, 방법 3은 약 5분
  • 준비물:
    • Python 3.8+ 및 pip(방법 1, 2)
    • Chrome 브라우저(모든 방법)
    • Thunderbit Chrome Extension(방법 3)
    • 대규모 추출용 미국 주거용 프록시(방법 1, 2)

AI로 Redfin 데이터 추출 Get Started Free

방법 1: BeautifulSoup + Selenium으로 Python에서 Redfin 추출하기

이 방식은 “완전한 제어”를 주는 길입니다. 셀렉터를 직접 쓰고, 브라우저를 관리하고, 오류도 직접 처리합니다.

가장 배우기 좋지만, 동시에 가장 쉽게 깨지는 방법이기도 합니다.

1단계: Python 환경 설정

가상환경을 만들고 필요한 라이브러리를 설치합니다:

python -m venv redfin-scraper
source redfin-scraper/bin/activate  # Windows에서는 redfin-scraper\Scripts\activate
pip install requests beautifulsoup4 selenium webdriver-manager pandas curl_cffi

여기서 curl_cffi는 핵심입니다. requests의 기본 TLS 지문 대신, Cloudflare가 막지 않는 실제 Chrome에 가까운 TLS 지문으로 HTTP 요청을 보내게 해 주니까요.

2단계: 브라우저 헤더와 세션 설정

초보자가 가장 자주 놓치는 부분입니다. Redfin과 Cloudflare가 확인하는 Sec-Fetch-* 헤더를 포함한 Chrome 전체 헤더 세트가 필요합니다:

from curl_cffi import requests as curl_requests

HEADERS = {
    "User-Agent": "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",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.9",
    "Accept-Encoding": "gzip, deflate, br",
    "Sec-Fetch-Site": "none",
    "Sec-Fetch-Mode": "navigate",
    "Sec-Fetch-Dest": "document",
    "Sec-Fetch-User": "?1",
}

session = curl_requests.Session(impersonate="chrome120")
session.headers.update(HEADERS)

# 세션 초기화 — cf_clearance와 RF_BROWSER_ID를 확보
session.get("https://www.redfin.com/")

세션 초기화는 매우 중요합니다. 쿠키나 Referer 없이 바로 깊은 부동산 링크로 들어가면 Cloudflare 점수가 바로 떨어집니다.

항상 홈페이지부터 시작하세요.

3단계: Redfin 검색 결과 추출하기

세션을 초기화했다면, 도시 검색 페이지를 가져와 매물 카드를 파싱할 수 있습니다. 현재(2024–2026) 기준 셀렉터 예시는 다음과 같습니다:

import time
import random
from bs4 import BeautifulSoup

base_url = "https://www.redfin.com/city/17151/CA/San-Francisco"
listings = []

for page_num in range(1, 6):  # 1~5페이지
    url = f"{base_url}/page-{page_num}" if page_num > 1 else base_url
    resp = session.get(url)

    if resp.status_code != 200:
        print(f"{page_num}페이지에서 차단됨: HTTP {resp.status_code}")
        break

    soup = BeautifulSoup(resp.text, "html.parser")
    cards = soup.select("[data-rf-test-id='property-card'], a.bp-Homecard")

    for card in cards:
        price_el = card.select_one("span.bp-Homecard__Price--value")
        addr_el = card.select_one("a.bp-Homecard__Address")
        stats = card.select("span.bp-Homecard__LockedStat--value")

        listing = {
            "price": price_el.text.strip() if price_el else None,
            "address": addr_el.text.strip() if addr_el else None,
            "beds": stats[0].text.strip() if len(stats) > 0 else None,
            "baths": stats[1].text.strip() if len(stats) > 1 else None,
            "sqft": stats[2].text.strip() if len(stats) > 2 else None,
            "url": "https://www.redfin.com" + addr_el["href"] if addr_el else None,
        }
        listings.append(listing)

    # 2~5초 사이 랜덤 지연
    time.sleep(random.uniform(2, 5))

print(f"{len(listings)}개 매물 추출 완료")

이렇게 하면 샌프란시스코 매물의 가격, 주소, 침실/욕실/면적, 상세 링크가 들어 있는 딕셔너리 목록을 얻게 됩니다. 카드가 0개라면 HTTP 상태 코드를 먼저 확인하세요. 403이면 Cloudflare에 걸린 것이고, 주거용 프록시가 필요할 가능성이 큽니다.

4단계: 개별 부동산 상세 페이지 추출하기

검색 결과는 기본 정보만 줍니다. 상세 페이지에는 Redfin Estimate, 건축 연도, HOA 비용, 매매 이력, 에이전트 정보, 사진이 들어 있습니다. 이 페이지들은 JavaScript 렌더링이 필요하므로 Selenium으로 넘어갑니다:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
import time

options = webdriver.ChromeOptions()
options.add_argument("--headless=new")
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_argument("user-agent=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")

driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)

for listing in listings[:10]:  # 상위 10개만 보강
    driver.get(listing["url"])
    time.sleep(random.uniform(3, 6))  # JavaScript 렌더링 대기

    try:
        estimate_el = driver.find_element(By.CSS_SELECTOR, "[data-rf-test-name='avmLdpPrice']")
        listing["redfin_estimate"] = estimate_el.text.strip()
    except:
        listing["redfin_estimate"] = None

    try:
        year_built = driver.find_element(By.XPATH, "//span[contains(text(),'Year Built')]/following-sibling::span")
        listing["year_built"] = year_built.text.strip()
    except:
        listing["year_built"] = None

driver.quit()

이제 상위 10개 매물에 Redfin Estimate와 건축 연도 정보가 들어가 있을 겁니다. XPath 셀렉터는 이런 내장 필드에 대해 CSS보다 조금 더 버티는 편이지만, 그래도 DOM이 바뀌면 쉽게 깨집니다.

5단계: 차단과 오류 처리

지수 백오프를 넣은 재시도 로직을 사용하세요:

import time

def fetch_with_retry(session, url, max_retries=3):
    for attempt in range(max_retries):
        resp = session.get(url)
        if resp.status_code == 200:
            return resp
        elif resp.status_code in (403, 429, 503):
            wait = (2 ** attempt) + random.uniform(1, 3)
            print(f"차단됨 ({resp.status_code}). {wait:.1f}초 후 재시도...")
            time.sleep(wait)
        else:
            print(f"예상치 못한 상태 코드: {resp.status_code}")
            break
    return None

차단 징후는 다음과 같습니다: Cloudflare HTML이 들어 있는 403, 명시적 rate limiting인 429, 빈 응답 본문, 또는 본문에 "Error 1020 Access Denied"가 보이는 경우입니다. 이런 증상이 계속된다면, 주거용 프록시를 추가하거나 API 방식으로 넘어갈 때입니다.

방법 2: 숨겨진 Stingray API를 이용해 Python으로 Redfin 추출하기

이건 제가 가장 선호하는 방식입니다. Redfin 프런트엔드는 내부 JSON API인 /stingray/api/home/details/*와 통신하고, 응답은 깔끔한 JSON으로 돌아옵니다. HTML을 억지로 파싱할 필요가 없습니다.

Redfin의 숨겨진 Stingray 엔드포인트 찾는 법

Chrome DevTools를 열고 → Network 탭으로 이동한 뒤 → Fetch/XHR로 필터링 → Redfin의 부동산 페이지 아무거나 하나로 들어가 보세요. 아래와 같은 엔드포인트 요청이 보일 겁니다:

  • api/home/details/initialInfo — URL을 propertyId와 listingId로 변환
  • api/home/details/aboveTheFold — 가격, 침실, 욕실, 면적, 사진, 상태, 에이전트, MLS 번호
  • api/home/details/belowTheFold — 편의시설, HOA, 세금, 주차, 건축 연도, 토지, 매매 이력
  • api/home/details/avm — 매물 상태의 Redfin Estimate
  • api/home/details/owner-estimate — 오프마켓 Redfin Estimate
  • api/home/details/descriptiveParagraph — 마케팅용 설명문

렌탈 페이지에서는 <meta property="og:image"> URL에서 36자 UUID인 rentalId를 추출합니다.

Stingray API로 부동산 데이터 가져오기

중요한 점 하나가 있습니다. Stingray의 JSON 응답은 CSRF 방지용으로 문자 그대로 {}&& 접두사를 붙입니다. 파싱 전에 이 접두사를 제거해야 합니다:

import json
from curl_cffi import requests as curl_requests

session = curl_requests.Session(impersonate="chrome120")
session.headers.update(HEADERS)

# 세션 초기화
session.get("https://www.redfin.com/")

# 쿠키와 부동산 ID를 얻기 위해 페이지를 먼저 호출
property_url = "https://www.redfin.com/CA/San-Francisco/123-Main-St-94102/home/12345678"
page_resp = session.get(property_url)

# Stingray API 호출
api_url = "https://www.redfin.com/stingray/api/home/details/aboveTheFold?propertyId=12345678"
api_resp = session.get(api_url, headers={"Referer": property_url})

# CSRF 접두사 제거
payload = json.loads(api_resp.text.replace("{}&&", "", 1))

# 구조화된 데이터 추출
listing_data = payload.get("payload", {})
print(json.dumps(listing_data, indent=2))

응답에는 가격은 정수형, 침실/욕실은 숫자, 이미지 링크는 배열, 에이전트 정보는 중첩 객체처럼 잘 정리된 필드가 들어 있습니다. BeautifulSoup도, CSS 셀렉터도, 추측도 필요 없습니다.

숨겨진 API 방식의 장점과 한계

장점:

  • 애초에 JSON 구조라서 훨씬 깔끔함
  • HTML 파싱 없이 응답이 가벼워서 더 빠름
  • API처럼 보이는 요청이라 차단 위험이 상대적으로 낮음

한계:

  • 공식 문서가 없어서 엔드포인트가 예고 없이 바뀔 수 있음
  • robots.txt에서 /stingray/는 일반 user-agent에 대해 명시적으로 금지됨
  • 새 엔드포인트를 찾으려면 역공학이 필요함
  • Cloudflare를 피하려면 여전히 세션 초기화와 올바른 헤더가 필요함

노코드 대안: Thunderbit로 Redfin 데이터 추출하기

Python 스크립트 유지보수가 부담스럽거나, 그냥 5분 안에 결과가 필요하다면 여기서 시작하세요. Thunderbit는 바로 이런 목적에 맞게 만들었습니다. 코드를 쓰지 않고도 어떤 사이트에서든 구조화된 데이터를 뽑을 수 있습니다.

1단계: Thunderbit 설치 후 Redfin으로 이동

Thunderbit Chrome Extension을 Chrome 웹스토어에서 설치하세요. Redfin을 열고 검색 결과 페이지로 들어갑니다. 예를 들면 샌프란시스코 매물 목록처럼요.

2단계: “AI Suggest Fields” 클릭

브라우저 툴바의 Thunderbit 아이콘을 누르고 **“AI Suggest Fields”**를 클릭하세요. 그러면 AI가 Redfin 페이지를 읽고 “Address”, “Price”, “Beds”, “Baths”, “SqFt”, “Property Type”, “Listing Photo” 같은 컬럼을 자동으로 제안합니다. 데이터 유형도 알아서 맞춰 줍니다.

원하지 않는 컬럼은 지우면 되고, **“+ Add Column”**을 눌러 “등록 에이전트 이름”이나 “시장 체류 일수”처럼 자연어로 원하는 항목을 추가할 수도 있습니다.

이제 채울 준비가 된 테이블 미리보기가 보일 겁니다.

3단계: “Scrape”를 눌러 데이터 추출 시작

“Scrape” 버튼을 누르세요. Thunderbit가 보이는 매물을 처리하고 테이블을 채워 줍니다. 여러 페이지가 있으면 페이지네이션도 자동으로 따라갑니다. 루프를 따로 짤 필요가 없습니다.

제 테스트에서는 50행짜리 테이블이 약 45초 만에 채워졌습니다. 구조화된 데이터가 바로 내보낼 준비까지 끝납니다.

Thunderbit가 Redfin의 봇 방어를 어떻게 피하는가

Thunderbit는 브라우저 안에서 동작하므로, 현재 Redfin 세션 쿠키와 브라우저 지문을 그대로 사용합니다. Cloudflare 입장에서는 그냥 사람이 Redfin을 보고 있는 것처럼 보이죠. 실제로 기술적으로도 그렇습니다. 헤드리스 브라우저도, 데이터센터 IP도, 이상한 TLS 지문도 없습니다. 공개 페이지라면 Thunderbit의 클라우드 스크래핑 모드로 한 번에 50페이지까지 처리할 수 있습니다.

이건 서버에서 Python requests를 돌리는 방식과는 완전히 다릅니다.

이미 당신의 브라우저 세션이 신뢰를 얻고 있기 때문입니다.

Thunderbit로 Redfin 하위 페이지까지 추출하기

검색 결과를 뽑은 뒤 **“Scrape Subpages”**를 누르면, AI가 각 부동산 상세 페이지를 방문해서 Redfin Estimate, 건축 연도, HOA 비용, 에이전트 정보, 부동산 사진, 매매 이력 같은 추가 필드를 테이블에 채워 넣습니다.

이건 방법 1에서 Selenium 40줄로 하던 작업과 사실상 같습니다. 다만 클릭 한 번으로 되고, 유지보수는 필요 없습니다.

그리고 Redfin이 DOM을 homecardV2Price에서 span.bp-Homecard__Price--value로 바꾸더라도, AI는 적응합니다. Python 셀렉터는 그렇지 못하죠.

AI로 Redfin 하위 페이지 추출하기 Get Started Free

CSV를 넘어서: Redfin 데이터를 Google Sheets, Airtable, Notion으로 내보내기

대부분의 글은 df.to_csv()에서 끝납니다. 일회성 분석이라면 그걸로도 충분하죠. 하지만 부동산 팀에서 일한다면, 필요한 건 누군가의 데스크탑에 쌓여 있는 정적 CSV가 아니라 협업 가능한 살아 있는 데이터입니다.

Python으로 내보내기 (gspread, Airtable API)

gspread를 통한 Google Sheets:

import gspread
import pandas as pd
from gspread_dataframe import set_with_dataframe

df = pd.DataFrame(listings)
gc = gspread.service_account(filename="service_account.json")
sh = gc.open("Redfin Listings")
ws = sh.worksheet("Sheet1")
ws.clear()
set_with_dataframe(ws, df, include_index=False, resize=True)

# IMAGE() 수식으로 부동산 이미지를 셀 안에 표시
image_col = df.columns.get_loc("image_url") + 1
for row_idx, url in enumerate(df["image_url"], start=2):
    ws.update_cell(row_idx, image_col, f'=IMAGE("{url}")')

주의: Sheets는 시트당 1,000만 셀 제한이 있고, API도 프로젝트당 분당 읽기 300회 + 쓰기 300회 제한이 있습니다. 수십 행 이상 다룰 때는 셀 단위 루프보다 ws.batch_update()를 쓰는 편이 좋습니다.

pyairtable를 통한 Airtable:

2024년에 중요한 변화가 있었습니다. Airtable이 2024년 2월 1일부터 기존 API 키를 폐지했습니다. 이제는 Personal Access Token(PAT)을 써야 하며, 여전히 api_key=...를 보여주는 설명은 더 이상 유효하지 않습니다.

from pyairtable import Api

api = Api("patXXXXXXXXXXXXXX.yyyyyyyyyyyyyyyyyyyy")
table = api.table("appBaseId123", "Redfin Listings")

records = [
    {
        "Address": row["address"],
        "Price": row["price"],
        "Beds": row["beds"],
        "Photo": [{"url": row["image_url"]}],  # Airtable가 가져와 재호스팅
    }
    for row in listings
]
created = table.batch_create(records, typecast=True)

Airtable의 허용 속도는 base당 초당 5요청이며, 어기면 30초 차단이 걸립니다. 첨부 파일 필드는 [{"url": ...}] 형식의 페이로드를 받으며, Airtable 서버가 해당 이미지를 가져와 자체 CDN에 다시 호스팅하고 썸네일도 자동 생성합니다.

Thunderbit로 내보내기: Google Sheets, Airtable, Notion 원클릭 전송

Thunderbit는 Google Sheets, Airtable, Notion으로 바로 내보내는 기능을 제공합니다. 그리고 이건 정말 마음에 드는 부분인데, 부동산 이미지를 실제로 업로드해서 Notion과 Airtable 안에서 바로 보이게 만들어 줍니다. =IMAGE() 꼼수도 없고, 깨진 CDN 링크도 없습니다. 그냥 “Export to Airtable”을 누르면, 팀은 휴대폰으로도 훑어볼 수 있는 시각적인 부동산 데이터베이스를 받게 됩니다.

시각적으로 매물을 걸러보는 부동산 팀에게는, 이 차이가 유용한 도구와 그저 CSV 행 더미의 차이를 만듭니다.

Redfin 데이터 추출은 합법인가? 약관, robots.txt, 판례는 어떻게 말하나?

저는 변호사가 아니며, 이건 법률 자문이 아닙니다. 다만 오랫동안 데이터를 다뤄온 입장에서 말하면, “합법인가?”는 모두가 묻지만 대부분의 글이 피하는 질문입니다.

Redfin의 robots.txt

Redfin의 robots.txt는 꽤 상세합니다. 핵심은 다음과 같습니다:

  • 완전 차단된 봇: peer39_crawler/1.0, AmazonAdBot, FireCrawlAgent — Redfin은 대형 언어 모델 시대의 유명 추출 도구까지 명시적으로 적어 두고 있습니다
  • User-agent: * 아래 주요 차단 항목: /stingray/(내부 API 전체), /myredfin/, /api/v1/rentals/, /api/v1/properties/, /owner-estimate/
  • 어떤 user-agent에도 Crawl-delay: 없음
  • 50개 이상의 사이트맵 공개 — WAF와의 마찰이 가장 적고, 링크를 발견하기 가장 깔끔한 방식입니다

Redfin 이용약관

2.3.5항은 이렇게 말합니다. “당신은 사전 서면 허가 없이 어떤 목적이나 어떤 수단으로도 서비스에 대한 자동화된 크롤링이나 자동화된 쿼리를 해서는 안 된다.”

이건 browsewrap 성격입니다. 즉, 클릭으로 명시적으로 동의하는 clickwrap가 아니라, 계속 사용하는 것으로 동의가 간주되는 방식이죠. 미국 법원은 실제로 인지하지 못한 사용자에게 browsewrap을 강하게 집행하는 데 역사적으로 회의적이었습니다. (Nguyen v. Barnes & Noble, 9th Cir. 2014 참고)

관련 판례를 짧게 보면

  • Van Buren v. United States(대법원, 2021): CFAA의 “무단 접근 초과”는 문이 열려 있느냐 닫혀 있느냐를 기준으로 봅니다. 열린 문을 원래 의도와 다른 목적으로 썼다고 해서 연방법상 해킹이 되진 않습니다.
  • hiQ Labs v. LinkedIn(9th Cir., 2022): 공개 웹 데이터 추출은 CFAA 위반이 아니라는 입장입니다. 다만 hiQ는 LinkedIn 계정을 만들고 “I agree”를 눌렀기 때문에 계약 위반 이슈로 결국 50만 달러 합의에 이르렀습니다.
  • 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 주장의 근거가 될 수 있습니다.
  • 원본 데이터나 이미지를 대규모로 재배포하지 마세요. CoStar v. Zillow 소송은 2025년 7월 제기됐고, 손해배상 규모가 10억 달러를 넘을 수 있다는 점에서 부동산 이미지 권리가 얼마나 민감한지 보여 줍니다.
  • Thunderbit처럼 브라우저 안에서 동작하는 방식은, 당신의 인증된 세션 안에서 빠르게 수동 탐색을 하는 것에 가깝습니다. 헤드리스 데이터센터 봇보다는 훨씬 방어 가능한 위치에 있습니다. 물론 라이선스된 API가 따로 없다면 말이죠.

자주 하는 실수와 팁

저는 추출 도구를 만들면서, 그리고 수천 명의 사용자가 부동산 사이트를 긁는 걸 지켜보면서 얻은 교훈들이 있습니다.

  • 항상 세션을 먼저 초기화하세요. 어떤 깊은 링크보다 먼저 redfin.com/을 여세요. 깊은 링크로 바로 들어가는 게 Cloudflare 챌린지를 가장 쉽게 부르는 방식입니다.
  • User-Agent를 현실적으로 회전하세요. 하나만 쓰지 말고, 최신 Chrome/Firefox UA 5~10개 정도를 돌려 쓰세요. 다만 너무 자주 바꾸면 오히려 수상해집니다.
  • property ID로 중복을 제거하세요. Redfin 페이지네이션은 겹치는 항목이 나올 수 있습니다. 각 매물의 /home/{id}를 추출해 중복 제거 후 보강하세요.
  • 가능하면 피크 시간대를 피하세요. 경험상 미국 기준 심야나 이른 새벽이 WAF 감시가 덜합니다.
  • 429가 나오면 지수적으로 속도를 낮추세요. 바로 다시 보내지 마세요. 그게 soft rate limit에서 아예 IP 차단으로 가는 지름길입니다.
  • 1,000페이지 이상 대형 프로젝트는 주거용 프록시 비용을 계산하세요. 데이터센터 IP(AWS, GCP, Azure, OVH)는 Cloudflare의 ASN 평판 시스템에서 블랙리스트에 오를 가능성이 큽니다. 거의 바로 1020이 뜰 수 있습니다.

어떤 방법이 Redfin 데이터 추출에 가장 잘 맞을까?

그렇다면 무엇을 선택해야 할까요? 결국 당신이 누구이고, 무엇이 필요한지에 달려 있습니다.

HTML 분석(BeautifulSoup + Selenium): 완전한 제어가 필요한 개발자, CSS 셀렉터 유지보수에 익숙한 사람, 그리고 Redfin의 DOM이 바뀔 때마다 직접 손볼 수 있는 사람에게 가장 적합합니다. 6~12개월마다 코드를 다시 만질 가능성을 예상하세요.

숨겨진 Stingray API: 깔끔한 JSON이 필요하고, 문서화되지 않은 엔드포인트를 역공학할 수 있는 개발자에게 좋습니다. HTML 분석보다 유지보수는 덜하지만, 엔드포인트가 예고 없이 바뀔 수 있다는 점은 기억해야 합니다. 그리고 /stingray/는 robots.txt에서 명시적으로 금지되어 있습니다.

Thunderbit(노코드): 비개발자, 빠른 프로젝트, 그리고 개발 리소스 없이도 지속적으로 Redfin 데이터가 필요한 팀에 가장 좋습니다. AI가 레이아웃 변화에 적응하고, 하위 페이지를 한 번에 보강하며, Google Sheets, Airtable, Notion으로의 내보내기가 내장되어 있습니다. 팀이 필요한 게 일회성 CSV 덤프가 아니라 살아 있는 부동산 데이터베이스라면, 가장 쉬운 경로입니다.

어떤 길을 선택하든, 시작하기 전에 Redfin의 봇 방어를 먼저 이해하세요. 필요한 필드를 정하고, 팀의 작업 흐름에 맞는 내보내기 형식을 고르며, 법적 가이드라인 안에서 움직이세요.

노코드 경로를 직접 써 보고 싶나요? Thunderbit의 무료 플랜으로 몇 분 안에 Redfin 추출 결과를 확인할 수 있습니다. Python 방식이 필요하다면, 위 코드가 실전용 출발점이 될 겁니다. 여기에 프록시와 약간의 인내심만 더하면 됩니다.

지속적인 Redfin 데이터용 Thunderbit 체험하기

자주 묻는 질문

Redfin에 공개 API가 있나요?

없습니다. Redfin은 공식적인 공개 API를 제공하지 않습니다. 내부의 숨겨진 Stingray API(/stingray/api/home/details/*)는 구조화된 JSON을 반환하고 Redfin 프런트엔드도 내부적으로 사용하지만, 비공식적이고 문서화되어 있지 않으며 예고 없이 바뀔 수 있고 Redfin의 robots.txt에서도 명시적으로 금지되어 있습니다. PyPI의 reteps/redfin 같은 오픈소스 래퍼가 Python 접근을 제공하긴 하지만, 위험을 이해한 상태에서 사용해야 합니다.

Python 없이 Redfin 데이터를 추출할 수 있나요?

가능합니다. Thunderbit는 브라우저 세션을 그대로 활용하는 AI 기반 Chrome 확장으로 차단 저항성이 높습니다. 설치한 뒤 Redfin으로 가서 “AI Suggest Fields”를 누르고, Excel이나 Google Sheets, Airtable, Notion으로 내보내면 됩니다. 다른 노코드 추출 도구나 사전 구축된 데이터 공급업체도 선택지로 검토할 수 있습니다.

Redfin은 얼마나 자주 레이아웃을 바꾸나요?

공개 GitHub 기록을 보면 CSS 셀렉터가 약 6~12개월마다 깨집니다. Redfin은 부동산 카드 DOM을 두 세대 바꿨습니다. 예전 방식은 (homecardV2Price, homeAddressV2), 현재는 (bp-Homecard__Price--value, bp-Homecard__Address)입니다. 성숙한 추출 도구는 보통 두 패턴을 차례로 시도합니다.

Thunderbit 같은 AI 기반 도구는 자동으로 적응합니다. CSS 셀렉터가 아니라 내용 자체를 보고 필드를 찾기 때문이죠.

Redfin 추출에 가장 좋은 프록시 유형은 무엇인가요?

대규모 추출에는 미국 주거용 프록시가 가장 무난하며, 커뮤니티 기준 성공률이 약 80% 수준입니다. 데이터센터 프록시는 Cloudflare 1020 오류를 거의 즉시 맞기 쉽고, AWS, GCP, Azure, OVH 대역도 블랙리스트에 걸려 있습니다. 모바일 프록시가 성공률은 가장 높지만, 가격은 5~10배 비쌉니다.

소규모 개인 추출(<100페이지)이라면, 올바른 헤더 + curl_cffi 지문 위장 + 2~5초 지연만으로 프록시 없이도 충분할 수 있습니다.

Redfin의 매도 완료 매물이나 오프마켓 데이터도 추출할 수 있나요?

네. 매도 완료 매물과 오프마켓 Redfin Estimate(중앙 오차율 7.52%)도 같은 방식으로 상세 페이지에서 얻을 수 있습니다. 다만 필드는 활성 매물과 다릅니다. 오프마켓 페이지에는 매도 가격, 매도 날짜, 부동산 이력, owner-estimate 엔드포인트가 있지만, 현재 가격, 시장 체류 일수, 오픈하우스 정보는 없습니다. 오프마켓 추정의 Stingray 엔드포인트는 api/home/details/avm이 아니라 api/home/details/owner-estimate입니다.

Thunderbit로 Redfin 데이터 추출해 보기 Get Started Free

더 알아보기

Shuai Guan
Shuai Guan
الرئيس التنفيذي في Thunderbit | خبير في أتمتة البيانات بالذكاء الاصطناعي Shuai Guan هو الرئيس التنفيذي لشركة Thunderbit وخريج كلية الهندسة بجامعة ميشيغان. وبالاستناد إلى ما يقرب من عشر سنوات من الخبرة في مجالي التقنية وبنية SaaS، يتخصص في تحويل نماذج الذكاء الاصطناعي المعقدة إلى أدوات عملية لاستخراج البيانات بدون الحاجة إلى البرمجة. في هذه المدونة، يشارك رؤى صريحة ومجرّبة ميدانيًا حول استخراج البيانات من الويب واستراتيجيات الأتمتة، لمساعدتك على بناء سير عمل أذكى يعتمد على البيانات. وعندما لا يكون منشغلاً بتحسين تدفقات العمل الخاصة بالبيانات، يوجّه نفس دقته واهتمامه بالتفاصيل إلى شغفه بالتصوير الفوتوغرافي.
جدول المحتويات
Thunderbit · وكيل بيانات الويب بالذكاء الاصطناعي

Extract data from any page in 1 click

موثوق به من قبل أكثر من 250,000 مستخدم
الخطة المجانية متاحة
استخرج البيانات باستخدام الذكاء الاصطناعي
انقل البيانات بسهولة إلى Google Sheets أو Airtable أو Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week