Automatiza tu investigación de mercado: extrae datos de Shopify con Python

Última actualización: April 16, 2026

El endpoint /products.json de Shopify es uno de esos secretos a voces del ecommerce. Solo tienes que añadirlo a la URL de cualquier tienda Shopify y obtienes JSON estructurado de vuelta: sin claves API, sin autenticación y sin tener que extraer datos de un HTML lleno de capas.

Trabajo en el equipo del , así que paso bastante tiempo pensando en cómo la gente obtiene datos de la web. Y el scraping de Shopify aparece una y otra vez: equipos de ventas que siguen precios de la competencia, operaciones de ecommerce comparando catálogos de productos, y equipos de compras buscando nuevos proveedores. Con en Shopify y una cuota cercana al , el volumen de datos de producto que se puede extraer es enorme.

Esta guía cubre todo el proceso: qué devuelve el endpoint, cómo recorrer miles de productos con paginación, cómo manejar los límites de solicitudes sin ser bloqueado y cómo convertir el JSON anidado de Shopify en un CSV o archivo de Excel limpio usando pandas. También explicaré los endpoints que casi nadie menciona (/collections.json, /meta.json) y mostraré una alternativa sin código para quienes prefieran evitar Python por completo.

¿Qué es el endpoint /products.json de Shopify y por qué facilita tanto el scraping?

Todas las tiendas Shopify tienen un endpoint público en {store-url}/products.json que devuelve datos estructurados de productos. Sin claves API. Sin OAuth. Sin ningún tipo de autenticación. Literalmente solo añades /products.json a la URL de la tienda y recibes un array JSON con todos los productos del catálogo.

Pruébalo ahora mismo: abre o en tu navegador. Verás JSON limpio y estructurado con títulos, precios, variantes, imágenes, etiquetas... todo.

Compáralo con la alternativa: analizar los temas HTML de Shopify, que suelen estar profundamente anidados, varían de una tienda a otra y cambian cada vez que el comerciante actualiza el tema. Esto es con lo que tendrías que lidiar:

Enfoque HTML (doloroso):

1<div class="product-card__info">
2  <h3 class="product-card__title">
3    <a href="/products/classic-blue-jeans">Classic Blue Jeans</a>
4  </h3>
5  <span class="price price--on-sale" data-product-price>$149.00</span>
6</div>

Enfoque JSON (limpio):

1{
2  "title": "Classic Blue Jeans",
3  "handle": "classic-blue-jeans",
4  "vendor": "Hiut Denim",
5  "variants": [{"price": "149.00", "sku": "HD-BLU-32", "available": true}]
6}

JSON gana en consistencia, fiabilidad y facilidad de análisis. Además, el endpoint admite dos parámetros clave: ?limit= (hasta 250 productos por página; el valor predeterminado es 30) y ?page= para la paginación, que usaremos mucho en el código más abajo.

Importante: este es un endpoint público de la tienda, no la . La Admin API requiere tokens de acceso del propietario de la tienda y proporciona datos de pedidos, niveles de inventario e información de clientes. El endpoint público /products.json solo ofrece datos de productos de solo lectura a los que cualquiera puede acceder. Más adelante explicaré bien la diferencia, porque en foros hay mucha confusión al respecto.

Matiz importante: no todas las tiendas Shopify exponen este endpoint. En mis pruebas, alrededor del 71% de las tiendas devuelven JSON válido (allbirds.com, gymshark.com, colourpop.com, kyliecosmetics.com funcionan), mientras que algunas configuraciones personalizadas devuelven un 404 (hiutdenim.co.uk, bombas.com). La comprobación rápida es sencilla: visita {store-url}/products.json en tu navegador y mira qué obtienes.

¿Por qué extraer datos de Shopify con Python? Principales casos de uso empresarial

¿Para qué hacerlo? Por el ROI. ya usa scraping automatizado de precios para inteligencia competitiva, frente al 34% en 2020. Y la investigación muestra que una . Los datos valen dinero de verdad.

Estos son los casos de uso más comunes que veo:

Caso de usoQuién se beneficiaQué obtienes
Seguimiento de precios de la competenciaEquipos de operaciones de ecommerceVigilar cambios de precio, descuentos y precios comparados en catálogos rivales
Investigación de productos y búsqueda de proveedoresCompras / merchandisingComparar características, variantes, materiales y disponibilidad de productos
Generación de leadsEquipos de ventasExtraer nombres de proveedores, datos de marca e información de contacto de catálogos
Análisis de mercado y categoríasEquipos de marketingEntender mezcla de productos, etiquetas, estructura de colecciones y posicionamiento
Seguimiento de inventario y disponibilidadEquipos de cadena de suministroMonitorizar el estado de stock por variante (available: true/false) a lo largo del tiempo
Detección de nuevos productosEquipos de productoSeguir marcas de tiempo created_at para detectar lanzamientos nuevos de la competencia

