Scraping de Site Dinâmico

Sites dinâmicos carregam conteúdo usando JavaScript após o carregamento inicial da página. Este guia mostra como coletar dados desses sites usando o endpoint de navegador da FourA.

O problema

Quando você envia uma request HTTP padrão para um site com uso intenso de JavaScript, você obtém a estrutura HTML, mas não o conteúdo real. Os dados que você precisa (listagens de produtos, preços, resultados de busca) são carregados pelo JavaScript após a página renderizar em um navegador.

Isso é cada vez mais comum com frameworks modernos como React, Vue, Angular e Next.js.

A solução: Browser Requests

O endpoint de navegador da FourA (POST /api/browser/) abre sua URL em uma instância do navegador Chrome que:

  1. Carrega a página
  2. Executa todo o JavaScript
  3. Aguarda a renderização do conteúdo
  4. Retorna o HTML totalmente renderizado

Passo 1: Identifique o que você precisa

Antes de fazer a request, visite a página de destino no seu navegador e use o DevTools (F12) para encontrar um trecho de texto ou elemento que confirme que o conteúdo foi carregado. Por exemplo:

  • Um nome de produto que aparece após o JS renderizar
  • Uma classe CSS como product-grid no HTML renderizado
  • Uma string de texto como "results" que só aparece quando os dados são carregados

Passo 2: Envie uma Browser Request

curl -X POST https://eu.api.foura.ai/api/browser/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/products",
    "timeout_ms": 15000,
    "checkText": "product-grid"
  }'

A opção checkText instrui o FourA a verificar se "product-grid" está na página assim que o carregamento for concluído. Se não estiver, a request retorna como falha com checkText:product-grid not found, e uma request com falha não é cobrada. checkText não faz o FourA esperar mais tempo pelo texto.

Passo 3: Fazer o parse do HTML

A response contém o HTML totalmente renderizado no campo body. Faça o parse com sua biblioteca de preferência:

Python (BeautifulSoup)

import requests
from bs4 import BeautifulSoup

resp = requests.post("https://eu.api.foura.ai/api/browser/", headers={
    "X-API-Key": "YOUR_API_KEY",
    "Content-Type": "application/json"
}, json={
    "url": "https://example.com/products",
    "timeout_ms": 15000,
    "checkText": "product-grid"
})

html = resp.json()["body"]
soup = BeautifulSoup(html, "html.parser")

for product in soup.select(".product-card"):
    name = product.select_one(".product-name").text.strip()
    price = product.select_one(".product-price").text.strip()
    print(f"{name}: {price}")

Node.js (cheerio)

import * as cheerio from 'cheerio';

const resp = await fetch('https://eu.api.foura.ai/api/browser/', {
  method: 'POST',
  headers: { 'X-API-Key': 'YOUR_API_KEY', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    url: 'https://example.com/products',
    timeout_ms: 15000,
    checkText: 'product-grid'
  })
});

const { body: html } = await resp.json();
const $ = cheerio.load(html);

$('.product-card').each((i, el) => {
  console.log($(el).find('.product-name').text(), $(el).find('.product-price').text());
});

Solução de problemas

Ainda está recebendo conteúdo vazio?

  • Verifique se a página realmente usa renderização em JavaScript (compare "Exibir código-fonte da página" com o DevTools)
  • Aumente timeout_ms: algumas páginas demoram para carregar
  • Verifique se a página exige autenticação ou cookies (use o parâmetro cookies)

Recebendo uma página de verificação?

  • Para requests únicas/HTTP, mude para o endpoint de proxy (POST /api/proxy/) para rotação automática de IP.
  • Para rotear um request de navegador por um proxy, passe o parâmetro proxy do endpoint de navegador. O endpoint de proxy encapsula apenas requests únicas/HTTP, não requests de navegador.

O parâmetro proxy recebe o ID de proxy opaco retornado por uma response anterior, nunca um endereço de proxy próprio. Execute uma chamada POST /api/proxy/ (ou POST /api/auto/) primeiro, leia o campo proxy retornado e então fixe ele:

# Step 1: let FourA find a working exit. The response carries "proxy": "A1B2C3".
curl -X POST "https://eu.api.foura.ai/api/proxy/" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"maxTries": 5, "request": {"method": "GET", "url": "https://example.com/products"}}'

# Step 2: render through that same exit.
curl -X POST "https://eu.api.foura.ai/api/browser/" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com/products", "proxy": "A1B2C3", "timeout_ms": 20000}'

Enviar um endereço em vez de um ID retorna como 400 Invalid proxy format. O padrão completo está em Reutilizar um Proxy Entre Requests.

Próximos Passos

Atualizado em: 27 de setembro de 2026