Real estate data scraping - collect property listings with Python and proxies - DataImpulse

O scraping de dados imobiliários é a forma como plataformas de imóveis, investidores e equipes de proptech transformam anúncios online dispersos em um dataset estruturado — preços, endereços, quartos, banheiros, metragem quadrada e tendências em todo um mercado. Este guia mostra como fazer scraping de anúncios imobiliários com Python, da forma robusta (analisando os dados estruturados que os sites já incorporam), além da configuração anti-bot e de proxy que mantém a coleta em funcionamento em diferentes regiões.

Sou Andrii Byzov, um AI-Native Fractional CMO que cria pipelines de dados da web. Abaixo: quais dados imobiliários você pode coletar, um limite legal claro e código funcional para resultados de pesquisa e anúncios individuais — com proxies residenciais para dados geograficamente precisos e desbloqueados.


Fatos principais

  • A maioria dos dados de anúncios é pública e de menor risco — preço, quartos/banheiros, sqft, tipo — mas endereços, fotos, descrições e nomes de corretores podem ser pessoais ou protegidos por direitos autorais, portanto avalie antes de reutilizar.
  • Analise o JSON incorporado quando presente, não CSS frágil. Muitos sites imobiliários expõem dados de anúncios como JSON-LD (schema.org); analise isso quando disponível e recorra aos cards HTML quando não estiver.
  • Alguns sites personalizam por localização — resultados, disponibilidade, idioma ou moeda — portanto proxies com segmentação geográfica ajudam a corresponder a um mercado específico.
  • Grandes portais se protegem intensamente. Zillow, Realtor.com, Rightmove e similares aplicam limites de taxa e sinalizam IPs de datacenter rapidamente; proxies residenciais rotativos ajudam, mas nenhuma ferramenta garante acesso ou conformidade.
  • Dados de contato de corretores e proprietários são dados pessoais. Mantenha-os fora do pipeline; colete dados do imóvel, não de pessoas.

Quais dados imobiliários você pode extrair?

Um anúncio de imóvel é composto por dados ricos e estruturados. Os campos que geralmente vale a pena coletar — e aqueles que devem ser tratados com cuidado:

  • Fatos sobre imóveis de menor risco: preço, quartos, banheiros, metragem quadrada, tamanho do terreno, tipo de imóvel, ano de construção, status do anúncio, dias no mercado e histórico de preços.
  • Tratar com cuidado ou evitar: endereços exatos, fotos e descrições completas (muitas vezes protegidas por direitos autorais) e dados de contato de corretores/proprietários (dados pessoais). A disponibilidade pública não torna esses dados automaticamente reutilizáveis.

A extração de dados imobiliários é legal?

Coletar fatos públicos sobre imóveis é amplamente defensável, e é assim que funcionam a inteligência de preços e a proptech — mas a disponibilidade pública não torna automaticamente os dados não pessoais ou reutilizáveis: avalie privacidade, direitos autorais, direitos sobre bancos de dados, contratos e legislação local. A linha prática: não extraia dados por trás de um login, mantenha dados pessoais (dados de corretores/proprietários) fora, não republice fotos ou descrições protegidas por direitos autorais, respeite os termos de cada site e o robots.txt, e não burle controles de acesso ou CAPTCHAs. Grandes portais restringem o acesso automatizado, portanto, nesses casos, prefira uma API oficial, um feed de dados licenciado ou permissão por escrito. Para ver o framework completo, consulte nosso guia sobre se web scraping é legal. Estas são informações gerais, não aconselhamento jurídico.


Etapa 1 — Configure seu ambiente

Instale as bibliotecas necessárias para o scraper imobiliário. Sites estáticos compatíveis com JSON-LD funcionam com requests; portais com muito JavaScript, como Zillow, precisam de um navegador headless.



# Core libraries for real estate data scraping
# requests -> fetch pages | beautifulsoup4 + lxml -> parse HTML/JSON
pip install requests beautifulsoup4 lxml

# Many listing sites are JavaScript-heavy and well defended (e.g. Zillow).
# For those, add a headless browser:
pip install playwright && playwright install chromium







Etapa 2 — Buscar uma página de anúncios

Obtenha uma página de resultados de pesquisa (a URL de imóveis à venda de uma cidade) com cabeçalhos adequados, roteada por meio de um proxy residencial para que os anúncios correspondam ao mercado-alvo.



import requests

HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
                         "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36",
           "Accept-Language": "en-US,en;q=0.9"}

