Cómo extraigo Yelp con Python sin que me bloqueen

Última actualización: April 15, 2026

Yelp alberga repartidas en — y convertir esos datos en un formato útil nunca había sido tan complicado. La ofensiva anti-bots de Yelp de 2024–2025 ha roto, casi sin hacer ruido, la mayoría de los tutoriales de scraping con Python que siguen circulando.

Si últimamente has intentado ejecutar un scraper de Yelp y te has topado con una pared de errores 403, respuestas HTML vacías o CAPTCHAs que hace seis meses no estaban ahí, no te lo estás imaginando. Yelp ahora aplica fingerprinting TLS/JA3, nombres de clases CSS ofuscados y rotación, y una puntuación agresiva de reputación de IP — lo que significa que el viejo enfoque requests + BeautifulSoup que todavía recomiendan todos los tutoriales muere en la primera petición. He pasado semanas probando distintos métodos contra el stack actual de Yelp, y esta guía reúne todo lo que de verdad funciona en 2025: la API oficial Fusion (y por qué probablemente no te baste), un flujo completo de scraping con Python y una estrategia por capas para evitar bloqueos, y una alternativa sin código con solo 2 clics usando para quienes solo quieren los datos sin maratones de depuración.

Por qué extraer Yelp con Python (y quién se beneficia de verdad)

Antes de escribir una sola línea de código, ¿cuál es el caso de negocio real de los datos de Yelp? La plataforma no es solo un sitio de reseñas de restaurantes: en la práctica es una base de datos viva de negocios locales con información estructurada de contacto, valoraciones, categorías, horarios y cientos de millones de reseñas de clientes.

yelp_stats_bd6a43108e.png

Estos son los perfiles que más se benefician y qué suelen extraer:

Caso de usoCampos de datos clavePor qué importa
Ventas y generación de leadsNombre del negocio, teléfono, sitio web, dirección, categoría, valoraciónCrea listas segmentadas de prospectos locales — 4 de cada 5 usuarios de Yelp están listos para comprar al llegar
Inteligencia competitivaReseñas, estrellas, volumen de reseñas, sentimientoVigila la reputación de la competencia, detecta fallos de servicio y sigue tendencias
Investigación de mercado y NLPTexto completo de reseñas, fechas, metadatos del revisorAnálisis de sentimiento, modelado temático — las reseñas de Yelp son uno de los corpus de NLP más usados en la investigación académica
Inmobiliario y selección de ubicacionesDensidad de negocios, mezcla de categorías, calidad de reseñas por zonaSelección de ubicaciones para franquicias y retail — Yelp vende Location Intelligence como producto B2B licenciado precisamente para esto
Ecommerce y operacionesSeñales de precios, quejas de clientes, horarios de atenciónAnaliza cómo valoran a la competencia y detecta patrones operativos

El hilo conductor es claro: el objetivo real son los datos estructurados, y Python solo es un medio para conseguirlos. Algunos lectores querrán control programático total. Otros solo necesitan una hoja de cálculo con contactos de fontaneros en Austin. Aquí cubrimos ambas rutas.

API de Yelp Fusion vs. scraping web con Python: ¿cuál deberías usar?

La mayoría de las guías omiten por completo esta decisión y saltan directamente al código, sin evaluar si la oficial —ahora rebautizada como "Yelp Places API"— habría sido suficiente. En mi experiencia, esa evaluación ahorra horas de esfuerzo inútil, porque la API es excelente para algunas cosas y totalmente insuficiente para otras.

Lo que realmente ofrece la API Fusion

La API Fusion proporciona búsqueda estructurada de negocios, detalles de negocio, autocompletado y un endpoint de reseñas. Está autorizada, bien documentada y no requiere trucos anti-bot.

Pero el problema empieza justo en el endpoint de reseñas. Esto es lo que el propio personal de Yelp ha confirmado en GitHub:

"La API de Yelp no devuelve el texto completo de las reseñas. De forma predeterminada se proporcionan tres fragmentos de reseña de 160 caracteres." —

No es un fallo: está hecho así a propósito. La API se limita físicamente a 3 fragmentos de reseña (7 en Premium), cada uno recortado a unos 160 caracteres. No hay metadatos de reseña (votos de útil/divertida/cool), no hay historial del revisor, no hay respuestas del propietario. Y el después de mayo de 2023 — frente a las 5.000 anteriores. El precio de entrada parte de .

Marco de decisión

