🎯 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

Playwright + Scrapeless Scraping Browser: Capturar e Repetir uma Sessão HAR Completa

James Thompson
James Thompson

Scraping and Proxy Management Expert

30-Jul-2026

TL;DR:

  • Um arquivo HAR é um arquivo HTTP estruturado, não uma captura de tela ou vídeo. Seu array log.entries armazena um objeto por requisição HTTP capturada, incluindo metadados de requisição e resposta e, quando disponível, o conteúdo gravado.
  • Playwright grava arquivos HAR no nível do contexto do navegador. Defina record_har_path ao criar o contexto e chame context.close() para gravar o arquivo no disco.
  • O Scrapeless Scraping Browser fornece a sessão do navegador remoto. O Playwright se conecta a ele através do CDP, carrega a página, aciona requisições dinâmicas e salva o tráfego resultante localmente.
  • A análise HAR não requer um navegador. Uma vez que o arquivo existe, o módulo json padrão do Python pode inspecionar suas URLs, métodos, status, tipos MIME, cabeçalhos e corpos de resposta incorporados.
  • Uma requisição capturada pode ser reemitida sem o Playwright. O exemplo reconstrói uma requisição pública JSON com urllib após remover pseudo-cabeçalhos HTTP/2 e renegociar a codificação de conteúdo.
  • A reprodução HAR tem limitações. Cookies expirados, tokens CSRF, credenciais de portador, quadros WebSocket e dados do servidor em mudança podem impedir que uma requisição posterior reproduza a resposta original.
  • Gratuito para começar. Novas contas Scrapeless incluem um tempo de execução gratuito do Scraping Browser — inscreva-se em app.scrapeless.com.

Introdução: Capture Primeiro, Decida o que Importa Depois

Um arquivo HAR é um arquivo JSON de transações HTTP observadas durante uma sessão do navegador. Não é uma captura de tela de uma página renderizada, um instantâneo do DOM ou um vídeo da sessão.

Cada requisição capturada aparece como um objeto dentro de:

text Copy
log.entries

Uma entrada pode conter o método de requisição, URL, cabeçalhos, parâmetros de consulta, dados enviados, status de resposta, cabeçalhos de resposta, informações de tempo e conteúdo de resposta gravado. Conteúdo binário pode ser representado com uma codificação como Base64, enquanto corpos textuais podem aparecer diretamente na entrada.

Este guia conecta o Playwright ao Scrapeless Scraping Browser através do Protocolo DevTools do Chrome, grava um carregamento completo da página e uma sequência de rolagem com record_har_path, e fecha o navegador.

A segunda parte do fluxo de trabalho é sem navegador:

  1. Inspecione a estrutura HAR com json.
  2. Encontre uma requisição de API capturada.
  3. Reconstrua seus cabeçalhos reutilizáveis.
  4. Reemita-a com urllib.
  5. Compare a nova resposta JSON com o corpo armazenado no arquivo.

Todos os resultados exibidos vêm da sessão-alvo capturada.

O que Você Pode Fazer com um Arquivo HAR

A captura HAR é útil quando o endpoint importante não é conhecido antes do carregamento da página.

  • Audite um carregamento completo da página. Revise HTML, folhas de estilo, scripts, fontes, imagens e requisições de API de uma única sessão.
  • Descubra endpoints JSON internos. Pesquise no arquivo após a captura em vez de prever qual requisição será relevante.
  • Depure comportamentos de página que falharam. Inspecione URLs de requisição, status de resposta, cabeçalhos, tipos MIME e corpos após o navegador ser fechado.
  • Preserve evidências de rede. Armazene um artefato JSON portátil que pode ser analisado posteriormente ou transferido para outra máquina.
  • Compare o comportamento de carregamento de páginas. Capture sessões separadas e compare seus conjuntos de requisições, status ou conteúdos de resposta.
  • Extraia dados de resposta capturados. Leia corpos JSON ou textuais incorporados sem recarregar a página.
  • Reconstrua requisições elegíveis. Reemita requisições HTTP públicas ou ainda autenticadas com um cliente HTTP padrão.
  • Crie testes de navegador determinísticos. Use o recurso separado route_from_har() do Playwright para servir respostas gravadas de volta a um contexto do navegador ao vivo.

Um arquivo HAR é mais valioso quando uma captura ampla é mais útil do que anexar um ouvinte a um endpoint já conhecido.

Captura HAR, Gravação de Vídeo e Roteamento HAR são Diferentes