# Route through residential proxies for geo-accurate listings (see Step 5)
proxies = {"http":  "http://LOGIN:[email protected]:823",
           "https": "http://LOGIN:[email protected]:823"}

def get_html(url):
    r = requests.get(url, headers=HEADERS, proxies=proxies, timeout=30)
    r.raise_for_status()
    return r.text

html = get_html("https://example-realestate.com/homes/for_sale/CityName/")
















Etapa 3 — Extraia anúncios de JSON incorporado

Quando disponível, a forma mais confiável de extrair anúncios de imóveis é ler os dados estruturados que o site já incorpora. Muitas plataformas imobiliárias incluem application/ld+json (schema.org) com o preço, o endereço e o URL de um anúncio — estável em reformulações de design, ao contrário dos nomes de classes CSS. Nem todo site expõe isso (alguns mantêm os dados no estado da aplicação JS), então verifique cada um e, se necessário, recorra à análise dos cards na Etapa 4.



import json
from bs4 import BeautifulSoup

LISTING_TYPES = ("Residence", "Product", "RealEstateListing", "Offer",
                 "SingleFamilyResidence", "Apartment", "House")

def listings_from_jsonld(html):
    """Where available, sites embed listing data as JSON-LD (schema.org).
    Parsing it is more stable than CSS classes — but not every site has it,
    so fall back to the cards in Step 4 when this returns nothing."""
    soup = BeautifulSoup(html, "lxml")
    nodes, out = [], []
    for tag in soup.find_all("script", type="application/ld+json"):
        try:
            data = json.loads(tag.string or "{}")
        except json.JSONDecodeError:
            continue
        stack = data if isinstance(data, list) else [data]
        while stack:                      # flatten @graph / ItemList / nested
            n = stack.pop()
            if not isinstance(n, dict):
                continue
            if "@graph" in n:
                stack.extend(n["@graph"])
            if n.get("@type") == "ItemList":
                stack.extend(x.get("item", x) for x in n.get("itemListElement", []))
            nodes.append(n)
    for n in nodes:
        types = n.get("@type", "")
        types = types if isinstance(types, list) else [types]
        if any(t in LISTING_TYPES for t in types):
            offers = n.get("offers") or {}
            if isinstance(offers, list):
                offers = offers[0] if offers else {}
            out.append({"name": n.get("name"),
                        "price": offers.get("price") or n.get("price"),
                        "address": n.get("address"),
                        "url": n.get("url")})
    return out

print(listings_from_jsonld(html)[:3])









































Passo 4 — Analisar os cards de anúncios (fallback)

Quando um site não expõe JSON-LD limpo, analise diretamente os cards dos resultados de pesquisa: preço, endereço, quartos, banheiros, pés quadrados e o link do anúncio. Os seletores variam de acordo com o site e mudam com frequência, portanto confirme-os no DevTools.



def parse_listing_cards(html):
    """Fallback: parse the search-results cards directly. Selectors differ by
    site and change often — confirm the current ones in DevTools."""
    soup = BeautifulSoup(html, "lxml")
    cards = []
    for card in soup.select("[data-test='property-card']"):
        def t(sel):
            el = card.select_one(sel)
            return el.get_text(strip=True) if el else None
        cards.append({
            "price":   t("[data-test='property-price']"),
            "address": t("[data-test='property-address']"),
            "beds":    t("[data-test='property-beds']"),
            "baths":   t("[data-test='property-baths']"),
            "sqft":    t("[data-test='property-sqft']"),
            "url":     (card.select_one("a[href]") or {}).get("href"),
        })
    return cards


















Etapa 5 — Lidar com a paginação

Uma página de resultados não é um dataset. Percorra as páginas em loop até que os resultados acabem ou você atinja um limite, cadenciando as solicitações para não acionar os limites de taxa.



import time, random

def scrape_all_pages(base_url, max_pages=10):
    """Page through search results until empty or max_pages."""
    all_listings = []
    for page in range(1, max_pages + 1):
        html = get_html(f"{base_url}?page={page}")
        cards = parse_listing_cards(html)
        if not cards:        # no more results -> stop
            break
        all_listings.extend(cards)
        time.sleep(random.uniform(1, 3))   # pace requests
    return all_listings













Etapa 6 — Use proxies para obter dados geograficamente precisos e desbloqueados

