Quando você paga por tráfego de proxy por gigabyte, cada byte de uma página custa o mesmo: o parágrafo que você veio buscar, o menu ao redor dele, o script de analytics, a imagem principal e o arquivo de fonte. A maioria das equipes sabe que as páginas são pesadas. Poucas sabem quanto do que baixam é o dado que realmente mantêm.
Nós medimos isso. Em 8 de outubro de 2026, buscamos as páginas iniciais dos 1.000 principais domínios no ranking Tranco, seguimos um link no estilo artigo a partir de cada uma, e medimos para onde os bytes vão: na transmissão, no HTML e em tudo que um navegador baixa. Este estudo compartilha os resultados, o código que usamos e o que eles significam para orçamentos de scraping.
Principais conclusões
- O conteúdo principal de uma página típica é cerca de 1% do seu HTML. Na página de conteúdo mediana, 3,2 KB de texto principal estavam dentro de 260 KiB de HTML.
- A compressão faz a maior parte da economia de graça. O mesmo HTML chegou como 46 KiB na transmissão, cerca de 5,4 vezes menor, de modo que o texto principal era cerca de 6% dos bytes efetivamente transferidos.
- Scripts inline são a maior fatia isolada do HTML. Em todas as páginas de conteúdo, o JavaScript inline representou 38% dos bytes de HTML, o CSS inline 15% e o SVG inline 10%. O texto principal foi 1,3%.
- Um navegador multiplica a conta. A página de conteúdo mediana puxou 2,6 MB e 81 requisições em um navegador headless. O próprio documento HTML foi cerca de 3% disso.
- Bloquear imagens, mídia e fontes reduz o tráfego do navegador pela metade. Em todas as páginas, isso removeu 48% dos bytes; na página mediana, um carregamento enxuto foi 71% de um carregamento completo.
Como medimos
- Amostra. Os 1.000 principais domínios da lista Tranco (lista Q2K34). Muitos são hosts de API, CDN e rastreamento sem um site de fato, então 431 sites distintos retornaram uma página inicial utilizável. De cada página inicial, seguimos o primeiro link do mesmo site que parecia uma página de conteúdo (um caminho terminando em um slug de quatro ou mais palavras, excluindo páginas de login, jurídicas e de ajuda), o que resultou em 278 páginas de conteúdo utilizáveis.
- Camada de HTML. Uma requisição por página com um User-Agent de navegador desktop comum e compressão habilitada. Registramos os bytes recebidos, descomprimimos e dividimos o HTML em scripts inline, estilos inline (incluindo atributos
style), SVG inline e JSON-LD. Extraímos o conteúdo principal com trafilatura, uma biblioteca de extração open-source, e contamos seus bytes como texto normalizado. - Camada de navegador. Carregamos cada página de conteúdo em um Chromium headless, aguardamos o evento load mais três segundos, e somamos os bytes transferidos para cada resposta por tipo de recurso. Em seguida, carregamos novamente com imagens, mídia e fontes bloqueadas.
- Exclusões. Respostas de erro, respostas não HTML e páginas de bloqueio (páginas de desafio, páginas de “acesso negado” e respostas quase vazias) foram excluídas antes da análise, de modo que os resultados descrevem páginas que de fato serviram conteúdo.
A camada de HTML
| Medida (mediana por página) | Páginas de conteúdo | Páginas iniciais |
|---|---|---|
| Páginas medidas | 278 | 431 |
| Bytes na transmissão | 46 KiB | 51 KiB |
| HTML após descompressão | 260 KiB | 270 KiB |
| Texto de conteúdo principal | 3,2 KB | 1,4 KB |
| Conteúdo principal como fração do HTML | 1,2% | 0,6% |
| Conteúdo principal como fração dos bytes transferidos | 6,2% | 3,1% |
| Todo o texto visível como fração do HTML | 3,6% | 2,4% |
Páginas de conteúdo carregam mais texto do que páginas iniciais, como esperado, mas o padrão geral é o mesmo: o texto que um scraper mantém é uma fração mínima do documento que ele baixa. Mesmo contando cada palavra visível na página, incluindo menus, rodapés e avisos de cookies, o texto foi menos de 4% do HTML.
Para onde vai o resto? Em todas as 278 páginas de conteúdo:
| Parte do HTML | Fração dos bytes de HTML |
|---|---|
| JavaScript inline | 37,5% |
| CSS inline e atributos style | 15,4% |
| SVG inline | 9,8% |
| Dados estruturados JSON-LD | 0,9% |
| Texto de conteúdo principal | 1,3% |
| Marcação, atributos e todo o resto | 35,1% |
O JavaScript inline é o maior bloco isolado: estado de framework, configuração e código de rastreamento embutidos diretamente na página. Sites modernos frequentemente enviam todos os dados da página como um blob JSON em uma tag script e renderizam no cliente, razão pela qual os scripts superam em peso o texto que eventualmente exibem.
Isso também é uma oportunidade. O JSON-LD nessas páginas teve média de menos de 1% do HTML, e onde uma página incorpora seus dados como JSON, esse blob costuma ser muito mais fácil de analisar do que a marcação renderizada. Nossos guias sobre extrair JSON-LD em vez de analisar HTML e encontrar a API por trás da página cobrem ambos.
A compressão importa mais do que qualquer outra coisa nessa camada. A página mediana encolheu 5,4 vezes em trânsito. Apenas 10 das 278 páginas de conteúdo foram servidas sem compressão, mas um scraper que não solicita compressão recebe os 260 KiB completos sempre. Se o seu cliente HTTP envia Accept-Encoding: gzip, deflate, br, você já está pagando por 46 KiB, não 260.
A camada de navegador
Renderizar uma página em um navegador baixa tudo que a página solicita, não apenas o documento.
| Medida (por página de conteúdo) | Valor |
|---|---|
| Páginas medidas no navegador | 274 |
| Bytes transferidos, mediana, carregamento completo | 2,6 MB |
| Metade central das páginas | 1,2 a 4,3 MB |
| Requisições, mediana, carregamento completo | 81 |
| Documento HTML como fração do carregamento completo (mediana) | 3% |
| Texto de conteúdo principal como fração do carregamento completo (mediana) | 0,13% |
Por tipo de recurso, em todos os carregamentos completos:
| Tipo de recurso | Fração dos bytes |
|---|---|
| Imagens | 38,1% |
| Scripts | 35,9% |
| Mídia (vídeo e áudio) | 7,4% |
| Fontes | 6,6% |
| Folhas de estilo | 2,8% |
| Documentos HTML | 2,4% |
| Chamadas de API (fetch e XHR) | 4,9% |
| Outros | 1,9% |
Bloquear imagens, mídia e fontes, que um scraper quase nunca precisa, reduziu a página mediana para 1,5 MB e 55 requisições. Em todas as páginas, o carregamento bloqueado transferiu 52% dos bytes do carregamento completo. Scripts são mais difíceis de bloquear com segurança, porque a página frequentemente precisa deles para renderizar o conteúdo que você veio buscar.
O que isso significa para um orçamento de scraping
Considere um job que coleta um milhão de páginas de conteúdo por mês e mantém apenas o texto principal delas. Usando as medianas acima:
| Como as páginas são buscadas | Tráfego por milhão de páginas |
|---|---|
| Apenas texto principal, se fosse possível buscar só isso | cerca de 3,2 GB |
| Apenas HTML, comprimido | cerca de 47 GB |
| Apenas HTML, sem compressão | cerca de 265 GB |
| Navegador, imagens, mídia e fontes bloqueadas | cerca de 1,5 TB |
| Navegador, carregamento completo | cerca de 2,6 TB |
A diferença entre a primeira linha e a última é de aproximadamente 800 vezes. A ordem prática de economias decorre disso:
- Busque o HTML sem um navegador sempre que o dado estiver no HTML. Só isso já é a diferença entre gigabytes e terabytes.
- Sempre solicite compressão. Ela reduz o tráfego de HTML em cerca de cinco vezes sem custo algum.
- Quando for preciso renderizar, bloqueie imagens, mídia e fontes. Isso reduz o tráfego do navegador aproximadamente pela metade.
- Procure uma fonte menor do mesmo dado: JSON-LD, um blob JSON embutido ou a API que a própria página chama.
Nosso guia sobre reduzir custos de banda de proxy cobre cada uma dessas técnicas na prática, e estimar sua banda mensal mostra como transformar pesos de página em um plano.
Meça suas próprias páginas
Medianas entre os principais sites são um ponto de partida; seus alvos são o que importa. A função abaixo busca uma página e reporta para onde seus bytes vão, usando o mesmo método do estudo:
import gzip
import re
import zlib
import brotli
import requests
import trafilatura
from lxml import html as lxml_html
def decode(raw, content_encoding):
"""Undo Content-Encoding by hand, so we can count the compressed bytes first."""
for coding in reversed([c.strip() for c in content_encoding.lower().split(",") if c.strip()]):
if coding == "gzip":
raw = gzip.decompress(raw)
elif coding == "br":
raw = brotli.decompress(raw)
elif coding == "deflate":
raw = zlib.decompress(raw)
return raw
def size(text):
return len(text.encode("utf-8"))
def payload_breakdown(url, session=None):
"""Where the bytes of one HTML page go, from the wire down to the main content."""
session = session or requests.Session()
response = session.get(url, timeout=30, stream=True,
headers={"Accept-Encoding": "gzip, deflate, br"})
wire = response.raw.read(decode_content=False)
page = decode(wire, response.headers.get("Content-Encoding", "")).decode(
response.encoding or "utf-8", errors="replace")
doc = lxml_html.document_fromstring(page)
scripts = doc.xpath("//script")
json_ld = sum(size(s.text or "") for s in scripts if s.get("type") == "application/ld+json")
inline_js = sum(size(s.text or "") for s in scripts
if not s.get("src") and s.get("type") != "application/ld+json")
inline_css = sum(size(s.text or "") for s in doc.xpath("//style")) + sum(size(v) for v in doc.xpath("//@style"))
inline_svg = sum(size(lxml_html.tostring(s, encoding="unicode"))
for s in doc.xpath("//*[local-name()='svg'][not(ancestor::*[local-name()='svg'])]"))
main_text = trafilatura.extract(page, include_tables=True) or ""
return {
"status": response.status_code,
"wire_bytes": len(wire),
"html_bytes": size(page),
"inline_js": inline_js,
"inline_css": inline_css,
"inline_svg": inline_svg,
"json_ld": json_ld,
"main_text": size(re.sub(r"\s+", " ", main_text).strip()),
}
Ela lê o corpo da resposta antes da descompressão, então wire_bytes é o que você de fato transferiu, e depois a decodifica manualmente. Execute em algumas páginas de cada um dos seus alvos:
from payload import payload_breakdown
import requests
session = requests.Session()
session.headers["User-Agent"] = "ExampleStudy/1.0 (+https://example.com/bot)"
b = payload_breakdown("https://en.wikipedia.org/wiki/Web_scraping", session)
print(b)
print(f"main content: {b['main_text'] / b['html_bytes']:.1%} of the HTML, "
f"{b['main_text'] / b['wire_bytes']:.1%} of the bytes transferred")
{'status': 200, 'wire_bytes': 46860, 'html_bytes': 236286, 'inline_js': 6964, 'inline_css': 6303, 'inline_svg': 0, 'json_ld': 640, 'main_text': 26979}
main content: 11.4% of the HTML, 57.6% of the bytes transferred
A Wikipédia é uma página eficiente para esses padrões: seu texto principal é mais de 11% do HTML, quase dez vezes a mediana que medimos. Seus alvos cairão em algum ponto dessa faixa, e saber onde lhe diz se a coleta apenas de HTML, a compressão ou uma fonte de dados diferente trará a maior economia.
Limites da medição
- Apenas sites de topo. Os 1.000 principais domínios são sites grandes e bem projetados. Sites menores podem ser mais leves ou muito mais pesados.
- Uma página de conteúdo por site. Seguimos o primeiro link no estilo artigo em cada página inicial. Páginas de produto, resultados de busca e páginas de listagem podem diferir.
- O conteúdo principal é uma estimativa. Bibliotecas de extração podem deixar de incluir conteúdo ou incluí-lo em excesso, particularmente em páginas majoritariamente de navegação. Trate os números de texto principal como aproximados; as medições de bytes são exatas.
- Um instantâneo, uma rede. As páginas foram buscadas uma vez, em 8 de outubro de 2026, a partir de uma única rede na Europa. Sites servem páginas, anúncios e mídia diferentes por localização e ao longo do tempo.
- Carregamentos no navegador tiveram um limite. Paramos de medir três segundos após o evento load. Páginas que continuam carregando conteúdo depois disso transferiram mais do que registramos.
Perguntas frequentes
Qual fração de uma página web é o conteúdo real?
Na página de conteúdo mediana entre os 1.000 principais sites, o texto principal foi cerca de 1,2% do HTML e cerca de 6% dos bytes comprimidos transferidos. Em um carregamento completo de navegador, foi cerca de 0,13% dos bytes.
Bloquear imagens reduz a banda de proxy?
Sim. Bloquear imagens, mídia e fontes em um navegador headless removeu 48% dos bytes em nossa amostra. Apenas as imagens foram 38% do tráfego do navegador.
É mais barato fazer scraping sem um navegador?
Geralmente, por uma margem grande. A página de conteúdo mediana teve 46 KiB como HTML comprimido e 2,6 MB em um carregamento completo de navegador, uma diferença de mais de 50 vezes.
Devo solicitar respostas comprimidas ao fazer scraping?
Sim. A página mediana foi 5,4 vezes menor quando comprimida. A maioria dos clientes HTTP solicita compressão por padrão, mas verifique, porque um cliente que não o faz paga pelo tamanho completo de cada página.
Conclusão
O dado que um scraper mantém é uma fração minúscula do que ele baixa: cerca de 1% do HTML de uma página típica e uma fração de 1% do que um navegador puxa. A maior parte dessa sobrecarga é evitável. Busque HTML em vez de renderizar quando possível, mantenha a compressão ativada, bloqueie recursos pesados quando for preciso renderizar, e procure por dados estruturados ou APIs que carreguem a mesma informação em muito menos bytes.
Fontes e referências
- Tranco, lista Q2K34, o ranking voltado à pesquisa de sites principais usado para a amostra.
- Barbaresi, A. (2021). Trafilatura: A Web Scraping Library and Command-Line Tool for Text Discovery and Extraction. ACL 2021 System Demonstrations.
- Páginas medidas pela Shifter em 8 de outubro de 2026 usando o código acima e Chromium headless.