Três recursos nesta área usam uma linguagem semelhante, mas resolvem problemas diferentes.

Recurso O que grava ou faz Navegador necessário depois?
Playwright record_har_path Arquiva dados de requisição e resposta HTTP Não, para inspeção offline
Gravação de sessão Scrapeless Cria uma reprodução visual da sessão renderizada Não, para reprodução no painel
Playwright route_from_har() Serve respostas gravadas para requisições feitas por um contexto de navegador Sim
O exemplo urllib neste guia Reemite uma requisição capturada contra o servidor ao vivo Não

Interceptação ao Vivo

A interceptação ao vivo observa requisições à medida que ocorrem. Funciona bem quando o endpoint-alvo ou o padrão de resposta já é conhecido.

Uma vez que a sessão termina, qualquer coisa não capturada pelo ouvinte é perdida.

Captura HAR

A captura HAR grava amplamente o tráfego HTTP do contexto. O endpoint que importa pode ser selecionado após o navegador fechar.

Isso torna a captura HAR mais adequada para:

  • Depuração pós-sessão
  • Inventários de rede
  • Descoberta de API
  • Auditoria de todos os recursos carregados por uma página
  • Preservando os corpos de resposta para inspeção offline

Gravação de Sessão Sem Resíduos

O Navegador de Scraping Sem Resíduos suporta uma capacidade de gravação de sessão nativa separada. Isso produz um registro visual reprodutível da sessão do navegador renderizada.

Isso não substitui um arquivo HAR. Um vídeo mostra o que apareceu na tela; um HAR expõe transações HTTP estruturadas.

Playwright route_from_har()

O route_from_har() do Playwright envia respostas HAR salvas de volta para solicitações feitas por um contexto de navegador ao vivo. É comumente usado para simular o comportamento do backend em testes de navegador.

O exemplo de reprodução neste guia faz algo diferente: ele lê uma solicitação do arquivo de archive e envia uma nova solicitação HTTP ao vivo com urllib.

O Navegador de Scraping Sem Resíduos fornece o ambiente de navegador remoto que o Playwright controla através do CDP.

A sessão do navegador é executada em infraestrutura de nuvem e suporta a seleção de proxy geográfico através dos parâmetros de conexão. O Playwright ainda usa suas APIs normais de navegador, contexto, página e HAR.

Para esse fluxo de trabalho, a divisão de responsabilidades é simples:

Componente Responsabilidade
Navegador de Scraping Sem Resíduos Executa a sessão remota do Chromium e fornece o endpoint do CDP
Playwright Cria o contexto, controla a página e grava o HAR
Sistema de arquivos local Armazena session.har
Biblioteca padrão do Python Inspeciona o arquivo de archive e reemite a solicitação selecionada

A gravação HAR em si é um recurso do Playwright. Conectar o Playwright ao Scrapeless move a etapa de renderização ao vivo para um navegador remoto gerenciado, enquanto mantém o arquivo de archive resultante na máquina que executa o script Python.

A conexão usa o mesmo domínio de rede do Chrome DevTools Protocol que as ferramentas de navegador usam para observar a atividade de rede.

O quickstart do Scraping Browser aborda o modelo de conexão mais amplo do Playwright e Puppeteer.

Pré-requisitos

Você precisa de:

  • Python 3.9 ou mais recente
  • Playwright 1.59.0 para a execução reproduzida
  • Uma conta Scrapeless e uma chave de API
  • Acesso de gravação ao diretório onde session.har será criado
  • Acesso à rede à página de destino pública

O Playwright 1.59.0 exige Python 3.9 ou mais recente. Fixar essa versão faz com que a instalação corresponda aos resultados capturados neste guia.

Não é necessária nenhuma instalação local do Chrome para este fluxo de trabalho. O connect_over_cdp() se conecta a um navegador já em execução na infraestrutura do Scrapeless.

Os scripts de inspeção e reemissão de solicitações usam apenas a biblioteca padrão do Python. Eles não importam o Playwright ou abrem uma conexão de navegador.

Passo 1 — Instalar o Playwright

Instale a versão usada para a execução gravada:

bash Copy
pip install "playwright==1.59.0"

Como o script se conecta a um navegador remoto existente via CDP, ele não inicia um executável de navegador instalado localmente.

Defina a chave da API Scrapeless no shell:

bash Copy
export SCRAPELESS_API_KEY="sua_chave_api_scrapeless"

O código lê a chave do ambiente em vez de armazená-la no controle de versão.

Passo 2 — Construir a URL do CDP do Scrapeless

