Como Raspar Etsy para Pesquisa de Nichos: Guia Prático para Equipes POD

Aprenda a raspar Etsy de forma pragmática — estrutura do site, anti-bot, padrões de scraping para nichos, exemplos em Python com proxy residencial e ética para respeitar vendedores independentes.

Como Raspar Etsy para Pesquisa de Nichos: Guia Prático para Equipes POD

API vs. HTML: O Dilema do Scraping no Etsy

Se você está lendo isto, provavelmente quer dados do Etsy para pesquisa de nichos — termos trending, preços médios, contagem de vendedores por categoria. O Etsy não oferece uma API pública para busca de listagens. A Open API v3 exige OAuth por vendedor e só retorna dados da sua própria loja. Para pesquisa de mercado, resta o caminho do HTML.

Scraping de HTML no Etsy é viável, mas exige estratégia. O site usa Cloudflare, rate limits agressivos e fingerprints de navegador. Vamos detalhar cada camada e mostrar como contorná-las com proxies residenciais e rotação inteligente — sem queimar seus IPs.

Estrutura do Etsy: O Que Existe para Raspar

Antes de escrever código, você precisa entender como o Etsy organiza seus dados. Há quatro superfícies principais:

1. Páginas de Busca (Search)

URL: https://www.etsy.com/search?q=QUERY&ref=search_bar

Parâmetros úteis:

  • q — termo de busca
  • ordermost_relevant (padrão), price_asc, price_desc, newest
  • min_price / max_price — filtro de preço
  • ship_to — geotarget (código de país de 2 letras)
  • locationQuery — ID numérico de localização

Cada página de busca retorna até 48 listagens. A paginação usa &page=2, &page=3, etc. O Etsy corta resultados em torno de 250 páginas (~12.000 itens) para buscas populares.

2. Páginas de Listagem (Listing Detail)

URL: https://www.etsy.com/listing/LISTING_ID/SLUG

Contém: título, descrição, preço, imagens, variações, avaliações, dados do vendedor, badge de vendas.

Seletor CSS útil para o preço: div[data-testid='price'] ou .wt-text-title-01 dentro do container de preço. Para o título: h1[data-testid='listing-title'].

3. Páginas de Loja (Shop)

URL: https://www.etsy.com/shop/SHOP_NAME

Contém: contagem de listagens, badge de vendas ("X Sales"), avaliações da loja, localização, data de criação.

O badge de vendas aparece como <span class="wt-text-caption">1,234 Sales</span> ou similar. É arredondado — não é um número exato, mas suficiente para pesquisa de nichos.

4. Árvore de Categorias

O Etsy organiza categorias hierarquicamente: Jewelry > Necklaces > Pendant Necklaces.

URL base: https://www.etsy.com/c/CATEGORY_SLUG

Você pode mapear a árvore de categorias raspando o footer ou o menu de navegação. Cada categoria funciona como uma busca filtrada.

Anti-Bot no Etsy: Cloudflare + Rate Limits Internos

O Etsy usa Cloudflare como WAF/CDN. Isso significa:

  • Desafios JavaScript (Turnstile) em requisições suspeitas
  • Fingerprinting de TLS, HTTP/2 e headers
  • Bloqueio de IPs de datacenter conhecidos

Além do Cloudflare, o Etsy impõe rate limits internos:

  • ~80 requisições/minuto por IP antes de receber HTTP 429
  • ~200 requisições/minuto antes de um ban temporário (HTTP 403 com challenge Cloudflare)
  • Após múltiplos bans, o IP pode ser bloqueado por 24–48 horas
Recomendação: Use proxies residenciais com rotação por requisição. IPs de datacenter são bloqueados rapidamente pelo Cloudflare. IPs residenciais passam pela verificação de challenge com muito mais frequência de sucesso.

Para configurar rotação de IP com ProxyHat, use o formato de URL com flag de país:

# HTTP residencial — rotação por requisição (padrão)
http://user-country-US:SUA_SENHA@gate.proxyhat.com:8080

