Aviso legal: Este guia destina-se ao rastreamento de listagens públicas e dados de pesquisa da Amazon. Nos Estados Unidos, o Computer Fraud and Abuse Act (CFAA) restringe o acesso não autorizado a sistemas de terceiros. Na União Europeia, o GDPR regula o processamento de dados pessoais. Consulte sempre os Termos de Serviço da Amazon e considere a SP-API oficial quando disponível. Use apenas dados de pesquisa públicos e respeite limites de taxa.
O rastreamento de ranking de palavras-chave na Amazon com proxies é uma prática essencial para vendedores e desenvolvedores de SEO em marketplaces que precisam monitorar a posição orgânica de seus produtos ao longo do tempo. Diferente do Google, a Amazon opera sua própria SERP — a página de resultados é regida por relevância comercial e velocidade de vendas, não apenas por autoridade de conteúdo. Isso significa que um rastreador de ranking de palavras-chave da Amazon deve ser construído de forma diferente de um scraper de SERP convencional.
Neste guia, vamos cobrir como fazer scraping da SERP da Amazon com proxies residenciais, extrair posições orgânicas por ASIN, separar anúncios patrocinados de resultados orgânicos, e armazenar histórico de rankings em produção — tudo com código executável em Python.
Por que a SERP da Amazon é diferente do Google
O algoritmo de busca da Amazon — conhecido como A9 — prioriza produtos com alta probabilidade de conversão. Fatores como histórico de vendas, disponibilidade em estoque, preço competitivo e taxa de cliques (CTR) têm peso significativo na ordenação dos resultados. Um produto pode estar na página 1 para a palavra-chave "garrafa térmica" e na página 4 para "garrafa de água", mesmo sendo o mesmo ASIN.
Para vendedores, isso significa que rastrear a posição orgânica por palavra-chave, por marketplace e por ASIN é fundamental para entender o desempenho real. A Amazon também localiza resultados por marketplace — amazon.com, amazon.de, amazon.co.uk — e aplica filtros regionais de entrega, idioma e moeda. Um rastreador eficaz precisa respeitar essa localização.
Como a Amazon estrutura os resultados de busca
Cada resultado na SERP da Amazon é encapsulado em um container com o atributo data-component-type="s-search-result". Dentro desse container:
data-asincontém o identificador único do produto (ASIN).- A posição orgânica é determinada pela ordem dos containers na página, ignorando anúncios patrocinados.
- Anúncios patrocinados exibem um rótulo "Sponsored" ou "Patrocinado" visível no HTML.
Para rastrear corretamente, você deve iterar sobre todos os containers, identificar quais são patrocinados, e calcular a posição orgânica apenas entre os resultados não pagos.
Por que você precisa de proxies residenciais para rastrear a Amazon
A Amazon implementa defesas anti-bot agressivas, incluindo detecção de padrões de IP, CAPTCHAs, e bloqueios baseados em geolocalização. Se você fizer scraping de amazon.de a partir de um IP dos EUA, a Amazon pode redirecionar para amazon.com ou retornar resultados localizados incorretamente. Proxies de datacenter são frequentemente bloqueados por estar em faixas de IP conhecidas.
Proxies residenciais resolvem esses problemas porque usam IPs de dispositivos reais em residências reais, tornando o tráfego indistinguível de um consumidor comum. Com geo-targeting por país, você pode garantir que cada requisição para amazon.com venha de um IP nos EUA e cada requisição para amazon.de venha de um IP na Alemanha.
Configuração de geo-targeting no ProxyHat
O ProxyHat permite especificar país e cidade diretamente no username, além de IDs de sessão sticky para manter o mesmo IP durante paginação. Para rastrear amazon.com, use -country-US; para amazon.de, use -country-DE. Para paginar resultados de forma consistente, use -session-xxx para preservar o mesmo IP entre páginas 1-5.
| Marketplace | Domínio | Parâmetro ProxyHat | Porta |
|---|---|---|---|
| Amazon US | amazon.com | -country-US | 8080 |
| Amazon DE | amazon.de | -country-DE | 8080 |
| Amazon UK | amazon.co.uk | -country-GB | 8080 |
| Amazon FR | amazon.fr | -country-FR | 8080 |
Implementação: rastreamento de ranking com Python e curl_cffi
O curl_cffi é uma biblioteca Python que simula fingerprints de TLS de navegadores reais, contornando detecções baseadas em JA3/JA4. Combinado com proxies residenciais do ProxyHat, é uma ferramenta poderosa para scraping da SERP da Amazon.
Exemplo 1: Configuração do cliente com proxy residencial
from curl_cffi import requests
import os
# Credenciais ProxyHat
PROXYHAT_USER = os.environ.get("PROXYHAT_USER", "user-country-US")
PROXYHAT_PASS = os.environ.get("PROXYHAT_PASS", "pass")
# URL do proxy HTTP - geo-targeting para EUA
PROXY_URL = f"http://{PROXYHAT_USER}:{PROXYHAT_PASS}@gate.proxyhat.com:8080"
def create_session(marketplace="US", session_id=None):
"""Cria uma sessão curl_cffi com proxy residencial ProxyHat."""
username = f"user-country-{marketplace}"
if session_id:
username += f"-session-{session_id}"
proxy = f"http://{username}:{PROXYHAT_PASS}@gate.proxyhat.com:8080"
session = requests.Session(impersonate="chrome")
session.proxies = {"http": proxy, "https": proxy}
return session
Exemplo 2: Buscar uma palavra-chave e extrair resultados orgânicos
from curl_cffi import requests
from bs4 import BeautifulSoup
import time
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def fetch_amazon_search(keyword, marketplace="US", page=1, session_id=None):
"""Busca resultados da Amazon para uma palavra-chave e página específica."""
domains = {
"US": "amazon.com",
"DE": "amazon.de",
"GB": "amazon.co.uk",
"FR": "amazon.fr",
}
domain = domains.get(marketplace, "amazon.com")
url = f"https://www.{domain}/s?k={keyword}&page={page}"
session = create_session(marketplace, session_id)
headers = {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.9" if marketplace == "US" else "de-DE,de;q=0.9",
"Referer": f"https://www.{domain}/",
}
try:
resp = session.get(url, headers=headers, timeout=30)
if resp.status_code == 200:
return resp.text
elif resp.status_code == 503:
logger.warning("Amazon retornou 503 - possível CAPTCHA ou bloqueio")
return None
else:
logger.error(f"Status inesperado: {resp.status_code}")
return None
except Exception as e:
logger.error(f"Erro ao buscar: {e}")
return None
def parse_search_results(html):
"""Extrai ASINs e posições orgânicas dos resultados de busca."""
soup = BeautifulSoup(html, "html.parser")
results = []
organic_position = 0
containers = soup.find_all(attrs={"data-component-type": "s-search-result"})
for container in containers:
asin = container.get("data-asin", "")
if not asin:
continue
# Detectar anúncio patrocinado
sponsored_label = container.find(string=lambda t: t and "Sponsored" in t if t else False)
is_sponsored = sponsored_label is not None
if not is_sponsored:
organic_position += 1
results.append({
"asin": asin,
"organic_position": organic_position,
"is_sponsored": False,
})
else:
results.append({
"asin": asin,
"organic_position": None,
"is_sponsored": True,
})
return results
Exemplo 3: Rastrear posição de um ASIN em múltiplas páginas
import time
import logging
from datetime import datetime
logger = logging.getLogger(__name__)
def track_asin_ranking(keyword, target_asin, marketplace="US", max_pages=5):
"""
Rastreia a posição orgânica de um ASIN para uma palavra-chave
através de múltiplas páginas de resultados.
"""
session_id = f"track-{keyword.replace(' ', '-')}-{int(time.time())}"
ranking_data = {
"keyword": keyword,
"asin": target_asin,
"marketplace": marketplace,
"timestamp": datetime.utcnow().isoformat(),
"found": False,
"organic_position": None,
"page": None,
"sponsored": False,
}
for page in range(1, max_pages + 1):
logger.info(f"Buscando página {page} para '{keyword}' em amazon.{marketplace.lower()}")
html = fetch_amazon_search(keyword, marketplace, page, session_id)
if html is None:
logger.warning(f"Falha ao buscar página {page}, parando.")
break
results = parse_search_results(html)
for result in results:
if result["asin"] == target_asin:
ranking_data["found"] = True
ranking_data["page"] = page
ranking_data["sponsored"] = result["is_sponsored"]
if result["organic_position"]:
# Posição global = (página - 1) * resultados_por_página + posição_na_página
ranking_data["organic_position"] = (page - 1) * 16 + result["organic_position"]
logger.info(
f"ASIN {target_asin} encontrado na página {page}, "
f"posição orgânica: {ranking_data['organic_position']}"
)
return ranking_data
# Delay entre páginas para evitar detecção
time.sleep(2)
logger.info(f"ASIN {target_asin} não encontrado nas primeiras {max_pages} páginas.")
return ranking_data
# Uso
result = track_asin_ranking("garrafa térmica", "B08XYZ1234", marketplace="US")
print(result)
Exemplo 4: Armazenar histórico de posições com SQLite
import sqlite3
import json
from datetime import datetime
from contextlib import contextmanager
@contextmanager
def get_db_connection(db_path="rankings.db"):
conn = sqlite3.connect(db_path)
conn.row_factory = sqlite3.Row
try:
yield conn
conn.commit()
finally:
conn.close()
def init_db(db_path="rankings.db"):
with get_db_connection(db_path) as conn:
conn.execute("""
CREATE TABLE IF NOT EXISTS keyword_rankings (
id INTEGER PRIMARY KEY AUTOINCREMENT,
keyword TEXT NOT NULL,
asin TEXT NOT NULL,
marketplace TEXT NOT NULL,
organic_position INTEGER,
page INTEGER,
found INTEGER DEFAULT 0,
sponsored INTEGER DEFAULT 0,
timestamp TEXT NOT NULL,
UNIQUE(keyword, asin, marketplace, timestamp)
)
""")
conn.execute("""
CREATE INDEX IF NOT EXISTS idx_asin_keyword
ON keyword_rankings(asin, keyword, marketplace)
""")
def save_ranking(ranking_data, db_path="rankings.db"):
with get_db_connection(db_path) as conn:
conn.execute("""
INSERT OR REPLACE INTO keyword_rankings
(keyword, asin, marketplace, organic_position, page, found, sponsored, timestamp)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
""", (
ranking_data["keyword"],
ranking_data["asin"],
ranking_data["marketplace"],
ranking_data["organic_position"],
ranking_data["page"],
int(ranking_data["found"]),
int(ranking_data["sponsored"]),
ranking_data["timestamp"],
))
def get_ranking_history(asin, keyword, marketplace, days=30, db_path="rankings.db"):
with get_db_connection(db_path) as conn:
rows = conn.execute("""
SELECT * FROM keyword_rankings
WHERE asin = ? AND keyword = ? AND marketplace = ?
ORDER BY timestamp DESC
LIMIT ?
""", (asin, keyword, marketplace, days)).fetchall()
return [dict(row) for row in rows]
# Inicializar e salvar
init_db()
save_ranking(result)
history = get_ranking_history("B08XYZ1234", "garrafa térmica", "US")
for entry in history:
print(f"{entry['timestamp']}: página {entry['page']}, posição {entry['organic_position']}")
Usando Playwright para páginas renderizadas dinamicamente
Às vezes, a Amazon renderiza resultados dinamicamente com JavaScript, especialmente em marketplaces com alta proteção. O Playwright permite simular um navegador completo, incluindo execução de JavaScript e interação com a página.
Exemplo 5: Playwright com proxy SOCKS5 do ProxyHat
from playwright.async_api import async_playwright
import asyncio
import logging
logger = logging.getLogger(__name__)
async def fetch_amazon_playwright(keyword, marketplace="US", page=1, session_id=None):
"""Busca SERP da Amazon usando Playwright com proxy SOCKS5 ProxyHat."""
domains = {"US": "amazon.com", "DE": "amazon.de", "GB": "amazon.co.uk"}
domain = domains.get(marketplace, "amazon.com")
username = f"user-country-{marketplace}"
if session_id:
username += f"-session-{session_id}"
url = f"https://www.{domain}/s?k={keyword}&page={page}"
async with async_playwright() as p:
browser = await p.chromium.launch(
headless=True,
proxy={
"server": "socks5://gate.proxyhat.com:1080",
"username": username,
"password": "pass",
},
)
context = await browser.new_context(
locale="en-US" if marketplace == "US" else "de-DE",
user_agent=(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/120.0.0.0 Safari/537.36"
),
)
page_obj = await context.new_page()
try:
await page_obj.goto(url, wait_until="domcontentloaded", timeout=30000)
# Aguardar resultados carregarem
await page_obj.wait_for_selector(
'[data-component-type="s-search-result"]',
timeout=15000,
)
html = await page_obj.content()
return html
except Exception as e:
logger.error(f"Erro no Playwright: {e}")
# Verificar se é CAPTCHA
content = await page_obj.content()
if "captcha" in content.lower() or "robot" in content.lower():
logger.warning("CAPTCHA detectado - considere rotacionar IP")
return None
finally:
await browser.close()
async def track_with_playwright(keyword, target_asin, marketplace="US"):
"""Rastreia ranking usando Playwright."""
session_id = f"pw-{int(asyncio.get_event_loop().time())}"
html = await fetch_amazon_playwright(keyword, marketplace, 1, session_id)
if html:
results = parse_search_results(html)
for result in results:
if result["asin"] == target_asin and not result["is_sponsored"]:
return result["organic_position"]
return None
# Executar
# position = asyncio.run(track_with_playwright("garrafa térmica", "B08XYZ1234", "US"))
Erros comuns e armadilhas de produção
1. Não separar anúncios patrocinados de orgânicos
Um erro frequente é contar todos os containers s-search-result como orgânicos. A Amazon insere anúncios Sponsored no topo e no meio dos resultados. Se você não filtrar, suas posições estarão infladas. Sempre verifique a presença do rótulo "Sponsored" ou "Patrocinado".
2. Ignorar localização por marketplace
Se você rastrear amazon.de sem um proxy alemão, a Amazon pode retornar resultados de amazon.com ou filtrar produtos por entrega internacional. Use sempre -country-DE para amazon.de, -country-GB para amazon.co.uk, etc.
3. Não usar sessões sticky para paginação
Ao paginar resultados (páginas 1-5), cada requisição com um IP diferente pode receber resultados inconsistentes — a Amazon personaliza resultados por sessão. Use -session-xxx para manter o mesmo IP durante toda a paginação.
4. Não detectar CAPTCHAs
A Amazon retorna status 503 ou redireciona para páginas de CAPTCHA quando detecta comportamento automatizado. Verifique sempre o conteúdo da resposta por strings como "captcha", "robot", ou "Type the characters".
Dicas de produção para rastreamento diário
Agendamento com retries e backoff
import time
import random
from datetime import datetime
MAX_RETRIES = 3
BASE_DELAY = 5 # segundos
def fetch_with_retry(keyword, marketplace="US", page=1, session_id=None):
"""Busca com retries e backoff exponencial."""
for attempt in range(MAX_RETRIES):
html = fetch_amazon_search(keyword, marketplace, page, session_id)
if html is not None:
return html
delay = BASE_DELAY * (2 ** attempt) + random.uniform(0, 2)
logger.warning(
f"Tentativa {attempt + 1}/{MAX_RETRIES} falhou. "
f"Aguardando {delay:.1f}s..."
)
time.sleep(delay)
logger.error(f"Todas as {MAX_RETRIES} tentativas falharam para '{keyword}' página {page}.")
return None
def daily_ranking_check(keywords_asins, marketplace="US"):
"""
Executa verificação diária de rankings para múltiplos pares
palavra-chave/ASIN.
"""
results = []
for keyword, asin in keywords_asins:
result = track_asin_ranking(keyword, asin, marketplace, max_pages=5)
save_ranking(result)
results.append(result)
# Delay entre palavras-chave para respeitar limites de taxa
time.sleep(random.uniform(3, 7))
return results
# Exemplo de uso diário
keywords_to_track = [
("garrafa térmica", "B08XYZ1234"),
("garrafa de água", "B08XYZ1234"),
("termo inox", "B08XYZ1234"),
]
# daily_ranking_check(keywords_to_track, marketplace="US")
Verificação de indexação
Antes de rastrear rankings, verifique se o ASIN está indexado para a palavra-chave. Se o ASIN não aparece nas primeiras 5 páginas, ele pode não estar indexado para aquele termo. Registre found: false no banco de dados para identificar problemas de indexação e oportunidade de otimização.
Comparação: curl_cffi vs Playwright para scraping da Amazon
| Aspecto | curl_cffi | Playwright |
|---|---|---|
| Velocidade | ~200ms por requisição | ~2-5s por página |
| Consumo de recursos | Baixo (sem navegador) | Alto (navegador completo) |
| Bypass anti-bot | Fingerprint TLS simulado | Navegador real completo |
| Execução de JS | Não | Sim |
| Concorrência | Alta (100+ sessões) | Baixa (5-10 navegadores) |
| Custo de proxy | Menor (menos tráfego) | Maior (renderização completa) |
Para a maioria dos casos de rastreamento de ranking, curl_cffi é suficiente e mais eficiente. Use Playwright apenas quando a Amazon renderizar resultados dinamicamente via JavaScript ou quando curl_cffi for consistentemente bloqueado.
Considerações éticas e melhores práticas
- Rastreie apenas listagens públicas e seus próprios produtos. Não rastreie dados de concorrentes em escala que possa prejudicar a infraestrutura da Amazon.
- Respeite limites de taxa. Mantenha delays de 2-7 segundos entre requisições e não exceda 50 requisições por minuto por sessão.
- Considere a SP-API da Amazon. Para acesso autorizado a dados de produtos e vendas, a SP-API oficial oferece endpoints como Catalog Items e Product Pricing que podem complementar ou substituir o scraping.
- Monitore seus custos de proxy. Rastrear 100 palavras-chave em 3 marketplaces diariamente, 5 páginas cada, consome ~1.500 requisições por dia — planeje seu plano de proxy de acordo. Veja os preços em nossa página de preços.
Para mais detalhes sobre scraping de SERP em geral, consulte nosso guia de web scraping e rastreamento de SERP. Para ver todas as localizações disponíveis para geo-targeting, visite nossa página de localizações. A documentação técnica completa do ProxyHat está em docs.proxyhat.com.
Pontos-chave
- A SERP da Amazon é regida por relevância comercial e velocidade de vendas — não por autoridade de domínio como no Google.
- Separe sempre anúncios patrocinados ("Sponsored") de resultados orgânicos ao calcular posições.
- Use proxies residenciais com geo-targeting por país para cada marketplace (amazon.com → US, amazon.de → DE).
- Sessões sticky (
-session-xxx) são essenciais para paginação consistente.- curl_cffi com fingerprint TLS simulado é mais eficiente que Playwright para a maioria dos casos.
- Implemente retries com backoff exponencial, detecção de CAPTCHA e armazenamento de histórico para produção.
- Considere a SP-API da Amazon como alternativa ou complemento ao scraping.
FAQ
O que é rastreamento de ranking de palavras-chave na Amazon com proxies?
É o processo de monitorar a posição orgânica de um produto (ASIN) nos resultados de busca da Amazon para uma palavra-chave específica, utilizando proxies residenciais para contornar bloqueios anti-bot e garantir localização correta por marketplace. Diferente do Google, a Amazon prioriza relevância comercial e velocidade de vendas, tornando o rastreamento por palavra-chave essencial para vendedores otimizarem listings.
Por que o rastreamento de ranking com proxies é importante para usuários de proxy?
Porque a Amazon implementa defesas anti-bot agressivas, incluindo detecção de IP, CAPTCHAs e localização forçada por marketplace. Sem proxies residenciais com geo-targeting, requisições de datacenter são bloqueadas e resultados podem vir localizados incorretamente. Proxies residenciais permitem simular tráfego de consumidores reais no país correto, garantindo dados de ranking precisos e consistentes.
Qual tipo de proxy funciona melhor para rastreamento de ranking na Amazon?
Proxies residenciais são a melhor opção porque usam IPs de dispositivos reais em residências reais, tornando o tráfego indistinguível de consumidores comuns. Proxies de datacenter são frequentemente bloqueados pela Amazon. Proxies móveis também funcionam bem, mas têm custo mais alto. Para rastreamento de ranking, residenciais com geo-targeting por país e suporte a sessões sticky oferecem o melhor equilíbrio entre custo e confiabilidade.
Como evitar bloqueios ao implementar rastreamento de ranking na Amazon?
Use proxies residenciais com geo-targeting por país, sessões sticky para paginação consistente, delays de 2-7 segundos entre requisições, rotação de User-Agent, fingerprint TLS simulado (curl_cffi), e retries com backoff exponencial. Detecte CAPTCHAs verificando status 503 ou conteúdo com "captcha"/"robot". Não exceda 50 requisições por minuto por sessão e considere a SP-API oficial da Amazon como alternativa autorizada.
Como separar anúncios patrocinados de resultados orgânicos na Amazon?
Cada container de resultado tem o atributo data-component-type="s-search-result". Dentro dele, anúncios patrocinados exibem um rótulo "Sponsored" ou "Patrocinado" no HTML. Ao iterar os containers, verifique a presença desse rótulo e calcule a posição orgânica apenas entre os resultados não pagos, ignorando os patrocinados na contagem.






