---
id: api/node-events/browser-launch-api
title: Browser Launch Event | Cypress Node Events
description: >-
  The before:browser:launch event gives you the opportunity to modify the
  browser preferences, install extensions, add and remove command-line
  arguments, and modify other options before Cypress launches a browser.
section: api
source_path: docs/api/node-events/browser-launch-api.mdx
version: 7ada28c0cd90e81cf56fd3fc73de6e6d45c16de6
updated_at: '2026-05-13T21:55:41.935Z'
---
# Browser Launch Event

Before Cypress launches a browser, it gives you the opportunity to modify the browser preferences, install extensions, add and remove command-line arguments, and modify other options from the [setupNodeEvents](/llm/markdown/app/plugins/plugins-guide.md#Using-a-plugin) function.

## Syntax

⚠️ This code is part of the [setupNodeEvents](/llm/markdown/app/plugins/plugins-guide.md#Using-a-plugin) function and thus executes in the Node environment. You cannot call `Cypress` or `cy` commands in this function, but you do have the direct access to the file system and the rest of the operating system.

*   cypress.config.js
*   cypress.config.ts

```
const { defineConfig } = require('cypress')module.exports = defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser = {}, launchOptions) => {        /* ... */      })    },  },})
```

```
import { defineConfig } from 'cypress'export default defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser = {}, launchOptions) => {        /* ... */      })    },  },})
```

**browser _(object)_**

An object describing the browser being launched, with the following properties:

| Property | Type | Description |
| --- | --- | --- |
| `name` | `string` | Machine-friendly name, like `chrome`, `electron`, `edge`, or `firefox`. |
| `family` | `string` | Rendering engine being used. `chromium` or `firefox`. |
| `channel` | `string` | Release channel of the browser, such as `stable`, `dev`, or `canary`. |
| `displayName` | `string` | Human-readable display name for the browser. |
| `version` | `string` | Full version. |
| `path` | `string` | Path to the browser on disk. Blank for Electron. |
| `info` | `string` | _(Optional)_ Extra information about the browser (used for display in the browser selector) |
| `majorVersion` | `number` | The major version number of the browser. |
| `isHeadless` | `boolean` | Whether the browser is running headlessly. |
| `isHeaded` | `boolean` | Whether the browser displays headed. |

**launchOptions _(object)_**

Options that can be modified to control how the browser is launched, with the following properties:

| Property | Type | Description |
| --- | --- | --- |
| `preferences` | `object` | An object describing browser preferences. Differs between browsers. See [Change browser preferences](#Change-browser-preferences) for details. |
| `args` | `string[]` | An array of strings that will be passed as command-line args when the browser is launched. Has no effect on Electron. See [Modify browser launch arguments](#Modify-browser-launch-arguments) for details. |
| `extensions` | `string[]` | An array of paths to folders containing unpacked WebExtensions to be loaded before the browser starts. See [Add browser extensions](#Add-browser-extensions) for details. |
| `env` | `object` | An object of system environment variables to pass to the launched browser. See [Configure browser environment](#Configure-browser-environment) for details. |

## Usage

Using the [setupNodeEvents](/llm/markdown/app/plugins/plugins-guide.md#Using-a-plugin) function you can tap into the `before:browser:launch` event and modify how Cypress launches the browser (e.g. modify arguments, user preferences, and extensions).

This event will yield you the `browser` object, which gives you information about the browser, and the `launchOptions` object, which allows you to modify how the browser is launched.

The returned `launchOptions` object will become the new launch options for the browser.

### Modify browser launch arguments

Here are args available for the currently supported browsers:

*   [Chromium-based browsers](https://peter.sh/experiments/chromium-command-line-switches/)
*   [Firefox](https://developer.mozilla.org/docs/Mozilla/Command_Line_Options)

#### Open devtools by default

*   cypress.config.js
*   cypress.config.ts

```
const { defineConfig } = require('cypress')module.exports = defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser = {}, launchOptions) => {        // `args` is an array of all the arguments that will        // be passed to browsers when it launches        console.log(launchOptions.args) // print all current args        if (browser.family === 'chromium' && browser.name !== 'electron') {          // auto open devtools          launchOptions.args.push('--auto-open-devtools-for-tabs')        }        if (browser.family === 'firefox') {          // auto open devtools          launchOptions.args.push('-devtools')        }        if (browser.name === 'electron') {          // auto open devtools          launchOptions.preferences.devTools = true        }        // whatever you return here becomes the launchOptions        return launchOptions      })    },  },})
```

```
import { defineConfig } from 'cypress'export default defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser = {}, launchOptions) => {        // `args` is an array of all the arguments that will        // be passed to browsers when it launches        console.log(launchOptions.args) // print all current args        if (browser.family === 'chromium' && browser.name !== 'electron') {          // auto open devtools          launchOptions.args.push('--auto-open-devtools-for-tabs')        }        if (browser.family === 'firefox') {          // auto open devtools          launchOptions.args.push('-devtools')        }        if (browser.name === 'electron') {          // auto open devtools          launchOptions.preferences.devTools = true        }        // whatever you return here becomes the launchOptions        return launchOptions      })    },  },})
```

### Add browser extensions

**Limitations:**

*   Headless Chrome does not support loading extensions.
*   Chrome-branded browsers (e.g., standard Chrome) version 137 and above no longer support extension loading via this API, due to the removal of the `--load-extension` flag by Chrome. We recommend using Chrome for Testing or Chromium instead. See Cypress Docker image examples for [Chrome for Testing](https://github.com/cypress-io/cypress-docker-images/tree/master/examples/chrome-for-testing) and [Chromium](https://github.com/cypress-io/cypress-docker-images/tree/master/examples/chromium).
*   Electron currently supports only Chrome DevTools extensions.

*   cypress.config.js
*   cypress.config.ts

```
const { defineConfig } = require('cypress')module.exports = defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser, launchOptions) => {        // supply the absolute path to an unpacked extension's folder        launchOptions.extensions.push('Users/jane/path/to/extension')        return launchOptions      })    },  },})
```

```
import { defineConfig } from 'cypress'export default defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser, launchOptions) => {        // supply the absolute path to an unpacked extension's folder        launchOptions.extensions.push('Users/jane/path/to/extension')        return launchOptions      })    },  },})
```

### Configure browser environment

This option is not supported when targeting Electron.

*   cypress.config.js
*   cypress.config.ts

```
const { defineConfig } = require('cypress')module.exports = defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser, launchOptions) => {        launchOptions.env.CUSTOM_ENV_VALUE = '1'        return launchOptions      })    },  },})
```

```
import { defineConfig } from 'cypress'export default defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser, launchOptions) => {        launchOptions.env.CUSTOM_ENV_VALUE = '1'        return launchOptions      })    },  },})
```

### Change browser preferences

Here are preferences available for the currently supported browsers:

*   [Chromium-based browsers](https://src.chromium.org/viewvc/chrome/trunk/src/chrome/common/pref_names.cc?view=markup)
*   [Electron](https://github.com/electron/electron/blob/master/docs/api/browser-window.md#new-browserwindowoptions)
*   Firefox: visit `about:config` URL within your Firefox browser to see all available preferences.

If you want to ignore Chrome preferences altogether, you can set `IGNORE_CHROME_PREFERENCES` as a system environment variable when running Cypress.

*   cypress.config.js
*   cypress.config.ts

```
const { defineConfig } = require('cypress')module.exports = defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser, launchOptions) => {        if (browser.family === 'chromium' && browser.name !== 'electron') {          // in Chromium, preferences can exist in Local State, Preferences, or Secure Preferences          // via launchOptions.preferences, these can be acccssed as `localState`, `default`, and `secureDefault`          // for example, to set `somePreference: true` in Preferences:          launchOptions.preferences.default['preference'] = true          return launchOptions        }        if (browser.family === 'firefox') {          // launchOptions.preferences is a map of preference names to values          launchOptions.preferences['some.preference'] = true          return launchOptions        }        if (browser.name === 'electron') {          // launchOptions.preferences is a `BrowserWindow` `options` object          launchOptions.preferences.darkTheme = true          return launchOptions        }      })    },  },})
```

```
import { defineConfig } from 'cypress'export default defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser, launchOptions) => {        if (browser.family === 'chromium' && browser.name !== 'electron') {          // in Chromium, preferences can exist in Local State, Preferences, or Secure Preferences          // via launchOptions.preferences, these can be acccssed as `localState`, `default`, and `secureDefault`          // for example, to set `somePreference: true` in Preferences:          launchOptions.preferences.default['preference'] = true          return launchOptions        }        if (browser.family === 'firefox') {          // launchOptions.preferences is a map of preference names to values          launchOptions.preferences['some.preference'] = true          return launchOptions        }        if (browser.name === 'electron') {          // launchOptions.preferences is a `BrowserWindow` `options` object          launchOptions.preferences.darkTheme = true          return launchOptions        }      })    },  },})
```

### Modify Electron app switches

The Cypress Launchpad is an Electron application, and its behavior (and the behavior of the bundled-in Electron browser) can be customized using command line switches. The supported switches depend on the Electron version, see [Electron documentation](https://www.electronjs.org/docs/api/command-line-switches).

You can pass Electron-specific launch arguments using the `ELECTRON_EXTRA_LAUNCH_ARGS` system environment variable. For example, to disable HTTP browser cache and ignore certificate errors, you can set the environment variables before running Cypress like below:

#### Linux/OSX

```
export ELECTRON_EXTRA_LAUNCH_ARGS=--disable-http-cache --lang=es
```

#### Windows

```
set ELECTRON_EXTRA_LAUNCH_ARGS=--disable-http-cache --lang=es
```

Cypress already sets some the Electron command line switches internally. See file [packages/server/lib/environment.js](https://github.com/cypress-io/cypress/blob/develop/packages/server/lib/environment.js). There is no way to see all currently set switches after Electron's launch.

### See all Chrome browser switches

If you are running Cypress tests using a Chromium-based browser, you can see ALL currently set command line switches and the browser version information by opening a new tab and typing `chrome://version` url.

## Examples

### Set screen size when running headless

When a browser runs headless, there is no physical display. You can override the default screen size of 1280x720 when running headless as shown below. This will affect the size of screenshots and videos taken during the run.

This setting changes the display size of the screen and does not affect the `viewportWidth` and `viewportHeight` set in the [Cypress configuration](/llm/markdown/app/references/configuration.md). The `viewportWidth` and `viewportHeight` only affect the size of the application under test displayed inside the Cypress Test Runner. Read the blog post [Generate High-Resolution Videos and Screenshots](https://www.cypress.io/blog/2021/03/01/generate-high-resolution-videos-and-screenshots/) for details.

*   cypress.config.js
*   cypress.config.ts

```
const { defineConfig } = require('cypress')module.exports = defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser, launchOptions) => {        if (browser.name === 'chrome' && browser.isHeadless) {          // fullPage screenshot size is 1400x1200 on non-retina screens          // and 2800x2400 on retina screens          launchOptions.args.push('--window-size=1400,1200')          // force screen to be non-retina (1400x1200 size)          launchOptions.args.push('--force-device-scale-factor=1')          // force screen to be retina (2800x2400 size)          // launchOptions.args.push('--force-device-scale-factor=2')        }        if (browser.name === 'electron' && browser.isHeadless) {          // fullPage screenshot size is 1400x1200          launchOptions.preferences.width = 1400          launchOptions.preferences.height = 1200        }        if (browser.name === 'firefox' && browser.isHeadless) {          // menubars take up height on the screen          // so fullPage screenshot size is 1400x1126          launchOptions.args.push('--width=1400')          launchOptions.args.push('--height=1200')        }        return launchOptions      })    },  },})
```

```
import { defineConfig } from 'cypress'export default defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser, launchOptions) => {        if (browser.name === 'chrome' && browser.isHeadless) {          // fullPage screenshot size is 1400x1200 on non-retina screens          // and 2800x2400 on retina screens          launchOptions.args.push('--window-size=1400,1200')          // force screen to be non-retina (1400x1200 size)          launchOptions.args.push('--force-device-scale-factor=1')          // force screen to be retina (2800x2400 size)          // launchOptions.args.push('--force-device-scale-factor=2')        }        if (browser.name === 'electron' && browser.isHeadless) {          // fullPage screenshot size is 1400x1200          launchOptions.preferences.width = 1400          launchOptions.preferences.height = 1200        }        if (browser.name === 'firefox' && browser.isHeadless) {          // menubars take up height on the screen          // so fullPage screenshot size is 1400x1126          launchOptions.args.push('--width=1400')          launchOptions.args.push('--height=1200')        }        return launchOptions      })    },  },})
```

### Override the device pixel ratio

*   cypress.config.js
*   cypress.config.ts

```
const { defineConfig } = require('cypress')module.exports = defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser, launchOptions) => {        if (browser.name === 'chrome' && browser.isHeadless) {          // force screen to behave like retina          // when running Chrome headless browsers          // (2560x1440 in size by default)          launchOptions.args.push('--force-device-scale-factor=2')        }        return launchOptions      })    },  },})
```

```
import { defineConfig } from 'cypress'export default defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser, launchOptions) => {        if (browser.name === 'chrome' && browser.isHeadless) {          // force screen to behave like retina          // when running Chrome headless browsers          // (2560x1440 in size by default)          launchOptions.args.push('--force-device-scale-factor=2')        }        return launchOptions      })    },  },})
```

### Start fullscreen

*   cypress.config.js
*   cypress.config.ts

```
const { defineConfig } = require('cypress')module.exports = defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser = {}, launchOptions) => {        if (browser.family === 'chromium' && browser.name !== 'electron') {          launchOptions.args.push('--start-fullscreen')          return launchOptions        }        if (browser.name === 'electron') {          launchOptions.preferences.fullscreen = true          return launchOptions        }      })    },  },})
```

```
import { defineConfig } from 'cypress'export default defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser = {}, launchOptions) => {        if (browser.family === 'chromium' && browser.name !== 'electron') {          launchOptions.args.push('--start-fullscreen')          return launchOptions        }        if (browser.name === 'electron') {          launchOptions.preferences.fullscreen = true          return launchOptions        }      })    },  },})
```

### Use fake video for webcam testing

By default, Cypress passes the Chrome command line switch to enable a fake video for a media stream. This is to better enable testing webcam functionality without having to have the necessary hardware to test.

You can however send your own video file for testing by passing a Chrome command line switch pointing to a video file.

*   cypress.config.js
*   cypress.config.ts

```
const { defineConfig } = require('cypress')module.exports = defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser = {}, launchOptions) => {        if (browser.family === 'chromium' && browser.name !== 'electron') {          // Mac/Linux          launchOptions.args.push(            '--use-file-for-fake-video-capture=cypress/fixtures/my-video.y4m'          )          // Windows          // launchOptions.args.push('--use-file-for-fake-video-capture=c:\\path\\to\\video\\my-video.y4m')        }        return launchOptions      })    },  },})
```

```
import { defineConfig } from 'cypress'export default defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser = {}, launchOptions) => {        if (browser.family === 'chromium' && browser.name !== 'electron') {          // Mac/Linux          launchOptions.args.push(            '--use-file-for-fake-video-capture=cypress/fixtures/my-video.y4m'          )          // Windows          // launchOptions.args.push('--use-file-for-fake-video-capture=c:\\path\\to\\video\\my-video.y4m')        }        return launchOptions      })    },  },})
```

### Support unique file download mime types

Cypress supports a myriad of mime types when testing file downloads, but in case you have a unique one, you can add support for it.

*   cypress.config.js
*   cypress.config.ts

```
const { defineConfig } = require('cypress')module.exports = defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser, options) => {        // only Firefox requires all mime types to be listed        if (browser.family === 'firefox') {          const existingMimeTypes =            options.preferences['browser.helperApps.neverAsk.saveToDisk']          const myMimeType = 'my/mimetype'          // prevents the browser download prompt          options.preferences['browser.helperApps.neverAsk.saveToDisk'] =            `${existingMimeTypes},${myMimeType}`          return options        }      })    },  },})
```

```
import { defineConfig } from 'cypress'export default defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser, options) => {        // only Firefox requires all mime types to be listed        if (browser.family === 'firefox') {          const existingMimeTypes =            options.preferences['browser.helperApps.neverAsk.saveToDisk']          const myMimeType = 'my/mimetype'          // prevents the browser download prompt          options.preferences['browser.helperApps.neverAsk.saveToDisk'] =            `${existingMimeTypes},${myMimeType}`          return options        }      })    },  },})
```

[Check out our example recipe showing how to download and validate CSV and Excel files.](/llm/markdown/app/references/recipes.md#Testing-the-DOM)

### Set a Firefox flag

If we need to set a particular Firefox flag, like `browser.send_pings` we can do it via preferences

*   cypress.config.js
*   cypress.config.ts

```
const { defineConfig } = require('cypress')module.exports = defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser = {}, launchOptions) => {        if (browser.family === 'firefox') {          launchOptions.preferences['browser.send_pings'] = true        }        return launchOptions      })    },  },})
```

```
import { defineConfig } from 'cypress'export default defineConfig({  // setupNodeEvents can be defined in either  // the e2e or component configuration  e2e: {    setupNodeEvents(on, config) {      on('before:browser:launch', (browser = {}, launchOptions) => {        if (browser.family === 'firefox') {          launchOptions.preferences['browser.send_pings'] = true        }        return launchOptions      })    },  },})
```

## History

| Version | Changes |
| --- | --- |
| [4.0.0](/llm/markdown/app/references/changelog.md#4-0-0) | New `options` object replaces old `args` as second argument to `before:browser:launch` |
| [4.0.0](/llm/markdown/app/references/changelog.md#4-0-0) | All Chromium-based browsers, including Electron, have `chromium` set as their `family` property. |
| [4.0.0](/llm/markdown/app/references/changelog.md#4-0-0) | Added `channel` property to browser. |