# Sticky session (mesmo IP por ~10 min)
http://user-country-US-session-abc123:SUA_SENHA@gate.proxyhat.com:8080

Proxies Residenciais vs. Datacenter vs. Mobile para Etsy

TipoSuccess Rate no EtsyVelocidadeCustoUso Recomendado
Residencial~92–96%Média$$Busca + listagem + loja (uso geral)
Datacenter~30–50%Alta$Não recomendado para Etsy
Mobile~97–99%Baixa$$$Scraping pesado em alto volume

Padrões de Scraping para Descoberta de Nichos

O objetivo não é copiar designs — é identificar oportunidades. Aqui estão os padrões que importam para equipes POD:

Termos de Busca em Alta (Trending)

O Etsy não tem uma página pública de "trending searches" como o Google Trends. Mas você pode:

  • Raspar a API de autocomplete — retorna sugestões em tempo real
  • Monitorar categorias sazonais (Halloween em setembro, Natal em outubro)
  • Comparar contagens de resultados entre buscas relacionadas

A URL de autocomplete: https://www.etsy.com/search/suggestions?query=custom+name

Resposta (truncada):

{
  "results": [
    {"query": "custom name necklace", "type": "search_suggestion"},
    {"query": "custom name bracelet", "type": "search_suggestion"},
    {"query": "custom name shirt", "type": "search_suggestion"}
  ]
}

Contagem de Vendedores por Nicho

Na página de busca, o Etsy mostra "X results" no topo. Este número é a contagem total de listagens — não de vendedores únicos. Para obter vendedores únicos:

  1. Raspe as primeiras 5–10 páginas de resultados
  2. Extraia o nome da loja de cada listagem
  3. Conte valores únicos

Se um nicho tem 10.000 listagens mas apenas 50 vendedores, é um mercado concentrado. Se tem 5.000 listagens com 2.000 vendedores, é fragmentado — mais fácil de entrar.

Pontos de Preço Médio

Use o parâmetro order=price_asc e order=price_desc para mapear a distribuição de preços de um nicho. Extraia preços dos cards de busca:

Seletor CSS: span.currency-value dentro de cada div.v2-listing-card.

Exemplo em Python: Busca → Listagem → Detalhes com Proxy Residencial

Abaixo, um script completo que (1) busca um termo no Etsy, (2) extrai dados dos cards de resultado, (3) visita cada página de listagem para obter detalhes adicionais — tudo com rotação de IP via ProxyHat.

import requests
from bs4 import BeautifulSoup
import re
import time
import random

# --- Configuração ProxyHat ---
PROXY_USER = "user-country-US"  # Rotação por requisição
PROXY_PASS = "SUA_SENHA"
PROXY_URL = f"http://{PROXY_USER}:{PROXY_PASS}@gate.proxyhat.com:8080"
PROXIES = {"http": PROXY_URL, "https": PROXY_URL}

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": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br",
}

SESSION = requests.Session()
SESSION.headers.update(HEADERS)
SESSION.proxies.update(PROXIES)


def search_etsy(query, page=1):
    """Raspa página de busca do Etsy e retorna listagens."""
    url = "https://www.etsy.com/search"
    params = {"q": query, "page": page, "order": "most_relevant"}
    resp = SESSION.get(url, params=params, timeout=30)
    resp.raise_for_status()
    soup = BeautifulSoup(resp.text, "html.parser")

    listings = []
    cards = soup.select("div.v2-listing-card")
    for card in cards:
        link_tag = card.select_one("a.listing-link")
        title_tag = card.select_one("h3")
        price_tag = card.select_one("span.currency-value")
        shop_tag = card.select_one("a[href*='/shop/']")

        listing_url = link_tag["href"] if link_tag else None
        listing_id = re.search(r"/listing/(\d+)", listing_url).group(1) if listing_url else None
        title = title_tag.get_text(strip=True) if title_tag else None
        price = price_tag.get_text(strip=True) if price_tag else None
        shop_name = shop_tag.get_text(strip=True) if shop_tag else None

        if listing_id:
            listings.append({
                "listing_id": listing_id,
                "title": title,
                "price": price,
                "shop_name": shop_name,
                "url": listing_url,
            })

    return listings