Python encaja de forma natural para este trabajo. usan Python como lenguaje principal, y su ecosistema —requests para HTTP, pandas para manipulación de datos, httpx para asincronía— hace muy sencillo pasar de “tengo una URL” a “tengo una hoja de cálculo” en menos de 80 líneas de código.

Referencia completa de campos de products.json: explicación de cada campo

Todos los tutoriales de la competencia te enseñan title, id y handle, y luego siguen adelante. La respuesta JSON de Shopify contiene más de 40 campos entre productos, variantes, imágenes y opciones. Saber qué está disponible antes de escribir el scraper te ahorra tener que volver a extraer datos después.

Tomé esta referencia de respuestas reales de /products.json obtenidas el 16 de abril de 2026. La estructura es consistente en todas las tiendas que exponen el endpoint.

Campos a nivel de producto

CampoTipo de datoValor de ejemploUso empresarial
idEntero123456789Identificador único del producto para deduplicación
titleCadena"Classic Blue Jeans"Nombre del producto para catálogos y comparaciones
handleCadena"classic-blue-jeans"Slug de URL: construye enlaces como {store}/products/{handle}
body_htmlCadena (HTML) o null

Our best-selling...

Descripción del producto para análisis de contenido e investigación SEO
vendorCadena"Hiut Denim"Nombre de marca/proveedor para generación de leads o sourcing
product_typeCadena"Jeans"Clasificación de categoría para análisis de mercado
created_atFecha y hora ISO"2024-01-15T10:30:00-05:00"Saber cuándo se añadió el producto (detección de nuevos lanzamientos)
updated_atFecha y hora ISO"2025-03-01T08:00:00-05:00"Detectar cambios recientes en el catálogo
published_atFecha y hora ISO"2024-01-16T00:00:00-05:00"Saber cuándo el producto salió a la tienda pública
tagsArray de cadenas["organic", "women", "straight-leg"]Análisis de palabras clave/etiquetas para SEO, categorización y detección de tendencias
variantsArray de objetos(ver campos de variantes abajo)Precio, SKU y disponibilidad por variante
imagesArray de objetos(ver campos de imágenes abajo)URLs de imágenes para catálogos y análisis visual
optionsArray de objetos[{"name": "Size", "values": ["S","M","L"]}]Entender la configuración del producto (talla, color, material)

Campos a nivel de variante (anidados dentro de cada producto)

CampoTipo de datoEjemploUso
idEntero987654321Identificador único de la variante
titleCadena"32 / Blue"Nombre visible de la variante
skuCadena"HD-BLU-32"Coincidencia de SKU para sistemas de inventario
priceCadena"185.00"Seguimiento de precios (ojo: es una cadena; conviértela a float para cálculos)
compare_at_priceCadena o null"200.00"Precio original: esencial para seguir descuentos
availableBooleanotrueDisponibilidad de stock (el único indicador público de stock)
weightFlotante1.2Análisis de envío y logística
option1, option2, option3Cadena"32", "Blue", nullValores individuales de opciones
created_at, updated_atFecha y hora ISOSeguimiento de cambios a nivel de variante

Campos a nivel de imagen

CampoTipo de datoEjemploUso
idEntero111222333Identificador único de la imagen
srcCadena (URL)"https://cdn.shopify.com/..."Enlace directo para descargar la imagen
altCadena o null"Front view of jeans"Texto alternativo para análisis de accesibilidad
positionEntero1Orden de las imágenes
width, heightEntero2048, 2048Dimensiones de la imagen

Lo que NO está en el endpoint público

Un detalle crítico: inventory_quantity NO está disponible en las respuestas públicas de /products.json. Este campo se eliminó de los endpoints JSON públicos en diciembre de 2017 por motivos de seguridad. El único indicador de stock que obtienes es el campo booleano available de cada variante (true o false). Para acceder a cantidades reales de inventario, necesitas la Admin API autenticada con credenciales del propietario de la tienda.

Antes de escribir tu scraper, revisa esta tabla y decide qué campos te importan según tu caso de uso. Si haces seguimiento de precios, necesitas variants[].price, variants[].compare_at_price y variants[].available. Si buscas leads, céntrate en vendor, product_type y tags. Filtra en consecuencia: tu CSV quedará mucho más limpio.

