5

I have an application written in python/selenium which set some experimental options on the chrome driver:

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

chrome_options = Options()
chrome_options.add_argument('--disable-gpu')
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--lang=en')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument('--disable-browser-side-navigation')
chrome_options.add_argument('--mute-audio')
chrome_options.add_argument('--headless')

chrome_options.add_experimental_option(
    'prefs', {
        'intl.accept_languages': 'en,en_US',
        'download.prompt_for_download': False,
        'download.default_directory': '/dev/null',
        'automatic_downloads': 2,
        'download_restrictions': 3,
        'notifications': 2,
        'media_stream': 2,
        'media_stream_mic': 2,
        'media_stream_camera': 2,
        'durable_storage': 2,
        'plugins': 2,
        'popups': 2,
        'site_engagement': 2,
        'midi_sysex': 2,
        'mouselock': 2,
        'geolocation': 2,
    }
)

driver = webdriver.Chrome(options=chrome_options)

I need to port the same application to node/puppeteer but I am not sure how to pass the experimental options to puppeteer/chromium:

const puppeteer = require('puppeteer');

(async () => {

    const options = {
        headless: true,
        args: [
            '--disable-gpu',
            '--no-sandbox',
            '--lang=en',
            '--disable-dev-shm-usage',
            '--disable-browser-side-navigation',
            '--mute-audio',
        ],
    };

    // experimental options ??

    const browser = await puppeteer.launch(options);

})();

Is it possible to pass Chrome experimental options to puppeteer?

revy
  • 3,945
  • 7
  • 40
  • 85

1 Answers1

2

I.) Normally you should be able to set any experimental features among the args if you are able to position them between the --flag-switches-begin and --flag-switches-end flags and you give them in the following format: Pascal case option names, separated by a single comma without a space. E.g. if you want to set enable-nacl and network-service:

--enable-features=EnableNacl,NetworkService

Experimental features can be checked here: chrome://flags if they are indeed enabled.

The Command Line of Chrome/Chromium can be checked here: chrome://version to see if the flags are added at the launch.


II.) For me this solution haven't worked (it doesn't mean it wouldn't work for you, it worths a try). So I use a workaround of creating a Chrome profile (Experimental Profile 1) where I enable manually the experimantal flags and then using this profile with puppeteer (--user-data-dir= and --profile-directory= are required):

const puppeteer = require('puppeteer')

async function fn() {
  const browser = await puppeteer.launch({
    headless: false,
    args: [
      // '--enable-features=EnableNacl,NetworkService',
      '--user-data-dir=C:\\Users\\user.name\\AppData\\Local\\Chromium\\User Data',
      '--profile-directory=Experimental Profile 1'
    ]
  })
  const page = await browser.newPage()

  await page.goto('chrome://flags/#enable-nacl')
}
fn()

The example above is for Windows, see more platforms and more info here.

Note: You can retrieve executable and profile paths on the chrome://version page.

Note 2: The example above can be run only with headless: false as headless mode cannot visit invalid URLs like chrome://flags/#enable-nacl but the user profile should work. If it isn't then there is a known chromium bug related to relative path of data dir which be solved with path.resolve, e.g.:

const path = require('path')
const browser = await puppeteer.launch({ headless: true, args: [`--user-data-dir=${path.resolve(__dirname, 'User Data') }`] })

[source]


Edit

Actually the options you want to set are only called experimental options by ChromeDriver but available as chrome policies at chrome://policy page. Make sure you've set Show policies with no value set to see them.

But as far as I see it doesn't provide a simple solution (e.g. in case of Windows you are limited to set it via registry). After searching on GitHub I've found in this discussion that chrome_options.add_experimental_option is not implemented in puppeteer as in ChromeDriver. But in puppeteer-extra there is a dedicated plugin for this, called: user-preferences.

For example:

const puppeteer = require('puppeteer-extra')
puppeteer.use(require('puppeteer-extra-plugin-user-preferences')({ userPrefs: {
  download: {
    prompt_for_download: false
  }
}}))
const browser = await puppeteer.launch()

Reference of pref names and their access: https://chromium.googlesource.com/chromium/src/+/master/chrome/common/pref_names.cc

theDavidBarton
  • 7,643
  • 4
  • 24
  • 51
  • Thanks for the answer. Unfortunately the first way didn't work for me either and can't go with the second since I need headless automation – revy Jul 13 '20 at 19:26
  • 1
    I see. Sorry for the confusion with the 2nd solution, I think it can work even with headless mode: I meant my specific example script cannot be run headless, but if you are using a full (not relative) `--user-data-dir` path the experimental features can be set on a headless chrome as well. It may worths a try as well. – theDavidBarton Jul 13 '20 at 19:53
  • Ok I am trying to set some experimental flags on a new Chrome profile...the problem is in chrome://flags I can't find any of the experimental option I need to set, like `download_restrictions` or `prompt_for_download`. Do you have any idea where I can find them and save in the profile so I can then try to load the profile in `puppeteer`? – revy Jul 13 '20 at 21:08
  • Actually these two are not experimental options but chrome policies and available at _chrome://policy/_ page. Make sure you've set _ Show policies with no value set_ to see them. FYI: `prompt_for_download` is called now _PromptForDownloadLocation_. – theDavidBarton Jul 14 '20 at 07:00
  • 1
    _Update:_ But as far as I see it doesn't provide a simple solution (e.g. in case of Windows you are limited to set it via registry). After searching on GitHub I've found the `chrome_options.add_experimental_option` is not implemented in puppeteer as in ChromeDriver: https://github.com/puppeteer/puppeteer/issues/1693 but in [puppeteer-extra](https://github.com/berstend/puppeteer-extra) there is a dedicated plugin for this, called: [user-preferences](https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-user-preferences). I will update my answer with this. – theDavidBarton Jul 14 '20 at 08:00
  • It seems that the plugin `user-preferences` does not support headless chrome unfortunately. I got this warning: ```Warning: Plugin 'user-preferences' is not supported in headless mode.``` – revy Jul 14 '20 at 10:37
  • this topic seems to be cursed If you'd find the solution later on: make sure to post it here as an answer. I have already become obsessed with it, as it should be possible to use headless chrome with user prefrences and even with experimental feature flags. – theDavidBarton Jul 14 '20 at 11:19
  • Sure! It seems weird that `puppeteer` which is specifically for Chrome/Chromium does not support user preferences while `Selenium` with Chrome driver does – revy Jul 14 '20 at 12:11