FactorAPI Yelp FusionScraping web con PythonThunderbit (sin código)
Reseñas completas❌ Solo 3 fragmentos (~160 caracteres cada uno)✅ Todas las reseñas vía GraphQL✅ Todas las reseñas visibles
Límites de uso300–500/día (nuevos); 5.000 (heredados)Lo gestionas tú (con presupuesto de proxies)Basado en créditos
Esfuerzo de configuración~15 min (clave API + SDK)Horas o días~2 minutos
Campos de negocio~20 campos estructuradosIlimitados (parseando HTML/JSON)Campos sugeridos por IA
Gestión anti-botN/A (autorizado)Debes construirla túGestionada automáticamente
Riesgo legal✅ Autorizado⚠️ Zona gris en los Términos⚠️ Igual que el scraping
CosteDesde $29/mesGratis (+ coste de proxies de $0,75–$4/GB)Hay plan gratis disponible
MantenimientoBajo (API estable)Alto (los selectores se rompen, la defensa anti-bot se endurece)Bajo (la IA se reajusta)

Usa la API Fusion si: necesitas información básica del negocio, consultas a pequeña escala o una integración autorizada — y te bastan 3 fragmentos de reseña por negocio.

Usa scraping con Python si: necesitas el texto completo de las reseñas, todas las reseñas de un negocio, metadatos de reseñas, más de 240 resultados por búsqueda o tu presupuesto es inferior a $29/mes.

Usa Thunderbit si: quieres los datos rápido sin escribir ni mantener código. Más sobre esto en la sección sin código más abajo.

El atajo sin código: extrae Yelp con Thunderbit (sin Python)

Antes de entrar en el detalle con Python, aquí tienes la ruta más rápida para quienes realmente quieren los datos, no hacer un ejercicio de programación. Todas las guías de la competencia asumen que dominas Python, pero en mi trabajo en Thunderbit he visto que una gran parte de quienes buscan "scrape Yelp" son comerciales, responsables de operaciones y dueños de pequeñas empresas que solo quieren una hoja de cálculo con negocios locales — no un curso intensivo de fingerprinting TLS.

ya incluye plantillas preconstruidas para Yelp:

  • — extrae nombre del negocio, valoración, datos de contacto, dirección, horarios y categoría
  • — extrae usuario del revisor, contenido de la reseña, valoración, fecha y ubicación del revisor

Cómo funciona en la práctica

  1. Abre una página de resultados de búsqueda de Yelp o una ficha de negocio en Chrome
  2. Haz clic en AI Suggest Fields en la — la IA lee la página y propone columnas (nombre del negocio, valoración, número de reseñas, rango de precio, categoría, dirección, teléfono, URL)
  3. Haz clic en Scrape — y listo

Con las plantillas de Yelp ya preparadas, es todavía más fácil: abre la plantilla y pulsa Scrape.

El scraping de subpáginas automatiza el ciclo de enriquecimiento — empiezas desde una página de resultados de Yelp, activas el scraping de subpáginas y Thunderbit visita cada ficha de negocio para extraer horarios, reseñas completas, sitio web, fotos y servicios. Sin configuración adicional.

La paginación es automática — tanto la basada en clics como la de desplazamiento, gestionada de serie. (Si quieres saber más, consulta nuestra .)

Las exportaciones son gratis en todos los planes — Excel, Google Sheets, Airtable, Notion, CSV, JSON. Sin pandas, sin código para escribir CSV.

Comparación de tiempo

TiempoScraper con PythonThunderbit
Primera ejecuciónHoras o días (escribir selectores, manejar paginación, proxies y lógica de reintentos)~30 segundos con la plantilla preconstruida de Yelp
Cuando Yelp cambia el marcadoReescribir selectores manualmenteVuelve a hacer clic en AI Suggest Fields — se reajusta solo
Cuando bloquean la IPDepurar, rotar pools de proxies, volver a probarEl modo Cloud gestiona la rotación de IP
Exportar a Google SheetsEscribir OAuth + pegar con pandasUn clic, gratis

Si pruebas Thunderbit primero y ves que cubre lo que necesitas, puedes saltarte el resto del artículo. Si necesitas control programático total, campos personalizados o escalar más allá de unos pocos miles de registros al mes, sigue leyendo.

Librerías de Python para extraer Yelp: cuál elegir

"¿Debería usar Scrapy, BS4+requests o Selenium?" es una de las preguntas más comunes en hilos de r/webscraping sobre Yelp. Y, aun así, cada tutorial elige su librería favorita y sigue adelante sin explicar por qué. Aquí va un resumen honesto.

La realidad de 2025: requests + BeautifulSoup está roto para Yelp