Más allá de products.json: collections, meta y otros endpoints de Shopify

Ningún tutorial de la competencia menciona estos endpoints. Son esenciales para un trabajo serio de inteligencia competitiva.

/collections.json — todas las categorías de la tienda

Devuelve todas las colecciones (categorías) de la tienda con títulos, handles, descripciones y número de productos. Lo comprobé en zoologistperfumes.com, allbirds.com y gymshark.com: todos devolvieron JSON válido.

1{
2  "collections": [
3    {
4      "id": 308387348539,
5      "title": "Attars",
6      "handle": "attars",
7      "published_at": "2026-03-29T12:20:32-04:00",
8      "products_count": 1,
9      "image": { "src": "https://cdn.shopify.com/..." }
10    }
11  ]
12}

¿Quieres entender cómo organiza su catálogo un competidor? Este es el endpoint que necesitas.

/collections/{handle}/products.json — productos por categoría

Devuelve productos filtrados por una colección específica. Usa la misma estructura JSON que /products.json, pero limitado a una sola categoría. Esto es clave para scraping a nivel de categoría, por ejemplo si solo quieres monitorizar la colección “Sale” o “New Arrivals” de un competidor.

/meta.json — metadatos a nivel de tienda

Devuelve el nombre de la tienda, descripción, moneda, país y, aquí viene lo bueno, published_products_count. Ese número te permite calcular exactamente cuántas páginas de paginación necesitas: ceil(published_products_count / 250). Ya no hace falta seguir aumentando páginas a ciegas hasta recibir una respuesta vacía.

¿Qué endpoint deberías usar?

Lo que buscasEndpoint¿Requiere autenticación?
Todos los productos (público)/products.jsonNo
Productos de una categoría concreta/collections/{handle}/products.jsonNo
Metadatos de la tienda + número de productos/meta.jsonNo
Todas las colecciones (categorías)/collections.jsonNo
Datos de pedidos/ventas (solo tu tienda)Admin API /orders.jsonSí (clave API)
Cantidades de inventario (solo tu tienda)Admin API /inventory_levels.json

La pregunta que se repite en foros —“¿Puedo extraer cuántas unidades vendió un competidor?”— tiene una respuesta corta: no. No desde endpoints públicos. Los datos de ventas y las cantidades de inventario requieren la Admin API autenticada, lo que significa que necesitas acceso del propietario de la tienda. Los endpoints públicos solo te dan datos del catálogo de productos.

shopify-data-access-methods.webp

Cómo extraer datos de Shopify con Python: configuración paso a paso

  • Dificultad: Principiante
  • Tiempo necesario: ~15 minutos (configuración + primera extracción)
  • Lo que necesitas: Python 3.11+, pip, una terminal y la URL de una tienda Shopify para extraer datos

Paso 1: instala Python y las librerías necesarias

Asegúrate de tener instalado Python 3.11 o una versión superior (pandas 3.0.x lo requiere). Luego instala las dos librerías que vamos a usar:

1pip install requests pandas

Para exportar a Excel, también te conviene instalar:

1pip install openpyxl

Al principio de tu script, añade estas importaciones:

1import requests
2import pandas as pd
3import time
4import random
5import json

No deberías ver errores de importación al ejecutar el script. Si pandas lanza un error de versión, actualiza Python a 3.12.

Paso 2: obtener datos de productos desde /products.json

Aquí tienes una función básica que recibe la URL de una tienda, llama al endpoint y devuelve el JSON analizado:

1def fetch_products_page(store_url, page=1, limit=250):
2    """Obtener una sola página de productos de una tienda Shopify."""
3    url = f"{store_url.rstrip('/')}/products.json"
4    params = {"limit": limit, "page": page}
5    headers = {
6        "User-Agent": "Mozilla/5.0 (compatible; ProductResearch/1.0)"
7    }
8    response = requests.get(url, params=params, headers=headers, timeout=30)
9    response.raise_for_status()
10    return response.json().get("products", [])

Detalles clave:

  • limit=250 es el máximo que Shopify permite por página. El valor predeterminado es 30, así que fijarlo explícitamente reduce tus solicitudes totales hasta 8 veces.
  • Encabezado User-Agent: usa siempre uno realista. Las solicitudes sin User-Agent tienen más probabilidades de activar los sistemas anti-bot de Shopify.
  • timeout=30: evita que una solicitud se quede colgada indefinidamente.

Pruébalo con una tienda conocida:

1products = fetch_products_page("https://allbirds.com")
2print(f"Fetched {len(products)} products")
3print(f"First product: {products[0]['title']}")

