Porque precisas de um R proxy para coleta de dados
Se já tentaste raspar um site com rvest e recebeste um HTTP 403 ao terceiro pedido, não estás sozinho. A maioria dos sites modernos usa rate limiting por IP e sistemas anti-bot que bloqueiam endereços de datacenter em segundos. Usar proxies em R — especificamente proxies residenciais — resolve este problema encaminhando cada pedido através de um IP real de um ISP, tornando o teu tráfego indistinguível de um visitante humano comum.
O ecossistema R evoluiu muito. O pacote httr foi substituído por httr2, que oferece uma API baseada em request() com pipelines reutilizáveis, retries nativos e throttling. Combinado com rvest para parsing e purrr para iteração funcional, tens um stack moderno e resiliente para web scraping in R.
Neste guia vais aprender a configurar httr2 req_proxy com o gateway gate.proxyhat.com, aplicar geo-targeting no nome de utilizador, rodar sessões por pedido e lidar com páginas JavaScript — tudo com código executável.
Stack moderna: httr2 + rvest + purrr
O fluxo típico é: construir um objeto request, adicionar proxy e headers, executar com req_perform() e depois passar o corpo da resposta ao rvest::read_html(). O httr2 separa a configuração da execução, o que facilita testar e reutilizar.
Exemplo 1: pedido básico com proxy HTTP
library(httr2)
library(rvest)
# Credenciais ProxyHat
proxy_user <- "user-country-PT"
proxy_pass <- "a_sua_password"
req <- request("https://httpbin.org/ip") |>
req_proxy(
url = "http://gate.proxyhat.com",
port = 8080,
username = proxy_user,
password = proxy_pass
) |>
req_user_agent("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36") |>
req_timeout(30)
resp <- req_perform(req)
if (resp_status(resp) == 200) {
body <- resp_body_string(resp)
page <- read_html(body)
print(page)
} else {
message("Erro HTTP: ", resp_status(resp))
}
Aqui o nome de utilizador user-country-PT diz ao gateway ProxyHat para usar um IP residencial em Portugal. Se omitires a flag de país, o gateway escolhe um IP aleatório do pool global.
Exemplo 2: extrair uma tabela com rvest
library(httr2)
library(rvest)
library(dplyr)
scrape_table <- function(url, user, pass) {
req <- request(url) |>
req_proxy("http://gate.proxyhat.com", 8080, user, pass) |>
req_user_agent("Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36") |>
req_retry(max_tries = 3, max_seconds = 60) |>
req_throttle(1 / 2) # 1 pedido a cada 2 segundos
resp <- tryCatch(
req_perform(req),
error = function(e) {
message("Falha: ", conditionMessage(e))
return(NULL)
}
)
if (is.null(resp) || resp_status(resp) != 200) return(NULL)
read_html(resp_body_string(resp)) |>
html_elements("table") |>
first() |>
html_table()
}
df <- scrape_table(
"https://example.com/dados",
"user-country-DE",
"a_sua_password"
)
glimpse(df)
O req_retry() reexecuta automaticamente até 3 vezes em falhas transitórias (5xx e timeouts). O req_throttle() garante um intervalo mínimo de 2 segundos entre pedidos — essencial para não saturar o alvo.
Porque proxies residenciais e não datacenter
Proxies datacenter são baratos e rápidos, mas os seus IPs pertencem a ranges conhecidos (AWS, Hetzner, OVH) que aparecem em listas negras públicas. Sites como Amazon, Google e plataformas de e-commerce bloqueiam estes ranges por defeito. Proxies residenciais usam IPs atribuídos por ISPs reais a lares reais, pelo que o risco de bloqueio é drasticamente menor.
| Característica | Datacenter | Residencial |
|---|---|---|
| Velocidade média | ~50 ms | ~200–800 ms |
| Risco de bloqueio | Alto (ranges conhecidos) | Baixo (IPs de ISP) |
| Custo por GB | $0.5–$1.5 | $3–$15 |
| Ideal para | APIs, tarefas internas | Scraping de sites com anti-bot |
Para coleta de dados em sites com proteção anti-bot ou restrições geográficas, o proxy residencial é a escolha correta. Para tarefas internas ou APIs sem rate limiting agressivo, o datacenter basta. O ProxyHat oferece ambos — consulta a página de preços para comparar.
Geo-targeting e sessões sticky no nome de utilizador
O ProxyHat codifica parâmetros de rotação diretamente no nome de utilizador. Isto significa que não precisas de configurar nada no lado do cliente além do req_proxy(). Basta alterar a string do username.
Formatos suportados
# País específico
user <- "user-country-GB"
# País + cidade
user <- "user-country-GB-city-london"
# Sessão sticky (mesmo IP em todos os pedidos)
user <- "user-session-abc123"
# País + sessão sticky
user <- "user-country-DE-session-sess42"
A flag session- é crítica quando precisas de manter estado entre pedidos — por exemplo, num fluxo de login ou num carrinho de compras. Sem ela, cada pedido recebe um IP novo do pool.
Exemplo 3: SOCKS5 na porta 1080
library(httr2)
req <- request("https://httpbin.org/headers") |>
req_proxy(
url = "socks5://gate.proxyhat.com",
port = 1080,
username = "user-country-US-session-myid",
password = "a_sua_password"
) |>
req_user_agent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)")
resp <- req_perform(req)
cat(resp_body_string(resp))
O SOCKS5 é útil quando o tráfego precisa de atravessar firewalls que bloqueiam ligações HTTP CONNECT ou quando queres túnel UDP (não suportado por todos os gateways). A porta 1080 é o padrão SOCKS5 do ProxyHat.
Exemplo prático: tabela paginada com rotação por página
Vamos raspar uma tabela paginada com 50 páginas, rodando a sessão a cada pedido e usando purrr::map_dfr para concatenar os resultados num tibble único.
library(httr2)
library(rvest)
library(purrr)
library(dplyr)
library(stringr)
PROXY_PASS <- "a_sua_password"
BASE_URL <- "https://example.com/page/"
# Constrói um pedido com sessão única por página
build_req <- function(page_num) {
session_id <- paste0("pg", page_num, "-", as.integer(Sys.time()))
user <- paste0("user-country-GB-session-", session_id)
request(paste0(BASE_URL, page_num)) |>
req_proxy("http://gate.proxyhat.com", 8080, user, PROXY_PASS) |>
req_user_agent(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36"
) |>
req_headers(
`Accept` = "text/html,application/xhtml+xml",
`Accept-Language` = "en-GB,en;q=0.9"
) |>
req_retry(max_tries = 4, max_seconds = 90) |>
req_throttle(1 / 3) # 1 pedido a cada 3s
}
# Extrai a tabela de uma página
scrape_page <- function(page_num) {
tryCatch({
resp <- req_perform(build_req(page_num))
if (resp_status(resp) != 200) return(NULL)
tbl <- read_html(resp_body_string(resp)) |>
html_elements("table.data-table") |>
html_table()
if (length(tbl) == 0) return(NULL)
tbl[[1]] |> mutate(page = page_num)
}, error = function(e) {
message("Erro na página ", page_num, ": ", conditionMessage(e))
NULL
})
}
# Executa as 50 páginas
all_data <- map_dfr(1:50, scrape_page)
cat("Linhas coletadas:", nrow(all_data), "\n")
glimpse(all_data)
Cada página usa uma sessão distinta (pg1-..., pg2-...), garantindo um IP diferente por pedido. O map_dfr concatena automaticamente todos os tibbles. Se uma página falhar após 4 retries, a função devolve NULL e o map_dfr ignora-a sem quebrar o pipeline.
Concorrência com furrr
Para acelerar, podes paralelizar com furrr::future_map_dfr. Mantém a concorrência moderada (4–8 workers) para não exceder limites do gateway:
library(furrr)
plan(multisession, workers = 4)
all_data <- future_map_dfr(1:50, scrape_page, .options = furrr_options(seed = TRUE))
Com 4 workers e throttle de 3s por worker, obtens ~1.3 pedidos/segundo — uma taxa sustentável que raramente aciona anti-bot.
Páginas JavaScript com read_html_live()
Muitos sites modernos renderizam conteúdo via JavaScript. O read_html() não executa JS, pelo que precisas de um browser headless. O rvest oferece read_html_live(), baseado no pacote chromote, que controla um Chrome headless.
library(rvest)
# Configura o proxy ao nível do Chrome
session <- chromote_session(
proxy = list(
proxyRules = "http=gate.proxyhat.com:8080;socks5=gate.proxyhat.com:1080"
)
)
# Navega e espera pelo seletor
page <- read_html_live(
"https://example.com/js-app",
session = session,
wait = css("div.results-loaded", timeout = 15000)
)
dados <- page |>
html_elements("div.result-card") |>
map(~ list(
titulo = html_element(.x, "h3") |> html_text2(),
preco = html_element(.x, ".price") |> html_text2()
)) |>
list_rbind()
O argumento wait bloqueia até que o seletor CSS apareça ou o timeout expire (15 segundos neste caso). Isto é mais fiável do que Sys.sleep() arbitrário.
Erros comuns e como evitá-los
- Esquecer o esquema no URL do proxy:
req_proxy("gate.proxyhat.com", ...)falha. Usa sempre"http://gate.proxyhat.com"ou"socks5://gate.proxyhat.com". - Usar a porta errada: HTTP é 8080, SOCKS5 é 1080. Trocá-las causa falhas de handshake.
- Não definir User-Agent: httr2 envia
httr2/1.0.0por defeito, que é instantaneamente bloqueado. Usa semprereq_user_agent()com uma string de browser real. - Throttle demasiado agressivo: 10 pedidos/segundo num site com Cloudflare resulta em 429s. Começa com 1 pedido a cada 2–3 segundos.
- Ignorar encoding: se o site usa UTF-8 mas a resposta chega como Latin-1,
read_html()pode mostrar caracteres corrompidos. Usaresp_body_string(resp, encoding = "UTF-8")se necessário.
Ética e conformidade
Coletar dados públicos é legal na maioria das jurisdições, mas há limites. Para sujeitos na União Europeia, o GDPR rege o processamento de dados pessoais — mesmo dados publicamente disponíveis podem ser considerados dados pessoais se identificarem um indivíduo. Se estás a coletar dados de utilizadores da UE, considera anonimizar ou agregar.
Boas práticas:
- Respeita o
robots.txt— verifica sempre antes de raspar. - Consulta os Termos de Serviço do site; alguns proíbem scraping explicitamente.
- Se existe uma API oficial, usa-a. É mais estável e legalmente mais segura.
- Limita a taxa de pedidos para não degradar o serviço do alvo.
- Não coletes dados pessoais sem base legal.
Para casos de uso específicos, consulta as páginas de web scraping e SERP tracking. A lista completa de geolocalizações disponíveis está em locations.
ProxyHat SDK para pipelines mistos
Se a tua equipa usa R para análise mas Python ou Node.js para coleta, o padrão é idêntico. O gateway gate.proxyhat.com:8080 funciona com qualquer cliente HTTP que suporte proxies com autenticação. A documentação completa está em docs.proxyhat.com.
Num pipeline típico, o Python coleta via ProxyHat e guarda num Parquet; o R lê o Parquet com arrow::read_parquet() para análise. O proxy é transparente em ambos os lados — só muda a string de username para geo-targeting.
Pontos-chave
- Usa
httr2::req_proxy("http://gate.proxyhat.com", 8080, user, pass)para configurar proxies residenciais em R.- Codifica geo-targeting e sessões no username:
user-country-GB-city-london-session-abc.- Combina
req_retry()+req_throttle()para resiliência e cortesia.- Para JS, usa
read_html_live()com proxy ao nível do Chrome.- Proxies residenciais (~200 ms) custam mais que datacenter (~50 ms) mas evitam 90% dos bloqueios anti-bot.
- Sempre define
req_user_agent()— o UA padrão do httr2 é bloqueado instantaneamente.
FAQ
O que é usar proxies em R?
Usar proxies em R significa encaminhar pedidos HTTP feitos por pacotes como httr2, rvest ou curl através de um servidor intermediário que substitui o teu IP por outro. No caso de proxies residenciais, esse IP pertence a um ISP real, tornando o tráfego indistinguível de um visitante humano. Configura-se em httr2 com req_proxy(), especificando host, porta, username e password.
Porque usar proxies em R é importante para coleta de dados?
Sites modernos bloqueiam IPs de datacenter e aplicam rate limiting por endereço. Sem proxy, um scraper em R faz 5–10 pedidos antes de receber 403 ou 429. Com proxies residenciais, cada pedido pode vir de um IP diferente, distribuindo a carga e evitando bloqueios. Isto é essencial para coleta de dados em escala — séries temporais de preços, monitorização SERP ou extração de catálogos.
Que tipo de proxy funciona melhor para R?
Depende do alvo. Para sites com anti-bot forte (Cloudflare, PerimeterX), proxies residenciais são a melhor escolha — IPs de ISP real passam por humanos. Para APIs internas ou endpoints sem proteção, proxies datacenter são mais rápidos e baratos (~50 ms vs ~200 ms). Em R, ambos configuram-se da mesma forma com req_proxy(); a diferença está no tipo de pool que o gateway ProxyHat atribui.
Como evitar bloqueios ao usar proxies em R?
Combina quatro técnicas: (1) roda a sessão a cada pedido com user-session-xxx no username; (2) usa req_throttle() para limitar a 1 pedido a cada 2–3 segundos; (3) define um User-Agent realista com req_user_agent(); (4) adiciona req_retry(max_tries = 4) para recuperar de falhas transitórias. Para sites com JS, usa read_html_live() com proxy ao nível do Chrome.
Posso usar SOCKS5 com httr2 em R?
Sim. Especifica req_proxy("socks5://gate.proxyhat.com", 1080, user, pass). O httr2 delega ao libcurl, que suporta SOCKS5 nativamente. A porta 1080 é o padrão SOCKS5 do ProxyHat. SOCKS5 é útil quando precisas de túnel mais opaco ou quando firewalls bloqueiam HTTP CONNECT.