El stack que recomiendan todos los tutoriales clásicos de Yelp — pip install requests beautifulsoup4te bloquea en la primera petición en 2025. No en la 50. En la primera.

La razón: la librería requests de Python envía una huella TLS/JA3 que no coincide con la de un navegador real. La capa anti-bot de Yelp la detecta en el handshake TLS, antes incluso de leer tu cabecera User-Agent. Lo he probado repetidamente — IP nueva, cabeceras realistas, retrasos aleatorios — y aun así recibí un 403 Forbidden inmediato con requests puro.

Matriz de decisión de librerías

LibreríaIdeal para¿Maneja JS?¿Anti-bot?Curva de aprendizajeVelocidad
requests + BeautifulSoupScraping simple de una sola página (roto para Yelp)Muy bajaRápido (hasta que te bloquean)
httpx async + parselScraping asíncrono a gran escalaBajaMuy rápido
curl_cffi + parselEspecífico para Yelp: suplantación TLS✅ TLS/JA3/HTTP2BajaMuy rápido
Scrapy 2.14Pipelines completos con paginaciónParcial (vía scrapy-playwright)AutoThrottle, middleware de reintentosMedia-altaRápido
Selenium 4.43 / Playwright 1.58Páginas muy cargadas de JS, evasión de CAPTCHAsParcialMediaLento (~10–30 páginas/min)
ThunderbitUsuarios no técnicos, extracción rápida✅ (navegador)Integrado (modo Cloud)Muy bajaRápido

La revelación de curl_cffi

La librería que cambió mi flujo de trabajo para extraer Yelp es — un binding de Python para curl-impersonate. Emite exactamente la misma huella TLS/JA3 + HTTP/2 que Chrome real, y su API se puede usar como sustituto directo de requests:

1from curl_cffi import requests
2r = requests.get(
3    "https://www.yelp.com/biz/some-restaurant",
4    impersonate="chrome131",
5)
6print(r.status_code, len(r.text))

Ese único cambio — from curl_cffi import requests más impersonate="chrome131" — sortea la sin levantar un navegador. En mis pruebas, la diferencia es pasar de 403 instantáneos a respuestas 200 limpias.

Mi stack recomendado para Yelp en 2025: curl_cffi + parsel + jmespath + proxies residenciales. Si necesitas un pipeline completo con programación, envuélvelo en Scrapy 2.14 con un middleware de descarga basado en curl_cffi.

Configurar tu entorno Python para extraer Yelp

  • Dificultad: Intermedia
  • Tiempo necesario: ~15 minutos para la configuración, 1–2 horas para un scraper funcional
  • Lo que necesitas: Python 3.10+ (recomendado 3.12), una terminal y, opcionalmente, un proveedor de proxies residenciales

Paso 1: crea un entorno virtual e instala los paquetes

1python3.12 -m venv .venv
2source .venv/bin/activate  # En Windows: .venv\Scripts\activate
3pip install "curl_cffi>=0.11" "parsel>=1.9" "jmespath>=1.0" pandas

Qué hace cada paquete:

  • curl_cffi — hace peticiones HTTP con la huella TLS de Chrome (el bypass anti-bot)
  • parsel — selectores CSS/XPath para analizar HTML (el mismo motor que usa Scrapy, pero más ligero)
  • jmespath — consultas declarativas sobre JSON (más limpio que acceder a diccionarios anidados en el JSON embebido de Yelp)
  • pandas — exportación de datos a CSV/Excel

Opcional, pero útil:

1pip install fake-useragent  # Nota: el repositorio fue archivado en abril de 2026, pero sigue siendo instalable

Paso a paso: cómo extraer Yelp con Python

Este es el tutorial principal. La idea clave que hace todo mucho más resistente: salta los selectores CSS y extrae el JSON oculto. Yelp randomiza los nombres de las clases CSS en cada compilación (y-css-14xwok2 una semana, y-css-hcq7b9 la siguiente), así que cualquier scraper que dependa de ellos se rompe en cuestión de semanas. Las cargas JSON embebidas — application/ld+json y react-root-props — son estables.

Paso 2: extraer los resultados de búsqueda de Yelp

Las URLs de búsqueda de Yelp siguen un patrón predecible: https://www.yelp.com/search?find_desc={term}&find_loc={location}. Los datos de resultados están incrustados en una etiqueta <script data-id="react-root-props"> como JSON — no se renderizan en el caos de clases CSS.

