Extracción de products.json de Shopify: El Endpoint que Cada Tienda Expone
Olvídate de analizar HTML. Cada tienda de Shopify te ofrece JSON limpio en /products.json: catálogo completo, precios, variantes, stock. Aquí están los límites de paginación, los trucos de velocidad y cómo convertirlo en monitoreo de competidores.
Cualquiera que haya extraído datos de comercio electrónico conoce el dolor: selectores CSS frágiles, divs anidados, diseños que cambian y rompen todo de la noche a la mañana. Shopify te ofrece una salida. Casi todas las tiendas construidas en Shopify exponen un endpoint público /products.json que devuelve el catálogo completo como JSON limpio y estructurado: títulos, handles, proveedores, etiquetas, variantes, precios, indicadores de stock e imágenes. Sin análisis de HTML, sin navegador sin cabeza. Esta guía cubre cómo funciona el endpoint, sus verdaderos límites de paginación, un truco que hace que la extracción de grandes tiendas sea dramáticamente más rápida y cómo convertir todo esto en monitoreo de precios y stock de competidores.
El endpoint en cada tienda de Shopify
Añade /products.json al dominio raíz de cualquier tienda de Shopify y obtendrás una lista JSON de productos. Es la misma información que utiliza la tienda, expuesta por diseño para el Ajax API. Cada producto lleva un id numérico estable, un handle, vendor, product_type, tags, un array de variants (cada uno con su propio precio, SKU y un booleano available), e imágenes. Eso es todo lo que normalmente extraerías de una página de producto, entregado en una sola solicitud.
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"])
Dos advertencias al principio. Shopify limita el endpoint público a 250 productos por página, un límite que no puedes exceder sin importar lo que pases, así que ignora el consejo de establecer limit=1000000 y obtener todo en una sola llamada. Y una minoría de tiendas desactivan el endpoint (algunas construcciones personalizadas a veces lo apagan), así que verifica una respuesta válida antes de construir un pipeline alrededor de él.
Paginar hasta el final
Debido al límite de 250, un catálogo completo significa recorrer páginas hasta que encuentres una vacía. El bucle ingenuo incrementa page y se detiene cuando una página regresa vacía. Es correcto y está bien para tiendas pequeñas: una tienda con unos pocos cientos de productos son un par de solicitudes.
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

El truco de 25x: encontrar la última página primero
La paginación secuencial es lenta en tiendas grandes porque no puedes paralelizar: no sabes cuándo detenerte, así que cada página espera a la anterior. La solución es una búsqueda binaria: sondea números de página para encontrar la última página no vacía, luego lanza todas las solicitudes de página de manera concurrente. En un benchmark público contra una tienda con 25,000 productos en 833 páginas, esto redujo una extracción de aproximadamente 120 segundos a unos 12 en la primera ejecución y alrededor de 5 una vez que se almacenó en caché el número de la última página: una aceleración de 25x. Dirige las sondas a través de IPs rotativas para que el estallido de solicitudes concurrentes no active el límite de velocidad.
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 dijo Rob Pike, los algoritmos sofisticados son lentos cuando n es pequeño: para una tienda de 200 productos, omite la búsqueda binaria y simplemente haz un bucle. Se justifica en catálogos de miles, donde la paginación secuencial se arrastra.
Reducir la extracción: colecciones y productos individuales
No siempre quieres todo el catálogo. Shopify expone el mismo JSON a nivel de colección: /collections/<handle>/products.json devuelve solo los productos en esa colección, paginados de la misma manera. Ese es el camino eficiente cuando solo rastreas una categoría: zapatillas, fragancias, una sola marca, en lugar de una tienda completa. Y para inspeccionar un producto, añade .json a su URL: /products/<handle>.json da el registro completo de ese producto, incluyendo cada variante y su indicador de inventario, lo cual es útil para un sondeo ajustado de reabastecimiento en un SKU específico sin volver a extraer el catálogo.
Combinar los dos mantiene el volumen de solicitudes —y el ancho de banda— bajo. Descubre el catálogo una vez con el endpoint completo, almacena los handles que te interesan, luego sondea productos individuales o colecciones en un horario ajustado. Ese patrón es la diferencia entre un monitor que escala a cientos de tiendas y uno que quema silenciosamente tu presupuesto de proxy volviendo a descargar catálogos que no han cambiado.
Conviértelo en monitoreo de competidores
El verdadero valor no es un volcado de catálogo único, es la diferencia a lo largo del tiempo. Haz una instantánea de products.json de un competidor en un horario, clave por id de variante, y compara ejecuciones para detectar cambios de precio, nuevos productos y reabastecimientos en el momento en que ocurren. Porque available y price viven en cada variante, obtienes señales de stock y precios sin tocar una página de producto.
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 es el pilar de monitoreo de precios de competidores e investigación de dropshipping, ambos se apoyan en el mismo patrón de instantánea y diferencia a través de muchas tiendas a la vez.
Obtén proxies de centro de datos rápidos para extracción de Shopify

