Guia Prático para Raspar Dados do eBay com Proxies em 2025

Aprenda quando usar as APIs do eBay vs scraping HTML, como extrair listagens, leilões e dados de vendedores com proxies residenciais e exemplos Python funcionais.

Guia Prático para Raspar Dados do eBay com Proxies em 2025

Porque Raspar o eBay é Diferente de Qualquer Outro Marketplace

Se você já tentou raspar o eBay em escala, sabe o que acontece: as primeiras 50 páginas funcionam bem, depois os CAPTCHAs aparecem, seu IP datacenter é banido e você volta ao ponto de partida. Equipas de reseller intelligence e pesquisa de mercado perdem horas — e dados — porque não entendem a relação entre a arquitetura anti-bot do eBay e a escolha correta de proxy.

Este guia é pragmático. Vamos comparar as APIs oficiais do eBay com scraping HTML, mostrar os seletores CSS reais que funcionam hoje, detalhar como escolher proxies para cada cenário, e entregar exemplos de código Python que você pode executar hoje.

APIs do eBay vs. Scraping HTML: O Trade-Off Real

O eBay oferece duas APIs principais para desenvolvedores: a Finding API (busca de itens) e a Browse API (detalhes de listagens). Ambas são úteis — até você atingir os limites.

Finding API — O que você precisa saber

  • Endpoint base: https://svcs.ebay.com/services/search/FindingService/v1
  • Limite padrão: 5.000 chamadas por dia por App ID (nível básico)
  • Rate limit: ~1 request/segundo por chave
  • Retorna até 100 itens por página, máximo de ~10.000 resultados por consulta
  • Campos de leilão limitados — sem contagem de bids em tempo real

Browse API — Para detalhes de listagem

  • Endpoint: https://api.ebay.com/buy/browse/v1/item/{item_id}
  • Limite: 1.500 chamadas por dia no tier gratuito
  • Requer OAuth token (Client Credentials ou User Token)
  • Dados estruturados: preço, condição, vendedor, imagens — mas sem HTML do anúncio completo

Quando o Scraping HTML é a Melhor Opção

  • Volume alto: Quando você precisa de 100K+ listagens/dia — as APIs não escalam sem negociação comercial com o eBay
  • Dados de leilão em tempo real: Contagem de bids, tempo restante, histórico — a API não entrega isso de forma completa
  • Perfil de vendedor completo: Feedback detalhado, categorias de listagem, padrões de cross-listing
  • eBay regionais: eBay.de, eBay.co.uk, eBay.com.au — as APIs cobrem principalmente eBay.com
  • Dados de variações/SKUs: A grade de variações nos anúncios é mais completa no HTML
Critério Finding API Browse API Scraping HTML
Volume/dia ~5K requests ~1.5K requests Ilimitado (com proxies)
Dados de leilão Limitados Limitados Completos
Perfil vendedor Básico Médio Completo
Cobertura regional Principalmente .com .com + alguns Todos os domínios
Setup inicial Médio (App ID) Alto (OAuth) Baixo (proxy + parser)
Risco de bloqueio Nenhum Nenhum Alto sem proxy correto

Estrutura HTML do eBay: Seletores que Funcionam

O eBay muda a estrutura HTML com frequência, mas alguns seletores são estáveis há anos. Aqui estão os que você precisa.

Página de Resultados de Busca

URL padrão: https://www.ebay.com/sch/i.html?_nkw={query}&_pgn={page}

  • Cada item: li.s-item — cada listagem na grade de resultados
  • Título: div.s-item__title
  • Preço: span.s-item__price
  • URL do anúncio: a.s-item__link (atributo href)
  • Imagem: img.s-item__image-img (atributo src)
  • Envio: span.s-item__shipping
  • Localização: span.s-item__location
  • Flag Buy It Now: span.s-item__dynamic-onsale ou texto "Buy It Now" em div.s-item__buy-it-now
  • Bids count: span.s-item__bid-count (apenas em leilões ativos)
  • Tempo restante: span.s-item__time-left

Página de Detalhe do Anúncio