1import re, json, jmespath
2from curl_cffi import requests
3from parsel import Selector
4HEADERS = {
5    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
6                  "AppleWebKit/537.36 (KHTML, like Gecko) "
7                  "Chrome/124.0.0.0 Safari/537.36",
8    "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,"
9              "image/avif,image/webp,image/apng,*/*;q=0.8",
10    "accept-language": "en-US,en;q=0.9",
11    "accept-encoding": "gzip, deflate, br",
12    "cookie": "intl_splash=false",
13}
14def scrape_search(term: str, location: str, max_pages: int = 3):
15    results = []
16    for page in range(max_pages):
17        url = (f"https://www.yelp.com/search?"
18               f"find_desc={term}&find_loc={location}&start={page * 10}")
19        r = requests.get(url, headers=HEADERS, impersonate="chrome131")
20        if r.status_code != 200:
21            print(f"Bloqueado en la página {page}: {r.status_code}")
22            break
23        sel = Selector(text=r.text)
24        script = sel.xpath(
25            "//script[@data-id='react-root-props']/text()"
26        ).get() or ""
27        m = re.search(r"react_root_props\s*=\s*(\{.*?\});", script, re.S)
28        if not m:
29            print(f"No se encontró react-root-props en la página {page} — posible bloqueo suave")
30            break
31        data = json.loads(m.group(1))
32        businesses = jmespath.search(
33            "legacyProps.searchAppProps.searchPageProps"
34            ".mainContentComponentsListProps"
35            "[?searchResultBusiness].searchResultBusiness.{"
36            "name: name, url: businessUrl, rating: rating, "
37            "reviews: reviewCount, phone: phone, "
38            "neighborhoods: neighborhoods}",
39            data,
40        ) or []
41        results.extend(businesses)
42        import time, random
43        time.sleep(random.uniform(3, 7))
44    return results

Deberías obtener una lista de diccionarios con nombres de negocio, URLs, valoraciones y número de reseñas. Si react-root-props falta en la respuesta, te han servido un shell de bloqueo — rota tu IP y vuelve a intentarlo.

La cabecera Cookie: intl_splash=false es un truco estándar para evitar el redireccionamiento de la pantalla de país de Yelp. Sin ella, las IP fuera de EE. UU. acaban en una pantalla de aviso que parece un bloqueo suave pero no lo es.

Paso 3: extraer páginas de negocio de Yelp

Cada URL de negocio obtenida en los resultados lleva a una página de detalle con datos más ricos. El objetivo de extracción más estable es el bloque <script type="application/ld+json"> — contiene datos estructurados de schema.org que Yelp mantiene por SEO y no ofusca.

1def scrape_business(biz_url: str) -> dict:
2    url = f"https://www.yelp.com{biz_url}" if biz_url.startswith("/") else biz_url
3    r = requests.get(url, headers=HEADERS, impersonate="chrome131")
4    if r.status_code != 200:
5        return {"url": url, "error": r.status_code}
6    sel = Selector(text=r.text)
7    biz_id = sel.css('meta[name="yelp-biz-id"]::attr(content)').get()
8    for raw in sel.css('script[type="application/ld+json"]::text').getall():
9        try:
10            data = json.loads(raw)
11        except json.JSONDecodeError:
12            continue
13        for node in (data if isinstance(data, list) else [data]):
14            if node.get("@type") in (
15                "Restaurant", "LocalBusiness", "FoodEstablishment",
16                "HealthAndBeautyBusiness", "HomeAndConstructionBusiness",
17            ):
18                return {
19                    "biz_id": biz_id,
20                    "name": node.get("name"),
21                    "rating": (node.get("aggregateRating") or {}).get("ratingValue"),
22                    "review_count": (node.get("aggregateRating") or {}).get("reviewCount"),
23                    "address": node.get("address"),
24                    "telephone": node.get("telephone"),
25                    "price_range": node.get("priceRange"),
26                    "hours": node.get("openingHours"),
27                    "url": url,
28                }
29    return {"biz_id": biz_id, "url": url}

El valor de meta[name="yelp-biz-id"] es el ID de negocio codificado que necesitarás para el endpoint de reseñas. Consíguelo aquí: lo usarás en el siguiente paso.

Paso 4: extraer reseñas de Yelp con paginación

Aquí es donde la API Fusion se queda corta y el scraping gana. El endpoint interno GraphQL de Yelp devuelve el texto completo de la reseña, información del revisor, fechas, valoraciones y recuento de votos — todo lo que la API oculta.

El endpoint es https://www.yelp.com/gql/batch y usa un documentId estático para la operación GetBusinessReviewFeed. La paginación funciona mediante un cursor codificado en base64.