def get_listing_detail(listing_id, slug=""):
    """Raspa detalhes de uma listagem específica."""
    url = f"https://www.etsy.com/listing/{listing_id}/{slug}"
    resp = SESSION.get(url, timeout=30)
    resp.raise_for_status()
    soup = BeautifulSoup(resp.text, "html.parser")

    title = soup.select_one("h1[data-testid='listing-title']")
    title = title.get_text(strip=True) if title else None

    price_el = soup.select_one("div[data-testid='price']")
    price = price_el.get_text(strip=True) if price_el else None

    # Badge de vendas do vendedor
    sales_badge = soup.find(string=re.compile(r"\d+[\d,]*\s+Sales"))
    sales_count = sales_badge.strip() if sales_badge else None

    # Contagem de avaliações
    review_count = soup.select_one("button[data-testid='reviews-header']")
    reviews = review_count.get_text(strip=True) if review_count else None

    return {
        "listing_id": listing_id,
        "title": title,
        "price": price,
        "seller_sales": sales_count,
        "reviews_summary": reviews,
    }


# --- Execução ---
niche = "custom name mug"
print(f"Buscando nicho: {niche}")

all_listings = []
for page_num in range(1, 4):  # 3 páginas = até 144 listagens
    listings = search_etsy(niche, page=page_num)
    all_listings.extend(listings)
    print(f"  Página {page_num}: {len(listings)} listagens")
    time.sleep(random.uniform(2, 5))  # Rate limiting manual

# Detalhes das primeiras 10 listagens
for listing in all_listings[:10]:
    detail = get_listing_detail(listing["listing_id"])
    print(f"  {detail['title'][:50]}... | Preço: {detail['price']} | Vendas vendedor: {detail['seller_sales']}")
    time.sleep(random.uniform(3, 7))

Pontos-chave do script:

  • Rotação automática de IP: cada requisição passa pelo ProxyHat com rotação residencial
  • Delay aleatório entre requisições (2–7s) para simular comportamento humano
  • Headers realistas para reduzir chance de challenge Cloudflare
  • Parse defensivo: verifica se elementos existem antes de extrair texto

Analytics de Loja: Extraindo Dados do Vendedor

Para análise competitiva, você precisa de dados por loja — não apenas por listagem. O Etsy expõe informações úteis nas páginas de shop:

Contagem de Listagens da Loja

Seletor: span[data-testid='shop-listing-count'] ou o texto "X items" no header da loja.

Badge de Vendas

O Etsy mostra badges como "1,234 Sales", "5,000+ Sales". Este número é arredondado — não é exato, mas é excelente para comparar vendedores.

XPath: //span[contains(text(), 'Sales')]

Avaliações da Loja

URL: https://www.etsy.com/shop/SHOP_NAME/reviews

Contém avaliações com texto, estrelas e data. O número total de reviews aparece no header: "X reviews".

Aqui está um script para raspar dados de uma loja:

def scrape_shop(shop_name):
    """Raspa dados de uma loja Etsy."""
    url = f"https://www.etsy.com/shop/{shop_name}"
    resp = SESSION.get(url, timeout=30)
    resp.raise_for_status()
    soup = BeautifulSoup(resp.text, "html.parser")

    # Contagem de listagens
    listing_count_el = soup.select_one("span[data-testid='shop-listing-count']")
    listing_count = listing_count_el.get_text(strip=True) if listing_count_el else "N/A"

    # Badge de vendas
    sales_text = None
    for el in soup.find_all(string=re.compile(r"[\d,]+\s*Sales?", re.I)):
        sales_text = el.strip()
        break

    # Avaliação média
    rating_el = soup.select_one("[data-testid='shop-rating']")
    rating = rating_el.get("aria-label", "N/A") if rating_el else "N/A"

    # Localização
    location_el = soup.select_one("[data-testid='shop-location']")
    location = location_el.get_text(strip=True) if location_el else "N/A"

    return {
        "shop": shop_name,
        "listing_count": listing_count,
        "sales_badge": sales_text,
        "rating": rating,
        "location": location,
    }


