Raspagem de products.json do Shopify: O Endpoint Que Toda Loja Exibe
Esqueça a análise de HTML. Toda loja Shopify oferece JSON limpo em /products.json — catálogo completo, preços, variantes, estoque. Aqui estão os limites de paginação, truques de velocidade e como transformá-lo em monitoramento de concorrentes.
Qualquer pessoa que já raspou e-commerce conhece a dor: seletores CSS frágeis, divs aninhados, layouts que mudam e quebram tudo da noite para o dia. Shopify oferece uma saída. Quase toda loja construída no Shopify expõe um endpoint público /products.json que retorna o catálogo inteiro como JSON limpo e estruturado — títulos, identificadores, fornecedores, tags, variantes, preços, indicadores de estoque e imagens. Sem análise de HTML, sem navegador sem cabeça. Este guia cobre como o endpoint funciona, seus limites reais de paginação, um truque que torna a raspagem de grandes lojas dramaticamente mais rápida e como transformar tudo isso em monitoramento de preços e estoque de concorrentes.
O endpoint em toda loja Shopify
Adicione /products.json ao domínio raiz de qualquer loja Shopify e você obtém uma lista JSON de produtos. É o mesmo dado que a vitrine usa, exposto por design para a Ajax API. Cada produto possui um id numérico estável, um handle, vendor, product_type, tags, um array de variants (cada um com seu próprio preço, SKU e booleano available), e imagens. Isso é tudo que você normalmente rasparia de uma página de produto, entregue em uma única solicitação.
import requests
url = "https://store.example.com/products.json"
r = requests.get(url, params={"limit": 250, "page": 1}, timeout=15)
products = r.json()["products"]
print(len(products), products[0]["title"])
for v in products[0]["variants"]:
print(v["sku"], v["price"], v["available"])
Duas ressalvas de início. Shopify limita o endpoint público a 250 produtos por página — um limite que você não pode exceder, não importa o que você passe, então ignore conselhos para definir limit=1000000 e pegar tudo em uma chamada. E uma minoria de lojas desativa o endpoint (construções personalizadas às vezes o desligam), então verifique uma resposta válida antes de construir um pipeline em torno disso.
Paginar até o fim
Devido ao limite de 250, um catálogo completo significa percorrer páginas até encontrar uma vazia. O loop ingênuo incrementa page e para quando uma página retorna vazia. Está correto e é adequado para lojas pequenas — uma loja com algumas centenas de produtos requer apenas algumas solicitações.
def all_products(base):
page, out = 1, []
while True:
r = requests.get(f"{base}/products.json",
params={"limit": 250, "page": page}, timeout=15)
batch = r.json()["products"]
if not batch:
break
out.extend(batch)
page += 1
return out

O truque 25x: encontre a última página primeiro
A paginação sequencial é lenta em grandes lojas porque você não pode paralelizar — você não sabe quando parar, então cada página espera pela anterior. A solução é uma busca binária: sonde números de página para encontrar a última página não vazia, depois dispare todas as solicitações de página simultaneamente. Em um benchmark público contra uma loja com 25.000 produtos em 833 páginas, isso reduziu uma raspagem de aproximadamente 120 segundos para cerca de 12 na primeira execução e cerca de 5 uma vez que o número da última página foi armazenado em cache — um aumento de velocidade de 25x. Direcione as sondas por IPs rotativos para que o surto de solicitações simultâneas não acione o limite de taxa.
PROXY = "http://USER:PASS@gate.quantumproxies.io:8000"
proxies = {"http": PROXY, "https": PROXY}
def last_page(base, hi=1000):
lo, last = 1, 1
while lo <= hi:
mid = (lo + hi) // 2
r = requests.get(f"{base}/products.json",
params={"limit": 250, "page": mid},
proxies=proxies, timeout=15)
if r.json()["products"]:
last, lo = mid, mid + 1 # go higher
else:
hi = mid - 1 # go lower
return last
# then request pages 1..last_page concurrently
Como Rob Pike disse, algoritmos sofisticados são lentos quando n é pequeno — para uma loja com 200 produtos, pule a busca binária e apenas faça o loop. Ele se paga em catálogos de milhares, onde a paginação sequencial se arrasta.
Reduza a busca: coleções e produtos individuais
Você nem sempre quer o catálogo inteiro. Shopify expõe o mesmo JSON no nível da coleção: /collections/<handle>/products.json retorna apenas os produtos naquela coleção, paginados da mesma forma. Esse é o caminho eficiente quando você só rastreia uma categoria — tênis, fragrâncias, uma única marca — em vez de uma loja inteira. E para inspecionar um produto, adicione .json ao seu URL: /products/<handle>.json fornece o registro completo daquele produto, incluindo cada variante e seu indicador de inventário, o que é útil para monitoramento rigoroso de reabastecimento em um SKU específico sem re-raspar o catálogo.
Combinar os dois mantém o volume de solicitações — e a largura de banda — baixos. Descubra o catálogo uma vez com o endpoint completo, armazene os identificadores que importam para você, depois sonde produtos ou coleções individuais em um cronograma apertado. Esse padrão é a diferença entre um monitor que escala para centenas de lojas e um que silenciosamente consome seu orçamento de proxy re-baixando catálogos que não mudaram.
Transforme em monitoramento de concorrentes
O verdadeiro valor não é um despejo de catálogo único — é a diferença ao longo do tempo. Faça um snapshot do products.json de um concorrente em um cronograma, chave por id de variante, e compare execuções para capturar alterações de preço, novos produtos e reabastecimentos no momento em que acontecem. Como available e price vivem em cada variante, você obtém sinais de estoque e preços sem tocar em uma página de produto.
def snapshot(base):
rows = {}
for p in all_products(base):
for v in p["variants"]:
rows[v["id"]] = {
"product": p["title"],
"sku": v["sku"],
"price": v["price"],
"available": v["available"],
}
return rows
# diff today's snapshot against yesterday's to flag price + stock moves
def changes(old, new):
for vid, cur in new.items():
prev = old.get(vid)
if prev and (prev["price"] != cur["price"] or prev["available"] != cur["available"]):
yield cur["sku"], prev, cur
Este é o alicerce do monitoramento de preços de concorrentes e da pesquisa de dropshipping — ambos se baseiam no mesmo padrão de snapshot e diferença em várias lojas de uma vez.
Obtenha proxies de datacenter rápidos para raspagem de Shopify