Deberías ver algo como: Fetched 250 products y el título del primer producto.

Paso 3: manejar la paginación para extraer todos los productos

Una sola solicitud devuelve como máximo 250 productos. La mayoría de las tiendas tienen más que eso (Allbirds tiene más de 1.420). Necesitas recorrer las páginas hasta recibir una respuesta vacía.

1def scrape_all_products(store_url, delay=1.0):
2    """Extraer todos los productos de una tienda Shopify, manejando la paginación."""
3    all_products = []
4    page = 1
5    while True:
6        print(f"Fetching page {page}...")
7        products = fetch_products_page(store_url, page=page, limit=250)
8        if not products:
9            print(f"No more products. Total: {len(all_products)}")
10            break
11        all_products.extend(products)
12        print(f"  Got {len(products)} products (total so far: {len(all_products)})")
13        page += 1
14        # Sé prudente: espera entre solicitudes
15        time.sleep(delay + random.uniform(0, 0.5))
16    return all_products

Cuando products vuelva vacío, habrás llegado al final.

El time.sleep() con un pequeño jitter aleatorio te mantiene por debajo del límite informal de Shopify (~2 solicitudes por segundo).

Consejo pro: si primero consultas /meta.json, ya sabes el número total de productos y puedes calcular exactamente cuántas páginas necesitas: pages = ceil(product_count / 250). Así evitas el patrón de “una petición vacía extra al final”.

Paso 4: analizar y seleccionar los campos que necesitas

Ahora que tienes todos los productos como una lista de diccionarios en Python, extrae solo los campos que te interesan. Aquí tienes un ejemplo que toma los campos más habituales para seguimiento de precios:

1def extract_product_data(products):
2    """Extraer campos clave de los productos, aplanando las variantes."""
3    rows = []
4    for product in products:
5        for variant in product.get("variants", []):
6            rows.append({
7                "product_id": product["id"],
8                "title": product["title"],
9                "handle": product["handle"],
10                "vendor": product.get("vendor", ""),
11                "product_type": product.get("product_type", ""),
12                "tags": ", ".join(product.get("tags", [])),
13                "created_at": product.get("created_at", ""),
14                "variant_id": variant["id"],
15                "variant_title": variant.get("title", ""),
16                "sku": variant.get("sku", ""),
17                "price": variant.get("price", ""),
18                "compare_at_price": variant.get("compare_at_price", ""),
19                "available": variant.get("available", ""),
20                "image_url": product["images"][0]["src"] if product.get("images") else ""
21            })
22    return rows

Esto crea una fila por variante, que es el formato más útil para comparar precios, ya que un solo producto como “Classic Blue Jeans” puede tener 12 variantes (6 tallas × 2 colores), cada una con su propio precio y estado de disponibilidad.

Exporta los datos de Shopify a CSV y Excel con pandas

Todos los demás tutoriales de scraping de Shopify vuelcan el JSON en bruto a un archivo y dan el tema por cerrado. Bien para desarrolladores. Inútil para el analista de ecommerce que necesita una hoja de cálculo para el viernes.

El problema es que el JSON de Shopify está anidado. Un producto puede incluir una docena de variantes, cada una con su propio precio, SKU y disponibilidad. Aplanar eso en filas y columnas requiere algo de trabajo con pandas.

Convierte el JSON anidado en una tabla limpia

Hay dos enfoques, según tu caso de uso:

Opción A: una fila por variante (la mejor para seguimiento de precios e inventario)

1# Usando la función extract_product_data del Paso 4
2products = scrape_all_products("https://allbirds.com")
3rows = extract_product_data(products)
4df = pd.DataFrame(rows)
5print(f"DataFrame shape: {df.shape}")
6print(df.head())

Esto te da una tabla plana en la que cada fila es una combinación única de producto y variante. Una tienda con 500 productos y un promedio de 4 variantes por producto genera un DataFrame de unas 2.000 filas.

Opción B: una fila por producto resumido (la mejor para vistas generales del catálogo)

1def summarize_products(products):
2    """Una fila por producto con precio mínimo y máximo entre variantes."""
3    rows = []
4    for product in products:
5        prices = [float(v["price"]) for v in product.get("variants", []) if v.get("price")]
6        rows.append({
7            "product_id": product["id"],
8            "title": product["title"],
9            "vendor": product.get("vendor", ""),
10            "product_type": product.get("product_type", ""),
11            "variant_count": len(product.get("variants", [])),
12            "min_price": min(prices) if prices else None,
13            "max_price": max(prices) if prices else None,
14            "any_available": any(v.get("available", False) for v in product.get("variants", [])),
15            "tags": ", ".join(product.get("tags", []))
16        })
17    return rows