1import base64
2GQL_URL = "https://www.yelp.com/gql/batch"
3DOC_ID = "ef51f33d1b0eccc958dddbf6cde15739c48b34637a00ebe316441031d4bf7681"
4def fetch_reviews(enc_biz_id: str, num_pages: int = 5):
5    all_reviews = []
6    for page in range(num_pages):
7        offset = page * 10
8        cursor = base64.b64encode(
9            json.dumps({"version": 1, "offset": offset}).encode()
10        ).decode()
11        payload = [{
12            "operationName": "GetBusinessReviewFeed",
13            "variables": {
14                "encBizId": enc_biz_id,
15                "reviewsPerPage": 10,
16                "after": cursor,
17                "sortBy": "DATE_DESC",
18                "language": "en",
19            },
20            "extensions": {
21                "operationType": "query",
22                "documentId": DOC_ID,
23            },
24        }]
25        r = requests.post(
26            GQL_URL,
27            json=payload,
28            headers={
29                **HEADERS,
30                "content-type": "application/json",
31                "x-apollo-operation-name": "GetBusinessReviewFeed",
32                "apollographql-client-name": "yelp-main-frontend",
33            },
34            impersonate="chrome131",
35        )
36        if r.status_code != 200:
37            print(f"Falló la obtención de reseñas en el offset {offset}: {r.status_code}")
38            break
39        data = r.json()
40        # Navega la estructura de respuesta para extraer las reseñas
41        try:
42            reviews = data[0]["data"]["business"]["reviews"]["edges"]
43            for edge in reviews:
44                node = edge.get("node", {})
45                all_reviews.append({
46                    "reviewer": node.get("author", {}).get("displayName"),
47                    "rating": node.get("rating"),
48                    "date": node.get("localizedDate"),
49                    "text": node.get("text", {}).get("full"),
50                })
51        except (KeyError, IndexError, TypeError):
52            break
53        import time, random
54        time.sleep(random.uniform(3, 7))
55    return all_reviews

Cada página devuelve 10 reseñas. Incrementa el offset en el cursor base64 para paginar. El parámetro sortBy admite DATE_DESC (más recientes primero), RATING_ASC, RATING_DESC y otros.

Paso 5: exportar tus datos de Yelp extraídos

1import pandas as pd
2# Suponiendo que ya has recopilado negocios y reseñas
3df_businesses = pd.DataFrame(businesses)
4df_businesses.to_csv("yelp_businesses.csv", index=False)
5df_reviews = pd.DataFrame(all_reviews)
6df_reviews.to_csv("yelp_reviews.csv", index=False)
7# O guárdalo como JSON para mayor flexibilidad
8import json
9with open("yelp_data.json", "w") as f:
10    json.dump({"businesses": businesses, "reviews": all_reviews}, f, indent=2)

Para quienes siguen la ruta sin código, Thunderbit exporta los mismos datos directamente a Excel, Google Sheets, Airtable o Notion — sin pandas ni código para escribir archivos.

El manual anti-bloqueo: cómo extraer Yelp sin que te bloqueen

Esta sección es la razón de ser de todo el artículo. Las medidas anti-bot de Yelp se han endurecido notablemente desde finales de 2024 — están todas en juego. La mayoría de las guías existentes están desactualizadas porque se escribieron antes de esta ofensiva.

yelp_antiblock_518f0447bb.png

La estrategia debe ser por capas. Cada capa reduce la tasa de bloqueo; combinadas, hacen viable el scraping continuo.

Capa 1: cabeceras de petición realistas

Las cabeceras por defecto de requests envían User-Agent: python-requests/2.x — bloqueo inmediato. Pero ni siquiera un User-Agent realista basta. Yelp comprueba el conjunto completo de cabeceras para ver si todo encaja.

1FULL_HEADERS = {
2    "authority": "www.yelp.com",
3    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
4                  "AppleWebKit/537.36 (KHTML, like Gecko) "
5                  "Chrome/124.0.0.0 Safari/537.36",
6    "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,"
7              "image/avif,image/webp,image/apng,*/*;q=0.8",
8    "accept-language": "en-US,en;q=0.9",
9    "accept-encoding": "gzip, deflate, br",
10    "sec-ch-ua": '"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"',
11    "sec-ch-ua-mobile": "?0",
12    "sec-ch-ua-platform": '"Windows"',
13    "sec-fetch-dest": "document",
14    "sec-fetch-mode": "navigate",
15    "sec-fetch-site": "same-origin",
16    "sec-fetch-user": "?1",
17    "upgrade-insecure-requests": "1",
18    "referer": "https://www.yelp.com/",
19    "cookie": "intl_splash=false",
20}

