Usar Proxies em R com httr2 e rvest: Guia Prático para Coleta de Dados

Aprenda a configurar proxies residenciais em R usando httr2 (req_proxy) e rvest, com geo-targeting, sessões sticky, SOCKS5, paginação e páginas renderizadas em JS.

Using Proxies in R: A Code-First Guide with httr2 and rvest
Neste artigo

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.0 por defeito, que é instantaneamente bloqueado. Usa sempre req_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. Usa resp_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.

Perguntas frequentes

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.

Pronto para começar?

Proxies residenciais, ISP e móveis em mais de 148 países. Crie uma conta grátis.

Criar conta grátis
← Voltar ao Blog