Exportar a CSV, Excel y Google Sheets

1# Exportación a CSV (usa utf-8-sig para que Excel maneje bien los caracteres especiales)
2df.to_csv("shopify_products.csv", index=False, encoding="utf-8-sig")
3# Exportación a Excel (requiere openpyxl)
4df.to_excel("shopify_products.xlsx", index=False, engine="openpyxl")
5print("Exported to shopify_products.csv and shopify_products.xlsx")

Para Google Sheets, puedes usar la biblioteca gspread con una cuenta de servicio, pero sinceramente, para la mayoría de los casos, exportar a CSV y subirlo a Google Drive es más rápido y simple.

Scraping en Python listo para producción: límites de frecuencia, reintentos y anti-bloqueo

El script básico funciona bien con tiendas pequeñas. ¿Pero extraer datos de una tienda con más de 5.000 productos o procesar varias tiendas en secuencia? Ahí es donde empiezan los problemas.

Entender los límites de frecuencia y el comportamiento de bloqueo de Shopify

Los endpoints JSON públicos de Shopify no tienen límites de frecuencia documentados de forma oficial (a diferencia del modelo de cubo con fugas de la Admin API), pero las pruebas empíricas muestran lo siguiente:

  • Ritmo seguro: ~2 solicitudes por segundo por tienda
  • Límite suave: ~40 solicitudes por minuto antes de que aparezca el throttling
  • HTTP 429: "Too Many Requests"; la respuesta estándar cuando alcanzas el límite
  • HTTP 430: Código específico de Shopify que indica un bloqueo a nivel de seguridad, no solo limitación por frecuencia
  • HTTP 403 o redirección a CAPTCHA: algunas tiendas con protección adicional de Cloudflare

Las solicitudes desde infraestructura compartida en la nube (AWS Lambda, Google Cloud Run) tienen más probabilidades de activar bloqueos, porque esos rangos de IP suelen asociarse con abuso.

Técnicas para extraer Shopify de forma fiable

Así evoluciona el enfoque de “funciona en mi portátil” a “está listo para producción”:

NivelTécnicaFiabilidad
Básicorequests.get() + ?page=Se rompe con catálogos grandes, puede ser bloqueado
Intermediorequests.Session() + ?limit=250 + time.sleep(1) + reintentos en 429Funciona para la mayoría de las tiendas
Avanzadohttpx asíncrono + rotación de User-Agent + backoff exponencialNivel producción, escala a más de 10K productos

Nivel intermedio (recomendado para la mayoría de usuarios):

1import requests
2from requests.adapters import HTTPAdapter
3from urllib3.util.retry import Retry
4def create_session():
5    """Crear una sesión requests con lógica automática de reintentos."""
6    session = requests.Session()
7    retries = Retry(
8        total=5,
9        backoff_factor=1,  # espera: 0.5s, 1s, 2s, 4s, 8s
10        status_forcelist=[429, 430, 500, 502, 503, 504],
11        respect_retry_after_header=True
12    )
13    session.mount("https://", HTTPAdapter(max_retries=retries))
14    session.headers.update({
15        "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"
16    })
17    return session

La configuración de Retry maneja automáticamente las respuestas 429 con backoff exponencial. backoff_factor=1 significa que la secuencia de espera es 0,5 s → 1 s → 2 s → 4 s → 8 s entre reintentos. Además, reutilizar la sesión (requests.Session()) te da pooling de conexiones, lo que reduce la sobrecarga cuando haces varias solicitudes al mismo dominio.

Rotación de User-Agent: si extraes datos de varias tiendas, alterna entre 3 y 5 cadenas realistas de User-Agent de navegador. No se trata de engañar a nadie; se trata de no parecer un bot que envía siempre los mismos encabezados.

Script completo en Python para extraer Shopify con exportación a CSV

Aquí tienes el script completo, listo para copiar y pegar, que combina todo lo anterior. Tiene unas 75 líneas de código reales, más comentarios, y lo he probado con Allbirds (1.420 productos), ColourPop (más de 2.000 productos) y Zoologist Perfumes (catálogo pequeño).

