🎯 Um navegador em nuvem personalizável e anti-detecção alimentado por Chromium desenvolvido internamente, projetado para rastreadores web e agentes de IA. 👉Experimente agora
De volta ao blog

Raspagem da Web RNet: Imitação de Impressão Digital TLS do Navegador

Alex Johnson
Alex Johnson

Senior Web Scraping Engineer

23-Jul-2026

TL;DR:

  • rnet é um cliente HTTP assíncrono que imita a impressão digital TLS de um navegador real, assim, um servidor que perfilou o handshake vê o Chrome, e não um padrão Python. É construído em Rust e exposto ao Python.
  • O que o rnet não faz é renderizar JavaScript. Uma impressão digital perfeita aceita a solicitação; não executa os scripts que constroem o conteúdo de uma página.
  • A impressão digital é real neste guia. Uma execução ao vivo imitando o Chrome produziu um JA3 em forma de navegador e um JA4 t13d1516h2 sobre HTTP/2 — e ainda assim não encontrou 0 blocos de citação em uma página construída por script.
  • rnet também é o cliente que chama o Scrapeless. O mesmo cliente assíncrono POSTou a URL para a API de Extração Universal do Scrapeless, obteve o HTML renderizado e puxou todos os 10 autores.
  • Duas problemas diferentes, claramente divididos. rnet lida com a camada de impressão digital TLS; Scrapeless lida com a renderização. Nenhum substitui o outro.
  • Grátis para começar do lado de fetch. Crie sua chave da API do Scrapeless em app.scrapeless.com.

O que é o rnet, e o que não é

rnet é um cliente HTTP assíncrono para Python construído sobre a pilha de rede do Rust, e sua característica distintiva é a imitação da impressão digital TLS e HTTP. Quando um cliente abre uma conexão TLS, a forma exata do seu handshake — ordem de cifras, extensões, curvas — forma uma impressão digital que os servidores podem perfilar; um cliente Python padrão tem uma impressão digital que nenhum navegador produz, e alguns sites a rejeitam antes que um único byte de HTML seja servido. rnet reproduz o handshake de um navegador escolhido, de modo que a conexão aparece como Chrome ou Firefox, e faz isso sobre HTTP/2 com uma API assíncrona.

O que não é, é um renderizador. Uma impressão digital correspondente permite que você passe pela perfuração do nível do handshake; não faz nada sobre JavaScript. A página ainda constrói seu conteúdo com scripts, e o rnet, como qualquer cliente HTTP, retorna o markup enviado pelo servidor — que em uma página construída por script está vazio de conteúdo. Assim, um scraper rnet separa dois problemas que muitas vezes são confundidos: a camada de impressão digital, onde o rnet ganha seu lugar, e a camada de renderização, que precisa de um navegador. Este guia usa a API de Extração Universal do Scrapeless para a renderização, com o rnet fazendo a chamada. Para uma visão mais ampla, o tutorial de web scraping em Python é o complemento.

Instalação

rnet é toda a cadeia de ferramentas para este guia. A versão contra a qual foi escrito é rnet 2.4.2:

bash Copy
pip install "rnet==2.4.2"

Mantenha sua chave no ambiente, nunca no código fonte:

bash Copy
export SCRAPELESS_API_KEY="sk_your_scrapeless_key"

Aponte o rnet para um endpoint de identificação de impressão digital com uma configuração de imitação de navegador, e o handshake será lido como esse navegador. JA3 e JA4 são resumos padrão do handshake TLS — a impressão digital negociada sob o padrão TLS 1.3 — e o rnet produz valores em forma de navegador. No entanto, o mesmo cliente em uma página construída por script não encontra nada, porque a impressão digital não tem relação com a renderização do lado do cliente que preenche a página:

python Copy
# fingerprint.py — um handshake real de navegador e seu limite
import asyncio
import json
import re

import rnet

FINGERPRINT_URL = "https://tls.peet.ws/api/all"
PAGE_URL = "https://quotes.toscrape.com/js/"