URL: https://www.ebay.com/itm/{item_id}

  • Título: h1#itemTitle ou h1.x-item-title__mainTitle
  • Preço: div.x-price-primary span
  • Condição: div.x-item-condition-text
  • Vendedor: div.x-seller-info__name
  • Feedback do vendedor: span.x-seller-info__feedback
  • Variações: div.x-variation-selector
  • Descrição: iframe em iframe#desc_ifr — conteúdo carregado separadamente

Página de Perfil do Vendedor

URL: https://www.ebay.com/usr/{username}

  • Feedback score: span.feedback ou área com div.str-profile__feedback
  • Positivo %: div.str-profile__feedback-percentage
  • Categorias de listagem: div.str-profile__categories
  • Membro desde: div.str-profile__info

Seleção de Proxy para Scraping do eBay

O eBay é agressivo contra IPs datacenter. Se você usar proxies datacenter para scraping em escala, vai ser bloqueado em minutos — não em horas. Aqui está a estratégia correta.

Proxies Residenciais — A Escolha Principal

Para qualquer scraping do eBay acima de 1.000 páginas/dia, residenciais são obrigatórios. O eBay verifica ASN (Autonomous System Number) e bloqueia ranges de IPs conhecidos como datacenter. IPs residenciais parecem usuários reais.

Com ProxyHat, configure o proxy residencial com rotação por request:

# Rotação automática por request — cada request usa um IP residencial diferente
http://USERNAME:PASSWORD@gate.proxyhat.com:8080

Geo-Targeting para eBay Regionais

Os eBay regionais mostram preços, disponibilidade e vendedores diferentes conforme a localização. Para raspar eBay.de ou eBay.co.uk com resultados corretos:

# Alemanha — resultados do eBay.de
curl -x http://user-country-DE:PASSWORD@gate.proxyhat.com:8080 \
  "https://www.ebay.de/sch/i.html?_nkw=iphone+15"

# Reino Unido — resultados do eBay.co.uk
curl -x http://user-country-GB:PASSWORD@gate.proxyhat.com:8080 \
  "https://www.ebay.co.uk/sch/i.html?_nkw=iphone+15"

Sticky Sessions para Múltiplas Páginas

Quando você precisa navegar entre páginas de resultados mantendo a mesma sessão (evitando CAPTCHAs mid-session), use sticky sessions:

# Sessão fixa — mesmo IP por até 30 minutos
http://user-session-myebay01:PASSWORD@gate.proxyhat.com:8080
Cenário Tipo de Proxy Rotação Geo-Target
Busca pontual (<1K páginas) Datacenter Por request Nenhum
Scraping em escala (1K-100K) Residencial Por request País do target
eBay regional (DE, UK, AU) Residencial Sticky (10-30 min) Paês específico
Monitoramento contínuo de preços Residencial Sticky Paês do marketplace
Verificação de conta/login Mobile Sticky Paês da conta

Exemplo Python: Scraper de Resultados de Busca

Aqui está um exemplo funcional que busca resultados no eBay, extrai dados estruturados de cada .s-item e lida com paginação e rotação de IP.

import requests
from bs4 import BeautifulSoup
import csv
import time
import random

PROXY = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080"
PROXIES = {"http": PROXY, "https": PROXY}
HEADERS = {
    "User-Agent": (
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
        "AppleWebKit/537.36 (KHTML, like Gecko) "
        "Chrome/125.0.0.0 Safari/537.36"
    ),
    "Accept-Language": "en-US,en;q=0.9",
}

def scrape_ebay_search(query, max_pages=5):
    """Raspa resultados de busca do eBay e retorna registros estruturados."""
    results = []
    base_url = "https://www.ebay.com/sch/i.html"

    for page in range(1, max_pages + 1):
        params = {"_nkw": query, "_pgn": page}
        try:
            resp = requests.get(
                base_url, params=params,
                headers=HEADERS, proxies=PROXIES, timeout=15
            )
            resp.raise_for_status()
        except requests.RequestException as e:
            print(f"Erro na página {page}: {e}")
            break

        soup = BeautifulSoup(resp.text, "html.parser")
        items = soup.select("li.s-item")
        if not items:
            print(f"Nenhum item na página {page} — possível bloqueio ou fim de resultados.")
            break

        for item in items:
            record = parse_s_item(item)
            if record:
                results.append(record)

        # Delay aleatório entre páginas
        time.sleep(random.uniform(2, 5))
        print(f"Página {page}: {len(items)} itens extraídos")

    return results


