---
title: "Como monitorar preços da concorrência no e-commerce"
description: "Monitorar preços da concorrência reúne pareamento de produtos, leituras periódicas e alertas. Veja as APIs de vendedor, um script Python testado e a frequência."
url: https://proxynet.io/pt-br/blog/competitor-price-tracking
date: 2026-09-19
author: "Enver Kaya"
category: "Casos de uso, Web scraping"
lang: pt-BR
---

# Como monitorar preços da concorrência no e-commerce

Segunda-feira de manhã, você abre o relatório de vendas: os pedidos dos seus três produtos mais vendidos caíram pela metade no fim de semana. O motivo aparece à tarde, quando você olha à mão a página de um concorrente. Ele baixou o preço na sexta à noite e você ficou dois dias mais caro. É esse o problema que o monitoramento de preços da concorrência resolve: saber da mudança pela própria mudança, e não pelas vendas perdidas.

Neste artigo montamos o trabalho de ponta a ponta. Primeiro comparamos de onde os dados podem vir (API de vendedor, ferramenta pronta, script próprio); depois tratamos do pareamento de produtos, de qual preço registrar e de como calcular a frequência de leitura. Para quem desenvolve, há um exemplo testado em Python que lê o preço na página, guarda o histórico em SQLite e avisa quando um limite é ultrapassado. No fim ficam os limites: termos do site, robots.txt e direito da concorrência.

> **Nota: Resposta rápida**
>
> O monitoramento de preços da concorrência tem quatro partes: uma lista que liga os seus produtos aos equivalentes no concorrente, um rastreador que lê essas páginas em intervalos definidos, uma tabela de histórico que guarda cada leitura com a data e um alerta que avisa quando a variação passa do limite que você escolheu. Os dados do seu próprio catálogo vêm da API de vendedor do marketplace. Os dados do concorrente são lidos em páginas de produto públicas, respeitando o robots.txt e com um ritmo baixo de requisições.

## Quais são as etapas do monitoramento de preços da concorrência?

Monitorar preços é ler e registrar, em intervalos regulares, o preço e o estoque exibidos nas páginas de produto dos concorrentes. A definição completa e o lado da infraestrutura estão na nossa página de [monitoramento de preços](/pt-br/price-monitoring); aqui olhamos como o trabalho é montado. Seja qual for a ferramenta, o fluxo é o mesmo:

1. **Defina o escopo.** Acompanhe não o catálogo inteiro, mas os produtos que sustentam o faturamento e são sensíveis a preço.
2. **Faça o pareamento dos produtos.** Ao lado de cada código de estoque (SKU), anote o endereço do mesmo produto no concorrente.
3. **Leia as páginas em intervalos regulares.** São coletados o preço, a moeda, a situação do estoque e, se houver, o nome do vendedor.
4. **Guarde cada leitura com a data.** Uma tabela que mantém só o último preço não responde a "quando mudou?".
5. **Compare a variação com um limite e avise.** Se chega um e-mail a cada centavo de oscilação, em três dias ninguém mais lê os alertas.
6. **Deixe a decisão com uma pessoa.** Um alerta é uma sugestão. Quem muda o preço, e com que regra, é uma decisão de negócio à parte.

## De onde vêm os dados: API de vendedor, ferramenta pronta ou script próprio?

