Twee flags komen vaak voor in voorbeelden voor extensie-automatisering:
--disable-extensions-except=/path/to/ext --load-extension=/path/to/ext
Oudere handleidingen sturen Puppeteer of Playwright naar een geïnstalleerde Chrome en geven beide flags mee.
In de standaard Google Chrome 150-build die hier is getest, startte de browser zonder command-line foutmelding, maar de extensieservice negeerde beide flags. De automatisering maakte normaal verbinding en de extensie ontbrak; het latere symptoom was een selector-time-out in deze testopzet.
Chrome logde de weigering in één regel, maar alleen nadat stderr-logging was ingeschakeld.
De belangrijkste bevinding is de vergelijking tussen browser-builds. Twee latere secties zijn nadrukkelijk testopmerkingen: de ene gaat over downloads die door een extensie worden getriggerd, en de andere over dit command-line installatietraject op file://-fixtures. Thunderbit is zelf een Chrome-extensie, dus we hebben directe interesse in dit probleem; Thunderbit was niet het testdoel.
De regel
Voeg --enable-logging=stderr toe en start standaard Chrome met die flags:
Officiële referentie: Chromium extensieservice broncode.
WARNING:chrome/browser/extensions/extension_service.cc:442]
--disable-extensions-except is not allowed in Google Chrome, ignoring.
Geef je --load-extension los mee, dan krijg je een eigen waarschuwing, uit een andere regel van hetzelfde bestand:
WARNING:chrome/browser/extensions/extension_service.cc:420]
--load-extension is not allowed in Google Chrome, ignoring.
Chrome for Testing geeft, met exact dezelfde flags, geen van beide meldingen.
"Not allowed in Google Chrome." Die waarschuwing maakt van een beperking die aan de branded build gekoppeld is de meest waarschijnlijke verklaring voor de geobserveerde weigering. Ze bewijst dat deze standaard Google Chrome 150-build de flag negeerde en wijst de bronlocatie aan. Ze bewijst niet apart dat de versie irrelevant is en onthult ook niet welke implementatiefactor de doorslag geeft.
Alles hieronder is bevestiging en gevolg.
Bevestigen via gedrag
Een minimale MV3-extensie, speciaal voor deze test gebouwd en niet gedownload, gebruikt een content script, popup, message round trip, DOM-extractie en chrome.downloads-export tegen een lokale fixture met drie producten. De harness registreert zes genummerde controles: service worker geregistreerd; extensiemarker bevat een ID; content-scriptmarker komt overeen; popupknop is zichtbaar; popup geeft drie rijen terug; vastgelegde CSV bevat de verwachte rij. Een aparte overeenstemmingscontrole vergelijkt de onafhankelijke signalen van service worker en paginamarker.
Drie builds gebruikten dezelfde expliciete extensieflags, extensiemap, HTTP-fixture, headed persistent-context-modus en een verse profielmap per arm. De standaardarm liep via channel: 'chrome'; de twee geslaagde armen gebruikten expliciete executable paths. Versies werden via CDP uitgelezen.
| Build | Versie gemeld door de browser | Extensie service worker | Content script geïnjecteerd | Volledige zes-stappenrun |
|---|---|---|---|---|
| Chrome for Testing | Chrome/149.0.7827.55 | ✅ | ✅ | GESLAAGD 6/6 |
| Standaard Google Chrome | Chrome/150.0.7871.187 | ❌ nooit geregistreerd | ❌ | Mislukt bij stap 0 |
| Chrome for Testing | Chrome/151.0.7922.10 | ✅ | ✅ | GESLAAGD 6/6 |
Ruwe samenvattingen: Chrome for Testing 149, standaard Chrome 150, Chrome for Testing 151, en stderr-waarschuwingen.
Chrome for Testing 149 is hier bewust opgenomen: het is ouder dan de standaardbuild waarmee het wordt vergeleken. Als de mogelijkheid door een versie-upgrade was verdwenen, dan zou een oudere build aan de werkende kant van de lijn moeten staan en zou de falende build de nieuwste zijn. In plaats daarvan zit de falende build tussen twee werkende builds, wat een simpele versieprogressie uitsluit.
Die tabel bewijst op zichzelf niet dat de gate build-gebaseerd is, en het is belangrijk om precies te zijn over waarom. De ene falende cel is tegelijk de enige standaardcel en de enige 150-cel — build en versie zijn in dit ontwerp nog steeds perfect met elkaar verstrengeld. Drie armen sluiten monotone verwijdering uit; ze sluiten niet uit dat het "in 150 regresseerde en in 151 hersteld werd". Dat alleen uit gedrag afleiden zou een cel vereisen die deze machine niet kan produceren: Chrome for Testing 150, of een branded build op een andere versie.
De waarschuwing versterkt de interpretatie van een branded build omdat ze expliciet Google Chrome noemt, terwijl het gedrag over drie armen alleen een simpele monotone verwijdering uitsluit. Een cross-build vergelijking op dezelfde versie of een bron/config-citaat zou nog steeds nodig zijn om een versie-onafhankelijk mechanisme te bewijzen.
De gelinkte artifacts per build tonen de samengevatte run voor elke arm; dit artikel publiceert geen run-per-run matrix voor de extra launch count, dus die telling wordt niet als onafhankelijk bewijs gebruikt.
Eén signaal is niet genoeg om te zeggen "het laadde niet"
De eerste versie van deze test bepaalde of de extensie geladen was door te zoeken naar een marker die het content script in de pagina schrijft — en op precies dezelfde manier bepaalde die ook of het content script was uitgevoerd. Één waarneming, gebruikt als twee metingen. Als de marker ontbreekt, kun je niet onderscheiden tussen "de extensie is nooit geladen" en "de extensie laadde wel, maar het content script injecteerde niet"; en dat vraagt om totaal andere oplossingen.
MV3-extensies draaien met een background service worker, en Playwright toont service workers direct. Dat is een onafhankelijk signaal: het raakt de pagina niet en kan dus niet verward worden met injectie. De huidige test leest beide signalen en controleert of ze overeenkomen.
In alle drie runs komen ze overeen. Op standaard Chrome was nooit een service worker geregistreerd — de sterke vorm van de claim. Op beide Chrome for Testing-builds kwam de worker op als chrome-extension://<id>/background.js nog voordat de pagina ooit werd geopend.
Gebruik Chrome for Testing, dat je misschien al hebt
De twee geslaagde armen gebruikten expliciete Chrome for Testing-executables met versies 149.0.7827.55 en 151.0.7922.10. Wijs Playwright’s executablePath naar de vastgepinde executable in plaats van standaard Chrome via channel: 'chrome' op te lossen. npx playwright install chromium installeert een door Playwright beheerde Chromium-build; die kan ook handig zijn voor automatisering, maar het is niet hetzelfde distributielabel als de twee Chrome for Testing-armen en was geen vierde arm in deze vergelijking.
Officiële referentie: aankondiging Chrome for Testing.
Gerelateerde analyse: audit van Chrome-extensie-machtigingen.
Er is ook een voordeel dat verder reikt dan deze specifieke breuk. Standaard Chrome update automatisch onder je voeten, waardoor een suite die vandaag slaagt op dinsdag kan falen om redenen die geen enkele commit verklaart. Chrome for Testing is vastgepind. Voor alles waarvan het resultaat over drie maanden nog steeds iets moet betekenen, weegt dat zwaarder dan gemak.
Testopmerking: de extensie-export vastleggen
Voor een scraping-extensie is de export juist het hele doel — daar gaan velden verloren, raken encoderingen beschadigd en worden geneste data verkeerd afgevlakt. Twee dingen eraan zijn ongedocumenteerd, en beide veroorzaken problemen.
| Wat de export-run vastlegde | Waarde |
|---|---|
playwright_download_event_fired | false |
suggestedFilename | null |
| Bestandsnaam die de extensie aanvraagt | probe-export.csv |
| Bestandsnaam die in de map terechtkomt | download.csv |
| Bestandsinhoud | de kopregel en alle drie rijen blijven intact |
In deze MV3/Playwright 1.56.0-harness triggerde chrome.downloads het download-event van Playwright niet. Toen de extensie via de API een CSV exporteerde, werd waitForEvent('download') niet geactiveerd. De harness ving het bestand op door een CDP-sessie te openen, downloadgedrag expliciet in te stellen en de uitvoermap uit te lezen:
const cdp = await ctx.newCDPSession(page);
await cdp.send('Browser.setDownloadBehavior', {
behavior: 'allow', downloadPath: DIR, eventsEnabled: true,
});
In dezelfde harness behield dat CDP-capturepad de aangevraagde bestandsnaam niet. De kopregel en alle drie rijen bleven intact, maar probe-export.csv kwam binnen als download.csv. Dit is waargenomen gedrag voor de geteste browser-builds en configuratie, niet een gedocumenteerde invariant voor elke extensiedownload. Controleer inhoud en bestandsnaam apart.
Testopmerking: file://-gedrag voor dit installatietraject
Bij het verifiëren van dit onderdeel bleek een veel herhaalde claim onjuist, en die had zelfs al in een eerdere versie van dit artikel gestaan: dat content scripts niet draaien op file://-pagina’s omdat extensies standaard geen bestands-toegang hebben.
Gemeten op beide Chrome for Testing-builds, door de extensie via de command line te laden en vervolgens direct naar file:///…/fixture/index.html te navigeren: het content script injecteert normaal. Marker aanwezig, extensie-ID klopt, op beide builds. Command-line geladen unpacked extensies krijgen bestands-toegang; de herinnerde "grant file access"-schakelaar geldt voor een ander installatietraject.
Fixtures via HTTP serveren blijft nog steeds de beste standaardkeuze, omdat een file://-pagina totaal niet lijkt op een echte target. Maar dat is een argument over realisme, niet over technische noodzaak, en het gebruikelijke mechanisme ervoor is fout.
Wat dit niet aantoont
- De implementatie van de gate reikt niet verder dan de waarschuwingsregel. Chrome zegt dat deze flags in deze build niet zijn toegestaan en noemt het bronbestand. Of dat door buildconfig, policy-plumbing of iets anders wordt bepaald, is niet uit de bron afgeleid.
- Dit is één machine. macOS op arm64, één standaard patchversie, twee Chrome for Testing-builds. Chrome verandert snel genoeg dat dit opnieuw gecontroleerd moet worden in plaats van geciteerd.
- Dit is alleen het
--load-extension-traject. Geïnstalleerde.crx-packs, laden in developer mode en enterprise allowlist-beleid zijn niet getest. Niets hier ondersteunt de claim dat "standaard Chrome geen extensies kan draaien". - De extensie is een bewust gemaakte stub. Ze test de mechanismen die elke scraper-extensie gebruikt, maar een echte extensie is groter en kan op manieren falen waar een stub niet aan blootstaat.
Wat ik onderweg verkeerd had
Het is goed om dat expliciet te zeggen, want beide fouten zijn van het type dat review overleeft als het resultaat er goed uitziet.
De eerste versie van deze tekst zei dat de fout stil was, dat er geen logregel bestond en dat het mechanisme niet te achterhalen was — dat wie dacht het te weten maar gokte. Het mechanisme lag één flag verderop, en Chrome printte het de hele tijd al op WARNING-niveau. "Ik kon het niet vinden" was opgeschreven als "het is niet vindbaar".
De tweede was de file://-claim hierboven: overgenomen uit notities en voorzien van een zelfverzekerd mechanisme nog vóór die getest was. Eén run maakte die claim onhoudbaar.
Het patroon is in beide gevallen hetzelfde. Een aannemelijke uitspraak waar niemand op zou reageren, meegezogen omdat controleren niet nodig leek. De oplossing is niet meer voorzichtigheid in de tekst, maar een regel over wat er überhaupt wordt geclaimd: een claim die niet naar een run te herleiden is, wordt niet gepubliceerd.
Gebruikte commando’s in de lokale harness
De versiegebonden probe, extensie-stub, fixture en ruwe samenvattingen zijn hier gelinkt, maar dit is nog geen zelfstandig publiek reproduceerbaar pakket. De exacte downloadbronnen en checksums van Chrome for Testing 149 en 151 zijn niet in het artikel vastgelegd, en de hieronder genoemde executable paths waren lokale inputs. Publiceer die browserbronnen plus een stabiele repository-commit voordat je de volledige vergelijking als onafhankelijk reproduceerbaar presenteert.
Gerelateerde analyse: Playwright-analyse.
cd harness
npm install playwright@1.56.0
npx playwright install chromium # Playwright Chromium; niet de twee CfT-armen hieronder
(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
Hetzelfde script en dezelfde expliciete extensieargumenten werden voor alle drie armen gebruikt, maar de resolutie van de executable verschilde: CHANNEL=chrome voor standaard Chrome en EXE voor de twee Chrome for Testing-binaries. De versie in elk uitvoerbestand wordt uit de browser gelezen en niet uit het label vertrouwd.
Voor de waarschuwingsregel is geen harness nodig:
"/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"
Per 2026-07-28.
Probeer Thunderbit voor webdata-extractie
Beslissing en kanttekeningen
In de geteste matrix weigerde standaard Google Chrome 150 --disable-extensions-except plus --load-extension, terwijl Chrome for Testing 149 en 151 de extensie laadden. Chrome logde de weigering op WARNING-niveau: "--load-extension is not allowed in Google Chrome, ignoring." De formulering ondersteunt een interpretatie als branded-build, en de versie-sandwich sluit een simpele monotone verwijdering uit, maar build en versie blijven met elkaar verstrengeld zonder een cross-build arm op dezelfde versie of bron/config-bewijs.
Gebruik voor een vastgepinde extensieharness een expliciet versiegebonden browser-executable en verifieer zowel de service worker als de content-scriptmarker. In deze Playwright 1.56.0-opzet vereiste de extensie-export CDP-capture naar een map en kwam die binnen onder een andere bestandsnaam. De via de command line geladen stub injecteerde ook op de geteste file://-fixture; andere installatietrajecten zijn niet getest.
Probeer Thunderbit voor webdata-extractie Get Started Free
FAQ's
Is --load-extension helemaal verwijderd uit Chrome?
Nee. Chrome for Testing 149.0.7827.55 en 151.0.7922.10 laadden beide de unpacked MV3-stub via die flag en doorliepen alle zes beoordeelde checks. Standaard Google Chrome 150.0.7871.187 weigerde de flag en logde "--load-extension is not allowed in Google Chrome, ignoring". Dat ondersteunt, maar bewijst niet, een gate voor branded builds: het gedrag sluit een simpele monotone verwijdering uit, terwijl een Chrome-150-specifieke regressie die in 151 is hersteld nog steeds past binnen het drie-armenontwerp.
Waarom zie ik geen foutmelding, en hoe onderscheid ik "nooit geladen" van "geladen en stilletjes gefaald"?
De waarschuwing verschijnt niet op standaard verbosity. Start met --enable-logging=stderr en ze verschijnt meteen; zonder die flag start Chrome normaal, maar de extensieservice negeert de flags en het eerste symptoom in de harness is een selector-time-out. Om "nooit geladen" te scheiden van een injectiefout gebruik je twee onafhankelijke signalen: de MV3 background service worker en een content-scriptmarker in de doel-DOM. Op de geteste standaard Chrome-arm verscheen geen van beide; op beide Chrome for Testing-armen verschenen beide.
Wat moet ik dan gebruiken om extensies te automatiseren?
De geslaagde armen gebruikten vastgepinde Chrome for Testing-executables via executablePath. Door Playwright beheerde Chromium is ook een mogelijke automatiseringsbinary, maar die was in deze test geen arm en mag niet als dezelfde distributie worden beschreven zonder de opgeloste executable te controleren.
Waarom wordt waitForEvent('download') nooit geactiveerd wanneer de extensie een bestand exporteert?
In deze MV3/Playwright 1.56.0-opzet werd het event niet geactiveerd en werd geen voorgestelde bestandsnaam gegeven. De harness opende een CDP-sessie, riep Browser.setDownloadBehavior aan met een expliciete map en las vervolgens het bestand van disk. In de geteste runs bleven de CSV-bytes intact, maar probe-export.csv kwam binnen als download.csv; bredere combinaties van extensie en browser zijn niet getest.
Wat zegt dit niet — over file://-URL's en over standaard Chrome in het algemeen?
Twee grenzen, in tegengestelde richtingen. Content scripts werken wel op file://-URL's voor extensies die vanaf de command line worden geladen — getest op beide Chrome for Testing-builds, waarbij het script normaal injecteerde en de extensie-ID correct werd gerapporteerd, dus de veelgehoorde claim dat dit niet zou kunnen omdat extensies standaard geen bestands-toegang hebben, is voor dit installatietraject onjuist. Fixtures via HTTP serveren blijft best practice omdat het meer lijkt op een echte target, niet omdat file:// injectie blokkeert. In de andere richting: niets hier zegt dat standaard Chrome geen extensies kan draaien. Alleen het command-line --load-extension-traject is gemeten. Installatie van verpakte .crx, laden in developer mode en enterprise allowlist-beleid zijn niet getest, en daarover wordt geen claim gedaan. De scope is het ene vlaggenpaar dat in automatiseringshandleidingen wordt aangeraden.