Quais proxies você realmente precisa
O endpoint products.json é JSON público, não um fluxo de checkout reforçado, então é tolerante — mas raspe centenas de lojas ou ataque uma em um cronograma e você atingirá limites de taxa por IP. A resposta econômica são proxies de datacenter rápidos com rotação: baratos, rápidos e suficientes para distribuir solicitações por IPs para que nenhum único seja limitado. Reserve IPs residenciais para lojas que bloqueiam intervalos de datacenter completamente. Se uma loja desativou products.json e esconde seu catálogo atrás de páginas renderizadas ou proteção contra bots, uma Scraper API que renderiza e rotaciona para você é a alternativa mais limpa. Nosso guia sobre quando os proxies de datacenter vencem cobre a decisão.
Perguntas frequentes
Como obtenho todos os produtos de uma loja Shopify como JSON?
Solicite /products.json no domínio da loja com ?limit=250&page=N e incremente page até que uma página retorne um array de produtos vazio. Cada resposta contém até 250 produtos com suas variantes, preços, SKUs e indicadores de estoque. Para catálogos grandes, faça uma busca binária na última página e busque páginas simultaneamente.
Qual é o limite no Shopify products.json?
O endpoint público é limitado a 250 produtos por página — o maior valor que limit aceita. Passar um número maior não retornará mais; você ainda terá que paginar pelo catálogo. Este é um limite rígido do Shopify, então planeje a paginação em vez de tentar puxar tudo em uma solicitação.
É legal raspar Shopify products.json?
O endpoint serve dados de produtos publicamente disponíveis sem login, e os tribunais dos EUA geralmente têm apoiado a raspagem de dados públicos. Dito isso, respeite os termos de serviço da loja, evite dados pessoais e não sobrecarregue o servidor. Esta é uma informação geral, não um conselho jurídico — verifique os detalhes para seu caso de uso e jurisdição.
Por que products.json está retornando um 404 ou resposta vazia?
Ou a loja não está no Shopify, ou o comerciante desativou o endpoint em uma construção personalizada. Algumas lojas também limitam solicitações repetidas de um IP, o que pode parecer um erro. Confirme se a loja é Shopify, rotacione seu IP e adicione um atraso entre as solicitações antes de assumir que o endpoint se foi.
O endpoint products.json transforma a raspagem de Shopify de uma tarefa de manipulação de seletores em uma extração de JSON limpa: catálogo completo, preços e estoque em uma URL, 250 por página, rápido para raspar com uma busca binária, e trivial para diferenciar em monitoramento de concorrentes. Descubra uma vez, sonde as coleções e produtos que importam, distribua solicitações por IPs de datacenter rotativos, e você pode rastrear centenas de lojas em um cronograma sem uma única execução bloqueada — sem parser de HTML, sem navegador sem cabeça, sem seletores frágeis para cuidar.