Tres errores que te hacen saltar las alarmas:

  1. El UA dice Chrome, pero sec-ch-ua falta o contradice la versión del UA
  2. sec-ch-ua-platform dice "Windows", pero la cadena UA indica macOS
  3. El mismo UA exacto en miles de peticiones desde una IP — rota entre 10–20 cadenas recientes de Chrome/Firefox/Safari

Capa 2: limitación de ritmo y pausas aleatorias

Los patrones temporales predecibles son una señal de alerta. Añade intervalos de sueño aleatorios e implementa backoff exponencial ante errores.

1import random, time
2def polite_get(client_get, url, attempt=0):
3    r = client_get(url, headers=FULL_HEADERS, impersonate="chrome131")
4    if r.status_code in (403, 429, 503):
5        if attempt >= 4:
6            raise RuntimeError(f"Bloqueado tras {attempt + 1} intentos en {url}")
7        backoff = 2 ** (attempt + 1) + random.random()
8        print(f"  Recibido {r.status_code}, aplicando espera {backoff:.1f}s (intento {attempt + 1})")
9        time.sleep(backoff)
10        return polite_get(client_get, url, attempt + 1)
11    time.sleep(random.uniform(3, 7))
12    return r
ParámetroValor recomendado
Pausa aleatoria entre peticionesrandom.uniform(3, 7) segundos
Backoff ante 429/403/5032 → 4 → 8 → 16s, máximo 5 intentos
Trabajadores concurrentes por IP1 (serializa por IP; usa proxies para paralelismo)
Ritmo sostenido máximo por IP residencial~1 petición / 5s (~12 rpm)

Capa 3: rotación de User-Agent y sesiones

Rota entre un conjunto de cadenas User-Agent de navegadores reales. Conserva sesiones y cookies para imitar el comportamiento de navegación auténtico: Yelp usa detección basada en cookies, así que crear una sesión nueva en cada petición también resulta sospechoso.

1UA_POOL = [
2    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
3    "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4_1) AppleWebKit/537.36 Chrome/124.0.0.0 Safari/537.36",
4    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:125.0) Gecko/20100101 Firefox/125.0",
5    "Mozilla/5.0 (Macintosh; Intel Mac OS X 14.4; rv:125.0) Gecko/20100101 Firefox/125.0",
6    "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_4_1) AppleWebKit/605.1.15 Safari/17.4.1",
7    # Añade 5-10 cadenas más recientes
8]

Capa 4: rotación de proxies

A cualquier volumen real, necesitas proxies residenciales. Los proxies de datacenter y los gratuitos no funcionan en Yelp — su capa de reputación de IP bloquea por adelantado rangos de AWS, GCP y DigitalOcean.

ProveedorPrecio inicial $/GBNotas
IPRoyal$1.75/GBEl más barato; ejecuta el tutorial de Yelp más citado
Decodo (antes Smartproxy)$3.20–$3.50La mejor relación GB/precio en volumen
Bright Data$4.00 (PAYG)Pool de más de 150M IPs; página dedicada de Yelp Proxies
Oxylabs$6.00–$8.00Premium; más de 10M IPs
Aluvia (SIM móvil)$3.00IPs móviles reales de operadores de EE. UU., pensado para Yelp

Los residenciales rotativos (una IP nueva por petición) funcionan mejor para rastreos masivos de búsquedas. Las sesiones persistentes (mantener una IP durante 10 minutos) son mejores cuando necesitas conservar cookies a lo largo de un flujo página de negocio → reseñas → paginación.

Capa 5: detectar y manejar bloqueos

No todos los bloqueos se ven igual. A menudo Yelp sirve una envoltura genérica de "página no disponible" en lugar de un CAPTCHA, por eso los scrapers ingenuos creen que reciben datos cuando en realidad están obteniendo respuestas vacías.

1BLOCK_MARKERS = (
2    "captcha", "px-captcha", "page not available",
3    "access denied", "unusual traffic",
4)
5def is_blocked(resp):
6    if resp.status_code in (401, 403, 429, 503):
7        return True
8    body = resp.text.lower()
9    if any(m in body for m in BLOCK_MARKERS):
10        return True
11    # Si es una página de búsqueda/negocio pero falta react-root-props,
12    # Yelp entregó una respuesta de bloqueo recortada
13    if "react-root-props" not in body and "/biz/" in str(resp.url):
14        return True
15    return False
SeñalSignificado
HTTP 403Bloqueo duro — IP/cabeceras/TLS quemados
HTTP 429Límite de ritmo — suele poder recuperarse con backoff
HTTP 503Bloqueo genérico o reducción de carga
Redirección a /error o cuerpo "page not available"Bloqueo suave
vacío con solo Página de desafío esperando JS
captcha / g-recaptcha / px-captcha en el cuerpoEscalada — se requiere CAPTCHA
Falta react-root-props en una página de listadoRespuesta de bloqueo recortada