A URL de conexão do Navegador de Scraping carrega a chave da API, duração da sessão e localização do proxy como parâmetros de consulta:

python Copy
import os
from urllib.parse import urlencode

API_KEY = os.environ["SCRAPELESS_API_KEY"]


def scraping_browser_url(proxy_country="US", session_ttl=180):
    params = urlencode({
        "token": API_KEY,
        "sessionTTL": session_ttl,
        "proxyCountry": proxy_country,
    })
    return f"wss://browser.scrapeless.com/api/v2/browser?{params}"

A função gera uma URL com esta forma:

text Copy
wss://browser.scrapeless.com/api/v2/browser?token=...&sessionTTL=180&proxyCountry=US

Os três valores configurados são:

  • token: a chave da API Scrapeless
  • sessionTTL: a duração máxima da sessão
  • proxyCountry: o país do proxy solicitado

Manter a construção da URL em uma única função também facilita a aplicação das mesmas configurações de conexão em vários scripts de captura.

A configuração record_har_path do Playwright pertence a browser.new_context(), não a connect_over_cdp().

A conexão do navegador fornece acesso ao Chromium. O contexto define o que será gravado.

python Copy
import os
from urllib.parse import urlencode

from playwright.sync_api import sync_playwright


API_KEY = os.environ["SCRAPELESS_API_KEY"]
HAR_PATH = "session.har"


def scraping_browser_url(proxy_country="US", session_ttl=180):
    params = urlencode({
        "token": API_KEY,
        "sessionTTL": session_ttl,
        "proxyCountry": proxy_country,
    })
    return f"wss://browser.scrapeless.com/api/v2/browser?{params}"
python Copy
com sync_playwright() como p:
    navegador = p.chromium.connect_over_cdp(scraping_browser_url())

    contexto = navegador.new_context(
        record_har_path=HAR_PATH,
        record_har_content="embed",
    )

    pagina = contexto.new_page()
    pagina.goto(
        "https://quotes.toscrape.com/scroll",
        wait_until="networkidle",
    )

    para _ em range(3):
        pagina.evaluate(
            "window.scrollTo(0, document.body.scrollHeight)"
        )
        pagina.wait_for_timeout(800)

    print(
        "elementos de citação visíveis após o deslocamento:",
        pagina.locator(".quote").count(),
    )

    contexto.close()
    navegador.close()

print(
    "HAR escrito:",
    HAR_PATH,
    "-",
    os.path.getsize(HAR_PATH),
    "bytes",
)

A execução ao vivo imprimiu:

```text
elementos de citação visíveis após o deslocamento: 40
HAR escrito: session.har - 333269 bytes

A meta-inicial renderizou dez citações. Cada rolagem perto da parte inferior acionou outra solicitação /api/quotes?page=N, trazendo o total visível para 40 citações em quatro páginas da API.

O script não precisou prever qual solicitação seria importante mais tarde. O HAR também capturou o documento, folhas de estilo, JavaScript, fonte e chamadas JSON.

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

Por Que context.close() É Necessário

O HAR é finalizado quando o contexto do navegador é fechado.

A documentação do Playwright define record_har_path como uma configuração do contexto do navegador e requer browser_context.close() para que o HAR seja salvo. Fechar apenas a conexão do navegador pode deixar artefatos de contexto sem uma descarregamento adequado.

A ordem correta de desligamento é:

python Copy
contexto.close()
navegador.close()

A chamada contexto.close() é, portanto, parte do procedimento de captura, não uma limpeza opcional.

record_har_content="embed" armazena o conteúdo da resposta gravada dentro do HAR, em vez de em arquivos acompanhantes separados. Isso torna session.har autônomo para a inspeção JSON posterior e comparação de corpo.

O histórico rascunho do formato HAR define o objeto log de nível superior e seu array entries requerido. Cada entrada representa uma solicitação HTTP exportada.

Após o fechamento do contexto, session.har é um documento JSON local.

O seguinte script usa apenas json, collections e pathlib:

python Copy
import json
from collections import Counter
from pathlib import Path


har = json.loads(Path("session.har").read_text())
entradas = har["log"]["entries"]

print("total de entradas:", len(entradas))

por_tipo = Counter(
    entrada["response"]["content"]["mimeType"].split(";")[0]
    para entrada em entradas
)

for tipo_mime, contagem em por_tipo.most_common():
    print(f"  {tipo_mime}: {contagem}")

print()

for entrada em entradas:
    pedido = entrada["request"]
    resposta = entrada["response"]

    print(
        f"{pedido['method']:4s} "
        f"{resposta['status']:3d}  "
        f"{pedido['url']}"
    )

O arquivo capturado continha:

text Copy
total de entradas: 10
  application/json: 4
  text/css: 3
  text/html: 1
  application/javascript: 1
  font/woff2: 1

GET  200  https://quotes.toscrape.com/scroll
GET  200  https://quotes.toscrape.com/static/bootstrap.min.css
GET  200  https://quotes.toscrape.com/static/main.css
GET  200  https://quotes.toscrape.com/static/jquery.js
GET  200  https://fonts.googleapis.com/css?family=Raleway:400,700
GET  200  https://fonts.gstatic.com/s/raleway/v37/1Ptug8zYS_SKggPNyC0ITw.woff2
GET  200  https://quotes.toscrape.com/api/quotes?page=1
GET  200  https://quotes.toscrape.com/api/quotes?page=2
GET  200  https://quotes.toscrape.com/api/quotes?page=3
GET  200  https://quotes.toscrape.com/api/quotes?page=4

As dez entradas cobrem cinco tipos MIME:

  • Um documento HTML
  • Três respostas CSS
  • Uma resposta JavaScript
  • Uma fonte da web
  • Quatro respostas JSON

Um ouvinte ao vivo filtrado para /api/quotes teria observado as quatro solicitações JSON, mas ignorado os outros seis recursos. O HAR preservou todas as dez para inspeção posterior.

Compreendendo a Estrutura da Entrada HAR

Cada item em har["log"]["entries"] contém objetos de solicitação e resposta aninhados.

Uma entrada simplificada tem esta forma:

json Copy
{
  "request": {
    "method": "GET",
    "url": "https://example.com/api/data",
    "headers": []
  },
  "response": {
    "status": 200,
    "headers": [],
    "content": {
      "mimeType": "application/json",
      "text": "{}"
    }
  }
}

Os campos de solicitação úteis incluem:

  • method
  • url
  • headers
  • queryString
  • postData

Os campos de resposta úteis incluem:

  • status
  • statusText
  • headers
  • content
  • redirectURL
Copy
O conteúdo HAR não é garantido para ser armazenado como texto diretamente legível em cada entrada. Dependendo do recurso e do gravador, `content.text` pode estar ausente, ser texto decodificado ou uma representação codificada cujo campo `encoding` identifica o formato.

## Passo 5 — Lidar com Pseudo-Cabeçalhos HTTP/2

Os cabeçalhos de solicitação para a chamada da API capturada `page=1` incluíram nomes como:

```text
:authority
:method
:path
:scheme

Estes são campos de pseudo-cabeçalho HTTP/2.

Eles transportam informações de controle que apareceriam em uma linha de solicitação HTTP/1.1 ou alvo:

  • :method identifica o método da solicitação.
  • :scheme identifica o esquema URI.
  • :authority identifica a autoridade alvo.
  • :path identifica o caminho e a consulta.

Os pseudo-cabeçalhos não são campos de cabeçalho HTTP comuns. Um cliente orientado a HTTP/1.1, como urllib, não pode aceitar um nome de cabeçalho prefixado por dois pontos.

Um script de reprodução deve traduzir seu significado para a URL e método, e então omiti-los do mapeamento de cabeçalhos comuns.

Passo 6 — Reemitir Uma Solicitação Capturada Com urllib

A solicitação selecionada /api/quotes?page=1 é agora um dicionário dentro de um arquivo JSON local.

O script abaixo:

  1. Encontra a entrada capturada.
  2. Lê seu método, URL e cabeçalhos.
  3. Remove pseudo-cabeçalhos HTTP/2.
  4. Remove accept-encoding.
  5. Cria uma nova urllib.request.Request.
  6. Analisa os corpos da resposta ao vivo e da capturada.
  7. Compara os dois objetos Python.
python Copy
import json
import urllib.error
import urllib.request
from pathlib import Path


har = json.loads(Path("session.har").read_text())
entries = har["log"]["entries"]

target = next(
    entry
    for entry in entries
    if entry["request"]["url"].endswith("page=1")
)

captured_request = target["request"]

# Os pseudo-cabeçalhos HTTP/2 descrevem a estrutura do protocolo e não podem ser
# passados como cabeçalhos comuns no estilo HTTP/1.1.
#
# accept-encoding também é omitido para que urllib possa negociar uma
# codificação que o script pode decodificar diretamente.
skip_headers = {"accept-encoding"}

