Chrome te dice por qué `--load-extension` dejó de funcionar. Solo que no lo estás viendo.

Última actualización: August 17, 2026
Chrome te dice por qué `--load-extension` dejó de funcionar. Solo que no lo estás viendo.
Resumen con IA
En la matriz probada, Google Chrome 150 estándar rechazó --disable-extensions-except junto con --load-extension, mientras que Chrome for Testing 149 y 151 cargaron la extensión. Chrome registró el rechazo con severidad WARNING: "--load-extension is not allowed in Google Chrome, ignoring." La redacción respalda una interpretación de compilación con marca, y el sandwich de versiones descarta una simple eliminación monótona, pero compilación y versión siguen confundidas sin un brazo de comparación entre compilaciones de la misma versión o evidencia de código/configuración. Para un harness de extensiones fijado, usa un ejecutable del navegador versionado explícitamente y verifica tanto el service worker como el marcador del content script.

Dos flags son habituales en ejemplos de automatización de extensiones:

--disable-extensions-except=/path/to/ext  --load-extension=/path/to/ext

Los tutoriales más antiguos suelen apuntar Puppeteer o Playwright a un Chrome instalado y pasan ambos flags.

En la compilación estándar de Google Chrome 150 probada aquí, el navegador arrancó sin error de línea de comandos, pero el servicio de extensiones hizo caso omiso de ambos flags. La automatización conectó con normalidad y la extensión no estaba presente; el síntoma tardío fue un timeout de selector en este harness.

Chrome dejó constancia del rechazo en una sola línea, pero solo después de activar el logging por stderr.

El hallazgo principal está en la comparación entre compilaciones del navegador. Las dos secciones siguientes son, de forma explícita, notas del harness: una sobre las descargas disparadas por la extensión y otra sobre esta ruta de instalación por línea de comandos en fixtures file://. Thunderbit es en sí una extensión de Chrome, así que este problema nos toca de cerca; Thunderbit no fue el objetivo de prueba.

La línea

Añade --enable-logging=stderr y arranca el Chrome estándar con esos flags:

Referencia oficial: código fuente del servicio de extensiones de Chromium.

WARNING:chrome/browser/extensions/extension_service.cc:442]
  --disable-extensions-except is not allowed in Google Chrome, ignoring.

Si pasas --load-extension por separado, verás su propia advertencia, en otra línea del mismo archivo:

WARNING:chrome/browser/extensions/extension_service.cc:420]
  --load-extension is not allowed in Google Chrome, ignoring.

Chrome for Testing, con flags idénticos, no imprime ninguna de las dos.

"No está permitido en Google Chrome." Esa advertencia convierte una regla propia de la compilación de marca en la interpretación principal de este rechazo observado. Demuestra que esta compilación estándar de Google Chrome 150 ignoró el flag e identifica la ubicación de origen. Pero por sí sola no demuestra que esa versión sea la causa ni revela cuál es el discriminador de implementación.

Todo lo que sigue es confirmación y consecuencias.

Confirmación conductual

Una extensión MV3 mínima, creada para esta prueba y no descargada de ningún sitio, usa un content script, popup, ida y vuelta de mensajes, extracción del DOM y exportación con chrome.downloads contra un fixture local con tres productos. El harness registra seis comprobaciones numeradas: el service worker se registró; el marcador de la extensión lleva un ID; el marcador del content script coincide; el botón del popup es visible; el popup devuelve tres filas; el CSV capturado contiene la fila esperada. Una aserción aparte compara las señales independientes del service worker y del marcador de página.

Tres compilaciones usaron los mismos flags explícitos de extensión, el mismo directorio de extensión, el mismo fixture HTTP, el modo de contexto persistente con interfaz gráfica y un perfil nuevo por brazo. El brazo estándar se resolvió mediante channel: 'chrome'; los dos brazos que sí pasaron usaron rutas ejecutables explícitas. Las versiones se leyeron de vuelta mediante CDP.

CompilaciónVersión informada por el navegadorService worker de la extensiónContent script inyectadoEjecución completa de seis comprobaciones
Chrome for TestingChrome/149.0.7827.55APROBADO 6/6
Google Chrome estándarChrome/150.0.7871.187❌ nunca se registróFALLO en el paso 0
Chrome for TestingChrome/151.0.7922.10APROBADO 6/6

Resúmenes en bruto: Chrome for Testing 149, Chrome estándar 150, Chrome for Testing 151 y advertencias de stderr.

Chrome for Testing 149 está incluido a propósito: es anterior a la compilación estándar con la que se compara. Si la capacidad se hubiera eliminado por un salto de versión, una compilación más antigua debería quedar del lado que funciona y la que falla debería ser la más nueva. En cambio, la compilación fallida queda entre dos que sí funcionan, lo que descarta una simple progresión por versión.

