Pular para o conteúdo

Extensões do Chrome

Carregue extensões descompactadas na inicialização com extensions. Manifest V2 e V3 funcionam, nos modos headed e headless, no Windows e no Linux.

Carregue uma extensão

Passe uma lista de diretórios de extensões descompactadas — cada um, uma pasta que contém um manifest.json — para launch(), launch_persistent_context() ou serve() (.NET: Extensions = new[] { ... }). Elas são carregadas no perfil do navegador, então as únicas inicializações que não as aceitam são as anônimas (ephemeral_profile=False, o launch() da API assíncrona, LaunchAsync do .NET). As extensões valem para navegadores que você inicia com o SDK; navegadores hospedados não as carregam.

python
from clearcote import launch_persistent_context

ctx = launch_persistent_context(
    "./profile",
    extensions=["./ext/ublock", "./ext/my-helper"],   # unpacked directories
)
page = ctx.pages[0] if ctx.pages else ctx.new_page()
page.goto("https://example.com")
javascript
import { launchPersistentContext } from "clearcote";

const ctx = await launchPersistentContext("./profile", {
  extensions: ["./ext/ublock", "./ext/my-helper"],
});

O SDK define tanto --load-extension quanto --disable-extensions-except para você. Essa combinação importa: sozinho, --load-extension é ignorado sob automação, e esse é o motivo mais comum de uma extensão não aparecer, sem nenhum aviso.

Como obter um diretório descompactado

O Clearcote carrega pastas, não arquivos .crx. Um .crx é um ZIP com um cabeçalho de assinatura, então basta descompactá-lo para ter um diretório que pode ser carregado:

bash
unzip extension.crx -d ./ext/extension

O Clearcote não consegue instalar nem atualizar extensões pela Chrome Web Store — os patches de privacidade do upstream removem essa integração. Distribua o diretório descompactado junto com a sua automação e atualize-o você mesmo: extensões carregadas dessa forma nunca se atualizam sozinhas. É o mesmo modelo que o Playwright e o Puppeteer usam.

O Manifest V2 continua funcionando

O Chrome padrão não roda mais extensões Manifest V2. O Clearcote ainda roda, porque o conjunto de patches de privacidade do upstream restaura esse suporte — então bloqueadores de conteúdo exclusivos de MV2 e ferramentas internas mais antigas continuam funcionando aqui depois de terem parado de funcionar no Chrome.

python
# both of these load and run
ctx = launch_persistent_context("./profile", extensions=["./ext/mv2-tool", "./ext/mv3-tool"])

Headless

As extensões carregam tanto no modo headless quanto no headed. Sem flags extras, e sem precisar rodar um servidor de display só para fazer uma extensão funcionar.

python
ctx = launch_persistent_context("./profile", extensions=["./ext/my-helper"], headless=True)

Considerações de fingerprint

Uma extensão é código seu rodando no seu perfil, e o Clearcote não a esconde. Daí decorrem duas coisas, e vale a pena decidir as duas de forma deliberada em vez de descobri-las mais tarde.

  • Extensões são observáveis. Um content script que reescreve o DOM, injeta estilos ou bloqueia requisições muda o que uma página mede. Um site que compara a própria marcação com o que ele serviu consegue perceber que algo modificou a página. Isso vale para qualquer navegador com extensões e não é um sinal específico do Clearcote, mas é um sinal.
  • Recursos acessíveis pela web podem ser sondados. Se uma extensão declara web_accessible_resources, qualquer página pode tentar buscar chrome-extension://<id>/<file> e descobrir que a extensão está presente. Prefira extensões que não declarem nenhum, e tenha use_dynamic_url em mente para as que precisam declarar.

Se o seu objetivo é bloquear requisições, e não oferecer uma interface, considere fazer isso na camada de automação com o Network.setBlockedURLs do CDP — ele bloqueia por padrão de URL, não adiciona superfície de extensão e mantém o cache do navegador (o page.route() do Playwright também funciona, mas desliga o cache). Veja Configurações recomendadas para o princípio geral: falsifique só o que você precisa, e só adicione superfície que justifique a sua presença.

Solução de problemas

  • Nada acontece. Confira se o caminho aponta para a pasta que contém o manifest.json, e não para a pasta pai nem para um .crx.
  • O content script nunca roda. Confirme que o padrão de matches cobre a URL que você está visitando — http://localhost/* não corresponde a http://127.0.0.1:8080/.
  • Funciona em headed, mas não em headless. Isso não deveria acontecer neste build; os dois funcionam. Se acontecer com você, por favor abra uma issue com o manifest.