Capa 6: el truco de análisis resistente — JSON oculto en lugar de selectores CSS

Conviene repetirlo: Yelp randomiza los nombres de las clases CSS en cada compilación. Un scraper anclado a h3.y-css-14xwok2 se romperá en pocas semanas cuando Yelp vuelva a desplegar con h3.y-css-hcq7b9.

Los payloads que no cambian son:

  • <script type="application/ld+json"> — datos estructurados schema.org (nombre, dirección, teléfono, valoración, horarios)
  • <script data-id="react-root-props"> — todos los resultados de búsqueda como JSON
  • https://www.yelp.com/gql/batch — endpoint GraphQL de reseñas con documentId estable

Si estás analizando clases CSS, estás construyendo sobre arena. Analiza el JSON en su lugar.

Capa 7: plan B con navegador sigiloso

Pasa a un navegador headless solo cuando curl_cffi + proxies residenciales no consigan pasar — normalmente cuando Yelp sirve una página de desafío JS o un CAPTCHA.

Para el 95% del scraping de negocios/búsquedas/reseñas, curl_cffi + JSON oculto + proxies residenciales es más rápido, barato y fiable que un navegador. Pero cuando de verdad necesites navegador:

HerramientaEstado (2025)Notas
rebrowser-playwrightPunto de partida recomendadoFork de Playwright con parches para corregir fugas de CDP
nodriverLo mejor para sigilo en ChromeSucesor de undetected-chromedriver; evita por completo el protocolo WebDriver
patchrightFork de Playwright con mantenimiento activoSupera pruebas modernas de detección
playwright-stealthMaduraCorrige navigator.webdriver y elimina HeadlessChrome del UA

Evita Selenium puro para Yelp. Se detecta demasiado fácil.

API Yelp Fusion vs. scraping con Python vs. Thunderbit: comparación completa

DimensiónAPI Yelp FusionScraping con PythonThunderbit
Texto completo de reseñas❌ 3 fragmentos × ~160 caracteres✅ Ilimitado (GraphQL)✅ Plantilla de reseñas integrada
Metadatos de reseñas (votos, respuestas del propietario)✅ Mediante campos sugeridos por IA
Fotos❌ (0 en Base)✅ Ilimitadas
Máximo de resultados por búsqueda240 (eran 1.000 antes de 2024)Ilimitado (paginado)Ilimitado
Límite diario300–500 (nuevos) / 5.000 (heredados)Solo tu presupuesto de proxiesBasado en créditos (3.000/mes en Pro)
Esfuerzo de configuración~15 minHoras o días~2 minutos
Gestión anti-botN/ATu problemaGestionada (modo Cloud)
Riesgo legalBajo (autorizado)Medio (zona gris de ToS)Medio (igual que el scraping)
Coste de entrada$29/mes~ $0,75–$4/GB en proxies + tiempo de desarrolloPlan gratis
Coste con uso intensivo$643+/mes$50–$500/mes en proxies + tiempo de desarrollo$38–$49/mes
Exportación de datosJSONCSV/JSON (lo programas tú)Excel / Sheets / Airtable / Notion — gratis
MantenimientoBajoAlto (los selectores se rompen, la defensa anti-bot se endurece)Bajo (la IA se reajusta)

Consejos legales y éticos para extraer Yelp

No soy abogado, y esto no es asesoramiento legal. Pero el panorama legal ha cambiado lo suficiente en los últimos dos años como para que convenga conocer lo básico antes de invertir tiempo en un proyecto de scraping de Yelp.

Qué dicen los Términos de Servicio de Yelp: la prohíbe expresamente usar "cualquier robot, spider... u otro dispositivo automatizado" para "acceder, recuperar, copiar, extraer o indexar cualquier parte del Servicio". También añadió lenguaje sobre "AI Technologies y/o otras herramientas automatizadas".

: "Yelp no permite ningún tipo de scraping del sitio".

Qué dice robots.txt: el de Yelp tiene un comodín User-agent: * / Disallow: / y además bloquea específicamente GPTBot, ClaudeBot, PerplexityBot, CCBot y Meta-ExternalAgent. Solo Googlebot, Bingbot y algunos rastreadores de redes sociales están permitidos.