Esa tabla sola no demuestra que la barrera dependa de la compilación, y conviene ser muy preciso sobre por qué. La única celda fallida es al mismo tiempo la única celda estándar y la única celda 150: compilación y versión siguen perfectamente confundidas en este diseño. Tres brazos descartan la eliminación monótona; no pueden descartar "se quitó en 150 y se restauró en 151". Obtener eso solo a partir del comportamiento exigiría una celda que esta máquina no puede producir: Chrome for Testing 150, o una compilación con marca en otra versión.

La advertencia refuerza la interpretación de compilación con marca porque nombra explícitamente Google Chrome, mientras que el comportamiento de tres brazos solo descarta una simple eliminación monótona. Haría falta todavía una comparación entre compilaciones de la misma versión o una cita de código/configuración para probar un mecanismo independiente de la versión.

Los artefactos por compilación enlazados muestran la ejecución resumida de cada brazo; este artículo no publica una matriz ejecución por ejecución para el conteo adicional de arranques, así que no usa ese conteo como evidencia independiente.

Una sola señal no basta para decir "no cargó"

La primera versión de esta prueba decidía si la extensión se había cargado buscando un marcador que el content script escribe en la página —y así también decidía si el content script se había ejecutado. Una sola lectura, usada como dos mediciones. Si el marcador falta, no puedes distinguir entre "la extensión nunca cargó" y "cargó pero su content script no se inyectó", y esas dos situaciones se arreglan de formas completamente distintas.

Las extensiones MV3 ejecutan un service worker en segundo plano, y Playwright expone los service workers directamente. Esa es una señal independiente: nunca toca la página, así que no puede confundirse con la inyección. La prueba actual lee ambas y comprueba que coincidan.

En las tres ejecuciones coinciden. En el Chrome estándar nunca llegó a registrarse ningún service worker —la forma fuerte de la afirmación. En ambos Chrome for Testing, el worker apareció en chrome-extension://<id>/background.js antes de que la página siquiera se abriera.

Usa Chrome for Testing, que quizá ya tengas

Los dos brazos que pasaron usaron ejecutables explícitos de Chrome for Testing que reportaban las versiones 149.0.7827.55 y 151.0.7922.10. Apunta executablePath de Playwright al ejecutable fijado, en lugar de resolver Chrome estándar mediante channel: 'chrome'. npx playwright install chromium instala una compilación Chromium gestionada por Playwright; también puede servir para automatización, pero no es la misma etiqueta de distribución que los dos brazos de Chrome for Testing y no fue un cuarto brazo en esta comparación.

Referencia oficial: anuncio de Chrome for Testing.

Revisión relacionada: auditoría de permisos de extensiones de Chrome.

Hay un beneficio adicional que dura más que este fallo concreto. El Chrome estándar se actualiza automáticamente por debajo de ti, así que una suite que hoy pasa puede fallar el martes por motivos que ningún commit explica. Chrome for Testing está fijado. Para cualquier cosa cuyo resultado deba seguir teniendo sentido dentro de tres meses, eso importa más que la comodidad.

Nota del harness: capturar la exportación de la extensión

Para una extensión de scraping, la exportación lo es todo: ahí es donde se pierden campos, se deforman codificaciones y se aplana mal la estructura anidada. Hay dos cosas sobre ello que no están documentadas, y ambas muerden.

Lo que registró la ejecución de exportaciónValor
playwright_download_event_firedfalse
suggestedFilenamenull
Nombre de archivo que solicita la extensiónprobe-export.csv
Nombre de archivo que acaba en el directoriodownload.csv
Contenido del archivoel encabezado y las tres filas sobreviven intactos

En este harness MV3/Playwright 1.56.0, chrome.downloads no activó el evento de descarga de Playwright. Cuando la extensión exportó un CSV mediante la API, waitForEvent('download') no se resolvió. El harness capturó el archivo abriendo una sesión CDP, configurando explícitamente el comportamiento de descarga y leyendo el directorio de salida:

const cdp = await ctx.newCDPSession(page);
await cdp.send('Browser.setDownloadBehavior', {
  behavior: 'allow', downloadPath: DIR, eventsEnabled: true,
});

En el mismo harness, esa ruta de captura por CDP no conservó el nombre de archivo solicitado. El encabezado y las tres filas sobrevivieron intactos, pero probe-export.csv terminó como download.csv. Este es un comportamiento observado para las compilaciones y la configuración probadas, no una invariante documentada para cualquier descarga de extensión. Comprueba el contenido por separado del nombre de archivo.

Nota del harness: comportamiento de file:// para esta ruta de instalación

Al verificar esta parte, una afirmación muy repetida resultó ser falsa, y había terminado en un borrador anterior de este mismo artículo: que los content scripts no se ejecutan en páginas file:// porque las extensiones no tienen acceso a archivos por defecto.