headers = {
    header["name"]: header["value"]
    for header in captured_request["headers"]
    if not header["name"].startswith(":")
    and header["name"].lower() not in skip_headers
}

print("contagem de cabeçalhos reemitidos:", len(headers))

request = urllib.request.Request(
    captured_request["url"],
    headers=headers,
    method=captured_request["method"],
)

with urllib.request.urlopen(request, timeout=10) as response:
    if response.status != 200:
        raise urllib.error.HTTPError(
            captured_request["url"],
            response.status,
            "status inesperado",
            response.headers,
            None,
        )

    live_data = json.loads(response.read())

captured_content = target["response"]["content"]
captured_data = json.loads(captured_content["text"])

print("status:", response.status, "-- nenhum processo de navegador em execução")
print(
    "primeiro autor da citação:",
    live_data["quotes"][0]["author"]["name"],
)
print(
    "corresponde ao corpo da resposta que o HAR já capturou:",
    live_data == captured_data,
)

A reprodução sem navegador imprimiu:

text Copy
contagem de cabeçalhos reemitidos: 12
status: 200 -- nenhum processo de navegador em execução
primeiro autor da citação: Albert Einstein
corresponde ao corpo da resposta que o HAR já capturou: True

O mapeamento filtrado continha 12 cabeçalhos comuns. Os pseudo-cabeçalhos HTTP/2 e accept-encoding foram excluídos.

accept-encoding é um campo de negociação de conteúdo HTTP. O cliente de reprodução pode anunciar as codificações de conteúdo que suporta ao invés de copiar a negociação Brotli do navegador cegamente.

A resposta alvo correspondeu ao corpo JSON armazenado no HAR para essa execução. Essa comparação foi feita nos objetos Python analisados em vez de em seu espaço em branco serializado ou formatação de chave.

Este é um reconstrutor de solicitação semântico, não uma reprodução byte a byte da troca de rede original. A nova solicitação pode usar uma versão HTTP diferente, ordem de cabeçalho, negociação de compressão, conexão e sessão TLS.

O Que Você Recebe de Volta

O fluxo de trabalho produz três artefatos ou resultados reutilizáveis:

Etapa Saída Navegador necessário?
Captura session.har Sim
Inspeção Inventário de solicitações e resumo de tipo MIME Não
Reemissão Comparação da resposta ao vivo analisada e corpo capturado Não

A sessão capturada produziu:

text Copy
Tamanho HAR: 333269 bytes
Entradas HTTP: 10
Entradas JSON: 4
Citações visíveis após rolagem: 40
Status da solicitação reemitida: 200
Correspondência JSON capturada/aos vivo: True

Esses números descrevem esta sessão alvo específica. Uma página diferente, versão do navegador, tempo de rolagem, localização do proxy ou resposta da página podem produzir um conjunto de solicitações e um tamanho de arquivo diferentes.

Confirme a Sequência Completa em Um Script

A captura, inspeção e programas de reprodução separados são mais fáceis de entender, mas as mesmas etapas podem ser combinadas:

python Copy
import json
import os
import urllib.error
import urllib.request
from collections import Counter
from pathlib import Path
from urllib.parse import urlencode

from playwright.sync_api import sync_playwright


API_KEY = os.environ["SCRAPELESS_API_KEY"]
HAR_PATH = "session.har"


def scraping_browser_url(proxy_country="US", session_ttl=180):
    params = urlencode({
        "token": API_KEY,
        "sessionTTL": session_ttl,
        "proxyCountry": proxy_country,
    })
    return f"wss://browser.scrapeless.com/api/v2/browser?{params}"


# Etapa 1: captura. Um navegador é necessário.
with sync_playwright() as p:
    browser = p.chromium.connect_over_cdp(
        scraping_browser_url()
    )

    context = browser.new_context(
        record_har_path=HAR_PATH,
        record_har_content="embed",
    )

    page = context.new_page()
    page.goto(
        "https://quotes.toscrape.com/scroll",
        wait_until="networkidle",
    )

    for _ in range(3):
        page.evaluate(
            "window.scrollTo(0, document.body.scrollHeight)"
        )
        page.wait_for_timeout(800)

    context.close()
    browser.close()

print("=== captura ===")
print(
    "HAR escrito:",
    HAR_PATH,
    "-",
    os.path.getsize(HAR_PATH),
    "bytes",
)


# Etapa 2: inspeção. O navegador está fechado.
har = json.loads(Path(HAR_PATH).read_text())
entries = har["log"]["entries"]