El precedente legal que importa: en (N.D. Cal. enero de 2024), el tribunal dictaminó que extraer datos públicos y cerrados a sesión no violaba los Términos de Servicio de Meta. La distinción clave: datos públicos sin iniciar sesión vs. datos con sesión iniciada. El caso estableció que el scraping de datos públicos probablemente no viola la CFAA, pero hiQ aún perdió en reclamaciones de derecho estatal (trespass to chattels, misappropriation) y recibió una sentencia de $500.000.

Pautas prácticas:

  • Extrae solo páginas públicas, sin iniciar sesión
  • Limita la velocidad de tus peticiones (los retrasos de esta guía sirven también como límites éticos)
  • No revendas texto bruto de reseñas atribuido a usuarios con nombre — respeta la privacidad de los revisores
  • Cumple las leyes locales de protección de datos (CCPA, GDPR)
  • No te autentiques para hacer scraping — eso cruza la línea de autorización
  • Trata la información del negocio (nombre/dirección/teléfono/valoración) como datos fácticos públicos; trata el texto de las reseñas como algo más sensible

Consulta a un profesional legal para tu caso concreto.

Cierre

Tres caminos, un mismo objetivo.

La API Yelp Fusion es la opción autorizada y de bajo mantenimiento — pero se limita a 3 fragmentos de reseña y parte de $29/mes. El scraping con Python te da control total sobre cada dato de Yelp, pero exige una inversión real: curl_cffi para suplantación de huella TLS, proxies residenciales, retrasos aleatorios, análisis de JSON oculto y mantenimiento continuo a medida que evolucionan las defensas de Yelp. Thunderbit te lleva de "necesito datos de Yelp" a "aquí está mi hoja de cálculo" en unos 30 segundos, sin código y sin configurar proxies.

Lo esencial para evitar bloqueos que sí funciona en 2025: cabeceras realistas con Client Hints completos, curl_cffi para suplantar la huella TLS, retrasos aleatorios con backoff exponencial, rotación de proxies residenciales y, sobre todo, analizar JSON oculto (application/ld+json y react-root-props) en lugar de selectores CSS frágiles.

¿No sabes qué ruta encaja mejor? Prueba primero el . Si cubre lo que necesitas, te habrás ahorrado horas. Si necesitas más control — pipelines programáticos completos, campos personalizados, integración estrecha con tu CRM — la guía de Python anterior te cubre. Y para una visión más amplia del panorama de herramientas de scraping, consulta nuestro resumen de las o nuestra guía para .

Prueba Thunderbit para extraer datos de Yelp

Preguntas frecuentes

¿Puedo extraer Yelp gratis con Python?

Sí — usando librerías gratuitas como curl_cffi, parsel y jmespath. Pero a cualquier volumen real (más de unas pocas decenas de páginas), necesitarás proxies residenciales de pago, que empiezan en torno a . Thunderbit también ofrece un plan gratis con 6 páginas al mes para extracción rápida sin código.

¿Yelp bloquea a los scrapers?

Sí, y de forma agresiva. Yelp usa . requests puro queda bloqueado en el primer intento. La estrategia por capas de esta guía — curl_cffi para suplantar la huella TLS, cabeceras realistas, retrasos aleatorios y proxies residenciales — es la que funciona en 2025.

¿La API Yelp Fusion es mejor que hacer scraping?

Depende de lo que necesites. La API está autorizada y tiene bajo riesgo, pero solo devuelve , limita los resultados de búsqueda a 240 y parte de $29/mes. Si necesitas texto completo de las reseñas, metadatos o más de unos pocos cientos de registros al día, el scraping es la única opción.

¿Cómo extraigo reseñas de Yelp con Python?

Usa curl_cffi con impersonate="chrome131" para obtener la página del negocio, extrae el ID codificado del negocio desde <meta name="yelp-biz-id"> y luego haz un POST a https://www.yelp.com/gql/batch con la operación GetBusinessReviewFeed, paginando mediante un cursor after codificado en base64. El código paso a paso está en la sección del tutorial de arriba. El también es una buena referencia.

¿Puedo extraer Yelp sin programar?

Sí — incluye plantillas preconstruidas de y . Abre una página de Yelp, haz clic en AI Suggest Fields y luego en Scrape. Las exportaciones a Google Sheets, Excel, Airtable y Notion son gratis en todos los planes, incluido el gratuito.

Más información

Tabla de contenido

Prueba Thunderbit

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

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