def parse_s_item(item):
    """Extrai campos de um elemento li.s-item."""
    title_el = item.select_one("div.s-item__title")
    if not title_el:
        return None

    price_el = item.select_one("span.s-item__price")
    link_el = item.select_one("a.s-item__link")
    shipping_el = item.select_one("span.s-item__shipping")
    location_el = item.select_one("span.s-item__location")
    bid_el = item.select_one("span.s-item__bid-count")
    time_el = item.select_one("span.s-item__time-left")
    bin_el = item.select_one("div.s-item__buy-it-now")

    return {
        "title": title_el.get_text(strip=True),
        "price": price_el.get_text(strip=True) if price_el else None,
        "url": link_el["href"] if link_el else None,
        "shipping": shipping_el.get_text(strip=True) if shipping_el else None,
        "location": location_el.get_text(strip=True) if location_el else None,
        "bid_count": bid_el.get_text(strip=True) if bid_el else None,
        "time_left": time_el.get_text(strip=True) if time_el else None,
        "buy_it_now": bool(bin_el),
    }


if __name__ == "__main__":
    data = scrape_ebay_search("mechanical keyboard", max_pages=3)
    with open("ebay_results.csv", "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=data[0].keys())
        writer.writeheader()
        writer.writerows(data)
    print(f"Total: {len(data)} itens salvos")

Exemplo de resposta truncada de um parse_s_item:

{
  "title": "Custom Mechanical Keyboard RGB Hot-Swap 87 Key",
  "price": "$89.99",
  "url": "https://www.ebay.com/itm/1234567890",
  "shipping": "+$12.50 shipping",
  "location": "Shenzhen, China",
  "bid_count": null,
  "time_left": null,
  "buy_it_now": true
}

Lidando com Leilões: Tempo, Bids e Buy-It-Now

Leilões são o grande diferencial do eBay — e os dados mais valiosos para resellers. A página de resultados mostra informações resumidas, mas os detalhes completos estão na página do anúncio.

Campos de Leilão nos Resultados de Busca

  • span.s-item__bid-count — ex: "23 bids"
  • span.s-item__time-left — ex: "1h 23m left"
  • Ausência de div.s-item__buy-it-now indica leilão puro (sem BIN)

Detalhes Completos na Página do Anúncio

Para obter o histórico de bids e tempo restante preciso, você precisa raspar a página do item:

def scrape_auction_details(item_url, session=None):
    """Raspa detalhes de leilão de uma página de anúncio do eBay."""
    PROXY = "http://user-country-US:PASSWORD@gate.proxyhat.com:8080"
    PROXIES = {"http": PROXY, "https": PROXY}
    HEADERS = {
        "User-Agent": (
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 (KHTML, like Gecko) "
            "Chrome/125.0.0.0 Safari/537.36"
        ),
    }

    resp = requests.get(item_url, headers=HEADERS, proxies=PROXIES, timeout=15)
    soup = BeautifulSoup(resp.text, "html.parser")

    auction = {
        "item_id": item_url.split("/itm/")[-1].split("?")[0],
        "title": None,
        "current_price": None,
        "bid_count": None,
        "time_left_seconds": None,
        "is_buy_it_now": False,
        "bid_history_url": None,
    }

    # Título
    title_el = soup.select_one("h1.x-item-title__mainTitle")
    if title_el:
        auction["title"] = title_el.get_text(strip=True)

    # Preço atual
    price_el = soup.select_one("div.x-price-primary span")
    if price_el:
        auction["current_price"] = price_el.get_text(strip=True)

    # Contagem de bids
    bid_el = soup.select_one("div.x-bid-count span")
    if bid_el:
        auction["bid_count"] = bid_el.get_text(strip=True)

    # Tempo restante (extraído do JavaScript na página)
    time_el = soup.select_one("span.x-time-left")
    if time_el:
        auction["time_left_seconds"] = time_el.get("data-timestamp")

    # Buy It Now
    bin_btn = soup.select_one("button[data-testid='x-bin-btn']")
    auction["is_buy_it_now"] = bin_btn is not None

    # Link para histórico de bids
    bid_hist = soup.select_one("a[href*='/bfl/view/bids']")
    if bid_hist:
        auction["bid_history_url"] = bid_hist["href"]

    return auction

Estratégia para Leilões em Tempo Real

  • Polling com sticky sessions: Use user-session-{id}:PASSWORD para manter o mesmo IP durante o monitoramento
  • Intervalo de 30-60 segundos: Para leilões ativos, polling a cada 30s é suficiente — mais rápido atrai atenção
  • Snapshot final: Capture o estado nos últimos 5 minutos para registrar o preço final

Analytics de Vendedores: Feedback, Categorias e Cross-Listing

Para equipas de reseller intelligence, entender o perfil do vendedor é tão importante quanto os dados do produto. Aqui está como extrair isso em escala.

def scrape_seller_profile(username):
    """Raspa o perfil público de um vendedor do eBay."""
    PROXY = "http://user-country-US:PASSWORD@gate.proxyhat.com:8080"
    PROXIES = {"http": PROXY, "https": PROXY}
    HEADERS = {
        "User-Agent": (
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
            "AppleWebKit/537.36 (KHTML, like Gecko) "
            "Chrome/125.0.0.0 Safari/537.36"
        ),
    }

    url = f"https://www.ebay.com/usr/{username}"
    resp = requests.get(url, headers=HEADERS, proxies=PROXIES, timeout=15)
    soup = BeautifulSoup(resp.text, "html.parser")

    seller = {"username": username}

    # Feedback score
    fb_score = soup.select_one("span.feedback")
    seller["feedback_score"] = fb_score.get_text(strip=True) if fb_score else None

    # Percentual positivo
    fb_pct = soup.select_one("div.str-profile__feedback-percentage")
    seller["positive_pct"] = fb_pct.get_text(strip=True) if fb_pct else None

    # Membro desde
    info = soup.select_one("div.str-profile__info")
    seller["member_since"] = info.get_text(strip=True) if info else None

    # Categorias de listagem
    categories = []
    cat_els = soup.select("div.str-profile__categories li")
    for cat in cat_els:
        categories.append(cat.get_text(strip=True))
    seller["categories"] = categories

    # Itens ativos (contagem)
    items_el = soup.select_one("div.str-profile__items-count")
    seller["active_items_count"] = items_el.get_text(strip=True) if items_el else None

    return seller


def detect_cross_listing(seller_data_list):
    """Detecta padrões de cross-listing entre vendedores."""
    from collections import Counter

    category_pairs = []
    for seller in seller_data_list:
        cats = seller.get("categories", [])
        if len(cats) >= 2:
            for i in range(len(cats)):
                for j in range(i + 1, len(cats)):
                    category_pairs.append((cats[i], cats[j]))

    return Counter(category_pairs).most_common(10)

Métricas de Vendedor que Importam

  • Feedback score vs. tempo: Um vendedor com 50K feedbacks em 2 anos é muito diferente de 50K em 15 anos
  • Distribuição de categorias: Vendedores com categorias muito diversas podem ser dropshippers
  • Padrões de cross-listing: Se muitos vendedores listam nas mesmas combinações de categorias, há um nicho ou uma fonte comum
  • Feedback recente vs. histórico: Uma queda no percentual positivo nos últimos 90 dias pode indicar problemas de qualidade

Tecnologia Anti-Bot do eBay e Como Lidar

O eBay usa múltiplas camadas de proteção:

  • Verificação de ASN: IPs de datacenters conhecidos (AWS, DigitalOcean, Hetzner) são bloqueados ou recebem CAPTCHAs imediatamente
  • Rate limiting por IP: Aproximadamente 100-200 requests/min por IP antes de CAPTCHA
  • AKAMAI Bot Manager: Fingerprinting de browser via JavaScript — detecta headless browsers
  • PerimeterX/HUMAN: Challenge em páginas de login e ações sensíveis
  • Cookie-based session tracking: Múltiplos requests sem cookies de sessão são suspeitos

Mitigações Práticas

  • Use proxies residenciais: Isso elimina 80% dos problemas — o ASN check é a primeira barreira
  • Rotacione IPs a cada 50-100 requests: Não espere ser bloqueado para trocar
  • Use headers realistas: User-Agent, Accept-Language, Accept-Encoding consistentes
  • Mantenha cookies de sessão: Use requests.Session() para manter cookies entre requests
  • Delays aleatórios: 2-8 segundos entre requests, nunca um intervalo fixo
  • Para escala muito alta: Considere Playwright ou Puppeteer com stealth plugins — o fingerprinting do AKAMAI é sofisticado

Node.js: Exemplo Rápido com Axios

Para equipas que preferem JavaScript, aqui está um exemplo mínimo funcional:

const axios = require("axios");
const { HttpsProxyAgent } = require("https-proxy-agent");
const cheerio = require("cheerio");

const PROXY_URL = "http://USERNAME:PASSWORD@gate.proxyhat.com:8080";
const agent = new HttpsProxyAgent(PROXY_URL);

async function scrapeEbaySearch(query, page = 1) {
  const url = "https://www.ebay.com/sch/i.html";
  const resp = await axios.get(url, {
    params: { _nkw: query, _pgn: page },
    httpsAgent: agent,
    headers: {
      "User-Agent":
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/125.0.0.0",
      "Accept-Language": "en-US,en;q=0.9",
    },
    timeout: 15000,
  });

  const $ = cheerio.load(resp.data);
  const items = [];

  $("li.s-item").each((_, el) => {
    const title = $(el).find("div.s-item__title").text().trim();
    const price = $(el).find("span.s-item__price").text().trim();
    const link = $(el).find("a.s-item__link").attr("href");
    const bids = $(el).find("span.s-item__bid-count").text().trim();
    const timeLeft = $(el).find("span.s-item__time-left").text().trim();
    const isBIN = $(el).find("div.s-item__buy-it-now").length > 0;

    if (title) {
      items.push({ title, price, link, bids, timeLeft, isBIN });
    }
  });

  return items;
}

scrapeEbaySearch("vintage watch", 1)
  .then((items) => console.log(JSON.stringify(items.slice(0, 3), null, 2)))
  .catch(console.error);

Considerações Éticas e Legais

  • Respeite robots.txt: O eBay permite crawling de áreas públicas, mas verifique https://www.ebay.com/robots.txt para restrições
  • Não raspe dados pessoais: Nome, endereço, telefone de compradores — isso viola GDPR e CCPA
  • Rate limits razoáveis: Mesmo com proxies, não sature os servidores do eBay
  • Terms of Service: O scraping pode violar os ToS do eBay — use por sua conta e risco, e consulte um advogado se for para uso comercial em larga escala
  • Dados públicos vs. privados: Preços, títulos e feedbacks são públicos; dados de transações completas não são

Conclusão e Próximos Passos

Raspar o eBay em escala exige a combinação certa de proxies residenciais, seletores CSS estáveis e estratégia de rotação. As APIs oficiais são úteis para volumes baixos e dados estruturados, mas o scraping HTML é insubstituível para leilões em tempo real, dados regionais e analytics de vendedores.

Comece com o exemplo Python acima, configure seus proxies residenciais no ProxyHat e escale gradualmente. Monitore suas taxas de sucesso — se cair abaixo de 90%, ajuste a velocidade de rotação ou os delays.

Key Takeaways

  • APIs primeiro, scraping como fallback: Use Finding API para volumes baixos; scraping quando a API não cobre seus dados ou volume
  • Residenciais são obrigatórios: O eBay bloqueia IPs datacenter agressivamente — proxies residenciais eliminam 80% dos bloqueios
  • Geo-targeting importa: eBay.de e eBay.co.uk mostram resultados diferentes — use proxies no país correto
  • .s-item é seu melhor amigo: Esse seletor é estável há anos e contém quase tudo que você precisa dos resultados de busca
  • Leilões exigem sticky sessions: Para monitorar leilões em tempo real, mantenha o mesmo IP com sessões fixas
  • Analytics de vendedores é ouro para resellers: Feedback, categorias e padrões de cross-listing revelam nichos e concorrentes

Para mais guias de scraping com proxies, veja nosso artigo sobre raspar resultados do Google e nosso use case de web scraping. Confira as localizações de proxy disponíveis para geo-targeting específico.

Pronto para começar?

Acesse mais de 50M de IPs residenciais em mais de 148 países com filtragem por IA.

Ver preçosProxies residenciais
← Voltar ao Blog