print("\n=== inspeção (sem navegador) ===")
print("total de entradas:", len(entries))

by_type = Counter(
    entry["response"]["content"]["mimeType"].split(";")[0]
    for entry in entries
)

for mime_type, count in by_type.most_common():
    print(f"  {mime_type}: {count}")


# Etapa 3: reemitir uma solicitação. O navegador permanece fechado.
target = next(
    entry
    for entry in entries
    if entry["request"]["url"].endswith("page=1")
)

captured_request = target["request"]
skip_headers = {"accept-encoding"}

headers = {
    header["name"]: header["value"]
    for header in captured_request["headers"]
    if not header["name"].startswith(":")
    and header["name"].lower() not in skip_headers
}

request = urllib.request.Request(
    captured_request["url"],
    headers=headers,
    method=captured_request["method"],
)

with urllib.request.urlopen(request, timeout=10) as response:
    if response.status != 200:
        raise urllib.error.HTTPError(
            captured_request["url"],
            response.status,
            "status inesperado",
            response.headers,
            None,
        )

    live_data = json.loads(response.read())

captured_data = json.loads(
    target["response"]["content"]["text"]
)

print("\n=== reemitir (sem navegador) ===")
print("status:", response.status)
print(
    "autor da primeira citação:",
    live_data["quotes"][0]["author"]["name"],
)
print(
    "correspondências com o corpo capturado:",
    live_data == captured_data,
)

A execução combinada imprimiu:

text Copy
=== captura ===
HAR escrito: session.har - 333259 bytes

=== inspeção (sem navegador) ===
total de entradas: 10
  application/json: 4
  text/css: 3
  text/html: 1
  application/javascript: 1
  font/woff2: 1

=== reemitir (sem navegador) ===
status: 200
autor da primeira citação: Albert Einstein
correspondências com o corpo capturado: True

Apenas a primeira etapa importa e usa o Playwright. As etapas posteriores operam no arquivo e no endpoint HTTP ao vivo selecionado.

O que um HAR Captura

Um arquivo HAR representa transações HTTP registradas pelo contexto do navegador.

Dependendo do gravador e da configuração, uma entrada pode conter:

  • Método e URL da requisição
  • Parâmetros de string de consulta
  • Cabeçalhos da requisição
  • Cookies da requisição
  • Dados postados
  • Status da resposta
  • Cabeçalhos da resposta
  • Cookies da resposta
  • Tipo MIME
  • Conteúdo da resposta
  • Tamanhos de transferência
  • Informações de tempo
  • Detalhes de redirecionamento
  • Informações de cache

Com record_har_content="embed", o Playwright armazena o conteúdo da resposta disponível dentro do HAR. Sem conteúdo incorporado, o inventário de requisições ainda pode ser útil, mas o arquivo pode não conter o corpo da resposta necessário para análise ou comparação offline.

O que um HAR Não Garante

Um arquivo HAR é um registro durável da atividade HTTP capturada, mas não é um registro completo de cada comportamento do navegador.

Quadros WebSocket Não São Arquivados

HAR modela transações de requisição e resposta. Ele não preserva a sequência de mensagens transportadas dentro de uma conexão WebSocket estabelecida.

Uma página que combina endpoints HTTP normais com um feed WebSocket ao vivo precisa de mecanismos de captura separados:

  • HAR para tráfego de requisição e resposta HTTP
  • Ouvintes de quadros WebSocket para mensagens de socket

A conexão inicial pode envolver uma atualização HTTP, mas o fluxo de quadros contínuo está fora do modelo normal de requisição-resposta HAR.

Um HAR Não É uma Captura do DOM

O arquivo não preserva a árvore do documento final da maneira que uma captura do DOM faria.
Um corpo de resposta pode conter o HTML ou JSON originais, mas as mutações de JavaScript posteriores, o estado dos elementos, o layout renderizado e a aparência visível para o usuário são preocupações separadas.

Um HAR Não É Um Vídeo

O arquivo não contém uma linha do tempo visual do que apareceu na página.

Use a gravação de sessão do Scrapeless quando o objetivo for revisar o comportamento visível do navegador. Use a captura HAR quando o objetivo for inspecionar o tráfego HTTP estruturado.

Algum Conteúdo Pode Estar Ausente ou Codificado

O HAR suporta campos de conteúdo opcionais. Um gravador pode omitir corpos, e recursos binários podem ser codificados.

Antes de analisar response.content.text, verifique se:

  • O campo text existe.
  • O tipo de conteúdo é o esperado.
  • O campo encoding é tratado se presente.
  • O corpo não foi omitido pela configuração de gravação.

