Se a sua equipa de dados precisa de conversas autênticas — opiniões de consumidores, tendências de memes, sinais de sentimento — o Reddit é um dos repositórios mais ricos da internet. Mas desde as mudanças drásticas na API em 2023, o acesso a esses dados ficou consideravelmente mais caro e restrito. Este guia explica como aceder a dados públicos do Reddit de forma legítima, usando proxies para distribuir pedidos e manter a fiabilidade.
Aviso importante: Este artigo aborda apenas o acesso a dados publicamente disponíveis. Respeite os Termos de Serviço do Reddit, o robots.txt e as leis aplicáveis (CFAA nos EUA, GDPR na UE). Se os dados exigem autenticação, use a API oficial. Scraping irresponsável pode violar a lei e prejudicar a plataforma.
O Cenário em Mudança da API do Reddit
Em julho de 2023, o Reddit implementou uma nova estrutura de preços para a sua API que alterou fundamentalmente o ecossistema de acesso a dados. Antes, a API era gratuita e generosa — qualquer pessoa podia extrair milhões de posts sem pagar um cêntimo. Com as novas regras:
- Preço por pedido: a API passou a cobrar aproximadamente US$ 0,24 por 1.000 pedidos para dados de nível superior, o que se traduz em custos de cinco dígitos mensais para projetos de escala média.
- Quotas reduzidas: aplicações gratuitas ficaram limitadas a 100 pedidos/minuto e 10.000 pedidos/dia — insuficiente para qualquer análise séria.
- Restrições de termos: o novo acordo proíbe o uso de dados do Reddit para treinar modelos de IA sem um contrato comercial separado.
O resultado? Equipas de pesquisa de mercado, análise de sentimento e monitorização de marcas que antes dependiam da API gratuita começaram a procurar alternativas — e o scraping de conteúdo público tornou-se uma opção viável para projetos com orçamento limitado.
API Oficial vs. Scraping — Comparação Rápida
| Aspecto | API Oficial (Gratuita) | API Oficial (Paga) | Scraping com Proxies |
|---|---|---|---|
| Custo | Gratuito (limitado) | US$ 0,24/1K pedidos | d>Custo do proxy (~US$ 1-5/GB)|
| Quota diária | 10.000 pedidos | Sob contrato | Limitado pela taxa de rotação |
| Qualidade dos dados | Estruturado (JSON) | Estruturado (JSON) | HTML (requer parsing) |
| Comentários aninhados | Sim, com profundidade | Sim, com profundidade | Parcial (flat na maioria) |
| Risco de bloqueio | Baixo (termos claros) | Baixo | Médio (requer gestão) |
Que Dados Públicos Estão Acessíveis
O Reddit expõe uma quantidade significativa de dados sem exigir login. Eis o que pode aceder legitimamente:
Feeds de Subreddits
Cada subreddit serve uma página HTML pública em https://old.reddit.com/r/nome/ com os 25 posts mais recentes (hot), ou variantes como new, top, rising. Estas páginas contêm títulos, scores, número de comentários, autor e timestamp — tudo em HTML parseável.
Páginas de Posts
A URL https://old.reddit.com/r/nome/comments/id/title/ mostra o post completo e os comentários de primeiro nível. Os comentários aninhados requerem mais atenção, mas os dados principais estão acessíveis.
Páginas de Utilizador
Perfis públicos em https://old.reddit.com/user/nome/ mostram atividade recente. Nem todos os perfis são públicos, mas muitos são.
Pesquisa
A pesquisa do Reddit em https://old.reddit.com/search?q=termo funciona sem autenticação, embora seja mais sujeita a rate limiting.
Porquê old.reddit.com?
O old.reddit.com é a versão legada do site que o Reddit mantém para utilizadores que preferem a interface clássica. Para scraping, é significativamente superior:
- HTML mais simples e sem JavaScript pesado — mais fácil de fazer parsing.
- Menos proteções anti-bot em comparação com o site principal.
- Estrutura de página previsível e consistente.
- Não requer JavaScript rendering —
requestsoucurlbastam.
Seleção de Proxies para Reddit
A escolha entre datacenter e proxies residenciais depende do volume e do padrão de scraping:
| Característica | Datacenter | Residencial | Móvel |
|---|---|---|---|
| Velocidade | Rápido (baixa latência) | Moderado | Variável |
| Custo | Baixo (~US$ 0,5-2/GB) | Médio (~US$ 3-8/GB) | Alto (~US$ 8-15/GB) |
| Risco de bloqueio | Alto (IPs são conhecidos) | Baixo (IPs parecem reais) | Muito baixo |
| Ideal para | Volume baixo, testes | Volume médio/alto, produção | Anti-bot extremo |
| Geo-targeting | Limitado | País e cidade | País e operadora |
Para a maioria dos projetos de Reddit data scraping, proxies residenciais oferecem o melhor equilíbrio entre custo e fiabilidade. O Reddit bloqueia ranges de IPs de datacenter agressivamente — se tentar extrair mais do que algumas centenas de páginas por dia com um IP de datacenter, vai encontrar o erro 429 rapidamente.
Se o seu projeto envolve scraping distribuído geograficamente (por exemplo, comparar tendências em diferentes regiões), os proxies residenciais com geo-targeting são essenciais. Com a ProxyHat, pode especificar o país diretamente no username.
Exemplo Prático em Python — Scraping com Proxies Residenciais
Vamos extrair os posts de um subreddit usando old.reddit.com, requests e BeautifulSoup, com rotação de IPs residenciais.
import requests
from bs4 import BeautifulSoup
import time
import random
# Configuração do proxy residencial ProxyHat
PROXY_URL = "http://user-country-US:PASSWORD@gate.proxyhat.com:8080"
HEADERS = {
"User-Agent": "DataResearchBot/1.0 (+https://exemplo.com/bot)",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Accept-Language": "en-US,en;q=0.5",
}
session = requests.Session()
session.proxies = {"http": PROXY_URL, "https": PROXY_URL}
session.headers.update(HEADERS)
def scrape_subreddit(subreddit, sort="hot", limit=5):
"""Extrai posts de um subreddit público."""
url = f"https://old.reddit.com/r/{subreddit}/{sort}/"
resp = session.get(url, timeout=15)
if resp.status_code == 429:
print("Rate limited! A aguardar antes de tentar novamente...")
time.sleep(60)
resp = session.get(url, timeout=15)
if resp.status_code != 200:
print(f"Erro {resp.status_code} ao aceder /r/{subreddit}")
return []
soup = BeautifulSoup(resp.text, "html.parser")
posts = []
for thing in soup.select("div.thing"):
title_el = thing.select_one("a.title")
if not title_el:
continue
score_el = thing.select_one("div.score.unvoted")
comments_el = thing.select_one("a.comments")
author_el = thing.select_one("a.author")
time_el = thing.select_one("time")
posts.append({
"title": title_el.text.strip(),
"url": title_el["href"],
"score": int(score_el.text) if score_el and score_el.text != "•" else 0,
"comments": comments_el.text.split()[0] if comments_el else "0",
"author": author_el.text if author_el else "[deleted]",
"created_utc": time_el["datetime"] if time_el else None,
})
if len(posts) >= limit:
break
return posts
# Utilização
data = scrape_subreddit("python", sort="hot", limit=25)
for post in data:
print(f"[{post['score']}] {post['title'][:60]}")
Rotação de Sessões Sticky
Para scraping sequencial onde precisa de manter a mesma IP por algum tempo (por exemplo, navegar entre páginas de um subreddit), use sessões sticky:
import uuid
# Gerar um ID de sessão único
session_id = uuid.uuid4().hex[:16]
# Sessão sticky — mantém o mesmo IP residencial por até 30 minutos
STICKY_PROXY = f"http://user-country-US-session-{session_id}:PASSWORD@gate.proxyhat.com:8080"
sticky_session = requests.Session()
sticky_session.proxies = {"http": STICKY_PROXY, "https": STICKY_PROXY}
sticky_session.headers.update(HEADERS)
# Agora pode fazer múltiplos pedidos com o mesmo IP
page1 = sticky_session.get("https://old.reddit.com/r/python/hot/")
time.sleep(3)
page2 = sticky_session.get("https://old.reddit.com/r/python/new/")
Exemplo em Node.js — Scraping com Axios e Cheerio
const axios = require('axios');
const cheerio = require('cheerio');
const PROXY_URL = 'http://user-country-US:PASSWORD@gate.proxyhat.com:8080';
const headers = {
'User-Agent': 'DataResearchBot/1.0 (+https://exemplo.com/bot)',
'Accept': 'text/html,application/xhtml+xml',
};
async function scrapeSubreddit(subreddit, sort = 'hot') {
const url = `https://old.reddit.com/r/${subreddit}/${sort}/`;
const resp = await axios.get(url, {
proxy: false,
httpsAgent: new (require('https-proxy-agent'))(PROXY_URL),
headers,
timeout: 15000,
});
const $ = cheerio.load(resp.data);
const posts = [];
$('div.thing').each((i, el) => {
const title = $(el).find('a.title').text().trim();
const score = parseInt($(el).find('div.score.unvoted').text()) || 0;
const author = $(el).find('a.author').text() || '[deleted]';
const commentsText = $(el).find('a.comments').text();
if (title) {
posts.push({ title, score, author, commentsText });
}
});
return posts;
}
scrapeSubreddit('datascience', 'hot')
.then(posts => posts.forEach(p => console.log(`[${p.score}] ${p.title.slice(0, 60)}`)))
.catch(err => console.error('Erro:', err.message));
Lidando com Rate Limits e Bloqueios
O Reddit aplica rate limits em múltiplas camadas. Compreender estas camadas é essencial para qualquer projeto de Reddit data scraping:
Padrão de Rate Limiting do Reddit
- Per-IP: aproximadamente 60 pedidos/minuto por IP para utilizadores não autenticados.
- Per-User-Agent: User-Agents genéricos ou suspeitos recebem quotas mais baixas.
- Escalonamento 429→403: se exceder consistentemente os limites, o Reddit escalona de 429 (tente novamente) para 403 (proibido) — primeiro temporariamente, depois permanentemente para esse IP.
Estratégia de Backoff Exponencial
import requests
import time
import random
PROXY_URL = "http://user-country-US:PASSWORD@gate.proxyhat.com:8080"
def fetch_with_retry(url, max_retries=4):
"""Faz um pedido com backoff exponencial e rotação de proxy."""
for attempt in range(max_retries):
try:
# Rotação de IP a cada tentativa
proxy = f"http://user-country-US-session-{random.randint(1000,9999)}:PASSWORD@gate.proxyhat.com:8080"
resp = requests.get(
url,
proxies={"http": proxy, "https": proxy},
headers={
"User-Agent": "DataResearchBot/1.0 (+https://exemplo.com/bot)",
"Accept": "text/html",
},
timeout=15,
)
if resp.status_code == 200:
return resp
elif resp.status_code == 429:
wait = (2 ** attempt) + random.uniform(0, 2)
print(f"Rate limited. Tentativa {attempt+1}/{max_retries}. Aguardando {wait:.1f}s")
time.sleep(wait)
elif resp.status_code == 403:
print(f"Bloqueado (403). IP pode estar banido. Rotacionando...")
time.sleep(5)
else:
print(f"Status inesperado: {resp.status_code}")
time.sleep(2)
except requests.RequestException as e:
print(f"Erro de rede: {e}")
time.sleep(3)
return None
Dicas para Evitar Bloqueios
- Respeite o limite de 1 pedido/segundo por IP — mesmo que o Reddit permita mais, ser conservador evita problemas.
- Use um User-Agent descritivo — inclua um contacto ou URL. Não use strings genéricas de bibliotecas.
- Varie o timing — adicione jitter aleatório entre pedidos (0,5-2 segundos).
- Monitore a taxa de 429s — se exceder 5%, reduza a velocidade.
- Pare ao ver 403 — significa que o IP foi sinalizado. Troque imediatamente.
Melhores Práticas para Reddit Data Scraping
1. Configure um User-Agent Realista e Descritivo
O Reddit recomenda que bots incluam um identificador de contacto. Um bom User-Agent:
# Bom — descritivo e com contacto
"User-Agent": "SentimentAnalysisBot/2.1 (contacto@exemplo.com)"
# Mau — genérico e suspeito
"User-Agent": "python-requests/2.28.0"
2. Cache Agressivo
Dados do Reddit não mudam a cada minuto. Implemente caching local para evitar pedidos redundantes:
import hashlib
import json
import os
from datetime import datetime, timedelta
CACHE_DIR = "./reddit_cache"
os.makedirs(CACHE_DIR, exist_ok=True)
def cached_fetch(url, ttl_hours=6):
"""Busca dados com cache em disco."""
cache_key = hashlib.md5(url.encode()).hexdigest()
cache_file = os.path.join(CACHE_DIR, f"{cache_key}.json")
if os.path.exists(cache_file):
mtime = datetime.fromtimestamp(os.path.getmtime(cache_file))
if datetime.now() - mtime < timedelta(hours=ttl_hours):
with open(cache_file) as f:
return json.load(f)
# Cache expirado ou inexistente — fazer o pedido
result = fetch_with_retry(url)
if result:
with open(cache_file, 'w') as f:
json.dump({"url": url, "html": result.text, "fetched": str(datetime.now())}, f)
return result
return None
3. Respeite o robots.txt
O robots.txt do Reddit especifica áreas que não devem ser acedidas por bots. Verifique sempre em https://www.reddit.com/robots.txt antes de iniciar o scraping. Note que old.reddit.com tem regras ligeiramente diferentes.
4. Limite o Escopo
Não tente extrair todo o Reddit. Foque em subreddits específicos, intervalos de tempo definidos e dados que realmente precisa. Isto reduz o risco de bloqueio e é mais ético.
5. Use Sticky Sessions para Navegação Sequencial
Quando navega entre páginas relacionadas (subreddit → post → comentários), use a mesma sessão de proxy. Isto parece comportamento humano e evita levantar suspeitas. Com a ProxyHat, basta usar o mesmo session-ID no username.
Considerações Éticas e Quando Usar a API Oficial
Scraping não é intrinsecamente mau, mas exige responsabilidade. Eis alguns princípios:
- Dados pessoais: não coleccione nem armazene dados pessoais identificáveis (nomes reais, emails) além do que é estritamente necessário. O GDPR aplica-se a dados de utilizadores europeus.
- Conteúdo apagado: se um utilizador apagar um post ou comentário, respeite essa decisão. Não armazene versões em cache indefinidamente.
- Impacto no serviço: não sobrecarregue os servidores do Reddit. Se o seu scraping está a degradar a experiência de outros utilizadores, está a ir longe demais.
- Termos de Serviço: leia os Termos do Reddit. Mesmo que o conteúdo seja público, certos usos podem violar os termos.
Quando Preferir a API Oficial
A API oficial é a escolha certa quando:
- Precisa de dados estruturados (JSON limpo em vez de HTML).
- O volume é baixo (menos de 10.000 pedidos/dia).
- Precisa de comentários aninhados com profundidade completa.
- O orçamento permite pagar os custos da API.
- Está a construir um produto comercial que depende de dados do Reddit — os termos de scraping são mais restritivos.
O scraping faz sentido quando a API é proibitivamente cara para o seu caso de uso, quando precisa de dados públicos que não requerem autenticação, ou quando a API não oferece os filtros que precisa. Em qualquer caso, faça-o de forma responsável.
Pontos-Chave (Key Takeaways)
- old.reddit.com é o melhor ponto de partida — HTML simples, sem JavaScript, mais fácil de parsear e com menos proteções anti-bot.
- Proxies residenciais são essenciais para produção — IPs de datacenter são bloqueados rapidamente pelo Reddit. Use proxies residenciais com rotação para volumes médios e altos.
- O escalonamento 429→403 é real — não ignore erros 429. Implemente backoff exponencial e troque de IP ao ver 403.
- User-Agent descritivo é obrigatório — inclua contacto. Nunca use User-Agents de bibliotecas padrão.
- Cache agressivo poupa pedidos — dados do Reddit não mudam a cada segundo. Cache com TTL de 6-12 horas reduz carga e custo.
- Seja ético — respeite dados pessoais, conteúdo apagado e o impacto nos servidores. Considere a API oficial quando possível.
Para projetos de análise de sentimento, monitorização de marcas ou pesquisa de mercado em escala, scrapear Reddit com proxies residenciais é a abordagem mais custo-eficaz — desde que feito com cuidado. A ProxyHat oferece proxies residenciais com geo-targeting por país e cidade, rotação por pedido ou sessões sticky, e uma pool de IPs que suporta scraping de produção.
Pronto para começar? Veja os planos ProxyHat e comece a extrair dados públicos do Reddit em minutos.