Olhe primeiro o caminho oficial. Os marketplaces oferecem aos vendedores APIs para gerenciar os próprios dados de produto, estoque e preço. A [documentação para desenvolvedores do Mercado Livre](https://developers.mercadolivre.com.br/), por exemplo, cobre publicação de produtos, estoque, preços e gestão de vendas. Essas APIs existem para a sua própria loja, e o que mostram sobre a concorrência é limitado. As [referências de preços](https://developers.mercadolivre.com.br/pt_br/referencias-de-precos) do Mercado Livre são recomendações para os seus anúncios, calculadas a partir dos preços atuais de produtos semelhantes dentro e fora da plataforma, do histórico de vendas e da demanda. Elas não mostram o preço de um concorrente específico, o estoque dele nem um produto que você não anuncia. Mesmo assim, a coluna da esquerda da comparação, ou seja, o seu preço atual, deve ser lida daqui e não de uma planilha mantida à mão.

Para o lado do concorrente, as opções ficam assim, lado a lado:

| Método | O que entrega | Esforço | Quando faz sentido |
|---|---|---|---|
| API de vendedor | Os seus próprios dados de preço, estoque e pedidos; em alguns marketplaces, uma referência de preço para os produtos que você vende | Integração feita uma vez | Sempre, para o seu lado da comparação |
| Conferência manual e planilha | O preço do momento de poucos produtos | Trabalho humano que se repete todo dia | 20-30 produtos, uma olhada semanal |
| Ferramenta pronta de monitoramento de preços | Pareamento, rastreamento e tela de relatórios | Assinatura mensal, pouca configuração | Sem equipe de desenvolvimento e com marketplaces comuns |
| Script próprio | O site, o campo e a frequência que você quiser | Desenvolvimento e manutenção | Sites específicos, fluxo para o seu próprio data warehouse, regras de alerta flexíveis |
| Fluxo em ferramenta de automação | O script, só que sem código | Médio | Lista pequena, conectores prontos para planilha e notificação |

Montamos um exemplo da última linha no artigo sobre [web scraping com n8n](/pt-br/blog/n8n-proxy). As formas de tirar uma tabela de uma página sem escrever código estão explicadas passo a passo em [como extrair dados de um site](/pt-br/blog/extract-data-from-website).

## Como fazer o pareamento de produtos?

Um produto pareado errado faz mais estrago do que um produto que não é acompanhado: um alerta que compara o preço do modelo de 64 GB com o de 128 GB leva você a um desconto desnecessário. Em ordem de confiabilidade, o pareamento funciona assim:

- **Código de barras (GTIN/EAN).** Se duas páginas trazem o mesmo código, o produto é o mesmo. Nos dados estruturados ele fica no campo `gtin13` ou `gtin`, e às vezes na tabela de características do produto.
- **Código do fabricante (MPN) e marca.** Em eletrônicos e peças de reposição aparece mais do que o código de barras.
- **Comparação de título e características.** Sem código de barras, compare separadamente marca, modelo, capacidade, cor e quantidade.

Em produtos com variações (tamanho, cor, capacidade), cada variação é uma linha separada e, na maioria dos sites, tem endereço próprio ou um parâmetro próprio no endereço. Em kits (com 3, com 6), não compare antes de converter para preço por unidade. Nos marketplaces, a mesma página de produto pode ter vários vendedores; o "concorrente" não é a página, e sim um vendedor específico dentro dela.

Para a tabela de pareamento bastam as colunas `sku`, `concorrente`, `url`, `tipo de pareamento` e `última conferência`. Revise de tempos em tempos as linhas pareadas à mão: o concorrente pode tirar o produto do ar e colocar o modelo novo no mesmo endereço.

## Qual preço você deve registrar?

Uma página de produto não tem um preço só. Se você não define desde o início o que registra, a tabela de histórico acaba comparando banana com laranja.

- **Preço de lista e preço com desconto.** Guarde os dois em colunas separadas. O que o cliente paga é o com desconto.
- **Preço que cai no carrinho ou com cupom.** Pode não aparecer na página do produto. Se não está na página pública, deixe fora do escopo; navegação automática com conta logada não é assunto deste artigo.
- **Frete.** O valor mínimo para frete grátis define a diferença real em produtos baratos.
- **Moeda.** Com concorrentes de outros países, registre a moeda junto com o preço e deixe a conversão para a etapa de relatório.
- **Situação do estoque.** O preço de um concorrente sem estoque não obriga você a nada.

## Como definir a frequência de leitura?

Quem define a frequência não é a curiosidade, e sim duas perguntas: com que velocidade os preços mudam nessa categoria e com que velocidade você consegue reagir? Para uma equipe que atualiza preços uma vez por semana, uma leitura de hora em hora gera carga no servidor do concorrente e, para você, dados que ninguém lê.

| Classe de produto | Ponto de partida razoável | Motivo |
|---|---|---|
| Mais vendidos em período de campanha | Algumas vezes por dia | O preço pode mudar ao longo do dia e o tempo de reação é curto |
| Produtos principais com venda regular | Uma vez por dia | A maioria das decisões de preço é diária |
| Cauda longa, produtos de giro lento | Uma vez por semana | Mudam pouco e pedem pouca reação |
| Produtos sem estoque no concorrente | Uma vez por dia, só o estoque | A volta do estoque é uma informação tão valiosa quanto o preço |

Calcule o número de requisições com uma multiplicação simples: **número de produtos × leituras por dia**. Ler 500 produtos quatro vezes por dia dá 2.000 requisições. Com dois segundos de espera entre as requisições, uma rodada leva cerca de 17 minutos, e esse é um ritmo tranquilo para um único site. Quando a mesma conta é feita para 50.000 produtos com leitura de hora em hora, entram em cena filas, limite de requisições e distribuição entre vários IPs. As formas de respeitar o limite de requisições estão em [web scraping sem bloqueios](/pt-br/blog/web-scraping-without-getting-blocked), e o que significa o servidor dizer "mais devagar" está no nosso artigo sobre [429 Too Many Requests](/pt-br/blog/http-429-too-many-requests).

## Em que parte da página fica o preço?

Passamos para o lado de quem desenvolve. Ler o preço de onde você o vê na tela, isto é, do texto dentro de alguma classe CSS, é o caminho mais frágil: o layout muda, o nome da classe muda e o script quebra em silêncio. A maioria das lojas coloca a mesma informação na página uma segunda vez, de forma estruturada, para os buscadores. Esses dados ficam dentro de uma tag `<script type="application/ld+json">` e trazem os campos `price`, `priceCurrency` e `availability` do tipo [Offer](https://schema.org/Offer) do schema.org. A [documentação do Google sobre dados estruturados para listagens de comerciantes](https://developers.google.com/search/docs/appearance/structured-data/merchant-listing?hl=pt-br) trata `price` e `priceCurrency` como obrigatórios; uma loja que quer aparecer na busca com o preço mantém esses dados atualizados.

Por isso a ordem de leitura deve ser esta:

1. Se a página tem dados JSON-LD do tipo `Product`, pegue o preço dali.
2. Se não tem, escreva um seletor de acordo com a estrutura HTML da própria página.
3. Se o preço não está em lugar nenhum do HTML, a página carrega os dados com JavaScript. Esse caso e outras formas de ler JSON embutido estão em [páginas estáticas e dinâmicas](/pt-br/blog/static-vs-dynamic-pages); para escrever seletores, veja [seletor CSS e XPath](/pt-br/blog/css-selector-vs-xpath).

## Exemplo em Python que funciona: histórico de preços e alerta por limite

Rodamos o exemplo não em uma loja real, mas em [books.toscrape.com](https://toscrape.com/). O site é uma livraria fictícia publicada para praticar scraping e, segundo o aviso da página inicial, os preços foram atribuídos ao acaso. As páginas não têm JSON-LD. Em lojas reais você vai encontrar os dois casos; por isso o script tenta primeiro o JSON-LD e, quando não encontra, recorre à tabela de informações do produto do site.

Você precisa de Python 3 e de dois pacotes (`pip install requests beautifulsoup4`). O SQLite vem com o módulo [`sqlite3`](https://docs.python.org/3/library/sqlite3.html) da biblioteca padrão do Python; não é preciso instalar um servidor de banco de dados à parte.

```python
import json
import re
import sqlite3
import time
from datetime import datetime, timezone
from decimal import Decimal

import requests
from bs4 import BeautifulSoup

DB = "prices.db"
THRESHOLD_PCT = Decimal("5")   # variação maior que esta gera um alerta
DELAY = 2.0                    # pausa entre duas requisições ao mesmo site (segundos)
PROXY = None                   # exemplo: "http://user:pass@pr.proxynet.io:8000"
USER_AGENT = "ExamplePriceBot/1.0 (+https://example.com/about-the-bot)"

# O seu SKU -> página do mesmo produto no concorrente
PRODUCTS = {
    "BK-001": "https://books.toscrape.com/catalogue/a-light-in-the-attic_1000/index.html",
    "BK-002": "https://books.toscrape.com/catalogue/tipping-the-velvet_999/index.html",
    "BK-003": "https://books.toscrape.com/catalogue/soumission_998/index.html",
}

CURRENCIES = {"£": "GBP", "€": "EUR", "$": "USD", "₺": "TRY", "TL": "TRY"}

def parse_price(text):
    """Converte um texto como '£51.77' ou '1.299,90' em Decimal."""
    number = re.sub(r"[^\d.,]", "", text)
    if re.fullmatch(r"\d{1,3}(\.\d{3})+", number):
        number = number.replace(".", "")                     # 1.299 -> 1299 (sem centavos)
    elif number.rfind(",") > number.rfind("."):
        number = number.replace(".", "").replace(",", ".")   # 1.299,90 -> 1299.90
    else:
        number = number.replace(",", "")                     # 1,299.90 -> 1299.90
    return Decimal(number)

def read_jsonld(soup):
    """Lê o preço nos dados Product do schema.org, se a página tiver."""
    for tag in soup.find_all("script", type="application/ld+json"):
        try:
            data = json.loads(tag.string or "")
        except json.JSONDecodeError:
            continue
        candidates = data if isinstance(data, list) else data.get("@graph", [data])
        for candidate in candidates:
            kind = candidate.get("@type")
            if "Product" not in (kind if isinstance(kind, list) else [kind]):
                continue
            offer = candidate.get("offers") or {}
            if isinstance(offer, list):
                offer = offer[0]
            price = offer.get("price") or offer.get("lowPrice")
            if price is None:
                continue
            return {
                "price": Decimal(str(price)),
                "currency": offer.get("priceCurrency"),
                "in_stock": str(offer.get("availability", "")).endswith("InStock"),
                "source": "json-ld",
            }
    return None

def read_html(soup):
    """Sem JSON-LD: a estrutura da própria página, aqui a tabela de produto do books.toscrape.com."""
    table = {
        row.th.get_text(strip=True): row.td.get_text(strip=True)
        for row in soup.select("table.table-striped tr")
    }
    raw = table.get("Price (incl. tax)") or soup.select_one("p.price_color").get_text()
    symbol = next((s for s in CURRENCIES if s in raw), None)
    return {
        "price": parse_price(raw),
        "currency": CURRENCIES.get(symbol),
        "in_stock": table.get("Availability", "").startswith("In stock"),
        "source": "html",
    }

def fetch_product(session, url):
    response = session.get(url, timeout=20)
    response.raise_for_status()
    response.encoding = "utf-8"   # o servidor não informa o charset; assim o símbolo £ não quebra
    soup = BeautifulSoup(response.text, "html.parser")
    if soup.select_one("h1") is None:
        raise ValueError("retornou 200, mas não é uma página de produto")
    return read_jsonld(soup) or read_html(soup)

def database():
    db = sqlite3.connect(DB)
    db.execute(
        """CREATE TABLE IF NOT EXISTS prices (
               sku TEXT NOT NULL,
               url TEXT NOT NULL,
               price_cents INTEGER NOT NULL,
               currency TEXT,
               in_stock INTEGER NOT NULL,
               source TEXT,
               checked_at TEXT NOT NULL
           )"""
    )
    db.execute("CREATE INDEX IF NOT EXISTS idx_sku_checked ON prices (sku, checked_at)")
    return db

def previous_row(db, sku):
    return db.execute(
        "SELECT price_cents, in_stock FROM prices WHERE sku = ? ORDER BY checked_at DESC LIMIT 1",
        (sku,),
    ).fetchone()

def alert(message):
    print("ALERTA:", message)   # ligue aqui o e-mail ou um webhook de chat

def main():
    db = database()
    session = requests.Session()
    session.headers["User-Agent"] = USER_AGENT
    if PROXY:
        session.proxies = {"http": PROXY, "https": PROXY}

    for sku, url in PRODUCTS.items():
        try:
            product = fetch_product(session, url)
        except (requests.RequestException, ValueError, AttributeError) as error:
            print(f"{sku}: não foi possível ler ({error})")
            time.sleep(DELAY)
            continue

        cents = int(product["price"] * 100)
        previous = previous_row(db, sku)
        if previous:
            old_cents, old_stock = previous
            change = Decimal(cents - old_cents) * 100 / Decimal(old_cents)
            if abs(change) >= THRESHOLD_PCT:
                alert(f"{sku}: {old_cents / 100:.2f} -> {cents / 100:.2f} "
                      f"{product['currency']} ({change:+.1f}%)")
            if bool(old_stock) != product["in_stock"]:
                alert(f"{sku}: o estoque mudou, agora {'tem' if product['in_stock'] else 'não tem'}")

        db.execute(
            "INSERT INTO prices VALUES (?, ?, ?, ?, ?, ?, ?)",
            (sku, url, cents, product["currency"], int(product["in_stock"]), product["source"],
             datetime.now(timezone.utc).isoformat(timespec="seconds")),
        )
        db.commit()
        print(f"{sku}: {product['price']} {product['currency']} "
              f"estoque={'sim' if product['in_stock'] else 'não'} ({product['source']})")
        time.sleep(DELAY)

    db.close()

if __name__ == "__main__":
    main()
```

Na primeira execução são gravadas três linhas e nenhum alerta aparece, porque ainda não há registro anterior para comparar:

```text
BK-001: 51.77 GBP estoque=sim (html)
BK-002: 53.74 GBP estoque=sim (html)
BK-003: 50.10 GBP estoque=sim (html)
```

Os preços do site de prática não mudam; para ver o alerta, alteramos à mão o último registro no banco de dados: colocamos o preço de `BK-001` em 45,00 e marcamos `BK-002` como sem estoque. A saída da segunda execução:

```text
ALERTA: BK-001: 45.00 -> 51.77 GBP (+15.0%)
BK-001: 51.77 GBP estoque=sim (html)
ALERTA: BK-002: o estoque mudou, agora tem
BK-002: 53.74 GBP estoque=sim (html)
BK-003: 50.10 GBP estoque=sim (html)
```

Quatro escolhas do código são deliberadas:

- **O preço é guardado como número inteiro de centavos.** Números de ponto flutuante (`float`) acumulam erro de arredondamento em contas com dinheiro. Interpretar com `Decimal` e converter para centavos mantém o cálculo do percentual exato.
- **Cada leitura é uma linha nova.** A linha é gravada mesmo quando o preço não mudou; assim dá para separar "olhamos naquele dia e estava igual" de "não conseguimos olhar naquele dia".
- **O produto que não pôde ser lido é pulado e a rodada continua.** O erro aparece na tela e o script segue para o próximo produto. Você pode combinar isso com o código de nova tentativa de [códigos de status HTTP no web scraping](/pt-br/blog/http-status-codes-web-scraping) para decidir em qual código tentar de novo e em qual parar.
- **O User-Agent diz quem é o bot.** Como escolher o valor está no nosso artigo [o que é User-Agent](/pt-br/blog/what-is-user-agent).

Com a linha `PROXY` preenchida, rodamos o mesmo script também por um proxy local de teste com autenticação. O resultado não mudou; com a senha errada, cada produto falhou com `ProxyError` (407) e a rodada terminou do mesmo jeito.

## Como montar a lista de produtos: páginas de categoria e paginação

Para reunir todos os endereços de produto de uma categoria do concorrente é preciso percorrer as páginas de categoria, e a lista quase sempre está dividida em páginas. O método mais firme não é inventar números de página, e sim seguir o link "próxima" da própria página:

```python
import time
from urllib.parse import urljoin

import requests
from bs4 import BeautifulSoup

def product_urls(session, start, max_pages=3, delay=2.0):
    """Percorre as páginas de categoria seguindo o link 'next' e reúne as URLs de produto."""
    url, found = start, []
    for _ in range(max_pages):
        response = session.get(url, timeout=20)
        response.raise_for_status()
        soup = BeautifulSoup(response.text, "html.parser")
        found += [urljoin(url, a["href"]) for a in soup.select("article.product_pod h3 a")]
        next_link = soup.select_one("li.next a")
        if next_link is None:
            break
        url = urljoin(url, next_link["href"])
        time.sleep(delay)
    return found

session = requests.Session()
session.headers["User-Agent"] = "ExamplePriceBot/1.0 (+https://example.com/about-the-bot)"
urls = product_urls(session, "https://books.toscrape.com/catalogue/category/books/mystery_3/index.html")
print(len(urls), "produtos encontrados")
```

Na categoria "Mystery" do site de prática, essa função percorreu duas páginas e devolveu 32 endereços de produto. O teto de páginas (`max_pages`) impede que um link "próxima" com defeito jogue o script em um laço sem fim. Rolagem infinita, botões "carregar mais", APIs baseadas em cursor e uma fila de URLs que retoma um rastreamento interrompido são assunto do artigo [paginação no web scraping](/pt-br/blog/pagination-web-scraping). Se preferir montar o mesmo trabalho sobre um framework pronto, veja [Scrapy e como usá-lo com proxy](/pt-br/blog/scrapy-proxy).

## Como consultar o histórico e agendar o script?

O menor e o maior preço dos últimos 30 dias saem de uma única consulta:

```sql
SELECT sku,
       MIN(price_cents) / 100.0 AS lowest,
       MAX(price_cents) / 100.0 AS highest,
       COUNT(*)                 AS readings
FROM prices
WHERE checked_at >= date('now', '-30 days')
GROUP BY sku
ORDER BY sku;
```

Essa tabela mostra quantos dias um desconto durou e se o preço anunciado como "promoção" era só o preço normal do mês anterior.

Para agendar, no Linux basta uma linha de `cron` (`0 */6 * * * python3 /opt/prices/price_tracker.py`, a cada seis horas); no Windows, o Agendador de Tarefas. Prefira a madrugada para as rodadas; o site do concorrente atende clientes durante o dia, assim como o seu.

## Por que o país de onde você olha faz diferença?

O preço e o estoque que uma loja exibe podem mudar conforme o país do visitante: moeda, impostos, região de entrega, campanhas regionais. Se o script roda em um servidor de nuvem em outro país, você pode estar registrando a página exibida para aquela localização, e não a que o seu cliente vê.

A solução é enviar a requisição do mesmo país do seu cliente. Com [Proxies residenciais](https://proxynet.io/pt-br/residential-proxy) você escolhe o país de saída; a lista de países disponíveis está na nossa página de [localizações de proxy](/pt-br/locations). Como a localização de um IP é determinada, e por que às vezes sai errada, está explicado em [qual é a precisão da geolocalização por IP](/pt-br/blog/ip-geolocation-accuracy). O segundo papel do proxy nesse trabalho é distribuir a carga por vários endereços quando se rastreia um grande número de produtos. A lógica da rotação está no nosso artigo sobre [rotação de IP](/pt-br/blog/ip-rotation-explained). A escolha entre proxies rotativos e de sessão fixa é respondida na seção de perguntas da nossa página de monitoramento de preços.

Proxy não é autorização. O limite de requisições do site e as regras do robots.txt valem do mesmo jeito, seja qual for o IP de onde a requisição sai.

## Dá para montar um aviso de estoque com o mesmo fluxo?

Sim. O script acima já registra a situação do estoque e avisa quando ela muda. O concorrente ficar sem estoque indica que você não precisa dar desconto naqueles dias; a volta do estoque é a hora de rever o preço.

A linha é esta: receber um aviso e comprar automaticamente não são a mesma coisa. Usar um bot para pegar produtos de quantidade limitada no instante em que entram em estoque e revendê-los prejudica os outros compradores, e a maioria das lojas proíbe isso nos termos. O fluxo deste artigo coleta informação e não encosta no carrinho. Por que agentes que automatizam a etapa de compra são bloqueados é o tema de [por que os agentes de compras com IA são bloqueados](/pt-br/blog/ai-shopping-agents-blocked).

## Limites: termos do site, robots.txt e direito da concorrência

Olhar o preço na vitrine do concorrente é tão antigo quanto o comércio. O que mantém o monitoramento automático legítimo é o método:

- **Somente páginas de produto públicas.** Áreas que exigem login, dados pessoais em avaliações de clientes e automação de contas ficam fora do escopo.
- **robots.txt e termos do site.** Leia os dois antes de rastrear. Os termos de uso dos marketplaces podem ter cláusulas que limitam o acesso automatizado; se houver uma cláusula assim, avalie a API oficial, uma parceria de dados ou um pedido de permissão. Como ler o arquivo está em [o que é o arquivo robots.txt](/pt-br/blog/robots-txt), e o quadro jurídico está em [web scraping é legal?](/pt-br/blog/is-data-web-scraping-legal).
- **Ritmo baixo e cache.** Espere entre as requisições e não peça a mesma página com mais frequência do que o ritmo das suas decisões exige.
- **Se aparecer uma tela de proteção, pare.** Uma página de verificação não é defeito, é uma resposta do site. Como esses sistemas funcionam está em [como funciona a detecção de bots](/pt-br/blog/how-bot-detection-works).

Há ainda o direito da concorrência. Acompanhar o preço público de um concorrente e definir o seu preço por conta própria é conduta comercial comum. Combinar preços com concorrentes, ou agir em conjunto trocando informações de preço, é outra coisa. No Brasil, o artigo 36 da [Lei nº 12.529/2011](https://www.planalto.gov.br/ccivil_03/_ato2011-2014/2011/lei/l12529.htm) inclui entre as infrações da ordem econômica acordar, combinar ou ajustar com concorrente os preços de bens ou serviços. Em Türkiye, o artigo 4 da [Lei nº 4054 de Proteção da Concorrência](https://www.mevzuat.gov.tr/mevzuatmetin/1.5.4054.pdf) traça a mesma linha, e a maioria das jurisdições tem uma regra equivalente. Se você está montando regras de precificação automática, converse sobre esse limite com um advogado.

## Casos de uso

- **Vendedores de marketplace:** O preço e o estoque de outros vendedores que oferecem o mesmo produto. As notas de infraestrutura por plataforma estão nas nossas páginas [Amazon Proxy](/pt-br/amazon-proxy), [Walmart Proxy](/pt-br/walmart-proxy) e [Alibaba Proxy](/pt-br/alibaba-proxy).
- **Marcas que vendem pelo próprio site:** Verificar se os revendedores autorizados seguem o preço sugerido. A montagem geral está na nossa página de [solução para e-commerce](/pt-br/e-commerce-proxy).
- **Equipes de dados:** Usar o histórico de preços como entrada para previsão de demanda e análise de campanhas. Como escalar a coleta está na nossa página de [extração de dados](/pt-br/data-scraping).

## Erros comuns

- **Guardar só o último preço.** Sem histórico você não vê quando um desconto começou, quantos dias durou nem se ele se repete.
- **Fazer o pareamento uma vez e esquecer.** O concorrente renova o produto, o endereço continua o mesmo e você compara o modelo antigo com o novo.
- **Tomar uma resposta `200` por um preço.** Uma tela de verificação ou uma página de "produto não encontrado" também pode devolver `200`. Uma checagem como a do `h1` no script é indispensável; se o campo de preço estiver vazio, não grave a linha.
- **Confundir vírgula e ponto.** `1.299,90` e `1,299.90` são o mesmo número. Teste a função de interpretação com exemplos reais do site de destino.
- **Igualar o preço do concorrente de forma automática e sem limite.** Quando duas regras automáticas trabalham uma contra a outra, o preço vai ao chão. O piso quem define é você, de acordo com o seu custo.

## Guia de decisão

| Necessidade | Recomendação |
|---|---|
| Manter o seu próprio preço e estoque atualizados | A API de vendedor do marketplace |
| 20-30 produtos, uma olhada semanal | Conferência manual e planilha |
| Centenas de produtos, sem equipe de desenvolvimento | Ferramenta pronta de monitoramento ou fluxo de automação |
| Sites específicos, data warehouse próprio, alertas flexíveis | Script próprio em Python e SQLite |
| Dezenas de milhares de produtos, leitura de hora em hora | Rastreador com fila (Scrapy), banco de dados em servidor, distribuição entre vários IPs |
| O preço muda conforme o país | Um IP que saia do país do seu cliente |
| O site mostra uma tela de verificação | Pare; reveja o ritmo, os termos e a opção da API oficial |

## Perguntas frequentes

### Monitorar preços da concorrência é legal?

Olhar o preço em uma página de produto pública e anotá-lo é atividade comercial comum. O problema aparece no método: acessar dados atrás de login, ignorar os termos do site ou o robots.txt, rastrear em um ritmo que sobrecarrega o servidor. Além disso, usar a informação coletada para combinar preços com concorrentes contraria o direito da concorrência.

### Dá para monitorar preços com Excel?

Para poucos produtos, sim. Uma planilha preenchida à mão ou o recurso do Excel de obter dados da web basta para começar. O limite aparece no histórico e no alerta: a planilha mostra a situação atual e não avisa da mudança. Quando o número de produtos passa de algumas dezenas, um banco de dados pequeno como o SQLite dá menos trabalho.

### A API do Mercado Livre entrega os preços dos concorrentes?

Em parte. As APIs de vendedor existem, antes de tudo, para gerenciar os dados de produto, estoque, preço e pedidos da sua própria loja. As referências de preços do Mercado Livre trazem uma sugestão para os seus anúncios, baseada em produtos semelhantes; não há um endpoint para o histórico de preços de um concorrente, para o estoque dele ou para os preços dele em outros sites. Confira na documentação de integração atual o que cada marketplace oferece. O trabalho principal dessas APIs é ler o seu preço atual e gravar a decisão de preço de volta na sua loja.

### Quantas vezes por dia devo fazer a leitura?

Tantas quantas forem as suas decisões de preço. Para a maioria dos catálogos, uma leitura por dia basta; nos mais vendidos em período de campanha sobe-se para algumas rodadas por dia, e os produtos de giro lento caem para uma por semana.

### Preciso de proxy para monitorar preços?

Para uma lista pequena e frequência baixa, não. Ele é necessário em dois casos: quando o preço muda conforme o país e o script roda em um país diferente do do seu cliente, ou quando o número de produtos é grande a ponto de tornar problemático enviar todas as requisições de um único endereço. Qual tipo de IP combina com cada trabalho está comparado na nossa página de [monitoramento de preços](/pt-br/price-monitoring).

### De onde leio o preço se a página não tem JSON-LD?

Primeiro veja no código-fonte da página se o preço está no HTML puro; se estiver, escreva um seletor como o do exemplo e, quando possível, apoie-se em uma estrutura mais estável, como a tabela de informações do produto, em vez de um nome de classe. Se o preço não aparece no código-fonte, a página carrega os dados depois. Nesse caso, encontrar na aba de rede do navegador a requisição de onde os dados vêm é uma solução mais leve do que rodar um navegador headless.

## Em resumo

O monitoramento de preços da concorrência não é um software, e sim um fluxo: uma lista de produtos bem pareada, uma frequência de leitura compatível com o ritmo das suas decisões, uma tabela de histórico com data e alertas poucos, mas com significado. Pegue os dados do seu lado na API de vendedor; do lado do concorrente, fique nas páginas públicas, no robots.txt e no ritmo baixo. Um script Python de umas 150 linhas e um banco SQLite de um único arquivo dão conta desse trabalho para a maioria dos catálogos. Quando a escala crescer e você precisar ver o preço a partir do país do seu cliente, as opções de infraestrutura estão na nossa página de [monitoramento de preços](/pt-br/price-monitoring).