async def main() -> None:
    client = rnet.Client(impersonate=rnet.Impersonate.Chrome131)

    resp = await client.get(FINGERPRINT_URL)
    fp = json.loads(await resp.text())
    ja3 = fp.get("tls", {}).get("ja3_hash", "")
    ja4 = fp.get("tls", {}).get("ja4", "")
    print("ja3 é 32-hex:", bool(re.fullmatch(r"[0-9a-f]{32}", ja3)))
    print("prefixo ja4:", ja4.split("_")[0])
    print("versão http:", fp.get("http_version"))

    page_resp = await client.get(PAGE_URL)
    page = await page_resp.text()
    print("blocos de citação da página js:", page.count('class="quote"'))


asyncio.run(main())

O handshake está em forma de navegador; a página ainda está vazia:

text Copy
ja3 é 32-hex: True
prefixo ja4: t13d1516h2
versão http: h2
blocos de citação da página js: 0

O hash JA3 varia de execução para execução por design — os navegadores randomizam uma extensão sob o mecanismo GREASE, e o rnet reproduz isso — então um scraper verifica a forma, não um valor fixo. O prefixo JA4 t13d1516h2 é a parte estável: TLS 1.3, 16 suítes de cifras, 16 extensões, HTTP/2. O que nada disso faz é renderizar a página.

Renderizar com Scrapeless, chamado pelo rnet

Mantenha o mesmo cliente assíncrono e mude o alvo: faça um POST da URL para a API de Scraping Universal da Scrapeless, que renderiza no lado do servidor e retorna o HTML final. O rnet lida com essa solicitação como qualquer outra, então um cliente cobre tanto as recuperações sensíveis à impressão digital quanto as renderizadas:

python Copy
# rendered.py — rnet chama a API de renderização e, em seguida, extrai
import asyncio
import json
import os
import re

import rnet


async def main() -> None:
    client = rnet.Client(impersonate=rnet.Impersonate.Chrome131)
    resp = await client.post(
        "https://api.scrapeless.com/api/v2/unlocker/request",
        headers={"x-api-token": os.environ["SCRAPELESS_API_KEY"], "Content-Type": "application/json"},
        json={"actor": "unlocker.webunlocker", "input": {"url": "https://quotes.toscrape.com/js/", "js_render": True}},
    )
    html = json.loads(await resp.text())["data"]

    authors = re.findall(r'<small class="author">(.*?)</small>', html)
    print("blocos de citações renderizadas:", html.count('class="quote"'))
    print("primeiro autor:", authors[0])


asyncio.run(main())

Agora o conteúdo está presente:

text Copy
blocos de citações renderizadas: 10
primeiro autor: Albert Einstein

Esse é todo o scraper, e ele permaneceu no rnet o tempo todo: o cliente assíncrono que carrega uma impressão digital de navegador também faz a chamada de renderização. A API de Scraping Universal faz a renderização; o rnet faz o HTTP.

Obtenha sua chave de API no plano gratuito: app.scrapeless.com

Padrões avançados

  • Combine a simulação com um navegador atual. rnet.Impersonate expõe versões específicas de navegadores; escolha uma recente, já que uma impressão digital de um build antigo é ela mesma um sinal. A API do cliente não muda com o alvo.
  • Reutilize um cliente. Um rnet.Client agrupa conexões; crie-o uma vez e compartilhe-o entre um grupo de tarefas assíncronas em vez de por solicitação, que é onde o transporte assíncrono se paga.
  • Verifique a forma, não o valor. Porque o GREASE randomiza o JA3 por conexão, assegure o padrão de 32 hexadecimais e o prefixo JA4, como faz o primeiro script — nunca um hash codificado.
  • Adicione um parser quando a forma crescer. A regex mantém isso com uma dependência; para registros aninhados, forneça o HTML renderizado a uma biblioteca de seletores e selecione os campos lá.