Medido en ambas compilaciones de Chrome for Testing, cargando la extensión desde la línea de comandos y navegando directamente a file:///…/fixture/index.html: el content script se inyecta con normalidad. Marcador presente, ID de la extensión correcto, ambas compilaciones. Las extensiones desempaquetadas cargadas por línea de comandos sí obtienen acceso a archivos; el interruptor de "conceder acceso a archivos" que mucha gente recuerda aplica a otra ruta de instalación.

Servir los fixtures por HTTP sigue siendo la mejor opción por defecto, porque una página file:// no se parece en nada a un objetivo real. Pero es un argumento de realismo, no un requisito técnico, y el mecanismo que suele citarse para ello es incorrecto.

Lo que esto no demuestra

  • La implementación de la barrera solo puede leerse hasta donde llega la cadena de advertencia. Chrome dice que estos flags no están permitidos en esta compilación y nombra el archivo de origen. No se leyó del código si eso depende de la configuración de compilación, del plumbing de políticas o de otra cosa.
  • Esto es una sola máquina. macOS en arm64, una versión de parche estándar, dos compilaciones de Chrome for Testing. Chrome cambia lo bastante rápido como para que esto deba volver a comprobarse en lugar de citarse.
  • Esto solo cubre la ruta --load-extension. No se probaron instalaciones de .crx empaquetadas, carga en modo desarrollador ni políticas empresariales de allowlist. Nada aquí respalda la afirmación de que "Chrome estándar no puede ejecutar extensiones".
  • La extensión es un stub creado ad hoc. Ejercita la mecánica que usa cualquier extensión de scraping, pero una extensión real es más grande y puede fallar de formas que un stub no puede.

Lo que me equivoqué por el camino

Conviene decirlo con claridad, porque ambos errores son del tipo que sobreviven a la revisión cuando el resultado parece correcto.

La primera versión de este texto decía que el fallo era silencioso, que no existía ninguna línea de log y que el mecanismo era imposible de conocer —que cualquiera que afirmara saberlo estaba adivinando. El mecanismo estaba a un flag de distancia, y Chrome lo había estado imprimiendo con severidad WARNING todo el tiempo. Lo que no supe encontrar se había escrito como si no pudiera encontrarse.

La segunda fue la afirmación sobre file:// de arriba: repetida a partir de notas y redactada con un mecanismo aparentemente seguro antes de ser probada. Una ejecución la falsó.

El patrón es el mismo en ambos casos. Una afirmación plausible que nadie cuestionaría, arrastrada hacia delante porque comprobarla parecía innecesario. La solución no es más cautela en la redacción, sino una regla sobre lo que se afirma: una afirmación que no pueda rastrearse hasta una ejecución no se publica.

Comandos usados en el harness local

El probe, el stub de extensión, el fixture y los resúmenes en bruto están enlazados aquí, pero todavía no forman un paquete de reproducción pública independiente. Las fuentes exactas de descarga de Chrome for Testing 149 y 151 y sus checksums no están registradas en el artículo, y las rutas ejecutables de abajo eran entradas locales. Publica esas fuentes del navegador más un commit estable del repositorio antes de presentar la comparación completa como reproducible de forma independiente.

Revisión relacionada: revisión de Playwright.

cd harness
npm install playwright@1.56.0
npx playwright install chromium      # Chromium gestionado por Playwright; no son los dos brazos de CfT de abajo
(cd fixture && python3 -m http.server 8731 &)

SP=$(pwd) OUT=cft-149.json   LABEL=cft-149   EXE="<Chrome for Testing 149>" node probe_v2.mjs
SP=$(pwd) OUT=stock-150.json LABEL=stock-150 CHANNEL=chrome                 node probe_v2.mjs
SP=$(pwd) OUT=cft-151.json   LABEL=cft-151   EXE="<Chrome for Testing 151>" node probe_v2.mjs

El mismo script y los mismos argumentos explícitos de extensión se usaron para los tres brazos, pero la resolución del ejecutable difería: CHANNEL=chrome para Chrome estándar y EXE para los dos binarios de Chrome for Testing. La versión en cada archivo de salida se lee del navegador y no se da por buena a partir de la etiqueta.

Para la línea de advertencia, no hace falta harness:

"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
  --user-data-dir=/tmp/p --enable-logging=stderr \
  --load-extension=/path/to/ext about:blank 2>&1 | grep "not allowed"

A fecha de 2026-07-28.

Prueba Thunderbit para extraer datos web

Decisión y advertencias

En la matriz probada, Google Chrome 150 estándar rechazó --disable-extensions-except junto con --load-extension, mientras que Chrome for Testing 149 y 151 cargaron la extensión. Chrome registró el rechazo con severidad WARNING: "--load-extension is not allowed in Google Chrome, ignoring." La redacción respalda una interpretación de compilación con marca, y el sandwich de versiones descarta una simple eliminación monótona, pero compilación y versión siguen confundidas sin un brazo de comparación entre compilaciones de la misma versión o evidencia de código/configuración.