# Exemplo: analisar vendedores de um nicho
shops_seen = set()
for listing in all_listings:
    shop = listing.get("shop_name")
    if shop and shop not in shops_seen:
        shops_seen.add(shop)
        shop_data = scrape_shop(shop)
        print(f"  {shop}: {shop_data['listing_count']} items | {shop_data['sales_badge']} | {shop_data['rating']}")
        time.sleep(random.uniform(4, 8))

Autocomplete do Etsy: Mineração de Palavras-chave

Uma das fontes mais valiosas para Etsy niche research é a API de autocomplete. Ela retorna termos que compradores realmente buscam. Aqui está como minerá-la sistematicamente:

import string

BASE_SUGGEST_URL = "https://www.etsy.com/search/suggestions"

def get_suggestions(prefix):
    """Obtém sugestões de busca do Etsy para um prefixo."""
    params = {"query": prefix}
    resp = SESSION.get(BASE_SUGGEST_URL, params=params, timeout=15)
    resp.raise_for_status()
    data = resp.json()
    return [r["query"] for r in data.get("results", [])]


# Mineração por letra — encontra todos os termos começando com "custom "
base_term = "custom "
all_suggestions = set()

for letter in string.ascii_lowercase:
    prefix = f"{base_term}{letter}"
    suggestions = get_suggestions(prefix)
    all_suggestions.update(suggestions)
    print(f"  Prefixo '{prefix}': {len(suggestions)} sugestões")
    time.sleep(random.uniform(1, 3))

print(f"\nTotal de termos únicos: {len(all_suggestions)}")
for term in sorted(all_suggestions):
    print(f"  - {term}")

Esta técnica gera centenas de termos de nicho em minutos. Combine com contagem de resultados de busca para ranquear oportunidades.

Usando cURL com ProxyHat para Testes Rápidos

Para validar se seu setup de proxy funciona antes de escrever código:

# Teste de proxy residencial — busca no Etsy
curl -x http://user-country-US:SUA_SENHA@gate.proxyhat.com:8080 \
  -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
  -H "Accept: text/html" \
  "https://www.etsy.com/search?q=custom+name+mug" \
  -o etsy_search.html -w "%{http_code}\n"

# Teste de autocomplete
curl -x http://user-country-US:SUA_SENHA@gate.proxyhat.com:8080 \
  -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
  "https://www.etsy.com/search/suggestions?query=custom+name" \
  2>/dev/null | python3 -m json.tool

Se o primeiro retornar 200 e o segundo retornar JSON válido, seu proxy está funcionando.

Estratégias de Rotação de IP para Volume Alto

Se você precisa raspar milhares de listagens por dia, a rotação por requisição não é suficiente. Estratégias avançadas:

Sessões Sticky para Múltiplas Páginas

Use sessões sticky ao paginar dentro da mesma busca — o Etsy detecta mudanças de IP no meio de uma sessão de navegação:

# Sessão sticky — mesmo IP por ~10 minutos
PROXY_USER_STICKY = "user-country-US-session-myniche123"
PROXY_URL_STICKY = f"http://{PROXY_USER_STICKY}:SUA_SENHA@gate.proxyhat.com:8080"

Rate Limiting por IP

Mantenha cada IP abaixo de 60 requisições/minuto (margem de segurança dos ~80 do Etsy). Se você precisa de 600 req/min, use pelo menos 10 IPs simultâneos.

Geo-targeting

O Etsy personaliza resultados por localização. Se seu público é americano, use user-country-US. Para o mercado britânico, user-country-GB. Veja todas as localizações disponíveis em nossa página de localizações.

Ética: Vendedores do Etsy São Pequenos Negócios

Este é o ponto mais importante deste guia. O Etsy não é a Amazon — a maioria dos vendedores são pequenos criadores independentes. Muitos vivem do seu negócio Etsy.