1import requests
2import pandas as pd
3import time
4import random
5from requests.adapters import HTTPAdapter
6from urllib3.util.retry import Retry
7def create_session():
8    """Crear una sesión con lógica de reintento para límites de frecuencia."""
9    session = requests.Session()
10    retries = Retry(
11        total=5,
12        backoff_factor=1,
13        status_forcelist=[429, 430, 500, 502, 503, 504],
14        respect_retry_after_header=True
15    )
16    session.mount("https://", HTTPAdapter(max_retries=retries))
17    session.headers.update({
18        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
19                      "AppleWebKit/537.36 (KHTML, like Gecko) "
20                      "Chrome/125.0.0.0 Safari/537.36"
21    })
22    return session
23def scrape_shopify(store_url, delay=1.0):
24    """Extraer todos los productos de una tienda Shopify vía /products.json."""
25    session = create_session()
26    all_products = []
27    page = 1
28    base_url = f"{store_url.rstrip('/')}/products.json"
29    while True:
30        print(f"  Page {page}...", end=" ")
31        resp = session.get(base_url, params={"limit": 250, "page": page}, timeout=30)
32        resp.raise_for_status()
33        products = resp.json().get("products", [])
34        if not products:
35            break
36        all_products.extend(products)
37        print(f"{len(products)} products (total: {len(all_products)})")
38        page += 1
39        time.sleep(delay + random.uniform(0, 0.5))
40    return all_products
41def flatten_to_variants(products):
42    """Aplanar el JSON anidado de productos en una fila por variante."""
43    rows = []
44    for p in products:
45        base = {
46            "product_id": p["id"],
47            "title": p["title"],
48            "handle": p["handle"],
49            "vendor": p.get("vendor", ""),
50            "product_type": p.get("product_type", ""),
51            "tags": ", ".join(p.get("tags", [])),
52            "created_at": p.get("created_at", ""),
53            "updated_at": p.get("updated_at", ""),
54            "image_url": p["images"][0]["src"] if p.get("images") else "",
55        }
56        for v in p.get("variants", []):
57            row = {**base}
58            row["variant_id"] = v["id"]
59            row["variant_title"] = v.get("title", "")
60            row["sku"] = v.get("sku", "")
61            row["price"] = v.get("price", "")
62            row["compare_at_price"] = v.get("compare_at_price", "")
63            row["available"] = v.get("available", "")
64            rows.append(row)
65    return rows
66if __name__ == "__main__":
67    STORE_URL = "https://allbirds.com"  # Cámbialo por la tienda objetivo
68    OUTPUT_CSV = "shopify_products.csv"
69    OUTPUT_EXCEL = "shopify_products.xlsx"
70    print(f"Scraping {STORE_URL}...")
71    products = scrape_shopify(STORE_URL)
72    print(f"\nTotal products scraped: {len(products)}")
73    print("Flattening to variant-level rows...")
74    rows = flatten_to_variants(products)
75    df = pd.DataFrame(rows)
76    print(f"DataFrame: {df.shape[0]} rows x {df.shape[1]} columns")
77    df.to_csv(OUTPUT_CSV, index=False, encoding="utf-8-sig")
78    df.to_excel(OUTPUT_EXCEL, index=False, engine="openpyxl")
79    print(f"\nExported to {OUTPUT_CSV} and {OUTPUT_EXCEL}")

Ejecuta esto con python scrape_shopify.py. Para Allbirds, tarda unos 45 segundos y genera un CSV con más de 5.000 filas aproximadamente (una por variante). La salida en terminal se parece a esto:

1Scraping https://allbirds.com...
2  Page 1... 250 products (total: 250)
3  Page 2... 250 products (total: 500)
4  ...
5  Page 6... 170 products (total: 1420)
6Total products scraped: 1420
7Flattening to variant-level rows...
8DataFrame: 5680 rows x 14 columns
9Exported to shopify_products.csv and shopify_products.xlsx

Salta Python: extrae datos de Shopify en 2 clics con Thunderbit (alternativa sin código)

No todo el mundo quiere instalar Python, depurar errores de importación o mantener un script de scraping. Para el comercial que necesita precios de la competencia para mañana por la mañana, Python puede ser demasiado.

Por eso creamos el : un extractor web con IA que funciona como extensión de Chrome. Sin código, sin claves API y sin configurar entornos.

Cómo Thunderbit extrae tiendas Shopify

Thunderbit incluye una plantilla de Shopify Scraper específica y preconfigurada para páginas de productos de Shopify. Instalas la , entras en una tienda Shopify y haces clic en “Scrape”. La plantilla extrae automáticamente nombres de producto, descripciones, precios, detalles de variantes, imágenes e información del proveedor.

En tiendas donde la plantilla no encaja a la perfección (temas personalizados, diseños poco habituales), la función AI Suggest Fields de Thunderbit lee la página y genera automáticamente los nombres de columna. Puedes personalizarlo: renombrar columnas, añadir campos o escribir instrucciones como “extrae solo productos con compare_at_price establecido”.