Uma solicitação capturada pode ser reemitida com sucesso quando o servidor ao vivo ainda aceita a solicitação reconstruída.

O endpoint público /api/quotes funciona porque não depende de uma sessão autenticada que expira.

A reemissão torna-se mais complicada quando a solicitação original usa:

  • Cookies de sessão
  • Tokens CSRF
  • Credenciais de portador de curta duração
  • URLs assinadas
  • Assinaturas de solicitação por sessão
  • Estado armazenado apenas dentro do navegador
  • Dados gerados por um passo de navegação anterior
  • Um corpo de solicitação cujo conteúdo muda por sessão

O HAR pode preservar os valores de credenciais originais, mas não pode estender sua validade. Uma vez que esses valores expirarem, pode ser necessária uma nova sessão do navegador para criar um estado novo.

Reproduzir Dados HAR com Segurança

Um arquivo HAR pode conter dados sensíveis de sessão.

Os cabeçalhos de solicitação e resposta podem expor:

  • Cookies
  • Cabeçalhos de autorização
  • Chaves de API
  • Identificadores de sessão
  • URLs internas
  • Dados pessoais retornados por um endpoint

Trate os arquivos HAR como artefatos sensíveis:

  • Não os comite em um repositório público.
  • Remova credenciais antes de compartilhá-los.
  • Restrinja o acesso a sessões de produção arquivadas.
  • Evite registrar cabeçalhos completos desnecessariamente.
  • Armazene apenas as capturas necessárias para a tarefa de depuração ou auditoria.
  • Exclua arquivos de acordo com os requisitos de retenção do projeto.

O arquivo nesta demonstração vem de uma página pública e não autenticada. As mesmas suposições não devem ser aplicadas automaticamente a aplicativos autenticados.

Problemas Comuns

O Arquivo HAR Não Aparece

A causa mais comum é fechar o navegador sem fechar explicitamente o contexto.

Use:

python Copy
context.close()
browser.close()

Confirme também se o processo pode escrever no diretório que contém HAR_PATH.

O HAR Não Contém Corpo de Resposta

Confirme se o contexto usa:

python Copy
record_har_content="embed"

Depois, verifique se entry["response"]["content"]["text"] existe. Alguns recursos podem ser omitidos ou representados com uma codificação.

urllib Rejeita Um Nome de Cabeçalho

Remova qualquer cabeçalho cujo nome comece com :. Esses são cabeçalhos pseudo do HTTP/2, não campos de cabeçalho normais.

A URL e o método da solicitação já carregam seu significado relevante.

A Resposta Reemitida É Comprimida Inesperadamente

Não copie o valor accept-encoding de um navegador cegamente a menos que o cliente de reprodução suporte toda codificação de conteúdo anunciada.

Deixe que o cliente HTTP negocie uma codificação que ele possa decodificar.

A Nova Resposta Não Corresponde ao HAR

Uma discrepância não significa necessariamente que o código de reconstrução está errado.

O servidor pode retornar conteúdo variável, timestamps, campos aleatórios, resultados específicos de geolocalização ou dados ligados a credenciais que não são mais válidas.

Compare os campos que se espera que permaneçam estáveis em vez de assumir que cada endpoint sempre retorna bytes idênticos.

Conclusão

O record_har_path do Playwright transforma um contexto de navegador em um arquivo HTTP durável.

O fluxo de trabalho tem três fases claras:

  1. Conecte o Playwright ao Scrapeless Scraping Browser e capture a sessão da página.
  2. Feche o navegador e inspecione log.entries como JSON comum.
  3. Reconstrua uma solicitação elegível com urllib e compare sua resposta ao vivo com o corpo capturado.

O navegador é necessário apenas para produzir o arquivo. Uma vez que context.close() esvazia o HAR, o arquivo pode ser analisado em uma máquina sem instalação do Playwright, processo do navegador ou conexão CDP.

Essa separação torna a captura HAR útil para depuração pós-sessão, descoberta de API interna, auditoria de rede e reconstrução de solicitações. Também mantém as limitações visíveis: o HAR não preserva quadros de WebSocket, estado visual renderizado ou a validade futura de credenciais capturadas.
Reveja a página do produto Scraping Browser para as capacidades de sessão do navegador por trás do fluxo de trabalho de captura e verifique os planos de preços da Scrapeless ao mover-se de uma sessão de demonstração para uma carga de trabalho de captura maior.