Qué proxies realmente necesitas
El endpoint products.json es JSON público, no un flujo de pago endurecido, por lo que es indulgente, pero si extraes cientos de tiendas o golpeas una en un horario, alcanzarás límites de velocidad por IP. La respuesta económica son proxies de centro de datos rápidos con rotación: baratos, rápidos y suficientes para distribuir solicitudes a través de IPs para que ninguna sola sea limitada. Reserva IPs residenciales para tiendas que bloquean rangos de centros de datos por completo. Si una tienda ha deshabilitado products.json y oculta su catálogo detrás de páginas renderizadas o protección contra bots, una Scraper API que renderiza y rota por ti es la alternativa más limpia. Nuestra guía sobre cuándo ganan los proxies de centro de datos cubre la decisión.
Preguntas frecuentes
¿Cómo obtengo todos los productos de una tienda de Shopify como JSON?
Solicita /products.json en el dominio de la tienda con ?limit=250&page=N e incrementa page hasta que una página devuelva un array de productos vacío. Cada respuesta contiene hasta 250 productos con sus variantes, precios, SKUs e indicadores de stock. Para catálogos grandes, busca binariamente la última página y obtén páginas de manera concurrente.
¿Cuál es el límite en Shopify products.json?
El endpoint público está limitado a 250 productos por página, el valor más alto que acepta limit. Pasar un número mayor no devolverá más; aún debes paginar a través del catálogo. Este es un límite estricto de Shopify, así que planifica la paginación en lugar de intentar obtener todo en una sola solicitud.
¿Es legal extraer datos de Shopify products.json?
El endpoint sirve datos de productos públicamente disponibles sin necesidad de inicio de sesión, y los tribunales de EE.UU. generalmente han respaldado la extracción de datos públicos. Dicho esto, respeta los términos de servicio de la tienda, evita los datos personales y no sobrecargues el servidor. Esta es información general, no asesoramiento legal: verifica los detalles para tu caso de uso y jurisdicción.
¿Por qué products.json devuelve un 404 o una respuesta vacía?
O la tienda no está en Shopify, o el comerciante ha deshabilitado el endpoint en una construcción personalizada. Algunas tiendas también limitan las solicitudes repetidas desde una IP, lo que puede parecer un error. Confirma que la tienda es de Shopify, rota tu IP y añade un retraso entre solicitudes antes de asumir que el endpoint se ha ido.
El endpoint products.json convierte la extracción de Shopify de una tarea de manejo de selectores en una extracción limpia de JSON: catálogo completo, precios y stock en una URL, 250 por página, rápido de extraer con una búsqueda binaria y trivial de diferenciar en monitoreo de competidores. Descubre una vez, sondea las colecciones y productos que importan, distribuye solicitudes a través de IPs rotativas de centro de datos, y puedes rastrear cientos de tiendas en un horario sin una sola ejecución bloqueada: sin analizador de HTML, sin navegador sin cabeza, sin selectores frágiles que cuidar.