Algunas funciones que equivalen directamente a lo que hace el script en Python:

  • Scraping de subpáginas: visita automáticamente cada página de detalle del producto y enriquece la tabla con descripciones completas, reseñas o detalles de variantes; hace lo mismo que nuestro script Python al iterar por páginas, pero sin código.
  • Paginación automática: gestiona paginación con clics e infinite scroll sin configuración.
  • Scraping programado: crea tareas recurrentes (por ejemplo, “todos los lunes a las 9:00”) para seguimiento continuo de precios, sin cron jobs ni servidor.
  • Exportación gratuita a CSV, Excel, Google Sheets, Airtable o Notion en todos los planes.

Script de Python vs. Thunderbit: comparación honesta

FactorScript en PythonThunderbit (sin código)
Tiempo de configuración15–60 min (entorno + código)~2 min (instalar extensión de Chrome)
Necesita programaciónSí (Python)No
PersonalizaciónIlimitadaCampos sugeridos por IA + prompts personalizados
Manejo de paginaciónHay que codificarlo manualmenteAutomático
Formatos de exportaciónLo programas tú (CSV/Excel)CSV, Excel, Google Sheets, Airtable, Notion (gratis)
Ejecuciones programadasCron job + hostingProgramador integrado
Gestión de límites de frecuenciaHay que programar reintentos/backoffSe maneja automáticamente
Ideal paraDesarrolladores, pipelines de datos a gran escalaUsuarios de negocio, extracciones rápidas, monitorización recurrente

Usa Python cuando necesites control total o cuando vayas a integrarlo en un pipeline de datos más grande. Usa Thunderbit cuando necesites datos rápido y no quieras mantener código. Para una visión más amplia sobre , hemos preparado una guía aparte sobre ese tema.

python-vs-thunderbit-comparison.webp

Consejos y buenas prácticas para extraer datos de tiendas Shopify

Estas recomendaciones aplican independientemente de la herramienta que uses:

  • Usa siempre ?limit=250 para reducir el número total de solicitudes. El valor predeterminado de 30 por página implica 8 veces más peticiones para obtener los mismos datos.
  • Respeta la tienda: añade pausas de 1 a 2 segundos entre solicitudes. Bombardear un servidor con peticiones rápidas es mala práctica y aumenta la probabilidad de bloqueo.
  • Comprueba primero robots.txt: el robots.txt por defecto de Shopify NO bloquea /products.json. Pero algunas tiendas añaden reglas personalizadas, así que conviene verificarlo antes de hacer scraping a gran escala.
  • Guarda primero el JSON bruto en local y luego procésalo. Si más adelante cambia tu lógica de análisis, no tendrás que volver a extraer los datos. Un simple json.dump(all_products, open("raw_data.json", "w")) antes de aplanar te ahorra dolores de cabeza.
  • Elimina duplicados por product.id: a veces las fronteras entre páginas devuelven productos repetidos. Un df.drop_duplicates(subset=["product_id", "variant_id"]) rápido lo soluciona.
  • Convierte price a float antes de hacer cálculos. Shopify devuelve los precios como cadenas ("185.00"), no como números.
  • Vigila cambios en el endpoint: aunque /products.json ha sido estable durante años, Shopify podría restringirlo en el futuro. Si tu scraper empieza a devolver 404 de repente, revisa primero la tienda manualmente.

Para más información sobre cómo crear scrapers robustos, consulta nuestra guía sobre .

Consideraciones legales y éticas al extraer datos de Shopify

Es una sección breve, pero importante.

El endpoint /products.json ofrece datos de productos disponibles públicamente, la misma información que ve cualquier visitante al navegar por la tienda. Los Términos de Servicio de Shopify incluyen lenguaje sobre no usar “medios automatizados” para acceder a “los Servicios”, pero ese lenguaje se refiere a la plataforma en sí (panel de administración, checkout), no a los datos públicos de la tienda. Hasta abril de 2026, no se habían presentado demandas específicas de Shopify por scraping.

Los precedentes legales clave respaldan el scraping de datos públicos: el caso hiQ v. LinkedIn estableció que extraer datos accesibles públicamente no viola la CFAA, y Meta v. Bright Data (2024) determinó que las restricciones de los TOS solo aplican cuando el usuario ha iniciado sesión.

Buenas prácticas:

  • Extrae solo datos de productos disponibles públicamente
  • No extraigas datos personales ni de clientes
  • Respeta robots.txt y los límites de frecuencia
  • Cumple con GDPR/CCPA si manejas datos personales (los catálogos de productos no son personales)
  • Identifícate con una cadena de User-Agent clara
  • Extraer datos de tu propia tienda Shopify mediante la Admin API siempre está bien