Solução de problemas

  • Um site ainda bloqueia a solicitação. Uma impressão digital TLS é um sinal entre muitos. Se um handshake com formato de navegador não é suficiente, o bloqueio está acima do transporte — reputação de IP, cabeçalhos ou um desafio — e a solicitação pertence ao caminho Scrapeless, que lida com isso.
  • Sem bloqueios de uma página que você pode ver em um navegador. O conteúdo é renderizado em JavaScript; a impressão digital fez com que a solicitação fosse aceita, mas os scripts nunca foram executados. Rote essa URL pela chamada Scrapeless com js_render.
  • O hash JA3 muda a cada execução. Isso está correto — o GREASE o randomiza, exatamente como um navegador real faz. Assegure o padrão e o prefixo JA4 em vez disso.
  • Erros de await na resposta. rnet é assíncrono: tanto a solicitação quanto a leitura de .text() são aguardadas, e tudo é executado dentro de asyncio.run, como mostram os exemplos.

Conclusão

O rnet ganha seu lugar como a camada que faz o handshake parecer correto: um cliente assíncrono, suportado por Rust, que carrega a impressão digital TLS de um navegador real e que também faz a chamada de renderização. O problema que ele não resolve é a própria página — o resultado de zero bloqueios do script de impressão digital resolve isso — e um POST Scrapeless, enviado pelo rnet, fecha a lacuna. Conecte a camada de impressão digital e a camada de renderização em um único cliente e os dez autores da página de demonstração retornam de uma conexão que um servidor lê como Chrome.

Criando uma conta gratuita na Scrapeless para obter uma chave de API, e a documentação do desenvolvedor cobre os parâmetros unlocker.webunlocker. Verifique os preços da Scrapeless ao planejar um trabalho recorrente.

FAQ

Q: O rnet pode raspar páginas renderizadas em JavaScript por si só?

Não. O rnet é um cliente HTTP com simulação de impressão digital; ele aceita uma solicitação na camada TLS, mas não executa JavaScript. Em uma página construída por script, a recuperação retorna uma marcação com o conteúdo ausente — o resultado de zero bloqueios do guia. Rote essas páginas pela API de Scraping Universal da Scrapeless, que as renderiza, com o rnet fazendo a chamada.

Q: O que a simulação de impressão digital TLS realmente faz?
Ele molda o handshake TLS do rnet para corresponder a um navegador escolhido, de modo que um servidor que perfil trata o fingerprint JA3 ou JA4 veja Chrome ou Firefox em vez de um cliente Python genérico. Isso limpa a filtragem em nível de handshake; não remove bloqueios baseados em IP, páginas de desafio ou a necessidade de renderizar JavaScript.

P: Como o rnet difere do curl_cffi?

Ambos usam fingerprints de navegador. O rnet é construído em Rust e é assíncrono; o curl_cffi envolve o curl-impersonate e é sincrono. Escolha com base em se seu scraper é assíncrono e quais alvos de impersonação você precisa — o padrão de duas camadas com uma API de renderização é o mesmo de qualquer forma.

P: Por que o hash JA3 muda em cada execução?

Porque navegadores reais randomizam uma extensão TLS através do mecanismo GREASE, e o rnet reproduz esse comportamento. Um JA3 fixo pareceria artificial. Verifique o padrão de 32 hexadecimais e o prefixo JA4 em vez de um valor específico.

P: É legal fazer scraping com o rnet?

O cliente HTTP não muda as regras de coleta. Busque apenas páginas públicas, respeite os termos do site e as diretivas de robôs padronizadas pelo Protocolo de Exclusão de Robôs, mantenha os volumes limitados e trate qualquer dado pessoal de acordo com as leis que se aplicam a você.

Na Scorretless, acessamos apenas dados disponíveis ao público, enquanto cumprem estritamente as leis, regulamentos e políticas de privacidade do site aplicáveis. O conteúdo deste blog é apenas para fins de demonstração e não envolve atividades ilegais ou infratoras. Não temos garantias e negamos toda a responsabilidade pelo uso de informações deste blog ou links de terceiros. Antes de se envolver em qualquer atividade de raspagem, consulte seu consultor jurídico e revise os termos de serviço do site de destino ou obtenha as permissões necessárias.

Artigos mais populares

Catálogo