O explicador do protocolo Chrome DevTools cobre a superfície do protocolo por trás da conexão do navegador.

Junte-se à comunidade Scrapeless para comparar padrões de captura do Playwright e fluxos de trabalho de depuração de navegador com outros desenvolvedores: Discord · Telegram.

Inscreva-se em app.scrapeless.com para obter gratuitamente o tempo de execução do Scraping Browser, e adapte os passos de captura, inspeção e reconstrução de solicitações a uma página pública relevante para o seu projeto.


FAQ

Q: O que é um arquivo HAR?

Um arquivo HAR é um arquivo JSON de transações HTTP capturadas durante uma sessão de navegador. Seu array log.entries contém um objeto por solicitação registrada, com informações aninhadas de solicitação, resposta, tempo e conteúdo.

Um arquivo HAR não é uma captura de tela, vídeo da página ou um instantâneo completo do DOM.

Q: Como a captura HAR é diferente da interceptação de solicitações ao vivo?

A captura HAR registra o tráfego HTTP do contexto do navegador de forma ampla, enquanto a interceptação ao vivo observa as solicitações correspondentes à medida que ocorrem.

A interceptação ao vivo é útil quando o endpoint já é conhecido. A captura HAR é útil quando a solicitação importante pode ser descoberta apenas após a sessão ter terminado.

Q: Você precisa de um navegador para ler um arquivo HAR?

Não. Um arquivo HAR completo é um documento JSON comum que pode ser lido com o módulo json do Python.

O navegador é necessário durante a captura, mas não durante a inspeção offline.

Q: A captura HAR inclui tráfego WebSocket?

A captura HAR não arquiva as mensagens trocadas dentro de uma conexão WebSocket estabelecida.

Use um ouvinte de quadros WebSocket quando a página depender de um feed de socket ao vivo. A HAR ainda pode cobrir o tráfego HTTP ordinário usado pela mesma página.

Q: A gravação HAR do Playwright é a mesma que a gravação de sessão do Scrapeless?

Não. A gravação HAR do Playwright cria um arquivo de rede estruturado, enquanto a gravação de sessão do Scrapeless cria uma reprodução visual da sessão do navegador renderizada.

Use HAR para análise de solicitação e resposta. Use a gravação de sessão quando o comportamento visível da página for o objeto da investigação.

Q: O exemplo urllib é o mesmo que route_from_har() do Playwright?

Não. route_from_har() serve respostas registradas para solicitações feitas dentro de um contexto de navegador Playwright ao vivo.

O exemplo urllib lê uma solicitação do HAR e envia uma nova solicitação ao servidor ativo sem iniciar um navegador.

Q: Por que um HAR contém cabeçalhos como :authority e :method?

Esses nomes são campos de cabeçalho pseudo-HTTP/2 usados para transmitir dados de controle de solicitação dentro do protocolo HTTP/2.

Eles não são campos de cabeçalho ordinários, portanto, um cliente no estilo HTTP/1.1 deve representar seu significado através do método de solicitação e URL em vez de copiar os nomes prefixados por dois pontos.

Q: Cada solicitação capturada pode ser reemitida com sucesso?

Não. Uma solicitação só pode ser reemitida enquanto o servidor ativo aceitar o método, URL, corpo, cabeçalhos e credenciais reconstruídos.

Solicitações que dependem de cookies expirados, tokens CSRF, URLs assinadas ou credenciais portadoras de curta duração podem exigir uma nova sessão de navegador.

Q: Você precisa de um proxy separado para esse fluxo de trabalho?

Nenhuma configuração de proxy separada é necessária quando a conexão do Scrapeless Scraping Browser já especifica o país do proxy desejado.

O exemplo define proxyCountry=US na URL de conexão CDP, então a sessão do navegador usa essa saída configurada.

Q: É seguro compartilhar um arquivo HAR?

Um arquivo HAR deve ser tratado como sensível até que seu conteúdo tenha sido revisado e sanitizado.

Ele pode conter cookies, cabeçalhos de autorização, chaves de API, endpoints internos, dados de formulário enviados ou conteúdo de resposta privado. Remova valores sensíveis antes de compartilhar ou comprometer o arquivo.

Q: A gravação HAR funciona apenas com o Scrapeless Scraping Browser?

Não. record_har_path é uma opção de contexto de navegador do Playwright e pode ser usada com navegadores locais ou remotos compatíveis.

O Scrapeless Scraping Browser fornece o ambiente remoto gerenciado do Chromium e a configuração do proxy usados durante a fase de captura.

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