Saltar al contenido

Extensiones de Chrome

Carga extensiones desempaquetadas al lanzar con extensions. Funcionan tanto Manifest V2 como V3, con ventana y en headless, en Windows y Linux.

Carga una

Pasa una lista de directorios de extensiones desempaquetadas (cada uno, una carpeta que contiene un manifest.json) a launch(), launch_persistent_context() o serve() (.NET: Extensions = new[] { ... }). Se cargan en el perfil del navegador, así que los únicos lanzamientos que no las admiten son los de incógnito (ephemeral_profile=False, el launch() de la API asíncrona, LaunchAsync de .NET). Las extensiones son para navegadores que inicias con el SDK; los navegadores alojados no las cargan.

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"],
});

El SDK configura por ti tanto --load-extension como --disable-extensions-except. Esa combinación importa: por sí solo, --load-extension se ignora bajo automatización, y ese es el motivo habitual por el que una extensión no aparece sin dar ningún error.

Cómo obtener un directorio desempaquetado

Clearcote carga carpetas, no archivos .crx. Un .crx es un ZIP con un encabezado de firma, así que al descomprimirlo obtienes un directorio que se puede cargar:

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

Clearcote no puede instalar ni actualizar extensiones desde la Chrome Web Store: los parches de privacidad de upstream eliminan esa integración. Distribuye el directorio desempaquetado junto con tu automatización y actualízalo tú mismo: las extensiones cargadas de esta forma nunca se actualizan solas. Es el mismo modelo que usan Playwright y Puppeteer.

Manifest V2 sigue funcionando

El Chrome estándar ya no ejecuta extensiones Manifest V2. Clearcote sí, porque el conjunto de parches de privacidad de upstream restaura ese soporte; así, los bloqueadores de contenido que solo existen para MV2 y las herramientas internas más antiguas siguen funcionando aquí cuando ya dejaron de funcionar en Chrome.

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

Headless

Las extensiones se cargan en modo headless igual que con ventana. Sin flags adicionales y sin necesidad de ejecutar un servidor gráfico solo para que una extensión funcione.

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

Consideraciones sobre la huella digital

Una extensión es código tuyo que se ejecuta en tu perfil, y Clearcote no la oculta. De ahí se derivan dos cosas, y conviene decidir ambas de forma deliberada en lugar de descubrirlas más tarde.

  • Las extensiones son observables. Un content script que reescribe el DOM, inyecta estilos o bloquea solicitudes cambia lo que mide una página. Un sitio que compara su propio markup con lo que sirvió puede darse cuenta de que algo modificó la página. Esto ocurre en cualquier navegador con extensiones y no es una señal propia de Clearcote, pero es una señal.
  • Los recursos accesibles desde la web se pueden sondear. Si una extensión declara web_accessible_resources, cualquier página puede intentar obtener chrome-extension://<id>/<file> y saber que la extensión está presente. Prefiere extensiones que no declaren ninguno, y ten en cuenta use_dynamic_url para las que sí deban hacerlo.

Si tu objetivo es bloquear solicitudes y no ofrecer una interfaz, considera hacerlo en la capa de automatización con Network.setBlockedURLs de CDP: bloquea por patrón de URL, no añade superficie de extensión y conserva la caché del navegador (page.route() de Playwright también funciona, pero desactiva la caché). Consulta Configuración recomendada para el principio general: falsea solo lo que necesitas y añade solo la superficie que se gane su lugar.

Solución de problemas

  • No pasa nada. Comprueba que la ruta apunte a la carpeta que contiene manifest.json, no a su carpeta padre ni a un .crx.
  • El content script nunca se ejecuta. Confirma que el patrón de matches cubra la URL que visitas: http://localhost/* no coincide con http://127.0.0.1:8080/.
  • Funciona con ventana pero no en headless. Eso no debería pasar en este build; ambos modos funcionan. Si te ocurre, por favor abre un issue con el manifest.