Para un harness de extensiones fijado, usa un ejecutable del navegador versionado explícitamente y verifica tanto el service worker como el marcador del content script. En esta configuración de Playwright 1.56.0, la exportación de la extensión requirió captura por CDP en un directorio y llegó con un nombre de archivo distinto. El stub cargado por línea de comandos también se inyectó en el fixture file:// probado; no se probaron otras rutas de instalación.

Prueba Thunderbit para extraer datos web Get Started Free

Preguntas frecuentes

¿--load-extension ha desaparecido por completo de Chrome? No. Chrome for Testing 149.0.7827.55 y 151.0.7922.10 cargaron ambos el stub MV3 desempaquetado desde ese flag y completaron las seis comprobaciones puntuadas. Google Chrome 150.0.7871.187 estándar lo rechazó y registró "--load-extension is not allowed in Google Chrome, ignoring". Esto respalda, pero no prueba, una barrera propia de la compilación con marca: el comportamiento descarta una simple eliminación monótona, mientras que una regresión específica de Chrome 150 restaurada en 151 sigue siendo compatible con el diseño de tres brazos.

¿Por qué no veo ningún error, y cómo distingues "nunca cargó" de "cargó y falló en silencio"? La advertencia no se imprime con la verbosidad predeterminada. Lanza Chrome con --enable-logging=stderr y aparecerá de inmediato; sin eso, Chrome arranca con normalidad pero su servicio de extensiones ignora los flags, y el primer síntoma del harness es un timeout de selector. Para separar “nunca cargó” de un fallo de inyección, usa dos señales independientes: el service worker de fondo MV3 y un marcador del content script en el DOM objetivo. En el brazo estándar probado no apareció ninguna; en ambos brazos de Chrome for Testing sí aparecieron.

¿Qué debería usar en su lugar para automatizar extensiones? Los brazos que pasaron usaron ejecutables fijados de Chrome for Testing mediante executablePath. Chromium gestionado por Playwright es otro binario posible para automatización, pero no fue un brazo en esta prueba y no debería describirse como la misma distribución sin comprobar el ejecutable resuelto.

¿Por qué waitForEvent('download') nunca se resuelve cuando la extensión exporta un archivo? En esta configuración MV3/Playwright 1.56.0, el evento no se resolvió y no se ofreció ningún nombre sugerido. El harness abrió una sesión CDP, llamó a Browser.setDownloadBehavior con un directorio explícito y luego leyó el archivo desde disco. En las ejecuciones probadas, los bytes del CSV sobrevivieron, pero probe-export.csv llegó como download.csv; no se probaron combinaciones más amplias de extensiones y navegadores.

¿Qué no dice esto —sobre URLs file:// y sobre Chrome estándar en general? Dos límites, en direcciones opuestas. Los content scripts funcionan en URLs file:// para extensiones cargadas desde la línea de comandos —probado en ambas compilaciones de Chrome for Testing, con el script inyectándose normalmente y el ID de la extensión reportado correctamente, así que la afirmación habitual de que no lo hacen (porque las extensiones no tienen acceso a archivos por defecto) es falsa para esta ruta de instalación. Servir los fixtures por HTTP sigue siendo mejor práctica porque se parece a un objetivo real, no porque file:// bloquee la inyección. En la otra dirección: nada de esto dice que Chrome estándar no pueda ejecutar extensiones. Solo se midió la ruta de línea de comandos --load-extension. No se probaron la instalación de .crx empaquetados, la carga en modo desarrollador ni las políticas empresariales de allowlist, y no se hace ninguna afirmación sobre ellas. El alcance es el par de flags que los tutoriales de automatización te dicen que uses.

Ke
Ke
CTO en Thunderbit | Científico de datos sénior y experto en ML Con casi una década de experiencia en aprendizaje automático y ciencia de datos, Ke Shen es exalumno de la Universidad de Columbia y antiguo científico de datos sénior en Walmart Labs. Con una sólida experiencia, reconocida por sus pares, en Python, R, Java y estadística, comparte conocimientos probados en el campo sobre cómo llevar algoritmos complejos de IA desde la teoría hasta una arquitectura lista para producción.
Tabla de contenidos
Thunderbit · Agente de datos web con IA

Extrae datos de cualquier página en 1 clic

Con la confianza de más de 250,000 usuarios
plan gratuito disponible
De la página web a la hoja de cálculo
Describe lo que necesitas: el agente de IA de Thunderbit lo extrae y lo exporta a Excel, Google Sheets, Airtable o Notion. Empieza gratis.
Chrome Store Rating
PRODUCT HUNT#1 Product of the Week