Duas coisas tornam o web scraping imobiliário mais difícil sem proxies. Primeiro, localização: alguns sites personalizam resultados, disponibilidade, idioma ou moeda por região, então, para corresponder a um mercado específico, você faz a consulta a partir de um IP de lá. Segundo, bloqueio: grandes portais sinalizam IPs de datacenter rapidamente e aplicam limites de taxa de forma agressiva. DataImpulse residential proxies ($1/GB, rotativos, 195 países com segmentação por cidade/estado) ajudam em ambos os casos — IPs de usuários reais no mercado certo que reduzem bloqueios baseados em IP — embora o acesso não seja garantido e você ainda precise seguir as regras de cada site. Encaminhe as solicitações por meio deles e exporte os dados que você coletou.



import time, random, json, csv

# Listings differ by region: route through a proxy in the target market so
# prices, availability, and currency match what a local user sees.
proxies = {
    "http":  "http://LOGIN__cr.us;sid.re1:[email protected]:823",
    "https": "http://LOGIN__cr.us;sid.re1:[email protected]:823",
}

listings = scrape_all_pages("https://example-realestate.com/homes/for_sale/CityName/")

with open("listings.json", "w", encoding="utf-8") as f:
    json.dump(listings, f, indent=2, ensure_ascii=False)
if listings:
    with open("listings.csv", "w", newline="", encoding="utf-8") as f:
        w = csv.DictWriter(f, fieldnames=listings[0].keys())
        w.writeheader(); w.writerows(listings)

















Perguntas frequentes

O scraping de dados imobiliários é legal?

Coletar dados públicos e não pessoais sobre imóveis (preço, endereço, quartos, sqft) é amplamente defensável e padrão em proptech. Evite dados pessoais (contatos de corretores/proprietários), não faça scraping atrás de logins, não republique fotos ou descrições protegidas por direitos autorais e respeite os termos do site e o robots.txt. Grandes portais restringem o acesso automatizado, portanto obtenha permissão ou aconselhamento jurídico para uso comercial. Estas são informações gerais, não aconselhamento jurídico — veja nosso guia sobre a legalidade do web scraping.

Qual é a melhor forma de fazer scraping de anúncios de imóveis?

Analise os dados estruturados que os sites já incorporam — a maioria das plataformas imobiliárias envia anúncios como JSON-LD (schema.org) no HTML da página, o que é muito mais estável do que perseguir nomes de classes CSS que mudam a cada redesign. Recorra à análise dos cards de anúncios apenas quando não houver JSON limpo disponível.

Preciso de proxies para fazer scraping de sites imobiliários?

Para volume, geralmente sim. Grandes portais (Zillow, Realtor.com, Rightmove) aplicam rate limits e sinalizam IPs de datacenter rapidamente, e alguns anúncios dependem da localização. Proxies residenciais rotativos no mercado-alvo ajudam a retornar dados precisos por localização e a reduzir bloqueios baseados em IP — embora não garantam acesso nem tornem o scraping compatível.

Posso fazer scraping diretamente do Zillow ou Realtor.com?

Eles são públicos, mas fortemente protegidos, renderizados por JavaScript, e seus termos restringem o acesso automatizado. Para esses portais, prefira uma API oficial, um feed de dados licenciado ou permissão por escrito em vez de contornar suas defesas. Se você coletar dados públicos, capture apenas fatos públicos sobre imóveis, permaneça desconectado, não burle controles de acesso e controle o ritmo das solicitações. Veja nosso guia de melhores proxies para Zillow.

Quais dados imobiliários posso coletar?

Principalmente fatos públicos sobre imóveis — preço, quartos, banheiros, metragem quadrada, tamanho do lote, tipo, status, dias no mercado, histórico de preços. Mas a disponibilidade pública não torna automaticamente os dados não pessoais ou reutilizáveis: endereços exatos, fotos, descrições e detalhes de corretores/proprietários podem envolver questões de privacidade ou direitos autorais, portanto avalie antes de armazenar ou republicar.


Conclusão

A raspagem de dados imobiliários transforma anúncios dispersos em um conjunto de dados utilizável — e a receita confiável é: leia o JSON-LD incorporado quando possível, recorra à análise dos cards quando não for, percorra os resultados por páginas e encaminhe tudo por proxies residenciais com segmentação geográfica para que os dados sejam precisos por localização e não sejam bloqueados. Limite-se a fatos públicos e não pessoais sobre imóveis e você se mantém em uma abordagem defensável. Para a infraestrutura, veja best proxies for real estate data e o guia mais amplo best proxies for web scraping.

Última atualização: June 25, 2026.




Share article: