Si tu equipo de datos necesita analizar tendencias, sentimiento o conversaciones en Reddit, te habrás encontrado con un problema: la API oficial de Reddit se volvió cara, los rate limits son agresivos, y scrapear sin proxies es un camino directo al bloqueo. Esta guía explica cómo acceder a datos públicos de Reddit de forma legítima y eficiente usando proxies residenciales, con ejemplos de código listos para ejecutar.
Aviso legal y ético
Este artículo cubre técnicas para acceder exclusivamente a datos públicos de Reddit. Debes respetar los Términos de Servicio de Reddit, el archivo robots.txt, y las leyes aplicables — incluyendo la CFAA (EE.UU.) y el GDPR (UE). Si Reddit ofrece una API oficial para tus necesidades y tu presupuesto lo permite, úsala. El scraping es una alternativa para equipos con restricciones de costo, pero nunca debe usarse para acceder a datos privados, eludir autenticación, ni violar acuerdos legales. Consulta siempre a tu equipo legal antes de implementar proyectos de scraping a escala.
El paisaje cambiante de la API de Reddit
Los cambios de precios de 2023
En julio de 2023, Reddit implementó su nuevo modelo de precios para la API oficial: 0,24 USD por cada 1.000 solicitudes para uso comercial. Para contexto, un proyecto que analiza 10 subreddits activos puede generar fácilmente millones de solicitudes al mes. El coste mensual rápidamente supera los miles de dólares — insostenible para equipos de investigación, startups y proyectos académicos con presupuesto limitado.
Antes de este cambio, la API de Reddit era gratuita con cuotas generosas. La transición dejó a muchos equipos buscando alternativas.
Cuotas actuales de la API oficial
Reddit mantiene una capa gratuita para clientes no comerciales, pero con límites estrictos:
- OAuth rate limits: 100 solicitudes/minuto para aplicaciones OAuth
- Rate limits por IP: 60 solicitudes/minuto sin autenticar
- Términos restrictivos: prohibición de uso comercial sin acuerdo previo
- Restricciones de redistribución: no se pueden compartir datasets derivados
Para equipos que necesitan datos de Reddit a escala, estos límites hacen que el scraping de contenido público sea la única opción viable desde el punto de vista económico.
El auge del scraping para proyectos sensibles al costo
La combinación de precios elevados y cuotas restrictivas ha impulsado el interés en Reddit data scraping como alternativa. Los datos públicos — posts, comentarios, metadatos de subreddits — están disponibles en la interfaz web sin login. Acceder a ellos mediante scraping no es intrínsecamente diferente a visitar la página en tu navegador, pero la automatización a escala requiere infraestructura de proxies para evitar bloqueos.
Qué datos de Reddit son accesibles públicamente
No todos los datos de Reddit son iguales. Es fundamental distinguir entre lo que es públicamente accesible y lo que requiere autenticación.
Datos accesibles sin login
- Feeds de subreddits: posts ordenados por hot, new, top, rising
- Páginas de posts: título, cuerpo, autor, puntuación, timestamp, flair
- Hilos de comentarios: comentarios anidados con sus metadatos
- Búsquedas: resultados de búsqueda pública por subreddit, keyword, o autor
- Perfiles de usuario: posts y comentarios públicos del usuario
- Metadatos de subreddit: descripción, reglas, número de suscriptores
Datos que requieren login (fuera del alcance ético)
- Mensajes privados y notificaciones
- Contenido en subreddits privados o restringidos
- Historial de votos personal
- Listas de usuarios bloqueados
No scrapees datos que requieren autenticación. Esto viola los ToS de Reddit y potencialmente la CFAA. Esta guía se limita estrictamente a datos públicos.
old.reddit.com: la alternativa más amigable para scraping
old.reddit.com es una joya para scrapers. Es la interfaz legacy de Reddit que mantiene el diseño original:
- HTML más simple y predecible — mucho más fácil de parsear
- Menos JavaScript dinámico — el contenido está en el HTML inicial
- Menos mecanismos anti-bot comparado con la nueva UI
- Mismo contenido, misma base de datos — no pierdes datos
Cualquier URL de Reddit puede convertirse a old.reddit.com simplemente cambiando el dominio: https://www.reddit.com/r/python → https://old.reddit.com/r/python.
Selección de proxy: datacenter vs residencial
Elegir el tipo de proxy correcto es crucial para el éxito de tu proyecto de Reddit data scraping.
| Característica | Datacenter | Residencial |
|---|---|---|
| Velocidad | Alta (baja latencia) | Media |
| Costo por GB | Bajo | Medio-alto |
| Riesgo de bloqueo | Alto | Bajo |
| Diversidad de IPs | Limitada (rangos conocidos) | Alta (IPs de ISPs reales) |
| Ideal para | Volumen bajo, tareas puntuales | Scraping intensivo, geo-distribuido |
| Rotación de IP | Manual o por rotación periódica | Por solicitud o sesión sticky |
Cuándo usar datacenter
Los proxies datacenter funcionan para proyectos pequeños: monitorizar un subreddit, verificar puntuaciones de posts, o extracciones puntuales. Si tu volumen es menor a ~1.000 solicitudes/hora y no necesitas geo-targeting, datacenter puede ser suficiente.
Cuándo usar residenciales
Los Reddit residential proxies son necesarios cuando:
- Scrapeas múltiples subreddits simultáneamente
- Necesitas sesiones prolongadas sin interrupción
- Ya has experimentado bloqueos con datacenter
- Requieres geo-targeting (algunos subreddits regionales muestran contenido diferente)
- Tu volumen supera las 5.000 solicitudes/hora
Las IPs residenciales provienen de ISPs reales, haciendo que tu tráfico sea indistinguible del de un usuario normal — exactamente lo que necesitas para scrapear Reddit con proxies de forma sostenible.
Ejemplo en Python: requests + old.reddit.com + pool residencial rotativo
Aquí tienes un ejemplo completo y ejecutable que extrae posts de un subreddit usando proxies residenciales de ProxyHat:
import requests
from bs4 import BeautifulSoup
import time
import json
import random
# Configuración de ProxyHat - pool residencial rotativo
PROXY_URL = "http://user-country-US:PASSWORD@gate.proxyhat.com:8080"
HEADERS = {
"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",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
"Connection": "keep-alive",
}
def create_session():
"""Crea una sesión con proxy residencial rotativo."""
session = requests.Session()
session.proxies = {"http": PROXY_URL, "https": PROXY_URL}
session.headers.update(HEADERS)
return session
def scrape_subreddit(subreddit, sort="hot", limit=25):
"""Extrae posts públicos de un subreddit vía old.reddit.com."""
url = f"https://old.reddit.com/r/{subreddit}/{sort}/"
session = create_session()
try:
response = session.get(url, timeout=15)
response.raise_for_status()
except requests.exceptions.HTTPError as e:
if response.status_code == 429:
print("Rate limited. Esperando antes de reintentar...")
time.sleep(60)
return scrape_subreddit(subreddit, sort, limit)
elif response.status_code == 403:
print("Bloqueado (403). Rotando IP...")
return scrape_subreddit(subreddit, sort, limit)
raise
soup = BeautifulSoup(response.text, "html.parser")
posts = []
for thing in soup.select("div.thing.link"):
title_el = thing.select_one("a.title")
score_el = thing.select_one("div.score.unvoted")
author_el = thing.select_one("a.author")
time_el = thing.select_one("time")
comments_el = thing.select_one("a.comments")
if not title_el:
continue
posts.append({
"title": title_el.text.strip(),
"url": title_el.get("href", ""),
"score": score_el.text.strip() if score_el else "0",
"author": author_el.text if author_el else "[deleted]",
"created_utc": time_el.get("datetime", "") if time_el else "",
"comments_link": comments_el.get("href", "") if comments_el else "",
})
if len(posts) >= limit:
break
return posts
# Uso
if __name__ == "__main__":
results = scrape_subreddit("python", sort="hot", limit=10)
for post in results:
print(json.dumps(post, indent=2, ensure_ascii=False))
Este script usa old.reddit.com para obtener HTML simple, parsea los posts con BeautifulSoup, y enruta todo el tráfico a través de un proxy residencial rotativo de ProxyHat. La rotación ocurre automáticamente — cada solicitud puede obtener una IP diferente del pool residencial.
Versión con sesiones sticky y geo-targeting
Si necesitas mantener la misma IP para múltiples solicitudes (por ejemplo, para paginar dentro de un hilo), usa sesiones sticky:
# Sesión sticky: misma IP durante la sesión
SESSION_ID = f"mysession{random.randint(1000,9999)}"
PROXY_STICKY = f"http://user-session-{SESSION_ID}-country-US:PASSWORD@gate.proxyhat.com:8080"
def scrape_post_with_comments(subreddit, post_id):
"""Extrae un post y sus comentarios usando sesión sticky."""
session = requests.Session()
session.proxies = {"http": PROXY_STICKY, "https": PROXY_STICKY}
session.headers.update(HEADERS)
url = f"https://old.reddit.com/r/{subreddit}/comments/{post_id}/"
response = session.get(url, timeout=15)
response.raise_for_status()
soup = BeautifulSoup(response.text, "html.parser")
# Extraer post principal
post = {}
post_area = soup.select_one("div.thing.id-{}".format(f"t3_{post_id}"))
if post_area:
title = post_area.select_one("a.title")
post["title"] = title.text.strip() if title else ""
# Extraer comentarios
comments = []
for comment in soup.select("div.comment"):
author = comment.select_one("a.author")
text = comment.select_one("div.md")
score = comment.select_one("span.score")
comments.append({
"author": author.text if author else "[deleted]",
"text": text.text.strip() if text else "",
"score": score.text.strip() if score else "0",
})
post["comments"] = comments[:50] # Limitar a 50 comentarios
return post
Ejemplo en Node.js: axios + cheerio
Para equipos que trabajan con JavaScript, aquí tienes el equivalente en Node.js:
const axios = require('axios');
const cheerio = require('cheerio');
const HttpsProxyAgent = require('https-proxy-agent');
const PROXY_URL = 'http://user-country-US:PASSWORD@gate.proxyhat.com:8080';
const agent = new HttpsProxyAgent(PROXY_URL);
const HEADERS = {
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ' +
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
};
async function scrapeSubreddit(subreddit, sort = 'hot') {
const url = `https://old.reddit.com/r/${subreddit}/${sort}/`;
try {
const response = await axios.get(url, {
httpsAgent: agent,
headers: HEADERS,
timeout: 15000,
});
const $ = cheerio.load(response.data);
const posts = [];
$('div.thing.link').each((i, el) => {
if (i >= 25) return false;
const title = $(el).find('a.title').text().trim();
const score = $(el).find('div.score.unvoted').text().trim();
const author = $(el).find('a.author').text() || '[deleted]';
const timeAttr = $(el).find('time').attr('datetime') || '';
posts.push({ title, score, author, created_utc: timeAttr });
});
return posts;
} catch (error) {
if (error.response?.status === 429) {
console.log('Rate limited. Reintentando en 60s...');
await new Promise(r => setTimeout(r, 60000));
return scrapeSubreddit(subreddit, sort);
}
throw error;
}
}
// Uso
scrapeSubreddit('datascience').then(posts => {
console.log(JSON.stringify(posts, null, 2));
});
Ejemplo con curl para pruebas rápidas
# Probar un proxy residencial con curl
curl -x http://user-country-US:PASSWORD@gate.proxyhat.com:8080 \
-H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36" \
-H "Accept: text/html" \
"https://old.reddit.com/r/python/hot/" \
-o reddit_page.html
# Verificar que la IP está rotando
curl -x http://user-country-US:PASSWORD@gate.proxyhat.com:8080 \
https://httpbin.org/ip
Manejo de rate limits: la progresión 429 → 403
Reddit implementa un sistema de rate limiting en capas que todo scraper debe entender:
Capa 1: Rate limit por IP (HTTP 429)
La primera señal es un código 429 Too Many Requests. Reddit limita por IP, con umbrales que varían según el endpoint:
- Páginas de subreddit: ~60 solicitudes/minuto por IP
- Páginas de comentarios: ~30 solicitudes/minuto por IP
- Búsqueda: ~10 solicitudes/minuto por IP
La respuesta incluye headers x-ratelimit-remaining y x-ratelimit-reset que debes monitorizar.
Capa 2: Rate limit por User-Agent
Reddit también aplica cuotas por User-Agent. Si muchas IPs comparten el mismo User-Agent genérico, el límite se comparte. Esto es relevante cuando usas proxies — rotar IPs no ayuda si tu User-Agent es el mismo y está saturado.
Capa 3: Escalada a 403 Forbidden
Si persistes después de múltiples 429 sin respetar los rate limits, Reddit escala a 403 Forbidden. Esto significa que la IP (o el rango) ha sido bloqueada temporal o permanentemente. Con proxies datacenter, este bloqueo es más probable porque los rangos de IPs están identificados. Con proxies residenciales, la rotación natural del pool mitiga este riesgo.
Estrategia de manejo
import time
import requests
def fetch_with_retry(session, url, max_retries=3):
"""Realiza solicitudes con reintentos inteligentes."""
for attempt in range(max_retries):
try:
response = session.get(url, timeout=15)
# Monitorizar rate limits
remaining = response.headers.get("x-ratelimit-remaining")
reset = response.headers.get("x-ratelimit-reset")
if remaining and int(remaining) < 5:
wait_time = int(reset) if reset else 60
print(f"Rate limit bajo ({remaining} restantes). "
f"Esperando {wait_time}s...")
time.sleep(wait_time)
if response.status_code == 200:
return response
elif response.status_code == 429:
wait = min(2 ** attempt * 30, 300) # Backoff exponencial
print(f"429 recibido. Esperando {wait}s...")
time.sleep(wait)
elif response.status_code == 403:
print("403 - IP bloqueada. Rotando...")
time.sleep(10)
return None # El pool residencial rotará la IP
else:
response.raise_for_status()
except requests.exceptions.RequestException as e:
print(f"Error en intento {attempt + 1}: {e}")
if attempt < max_retries - 1:
time.sleep(5 * (attempt + 1))
return None
Mejores prácticas para scrapear Reddit con proxies
1. Configura un User-Agent realista e informativo
No uses el User-Agent por defecto de tu librería HTTP. Reddit lo bloquea rápidamente. Usa un formato que incluya información de contacto:
# Bien: User-Agent descriptivo
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(compatible; ResearchBot/1.0; contact@ejemplo.com)"
# Mal: User-Agent genérico
"python-requests/2.31.0"
Para scraping de HTML (no API), usa un User-Agent de navegador real y completo, como en los ejemplos anteriores.
2. Respeta los rate limits
Monitoriza los headers x-ratelimit-* y ajusta tu velocidad. Una regla práctica: mantén un mínimo de 2 segundos entre solicitudes por IP. Con un pool de proxies residenciales, puedes paralelizar múltiples IPs, pero cada IP individual debe respetar este ritmo.
3. Cachea agresivamente
Los datos de Reddit no cambian cada segundo. Implementa un sistema de caché para evitar solicitudes redundantes:
import hashlib
import os
import json
from datetime import datetime, timedelta
cache_dir = "reddit_cache"
os.makedirs(cache_dir, exist_ok=True)
def cache_key(url):
return hashlib.md5(url.encode()).hexdigest()
def cached_get(session, url, ttl_hours=6):
"""GET con caché local."""
key = cache_key(url)
filepath = os.path.join(cache_dir, f"{key}.json")
# Verificar caché
if os.path.exists(filepath):
with open(filepath, "r") as f:
cached = json.load(f)
cached_time = datetime.fromisoformat(cached["timestamp"])
if datetime.now() - cached_time < timedelta(hours=ttl_hours):
return cached["data"]
# Solicitar
response = fetch_with_retry(session, url)
if response is None:
return None
# Guardar en caché
with open(filepath, "w") as f:
json.dump({
"timestamp": datetime.now().isoformat(),
"data": response.text,
}, f)
return response.text
4. Usa old.reddit.com de forma consistente
La interfaz old.reddit.com ofrece HTML más limpio y estable. Los selectores CSS cambian con menos frecuencia y el contenido se carga sin JavaScript dinámico. Esto reduce la fragilidad de tus scrapers.
5. Distribuye las solicitudes en el tiempo
No hagas ráfagas de solicitudes. Usa delays aleatorios entre solicitudes para simular comportamiento humano:
import random
import time
def human_delay(min_sec=1.5, max_sec=4.0):
"""Pausa aleatoria entre solicitudes."""
time.sleep(random.uniform(min_sec, max_sec))
# Entre cada solicitud:
human_delay()
6. Rotación inteligente de proxies
Con ProxyHat, puedes controlar la rotación mediante el formato del username:
- Rotación por solicitud: Cada request obtiene una IP nueva — ideal para scraping masivo de feeds
- Sesión sticky: Mantén la misma IP durante una sesión — necesario para paginación y hilos de comentarios
- Geo-targeting: Usa
country-US,country-DE, etc., para acceder a contenido regional
Para más detalles sobre configuración de proxies, consulta nuestra guía de configuración de proxies residenciales.
Casos de uso reales
Análisis de sentimiento de marca
Monitoriza menciones de tu marca en subreddits relevantes. Extrae posts y comentarios, analiza el sentimiento con NLP, y genera alertas cuando el sentimiento cambie significativamente.
Investigación de mercado
Identifica tendencias emergentes en subreddits de tu industria. Los posts en r/programming, r/datascience, o contienen opiniones tempranas sobre productos y tecnologías.
Tracking de memes y cultura
Los memes nacen en Reddit antes de llegar a otras plataformas. Rastrea subreddits como r/memes, r/dankmemes, o nichos específicos para detectar tendencias virales antes que la competencia.
Monitoreo de competencia
Sigue conversaciones sobre productos competidores. Los usuarios de Reddit son notablemente honestos en sus críticas — datos valiosos para product teams.
Cuándo usar la API oficial en lugar de scraping
El scraping no siempre es la mejor opción. Considera la API oficial cuando:
- Presupuesto disponible: Si puedes pagar los costos de la API, obtienes datos estructurados en JSON, sin necesidad de parsear HTML
- Datos en tiempo real: La API de WebSocket de Reddit ofrece actualizaciones en tiempo real que el scraping no puede igualar
- Proyectos pequeños: Para menos de 100 solicitudes/minuto, la capa gratuita puede ser suficiente
- Datos de moderación: Si necesitas datos de moderación (reportes, acciones de mods), la API es la única opción legítima
- Fiabilidad crítica: Los cambios en el HTML de Reddit pueden romper tus scrapers; la API ofrece estabilidad contractual
Para proyectos de investigación, análisis de sentimiento a escala, o monitorización de múltiples subreddits, el scraping con proxies residenciales sigue siendo la opción más económica y flexible.
Puntos clave
Recuerda estos principios al scrapear Reddit con proxies:
- Los cambios de precios de la API de Reddit en 2023 hicieron que el scraping de datos públicos sea la opción viable para equipos con presupuesto limitado
old.reddit.comes tu mejor aliado: HTML simple, estable, y fácil de parsear- Usa proxies residenciales para scraping intensivo; datacenter solo para volúmenes bajos
- Respeta siempre los rate limits: monitoriza headers, implementa backoff exponencial, y pausa entre solicitudes
- La progresión 429 → 403 es real: ignora los rate limits y tu IP será bloqueada
- Cachea agresivamente — los datos de Reddit no cambian cada segundo
- Solo accede a datos públicos; nunca evites autenticación ni scrapees contenido privado
- Cuando la API oficial sea suficiente para tu caso de uso y presupuesto, úsala
Si necesitas extraer datos públicos de Reddit a escala, los planes de proxies residenciales de ProxyHat ofrecen la infraestructura necesaria con rotación automática de IPs y geo-targeting por país y ciudad. Para explorar qué ubicaciones están disponibles, consulta nuestra página de ubicaciones.