O que é aceitável:

  • Pesquisa de nichos — identificar categorias com demanda e pouca concorrência
  • Análise de preços — entender faixas de preço para posicionar seus produtos
  • Monitoramento de tendências — detectar termos de busca em alta
  • Pesquisa de mercado — entender o tamanho de um nicho (contagem de vendedores, listagens)

O que NÃO é aceitável:

  • Copiar designs — raspar imagens e reimprimir em produtos POD é roubo intelectual
  • Copiar descrições — texto de descrição é conteúdo criativo do vendedor
  • Scraping agressivo — sobrecarregar o Etsy prejudica todos os vendedores
  • Re-vender dados — vender listas de vendedores ou designs raspados
Regra de ouro: Scrape para entender o mercado, não para copiar o mercado. Use os dados para encontrar lacunas e criar produtos originais que atendam a demandas não supridas.

Respeite também o robots.txt do Etsy e os Termos de Serviço. O Etsy proíbe scraping nos ToS, então esteja ciente dos riscos. Use dados apenas para pesquisa interna e nunca para redistribuição.

Considerações Técnicas Adicionais

Cloudflare Turnstile

Quando o Cloudflare detecta tráfego suspeito, ele serve um desafio Turnstile (CAPTCHA invisível). Proxies residenciais reduzem significativamente a frequência desses desafios, mas não eliminam completamente. Se você encontrar desafios:

  • Reduza a taxa de requisições
  • Adicione delays mais longos (8–15s)
  • Considere usar um browser headless (Playwright/Puppeteer) para resolver desafios automaticamente

Renderização JavaScript

Algumas partes do Etsy dependem de JavaScript para renderizar (avaliações, imagens lazy-loaded). Se você não obtém dados esperados com requests, pode precisar de renderização JS. Nesse caso, use Playwright com proxy:

from playwright.sync_api import sync_playwright

PROXY_SERVER = "gate.proxyhat.com:8080"
PROXY_USER = "user-country-US:SUA_SENHA"

with sync_playwright() as p:
    browser = p.chromium.launch(
        proxy={
            "server": f"http://{PROXY_SERVER}",
            "username": PROXY_USER.split(":")[0],
            "password": PROXY_USER.split(":")[1],
        },
        headless=True,
    )
    page = browser.new_page()
    page.goto("https://www.etsy.com/search?q=custom+name+mug", wait_until="networkidle")
    content = page.content()
    # Parse com BeautifulSoup como antes...
    browser.close()

Tratamento de Erros

Implemente retry com backoff exponencial. O Etsy retorna 429 e 403 intermitentemente:

  • HTTP 429 → espere 60s, tente novamente
  • HTTP 403 com Cloudflare → troque de IP (nova requisição = novo IP com ProxyHat)
  • HTTP 200 mas HTML sem dados → provavelmente challenge resolvido parcialmente, tente com outro IP

Key Takeaways

  • O Etsy não tem API pública de busca — scraping de HTML é o único caminho para pesquisa de mercado em escala.
  • Cloudflare + rate limits tornam proxies residenciais essenciais. Datacenter proxies têm taxa de sucesso abaixo de 50%.
  • A API de autocomplete é a fonte mais rápida de termos de nicho — combine com contagem de resultados para ranquear oportunidades.
  • Badge de vendas e contagem de listagens por loja são métricas suficientes para análise competitiva sem precisar de dados financeiros exatos.
  • Mantenha cada IP abaixo de 60 req/min para evitar bans. Use sticky sessions para paginação e rotação por requisição para buscas independentes.
  • Ética importa — scrape para pesquisa, nunca para copiar designs ou descrições de vendedores independentes.

Próximos Passos

Para começar com scraping ético no Etsy usando proxies residenciais confiáveis:

  1. Crie uma conta no ProxyHat e escolha um plano residencial
  2. Teste a conectividade com o comando cURL acima
  3. Adapte o script Python para seu nicho-alvo
  4. Configure alertas para HTTP 429/403 — se a taxa de erro passar de 10%, reduza a velocidade
  5. Veja mais padrões de scraping em nosso guia de web scraping

Para monitoramento contínuo de SERPs e preços, confira também nosso guia de SERP tracking.

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