Para profundizar, consulta nuestro artículo sobre .

Conclusión y puntos clave

El endpoint público /products.json de Shopify hace que extraer datos de ecommerce sea muy sencillo. El flujo es: añadir /products.json → obtener datos con Python → paginar con ?limit=250&page= → aplanar con pandas → exportar a CSV o Excel.

Lo que cubre esta guía y otras no:

  • Referencia completa de campos: sabes exactamente qué datos están disponibles (más de 40 campos entre productos, variantes e imágenes) antes de escribir una sola línea de código
  • Endpoints adicionales: /collections.json y /meta.json te dan inteligencia a nivel de categoría y metadatos de la tienda que ningún otro tutorial cubre
  • Técnicas listas para producción: reutilización de sesiones, backoff exponencial, encabezados User-Agent y ?limit=250 para gestionar límites de frecuencia reales
  • Exportación correcta a CSV/Excel: datos de variantes aplanados con pandas, no solo volcados JSON en bruto
  • Alternativa sin código: para quienes prefieren velocidad antes que flexibilidad de código

Si quieres hacer extracciones puntuales o recurrentes de datos de Shopify sin código, prueba la : la plantilla Shopify Scraper se encarga de todo, desde la paginación hasta la exportación. Para pipelines de datos personalizados o scraping a gran escala en muchas tiendas, el script de Python de esta guía te da control total.

Visita nuestro para ver tutoriales en vídeo, o explora nuestras guías sobre y para técnicas relacionadas.

Prueba Thunderbit para extraer datos de Shopify

Preguntas frecuentes

¿Se puede extraer cualquier tienda Shopify con products.json?

La mayoría de las tiendas Shopify exponen este endpoint por defecto; en nuestras pruebas, alrededor del 71% devolvieron JSON válido. Algunas tiendas con configuraciones personalizadas o capas de seguridad adicionales (Cloudflare, configuraciones headless) pueden devolver un 404 o bloquear la solicitud. La comprobación rápida: visita {store-url}/products.json en tu navegador. Si ves JSON, todo está bien.

Los datos públicos de productos (precios, títulos, imágenes, descripciones) suelen ser accesibles, y precedentes como hiQ v. LinkedIn respaldan la extracción de información pública. Dicho esto, revisa siempre los Términos de Servicio de la tienda concreta y la legislación de tu zona. No extraigas datos personales ni de clientes, y respeta los límites de frecuencia.

¿Cuántos productos se pueden extraer de una tienda Shopify?

No hay un límite fijo en el total. La paginación con ?limit=250&page= permite recuperar todo el catálogo. En tiendas muy grandes (más de 25.000 productos), usa reutilización de sesión y pausas para evitar límites de frecuencia. El endpoint /meta.json puede decirte por adelantado el número exacto de productos para que sepas cuántas páginas esperar.

¿Cuál es la diferencia entre products.json y la Shopify Admin API?

/products.json es un endpoint público: no requiere autenticación, ofrece datos de productos de solo lectura y cualquiera puede acceder a él. La Admin API requiere tokens de acceso del propietario de la tienda y proporciona pedidos, cantidades de inventario, datos de clientes y permisos de escritura. Si necesitas datos de ventas o cantidades reales de inventario, necesitas acceso a la Admin API (lo que significa que debes ser el propietario de la tienda o tener su permiso).

¿Puedo extraer datos de Shopify sin Python?

Por supuesto. Herramientas como el te permiten extraer datos de tiendas Shopify desde una extensión de Chrome sin escribir código. Gestiona la paginación automáticamente y exporta directamente a CSV, Excel, Google Sheets, Airtable o Notion. Para desarrolladores que prefieran otros lenguajes, el mismo endpoint /products.json funciona con JavaScript, Ruby, Go o cualquier lenguaje que pueda hacer solicitudes HTTP y analizar JSON.

Más información

Ke
Ke
CTO @ Thunderbit. Ke is the person everyone pings when data gets messy. He's spent his career turning tedious, repetitive work into quiet little automations that just run. If you've ever wished a spreadsheet could fill itself in, Ke has probably already built the thing that does it.
Tabla de contenidos

Prueba Thunderbit

Extrae leads y otros datos en solo 2 clics. Impulsado por IA.

Consigue Thunderbit Es gratis
Extrae datos usando IA
Transfiere datos fácilmente a Google Sheets, Airtable o Notion
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week