

What is Electron?
=================


Electron is a framework for building desktop applications using JavaScript, HTML, and CSS. By embedding [Chromium](https://www.chromium.org/) and [Node.js](https://nodejs.org/) into its binary, Electron allows you to maintain one JavaScript codebase and create cross-platform apps that work on Windows, macOS, and Linux — no native development experience required.


Getting started[​](#getting-started "Direct link to heading")
-------------------------------------------------------------


We recommend you to start with the [tutorial](tutorial/tutorial-prerequisites), which guides you through the process of developing an Electron app and distributing it to users. The [examples](tutorial/examples) and [API documentation](api/app) are also good places to browse around and discover new things.


Running examples with Electron Fiddle[​](#running-examples-with-electron-fiddle "Direct link to heading")
---------------------------------------------------------------------------------------------------------


[Electron Fiddle](https://electronjs.org/fiddle) is a sandbox app written with Electron and supported by Electron's maintainers. We highly recommend installing it as a learning tool to experiment with Electron's APIs or to prototype features during development.


Fiddle also integrates nicely with our documentation. When browsing through examples in our tutorials, you'll frequently see an "Open in Electron Fiddle" button underneath a code block. If you have Fiddle installed, this button will open a `fiddle.electronjs.org` link that will automatically load the example into Fiddle, no copy-pasting required.




[docs/fiddles/quick-start (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/quick-start)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/quick-start)


* main.js
* preload.js
* index.html





```
const { app, BrowserWindow } = require('electron')
const path = require('path')

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  win.loadFile('index.html')
}

app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow()
    }
  })
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

```




```
window.addEventListener('DOMContentLoaded', () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
  }

  for (const type of ['chrome', 'node', 'electron']) {
    replaceText(`${type}-version`, process.versions[type])
  }
})

```




```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
    <h1>Hello World!</h1>
    <p>
        We are using Node.js <span id="node-version"></span>,
        Chromium <span id="chrome-version"></span>,
        and Electron <span id="electron-version"></span>.
    </p>
</body>
</html>
```





What is in the docs?[​](#what-is-in-the-docs "Direct link to heading")
----------------------------------------------------------------------


All the official documentation is available from the sidebar. These are the different categories and what you can expect on each one:


* **Tutorial**: An end-to-end guide on how to create and publish your first Electron application.
* **Processes in Electron**: In-depth reference on Electron processes and how to work with them.
* **Best Practices**: Important checklists to keep in mind when developing an Electron app.
* **Examples**: Quick references to add features to your Electron app.
* **Development**: Miscellaneous development guides.
* **Distribution**: Learn how to distribute your app to end users.
* **Testing and debugging**: How to debug JavaScript, write tests, and other tools used to create quality Electron applications.
* **References**: Useful links to better understand how the Electron project works and is organized.
* **Contributing**: Compiling Electron and making contributions can be daunting. We try to make it easier in this section.


Getting help[​](#getting-help "Direct link to heading")
-------------------------------------------------------


Are you getting stuck anywhere? Here are a few links to places to look:


* If you need help with developing your app, our [community Discord server](https://discord.com/invite/APGC3k5yaH) is a great place to get advice from other Electron app developers.
* If you suspect you're running into a bug with the `electron` package, please check the [GitHub issue tracker](https://github.com/electron/electron/issues) to see if any existing issues match your problem. If not, feel free to fill out our bug report template and submit a new issue.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest>

Quick Start
===========


This guide will step you through the process of creating a barebones Hello World app in Electron, similar to [`electron/electron-quick-start`](https://github.com/electron/electron-quick-start).


By the end of this tutorial, your app will open a browser window that displays a web page with information about which Chromium, Node.js, and Electron versions are running.


Prerequisites[​](#prerequisites "Direct link to heading")
---------------------------------------------------------


To use Electron, you need to install [Node.js](https://nodejs.org/en/download/). We recommend that you use the latest `LTS` version available.



> Please install Node.js using pre-built installers for your platform. You may encounter incompatibility issues with different development tools otherwise.
> 
> 


To check that Node.js was installed correctly, type the following commands in your terminal client:




```
node -v
npm -v
```


The commands should print the versions of Node.js and npm accordingly.


**Note:** Since Electron embeds Node.js into its binary, the version of Node.js running your code is unrelated to the version running on your system.


Create your application[​](#create-your-application "Direct link to heading")
-----------------------------------------------------------------------------


### Scaffold the project[​](#scaffold-the-project "Direct link to heading")


Electron apps follow the same general structure as other Node.js projects. Start by creating a folder and initializing an npm package.



* npm
* Yarn





```
mkdir my-electron-app && cd my-electron-app
npm init
```




```
mkdir my-electron-app && cd my-electron-app
yarn init
```




The interactive `init` command will prompt you to set some fields in your config. There are a few rules to follow for the purposes of this tutorial:


* `entry point` should be `main.js`.
* `author` and `description` can be any value, but are necessary for [app packaging](#package-and-distribute-your-application).


Your `package.json` file should look something like this:




```
{
  "name": "my-electron-app",
  "version": "1.0.0",
  "description": "Hello World!",
  "main": "main.js",
  "author": "Jane Doe",
  "license": "MIT"
}
```


Then, install the `electron` package into your app's `devDependencies`.



* npm
* Yarn





```
npm install --save-dev electron
```




```
yarn add --dev electron
```





> Note: If you're encountering any issues with installing Electron, please refer to the [Advanced Installation](installation) guide.
> 
> 


Finally, you want to be able to execute Electron. In the [`scripts`](https://docs.npmjs.com/cli/v7/using-npm/scripts) field of your `package.json` config, add a `start` command like so:




```
{
  "scripts": {
    "start": "electron ."
  }
}
```


This `start` command will let you open your app in development mode.



* npm
* Yarn





```
npm start
```




```
yarn start
# couldn't auto-convert command
```





> Note: This script tells Electron to run on your project's root folder. At this stage, your app will immediately throw an error telling you that it cannot find an app to run.
> 
> 


### Run the main process[​](#run-the-main-process "Direct link to heading")


The entry point of any Electron application is its `main` script. This script controls the **main process**, which runs in a full Node.js environment and is responsible for controlling your app's lifecycle, displaying native interfaces, performing privileged operations, and managing renderer processes (more on that later).


During execution, Electron will look for this script in the [`main`](https://docs.npmjs.com/cli/v7/configuring-npm/package-json#main) field of the app's `package.json` config, which you should have configured during the [app scaffolding](#scaffold-the-project) step.


To initialize the `main` script, create an empty file named `main.js` in the root folder of your project.



> Note: If you run the `start` script again at this point, your app will no longer throw any errors! However, it won't do anything yet because we haven't added any code into `main.js`.
> 
> 


### Create a web page[​](#create-a-web-page "Direct link to heading")


Before we can create a window for our application, we need to create the content that will be loaded into it. In Electron, each window displays web contents that can be loaded from either a local HTML file or a remote URL.


For this tutorial, you will be doing the former. Create an `index.html` file in the root folder of your project:




```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    We are using Node.js <span id="node-version"></span>,
    Chromium <span id="chrome-version"></span>,
    and Electron <span id="electron-version"></span>.
  </body>
</html>
```



> Note: Looking at this HTML document, you can observe that the version numbers are missing from the body text. We'll manually insert them later using JavaScript.
> 
> 


### Opening your web page in a browser window[​](#opening-your-web-page-in-a-browser-window "Direct link to heading")


Now that you have a web page, load it into an application window. To do so, you'll need two Electron modules:


* The [`app`](../api/app) module, which controls your application's event lifecycle.
* The [`BrowserWindow`](../api/browser-window) module, which creates and manages application windows.


Because the main process runs Node.js, you can import these as [CommonJS](https://nodejs.org/docs/latest/api/modules.html#modules_modules_commonjs_modules) modules at the top of your file:




```
const { app, BrowserWindow } = require('electron')
```


Then, add a `createWindow()` function that loads `index.html` into a new `BrowserWindow` instance.




```
const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600
  })

  win.loadFile('index.html')
}
```


Next, call this `createWindow()` function to open your window.


In Electron, browser windows can only be created after the `app` module's [`ready`](../api/app#event-ready) event is fired. You can wait for this event by using the [`app.whenReady()`](../api/app#appwhenready) API. Call `createWindow()` after `whenReady()` resolves its Promise.




```
app.whenReady().then(() => {
  createWindow()
})
```



> Note: At this point, your Electron application should successfully open a window that displays your web page!
> 
> 


### Manage your window's lifecycle[​](#manage-your-windows-lifecycle "Direct link to heading")


Although you can now open a browser window, you'll need some additional boilerplate code to make it feel more native to each platform. Application windows behave differently on each OS, and Electron puts the responsibility on developers to implement these conventions in their app.


In general, you can use the `process` global's [`platform`](https://nodejs.org/api/process.html#process_process_platform) attribute to run code specifically for certain operating systems.


#### Quit the app when all windows are closed (Windows & Linux)[​](#quit-the-app-when-all-windows-are-closed-windows--linux "Direct link to heading")


On Windows and Linux, exiting all windows generally quits an application entirely.


To implement this, listen for the `app` module's [`'window-all-closed'`](../api/app#event-window-all-closed) event, and call [`app.quit()`](../api/app#appquit) if the user is not on macOS (`darwin`).




```
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})
```


#### Open a window if none are open (macOS)[​](#open-a-window-if-none-are-open-macos "Direct link to heading")


Whereas Linux and Windows apps quit when they have no windows open, macOS apps generally continue running even without any windows open, and activating the app when no windows are available should open a new one.


To implement this feature, listen for the `app` module's [`activate`](../api/app#event-activate-macos) event, and call your existing `createWindow()` method if no browser windows are open.


Because windows cannot be created before the `ready` event, you should only listen for `activate` events after your app is initialized. Do this by attaching your event listener from within your existing `whenReady()` callback.




```
app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})
```



> Note: At this point, your window controls should be fully functional!
> 
> 


### Access Node.js from the renderer with a preload script[​](#access-nodejs-from-the-renderer-with-a-preload-script "Direct link to heading")


Now, the last thing to do is print out the version numbers for Electron and its dependencies onto your web page.


Accessing this information is trivial to do in the main process through Node's global `process` object. However, you can't just edit the DOM from the main process because it has no access to the renderer's `document` context. They're in entirely different processes!



> Note: If you need a more in-depth look at Electron processes, see the [Process Model](process-model) document.
> 
> 


This is where attaching a **preload** script to your renderer comes in handy. A preload script runs before the renderer process is loaded, and has access to both renderer globals (e.g. `window` and `document`) and a Node.js environment.


Create a new script named `preload.js` as such:




```
window.addEventListener('DOMContentLoaded', () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
  }

  for (const dependency of ['chrome', 'node', 'electron']) {
    replaceText(`${dependency}-version`, process.versions[dependency])
  }
})
```


The above code accesses the Node.js `process.versions` object and runs a basic `replaceText` helper function to insert the version numbers into the HTML document.


To attach this script to your renderer process, pass in the path to your preload script to the `webPreferences.preload` option in your existing `BrowserWindow` constructor.




```
// include the Node.js 'path' module at the top of your file
const path = require('path')

// modify your existing createWindow() function
const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  win.loadFile('index.html')
}
// ...
```


There are two Node.js concepts that are used here:


* The [`__dirname`](https://nodejs.org/api/modules.html#modules_dirname) string points to the path of the currently executing script (in this case, your project's root folder).
* The [`path.join`](https://nodejs.org/api/path.html#path_path_join_paths) API joins multiple path segments together, creating a combined path string that works across all platforms.


We use a path relative to the currently executing JavaScript file so that your relative path will work in both development and packaged mode.


### Bonus: Add functionality to your web contents[​](#bonus-add-functionality-to-your-web-contents "Direct link to heading")


At this point, you might be wondering how to add more functionality to your application.


For any interactions with your web contents, you want to add scripts to your renderer process. Because the renderer runs in a normal web environment, you can add a `<script>` tag right before your `index.html` file's closing `</body>` tag to include any arbitrary scripts you want:




```
<script src="./renderer.js"></script>
```


The code contained in `renderer.js` can then use the same JavaScript APIs and tooling you use for typical front-end development, such as using [`webpack`](https://webpack.js.org) to bundle and minify your code or [React](https://reactjs.org) to manage your user interfaces.


### Recap[​](#recap "Direct link to heading")


After following the above steps, you should have a fully functional Electron application that looks like this:


![Simplest Electron app]


The full code is available below:




```
// main.js

// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron')
const path = require('path')

const createWindow = () => {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  // and load the index.html of the app.
  mainWindow.loadFile('index.html')

  // Open the DevTools.
  // mainWindow.webContents.openDevTools()
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})

// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
```




```
// preload.js

// All the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
window.addEventListener('DOMContentLoaded', () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
  }

  for (const dependency of ['chrome', 'node', 'electron']) {
    replaceText(`${dependency}-version`, process.versions[dependency])
  }
})
```




```
<!--index.html-->

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    We are using Node.js <span id="node-version"></span>,
    Chromium <span id="chrome-version"></span>,
    and Electron <span id="electron-version"></span>.

    <!-- You can also require other files to run in this process -->
    <script src="./renderer.js"></script>
  </body>
</html>
```




[docs/fiddles/quick-start (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/quick-start)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/quick-start)


* main.js
* preload.js
* index.html





```
const { app, BrowserWindow } = require('electron')
const path = require('path')

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  win.loadFile('index.html')
}

app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow()
    }
  })
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

```




```
window.addEventListener('DOMContentLoaded', () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
  }

  for (const type of ['chrome', 'node', 'electron']) {
    replaceText(`${type}-version`, process.versions[type])
  }
})

```




```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
    <h1>Hello World!</h1>
    <p>
        We are using Node.js <span id="node-version"></span>,
        Chromium <span id="chrome-version"></span>,
        and Electron <span id="electron-version"></span>.
    </p>
</body>
</html>
```





To summarize all the steps we've done:


* We bootstrapped a Node.js application and added Electron as a dependency.
* We created a `main.js` script that runs our main process, which controls our app and runs in a Node.js environment. In this script, we used Electron's `app` and `BrowserWindow` modules to create a browser window that displays web content in a separate process (the renderer).
* In order to access certain Node.js functionality in the renderer, we attached a preload script to our `BrowserWindow` constructor.


Package and distribute your application[​](#package-and-distribute-your-application "Direct link to heading")
-------------------------------------------------------------------------------------------------------------


The fastest way to distribute your newly created app is using [Electron Forge](https://www.electronforge.io).


1. Add Electron Forge as a development dependency of your app, and use its `import` command to set up Forge's scaffolding:




	* npm
	* Yarn



```
npm install --save-dev @electron-forge/cli
npx electron-forge import

✔ Checking your system
✔ Initializing Git Repository
✔ Writing modified package.json file
✔ Installing dependencies
✔ Writing modified package.json file
✔ Fixing .gitignore

We have ATTEMPTED to convert your app to be in a format that electron-forge understands.

Thanks for using "electron-forge"!!!
```




```
yarn add --dev @electron-forge/cli
npx electron-forge import

✔ Checking your system
✔ Initializing Git Repository
✔ Writing modified package.json file
✔ Installing dependencies
✔ Writing modified package.json file
✔ Fixing .gitignore

We have ATTEMPTED to convert your app to be in a format that electron-forge understands.

Thanks for using "electron-forge"!!!
```
2. Create a distributable using Forge's `make` command:




	* npm
	* Yarn



```
npm run make

> my-electron-app@1.0.0 make /my-electron-app
> electron-forge make

✔ Checking your system
✔ Resolving Forge Config
We need to package your application before we can make it
✔ Preparing to Package Application for arch: x64
✔ Preparing native dependencies
✔ Packaging Application
Making for the following targets: zip
✔ Making for target: zip - On platform: darwin - For arch: x64
```




```
yarn run make

> my-electron-app@1.0.0 make /my-electron-app
> electron-forge make

✔ Checking your system
✔ Resolving Forge Config
We need to package your application before we can make it
✔ Preparing to Package Application for arch: x64
✔ Preparing native dependencies
✔ Packaging Application
Making for the following targets: zip
✔ Making for target: zip - On platform: darwin - For arch: x64
```




Electron Forge creates the `out` folder where your package will be located:




```
// Example for macOS
out/
├── out/make/zip/darwin/x64/my-electron-app-darwin-x64-1.0.0.zip
├── ...
└── out/my-electron-app-darwin-x64/my-electron-app.app/Contents/MacOS/my-electron-app
```



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/quick-start>

Prerequisites
=============



Follow along the tutorial

This is **part 1** of the Electron tutorial.


1. **[Prerequisites](tutorial-prerequisites)**
2. [Building your First App](tutorial-first-app)
3. [Using Preload Scripts](tutorial-preload)
4. [Adding Features](tutorial-adding-features)
5. [Packaging Your Application](tutorial-packaging)
6. [Publishing and Updating](tutorial-publishing-updating)




Electron is a framework for building desktop applications using JavaScript, HTML, and CSS. By embedding [Chromium](https://www.chromium.org/) and [Node.js](https://nodejs.org/) into a single binary file, Electron allows you to create cross-platform apps that work on Windows, macOS, and Linux with a single JavaScript codebase.


This tutorial will guide you through the process of developing a desktop application with Electron and distributing it to end users.


Assumptions[​](#assumptions "Direct link to heading")
-----------------------------------------------------


Electron is a native wrapper layer for web apps and is run in a Node.js environment. Therefore, this tutorial assumes you are generally familiar with Node and front-end web development basics. If you need to do some background reading before continuing, we recommend the following resources:


* [Getting started with the Web (MDN Web Docs)](https://developer.mozilla.org/en-US/docs/Learn/)
* [Introduction to Node.js](https://nodejs.dev/learn)


Required tools[​](#required-tools "Direct link to heading")
-----------------------------------------------------------


### Code editor[​](#code-editor "Direct link to heading")


You will need a text editor to write your code. We recommend using [Visual Studio Code](https://code.visualstudio.com/), although you can choose whichever one you prefer.


### Command line[​](#command-line "Direct link to heading")


Throughout the tutorial, we will ask you to use various command-line interfaces (CLIs). You can type these commands into your system's default terminal:


* Windows: Command Prompt or PowerShell
* macOS: Terminal
* Linux: varies depending on distribution (e.g. GNOME Terminal, Konsole)


Most code editors also come with an integrated terminal, which you can also use.


### Git and GitHub[​](#git-and-github "Direct link to heading")


Git is a commonly-used version control system for source code, and GitHub is a collaborative development platform built on top of it. Although neither is strictly necessary to building an Electron application, we will use GitHub releases to set up automatic updates later on in the tutorial. Therefore, we'll require you to:


* [Create a GitHub account](https://github.com/join)
* [Install Git](https://github.com/git-guides/install-git)


If you're unfamiliar with how Git works, we recommend reading GitHub's [Git guides](https://github.com/git-guides/). You can also use the [GitHub Desktop](https://desktop.github.com/) app if you prefer using a visual interface over the command line.


We recommend that you create a local Git repository and publish it to GitHub before starting the tutorial, and commit your code after every step.




Installing Git via GitHub Desktop
GitHub Desktop will install the latest version of Git on your system if you don't already have it installed.



### Node.js and npm[​](#nodejs-and-npm "Direct link to heading")


To begin developing an Electron app, you need to install the [Node.js](https://nodejs.org/en/download/) runtime and its bundled npm package manager onto your system. We recommend that you use the latest long-term support (LTS) version.




tip
Please install Node.js using pre-built installers for your platform. You may encounter incompatibility issues with different development tools otherwise. If you are using macOS, we recommend using a package manager like [Homebrew](https://brew.sh/) or [nvm](https://github.com/nvm-sh/nvm) to avoid any directory permission issues.



To check that Node.js was installed correctly, you can use the `-v` flag when running the `node` and `npm` commands. These should print out the installed versions.




```
$ node -v
v16.14.2
$ npm -v
8.7.0
```




caution

Although you need Node.js installed locally to scaffold an Electron project, Electron **does not use your system's Node.js installation to run its code**. Instead, it comes bundled with its own Node.js runtime. This means that your end users do not need to install Node.js themselves as a prerequisite to running your app.


To check which version of Node.js is running in your app, you can access the global [`process.versions`](https://nodejs.org/api/process.html#processversions) variable in the main process or preload script. You can also reference the list of versions in the [electron/releases](https://github.com/electron/releases/blob/master/readme.md#releases) repository.





 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/tutorial-prerequisites>

Examples Overview
=================


In this section, we have collected a set of guides for common features that you may want to implement in your Electron application. Each guide contains a practical example in a minimal, self-contained example app. The easiest way to run these examples is by downloading [Electron Fiddle](https://www.electronjs.org/fiddle).


Once Fiddle is installed, you can press on the "Open in Fiddle" button that you will find below code samples like the following one:




[docs/fiddles/quick-start (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/quick-start)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/quick-start)


* main.js
* preload.js
* index.html





```
const { app, BrowserWindow } = require('electron')
const path = require('path')

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  win.loadFile('index.html')
}

app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow()
    }
  })
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

```




```
window.addEventListener('DOMContentLoaded', () => {
  const replaceText = (selector, text) => {
    const element = document.getElementById(selector)
    if (element) element.innerText = text
  }

  for (const type of ['chrome', 'node', 'electron']) {
    replaceText(`${type}-version`, process.versions[type])
  }
})

```




```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
    <h1>Hello World!</h1>
    <p>
        We are using Node.js <span id="node-version"></span>,
        Chromium <span id="chrome-version"></span>,
        and Electron <span id="electron-version"></span>.
    </p>
</body>
</html>
```





How to...?[​](#how-to "Direct link to heading")
-----------------------------------------------


You can find the full list of "How to?" in the sidebar. If there is something that you would like to do that is not documented, please join our [Discord server](https://discord.com/invite/electronjs) and let us know!



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/examples>

app
===



> Control your application's event lifecycle.
> 
> 


Process: [Main](../glossary#main-process)


The following example shows how to quit the application when the last window is closed:




```
const { app } = require('electron')
app.on('window-all-closed', () => {
  app.quit()
})
```


Events[​](#events "Direct link to heading")
-------------------------------------------


The `app` object emits the following events:


### Event: 'will-finish-launching'[​](#event-will-finish-launching "Direct link to heading")


Emitted when the application has finished basic startup. On Windows and Linux, the `will-finish-launching` event is the same as the `ready` event; on macOS, this event represents the `applicationWillFinishLaunching` notification of `NSApplication`. You would usually set up listeners for the `open-file` and `open-url` events here, and start the crash reporter and auto updater.


In most cases, you should do everything in the `ready` event handler.


### Event: 'ready'[​](#event-ready "Direct link to heading")


Returns:


* `event` Event
* `launchInfo` Record<string, any> | [NotificationResponse](structures/notification-response) *macOS*


Emitted once, when Electron has finished initializing. On macOS, `launchInfo` holds the `userInfo` of the [`NSUserNotification`](https://developer.apple.com/documentation/foundation/nsusernotification) or information from [`UNNotificationResponse`](https://developer.apple.com/documentation/usernotifications/unnotificationresponse) that was used to open the application, if it was launched from Notification Center. You can also call `app.isReady()` to check if this event has already fired and `app.whenReady()` to get a Promise that is fulfilled when Electron is initialized.


### Event: 'window-all-closed'[​](#event-window-all-closed "Direct link to heading")


Emitted when all windows have been closed.


If you do not subscribe to this event and all windows are closed, the default behavior is to quit the app; however, if you subscribe, you control whether the app quits or not. If the user pressed `Cmd + Q`, or the developer called `app.quit()`, Electron will first try to close all the windows and then emit the `will-quit` event, and in this case the `window-all-closed` event would not be emitted.


### Event: 'before-quit'[​](#event-before-quit "Direct link to heading")


Returns:


* `event` Event


Emitted before the application starts closing its windows. Calling `event.preventDefault()` will prevent the default behavior, which is terminating the application.


**Note:** If application quit was initiated by `autoUpdater.quitAndInstall()`, then `before-quit` is emitted *after* emitting `close` event on all windows and closing them.


**Note:** On Windows, this event will not be emitted if the app is closed due to a shutdown/restart of the system or a user logout.


### Event: 'will-quit'[​](#event-will-quit "Direct link to heading")


Returns:


* `event` Event


Emitted when all windows have been closed and the application will quit. Calling `event.preventDefault()` will prevent the default behavior, which is terminating the application.


See the description of the `window-all-closed` event for the differences between the `will-quit` and `window-all-closed` events.


**Note:** On Windows, this event will not be emitted if the app is closed due to a shutdown/restart of the system or a user logout.


### Event: 'quit'[​](#event-quit "Direct link to heading")


Returns:


* `event` Event
* `exitCode` Integer


Emitted when the application is quitting.


**Note:** On Windows, this event will not be emitted if the app is closed due to a shutdown/restart of the system or a user logout.


### Event: 'open-file' *macOS*[​](#event-open-file-macos "Direct link to heading")


Returns:


* `event` Event
* `path` string


Emitted when the user wants to open a file with the application. The `open-file` event is usually emitted when the application is already open and the OS wants to reuse the application to open the file. `open-file` is also emitted when a file is dropped onto the dock and the application is not yet running. Make sure to listen for the `open-file` event very early in your application startup to handle this case (even before the `ready` event is emitted).


You should call `event.preventDefault()` if you want to handle this event.


On Windows, you have to parse `process.argv` (in the main process) to get the filepath.


### Event: 'open-url' *macOS*[​](#event-open-url-macos "Direct link to heading")


Returns:


* `event` Event
* `url` string


Emitted when the user wants to open a URL with the application. Your application's `Info.plist` file must define the URL scheme within the `CFBundleURLTypes` key, and set `NSPrincipalClass` to `AtomApplication`.


You should call `event.preventDefault()` if you want to handle this event.


### Event: 'activate' *macOS*[​](#event-activate-macos "Direct link to heading")


Returns:


* `event` Event
* `hasVisibleWindows` boolean


Emitted when the application is activated. Various actions can trigger this event, such as launching the application for the first time, attempting to re-launch the application when it's already running, or clicking on the application's dock or taskbar icon.


### Event: 'did-become-active' *macOS*[​](#event-did-become-active-macos "Direct link to heading")


Returns:


* `event` Event


Emitted when mac application become active. Difference from `activate` event is that `did-become-active` is emitted every time the app becomes active, not only when Dock icon is clicked or application is re-launched.


### Event: 'continue-activity' *macOS*[​](#event-continue-activity-macos "Direct link to heading")


Returns:


* `event` Event
* `type` string - A string identifying the activity. Maps to [`NSUserActivity.activityType`](https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType).
* `userInfo` unknown - Contains app-specific state stored by the activity on another device.
* `details` Object
	+ `webpageURL` string (optional) - A string identifying the URL of the webpage accessed by the activity on another device, if available.


Emitted during [Handoff](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html) when an activity from a different device wants to be resumed. You should call `event.preventDefault()` if you want to handle this event.


A user activity can be continued only in an app that has the same developer Team ID as the activity's source app and that supports the activity's type. Supported activity types are specified in the app's `Info.plist` under the `NSUserActivityTypes` key.


### Event: 'will-continue-activity' *macOS*[​](#event-will-continue-activity-macos "Direct link to heading")


Returns:


* `event` Event
* `type` string - A string identifying the activity. Maps to [`NSUserActivity.activityType`](https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType).


Emitted during [Handoff](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html) before an activity from a different device wants to be resumed. You should call `event.preventDefault()` if you want to handle this event.


### Event: 'continue-activity-error' *macOS*[​](#event-continue-activity-error-macos "Direct link to heading")


Returns:


* `event` Event
* `type` string - A string identifying the activity. Maps to [`NSUserActivity.activityType`](https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType).
* `error` string - A string with the error's localized description.


Emitted during [Handoff](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html) when an activity from a different device fails to be resumed.


### Event: 'activity-was-continued' *macOS*[​](#event-activity-was-continued-macos "Direct link to heading")


Returns:


* `event` Event
* `type` string - A string identifying the activity. Maps to [`NSUserActivity.activityType`](https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType).
* `userInfo` unknown - Contains app-specific state stored by the activity.


Emitted during [Handoff](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html) after an activity from this device was successfully resumed on another one.


### Event: 'update-activity-state' *macOS*[​](#event-update-activity-state-macos "Direct link to heading")


Returns:


* `event` Event
* `type` string - A string identifying the activity. Maps to [`NSUserActivity.activityType`](https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType).
* `userInfo` unknown - Contains app-specific state stored by the activity.


Emitted when [Handoff](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html) is about to be resumed on another device. If you need to update the state to be transferred, you should call `event.preventDefault()` immediately, construct a new `userInfo` dictionary and call `app.updateCurrentActivity()` in a timely manner. Otherwise, the operation will fail and `continue-activity-error` will be called.


### Event: 'new-window-for-tab' *macOS*[​](#event-new-window-for-tab-macos "Direct link to heading")


Returns:


* `event` Event


Emitted when the user clicks the native macOS new tab button. The new tab button is only visible if the current `BrowserWindow` has a `tabbingIdentifier`


### Event: 'browser-window-blur'[​](#event-browser-window-blur "Direct link to heading")


Returns:


* `event` Event
* `window` [BrowserWindow](browser-window)


Emitted when a [browserWindow](browser-window) gets blurred.


### Event: 'browser-window-focus'[​](#event-browser-window-focus "Direct link to heading")


Returns:


* `event` Event
* `window` [BrowserWindow](browser-window)


Emitted when a [browserWindow](browser-window) gets focused.


### Event: 'browser-window-created'[​](#event-browser-window-created "Direct link to heading")


Returns:


* `event` Event
* `window` [BrowserWindow](browser-window)


Emitted when a new [browserWindow](browser-window) is created.


### Event: 'web-contents-created'[​](#event-web-contents-created "Direct link to heading")


Returns:


* `event` Event
* `webContents` [WebContents](web-contents)


Emitted when a new [webContents](web-contents) is created.


### Event: 'certificate-error'[​](#event-certificate-error "Direct link to heading")


Returns:


* `event` Event
* `webContents` [WebContents](web-contents)
* `url` string
* `error` string - The error code
* `certificate` [Certificate](structures/certificate)
* `callback` Function
	+ `isTrusted` boolean - Whether to consider the certificate as trusted
* `isMainFrame` boolean


Emitted when failed to verify the `certificate` for `url`, to trust the certificate you should prevent the default behavior with `event.preventDefault()` and call `callback(true)`.




```
const { app } = require('electron')

app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
  if (url === 'https://github.com') {
    // Verification logic.
    event.preventDefault()
    callback(true)
  } else {
    callback(false)
  }
})
```


### Event: 'select-client-certificate'[​](#event-select-client-certificate "Direct link to heading")


Returns:


* `event` Event
* `webContents` [WebContents](web-contents)
* `url` URL
* `certificateList` [Certificate[]](structures/certificate)
* `callback` Function
	+ `certificate` [Certificate](structures/certificate) (optional)


Emitted when a client certificate is requested.


The `url` corresponds to the navigation entry requesting the client certificate and `callback` can be called with an entry filtered from the list. Using `event.preventDefault()` prevents the application from using the first certificate from the store.




```
const { app } = require('electron')

app.on('select-client-certificate', (event, webContents, url, list, callback) => {
  event.preventDefault()
  callback(list[0])
})
```


### Event: 'login'[​](#event-login "Direct link to heading")


Returns:


* `event` Event
* `webContents` [WebContents](web-contents)
* `authenticationResponseDetails` Object
	+ `url` URL
* `authInfo` Object
	+ `isProxy` boolean
	+ `scheme` string
	+ `host` string
	+ `port` Integer
	+ `realm` string
* `callback` Function
	+ `username` string (optional)
	+ `password` string (optional)


Emitted when `webContents` wants to do basic auth.


The default behavior is to cancel all authentications. To override this you should prevent the default behavior with `event.preventDefault()` and call `callback(username, password)` with the credentials.




```
const { app } = require('electron')

app.on('login', (event, webContents, details, authInfo, callback) => {
  event.preventDefault()
  callback('username', 'secret')
})
```


If `callback` is called without a username or password, the authentication request will be cancelled and the authentication error will be returned to the page.


### Event: 'gpu-info-update'[​](#event-gpu-info-update "Direct link to heading")


Emitted whenever there is a GPU info update.


### Event: 'gpu-process-crashed' *Deprecated*[​](#event-gpu-process-crashed-deprecated "Direct link to heading")


Returns:


* `event` Event
* `killed` boolean


Emitted when the GPU process crashes or is killed.


**Deprecated:** This event is superceded by the `child-process-gone` event which contains more information about why the child process disappeared. It isn't always because it crashed. The `killed` boolean can be replaced by checking `reason === 'killed'` when you switch to that event.


### Event: 'renderer-process-crashed' *Deprecated*[​](#event-renderer-process-crashed-deprecated "Direct link to heading")


Returns:


* `event` Event
* `webContents` [WebContents](web-contents)
* `killed` boolean


Emitted when the renderer process of `webContents` crashes or is killed.


**Deprecated:** This event is superceded by the `render-process-gone` event which contains more information about why the render process disappeared. It isn't always because it crashed. The `killed` boolean can be replaced by checking `reason === 'killed'` when you switch to that event.


### Event: 'render-process-gone'[​](#event-render-process-gone "Direct link to heading")


Returns:


* `event` Event
* `webContents` [WebContents](web-contents)
* `details` Object
	+ `reason` string - The reason the render process is gone. Possible values:
		- `clean-exit` - Process exited with an exit code of zero
		- `abnormal-exit` - Process exited with a non-zero exit code
		- `killed` - Process was sent a SIGTERM or otherwise killed externally
		- `crashed` - Process crashed
		- `oom` - Process ran out of memory
		- `launch-failed` - Process never successfully launched
		- `integrity-failure` - Windows code integrity checks failed
	+ `exitCode` Integer - The exit code of the process, unless `reason` is `launch-failed`, in which case `exitCode` will be a platform-specific launch failure error code.


Emitted when the renderer process unexpectedly disappears. This is normally because it was crashed or killed.


### Event: 'child-process-gone'[​](#event-child-process-gone "Direct link to heading")


Returns:


* `event` Event
* `details` Object
	+ `type` string - Process type. One of the following values:
		- `Utility`
		- `Zygote`
		- `Sandbox helper`
		- `GPU`
		- `Pepper Plugin`
		- `Pepper Plugin Broker`
		- `Unknown`
	+ `reason` string - The reason the child process is gone. Possible values:
		- `clean-exit` - Process exited with an exit code of zero
		- `abnormal-exit` - Process exited with a non-zero exit code
		- `killed` - Process was sent a SIGTERM or otherwise killed externally
		- `crashed` - Process crashed
		- `oom` - Process ran out of memory
		- `launch-failed` - Process never successfully launched
		- `integrity-failure` - Windows code integrity checks failed
	+ `exitCode` number - The exit code for the process (e.g. status from waitpid if on posix, from GetExitCodeProcess on Windows).
	+ `serviceName` string (optional) - The non-localized name of the process.
	+ `name` string (optional) - The name of the process. Examples for utility: `Audio Service`, `Content Decryption Module Service`, `Network Service`, `Video Capture`, etc.


Emitted when the child process unexpectedly disappears. This is normally because it was crashed or killed. It does not include renderer processes.


### Event: 'accessibility-support-changed' *macOS* *Windows*[​](#event-accessibility-support-changed-macos-windows "Direct link to heading")


Returns:


* `event` Event
* `accessibilitySupportEnabled` boolean - `true` when Chrome's accessibility support is enabled, `false` otherwise.


Emitted when Chrome's accessibility support changes. This event fires when assistive technologies, such as screen readers, are enabled or disabled. See <https://www.chromium.org/developers/design-documents/accessibility> for more details.


### Event: 'session-created'[​](#event-session-created "Direct link to heading")


Returns:


* `session` [Session](session)


Emitted when Electron has created a new `session`.




```
const { app } = require('electron')

app.on('session-created', (session) => {
  console.log(session)
})
```


### Event: 'second-instance'[​](#event-second-instance "Direct link to heading")


Returns:


* `event` Event
* `argv` string[] - An array of the second instance's command line arguments
* `workingDirectory` string - The second instance's working directory
* `additionalData` unknown - A JSON object of additional data passed from the second instance


This event will be emitted inside the primary instance of your application when a second instance has been executed and calls `app.requestSingleInstanceLock()`.


`argv` is an Array of the second instance's command line arguments, and `workingDirectory` is its current working directory. Usually applications respond to this by making their primary window focused and non-minimized.


**Note:** If the second instance is started by a different user than the first, the `argv` array will not include the arguments.


This event is guaranteed to be emitted after the `ready` event of `app` gets emitted.


**Note:** Extra command line arguments might be added by Chromium, such as `--original-process-start-time`.


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `app` object has the following methods:


**Note:** Some methods are only available on specific operating systems and are labeled as such.


### 
`app.quit()`[​](#appquit "Direct link to heading")


Try to close all windows. The `before-quit` event will be emitted first. If all windows are successfully closed, the `will-quit` event will be emitted and by default the application will terminate.


This method guarantees that all `beforeunload` and `unload` event handlers are correctly executed. It is possible that a window cancels the quitting by returning `false` in the `beforeunload` event handler.


### 
`app.exit([exitCode])`[​](#appexitexitcode "Direct link to heading")


* `exitCode` Integer (optional)


Exits immediately with `exitCode`. `exitCode` defaults to 0.


All windows will be closed immediately without asking the user, and the `before-quit` and `will-quit` events will not be emitted.


### 
`app.relaunch([options])`[​](#apprelaunchoptions "Direct link to heading")


* `options` Object (optional)
	+ `args` string[] (optional)
	+ `execPath` string (optional)


Relaunches the app when current instance exits.


By default, the new instance will use the same working directory and command line arguments with current instance. When `args` is specified, the `args` will be passed as command line arguments instead. When `execPath` is specified, the `execPath` will be executed for relaunch instead of current app.


Note that this method does not quit the app when executed, you have to call `app.quit` or `app.exit` after calling `app.relaunch` to make the app restart.


When `app.relaunch` is called for multiple times, multiple instances will be started after current instance exited.


An example of restarting current instance immediately and adding a new command line argument to the new instance:




```
const { app } = require('electron')

app.relaunch({ args: process.argv.slice(1).concat(['--relaunch']) })
app.exit(0)
```


### 
`app.isReady()`[​](#appisready "Direct link to heading")


Returns `boolean` - `true` if Electron has finished initializing, `false` otherwise. See also `app.whenReady()`.


### 
`app.whenReady()`[​](#appwhenready "Direct link to heading")


Returns `Promise<void>` - fulfilled when Electron is initialized. May be used as a convenient alternative to checking `app.isReady()` and subscribing to the `ready` event if the app is not ready yet.


### 
`app.focus([options])`[​](#appfocusoptions "Direct link to heading")


* `options` Object (optional)
	+ `steal` boolean *macOS* - Make the receiver the active app even if another app is currently active.


On Linux, focuses on the first visible window. On macOS, makes the application the active app. On Windows, focuses on the application's first window.


You should seek to use the `steal` option as sparingly as possible.


### 
`app.hide()` *macOS*[​](#apphide-macos "Direct link to heading")


Hides all application windows without minimizing them.


### 
`app.isHidden()` *macOS*[​](#appishidden-macos "Direct link to heading")


Returns `boolean` - `true` if the application—including all of its windows—is hidden (e.g. with `Command-H`), `false` otherwise.


### 
`app.show()` *macOS*[​](#appshow-macos "Direct link to heading")


Shows application windows after they were hidden. Does not automatically focus them.


### 
`app.setAppLogsPath([path])`[​](#appsetapplogspathpath "Direct link to heading")


* `path` string (optional) - A custom path for your logs. Must be absolute.


Sets or creates a directory your app's logs which can then be manipulated with `app.getPath()` or `app.setPath(pathName, newPath)`.


Calling `app.setAppLogsPath()` without a `path` parameter will result in this directory being set to `~/Library/Logs/YourAppName` on *macOS*, and inside the `userData` directory on *Linux* and *Windows*.


### 
`app.getAppPath()`[​](#appgetapppath "Direct link to heading")


Returns `string` - The current application directory.


### 
`app.getPath(name)`[​](#appgetpathname "Direct link to heading")


* `name` string - You can request the following paths by the name:
	+ `home` User's home directory.
	+ `appData` Per-user application data directory, which by default points to:
		- `%APPDATA%` on Windows
		- `$XDG_CONFIG_HOME` or `~/.config` on Linux
		- `~/Library/Application Support` on macOS
	+ `userData` The directory for storing your app's configuration files, which by default is the `appData` directory appended with your app's name. By convention files storing user data should be written to this directory, and it is not recommended to write large files here because some environments may backup this directory to cloud storage.
	+ `sessionData` The directory for storing data generated by `Session`, such as localStorage, cookies, disk cache, downloaded dictionaries, network state, devtools files. By default this points to `userData`. Chromium may write very large disk cache here, so if your app does not rely on browser storage like localStorage or cookies to save user data, it is recommended to set this directory to other locations to avoid polluting the `userData` directory.
	+ `temp` Temporary directory.
	+ `exe` The current executable file.
	+ `module` The `libchromiumcontent` library.
	+ `desktop` The current user's Desktop directory.
	+ `documents` Directory for a user's "My Documents".
	+ `downloads` Directory for a user's downloads.
	+ `music` Directory for a user's music.
	+ `pictures` Directory for a user's pictures.
	+ `videos` Directory for a user's videos.
	+ `recent` Directory for the user's recent files (Windows only).
	+ `logs` Directory for your app's log folder.
	+ `crashDumps` Directory where crash dumps are stored.


Returns `string` - A path to a special directory or file associated with `name`. On failure, an `Error` is thrown.


If `app.getPath('logs')` is called without called `app.setAppLogsPath()` being called first, a default log directory will be created equivalent to calling `app.setAppLogsPath()` without a `path` parameter.


### 
`app.getFileIcon(path[, options])`[​](#appgetfileiconpath-options "Direct link to heading")


* `path` string
* `options` Object (optional)
	+ `size` string
		- `small` - 16x16
		- `normal` - 32x32
		- `large` - 48x48 on *Linux*, 32x32 on *Windows*, unsupported on *macOS*.


Returns `Promise<NativeImage>` - fulfilled with the app's icon, which is a [NativeImage](native-image).


Fetches a path's associated icon.


On *Windows*, there a 2 kinds of icons:


* Icons associated with certain file extensions, like `.mp3`, `.png`, etc.
* Icons inside the file itself, like `.exe`, `.dll`, `.ico`.


On *Linux* and *macOS*, icons depend on the application associated with file mime type.


### 
`app.setPath(name, path)`[​](#appsetpathname-path "Direct link to heading")


* `name` string
* `path` string


Overrides the `path` to a special directory or file associated with `name`. If the path specifies a directory that does not exist, an `Error` is thrown. In that case, the directory should be created with `fs.mkdirSync` or similar.


You can only override paths of a `name` defined in `app.getPath`.


By default, web pages' cookies and caches will be stored under the `sessionData` directory. If you want to change this location, you have to override the `sessionData` path before the `ready` event of the `app` module is emitted.


### 
`app.getVersion()`[​](#appgetversion "Direct link to heading")


Returns `string` - The version of the loaded application. If no version is found in the application's `package.json` file, the version of the current bundle or executable is returned.


### 
`app.getName()`[​](#appgetname "Direct link to heading")


Returns `string` - The current application's name, which is the name in the application's `package.json` file.


Usually the `name` field of `package.json` is a short lowercase name, according to the npm modules spec. You should usually also specify a `productName` field, which is your application's full capitalized name, and which will be preferred over `name` by Electron.


### 
`app.setName(name)`[​](#appsetnamename "Direct link to heading")


* `name` string


Overrides the current application's name.


**Note:** This function overrides the name used internally by Electron; it does not affect the name that the OS uses.


### 
`app.getLocale()`[​](#appgetlocale "Direct link to heading")


Returns `string` - The current application locale, fetched using Chromium's `l10n_util` library. Possible return values are documented [here](https://source.chromium.org/chromium/chromium/src/+/main:ui/base/l10n/l10n_util.cc).


To set the locale, you'll want to use a command line switch at app startup, which may be found [here](command-line-switches).


**Note:** When distributing your packaged app, you have to also ship the `locales` folder.


**Note:** On Windows, you have to call it after the `ready` events gets emitted.


### 
`app.getLocaleCountryCode()`[​](#appgetlocalecountrycode "Direct link to heading")


Returns `string` - User operating system's locale two-letter [ISO 3166](https://www.iso.org/iso-3166-country-codes.html) country code. The value is taken from native OS APIs.


**Note:** When unable to detect locale country code, it returns empty string.


### 
`app.addRecentDocument(path)` *macOS* *Windows*[​](#appaddrecentdocumentpath-macos-windows "Direct link to heading")


* `path` string


Adds `path` to the recent documents list.


This list is managed by the OS. On Windows, you can visit the list from the task bar, and on macOS, you can visit it from dock menu.


### 
`app.clearRecentDocuments()` *macOS* *Windows*[​](#appclearrecentdocuments-macos-windows "Direct link to heading")


Clears the recent documents list.


### 
`app.setAsDefaultProtocolClient(protocol[, path, args])`[​](#appsetasdefaultprotocolclientprotocol-path-args "Direct link to heading")


* `protocol` string - The name of your protocol, without `://`. For example, if you want your app to handle `electron://` links, call this method with `electron` as the parameter.
* `path` string (optional) *Windows* - The path to the Electron executable. Defaults to `process.execPath`
* `args` string[] (optional) *Windows* - Arguments passed to the executable. Defaults to an empty array


Returns `boolean` - Whether the call succeeded.


Sets the current executable as the default handler for a protocol (aka URI scheme). It allows you to integrate your app deeper into the operating system. Once registered, all links with `your-protocol://` will be opened with the current executable. The whole link, including protocol, will be passed to your application as a parameter.


**Note:** On macOS, you can only register protocols that have been added to your app's `info.plist`, which cannot be modified at runtime. However, you can change the file during build time via [Electron Forge](https://www.electronforge.io/), [Electron Packager](https://github.com/electron/electron-packager), or by editing `info.plist` with a text editor. Please refer to [Apple's documentation](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-102207-TPXREF115) for details.


**Note:** In a Windows Store environment (when packaged as an `appx`) this API will return `true` for all calls but the registry key it sets won't be accessible by other applications. In order to register your Windows Store application as a default protocol handler you must [declare the protocol in your manifest](https://docs.microsoft.com/en-us/uwp/schemas/appxpackage/uapmanifestschema/element-uap-protocol).


The API uses the Windows Registry and `LSSetDefaultHandlerForURLScheme` internally.


### 
`app.removeAsDefaultProtocolClient(protocol[, path, args])` *macOS* *Windows*[​](#appremoveasdefaultprotocolclientprotocol-path-args-macos-windows "Direct link to heading")


* `protocol` string - The name of your protocol, without `://`.
* `path` string (optional) *Windows* - Defaults to `process.execPath`
* `args` string[] (optional) *Windows* - Defaults to an empty array


Returns `boolean` - Whether the call succeeded.


This method checks if the current executable as the default handler for a protocol (aka URI scheme). If so, it will remove the app as the default handler.


### 
`app.isDefaultProtocolClient(protocol[, path, args])`[​](#appisdefaultprotocolclientprotocol-path-args "Direct link to heading")


* `protocol` string - The name of your protocol, without `://`.
* `path` string (optional) *Windows* - Defaults to `process.execPath`
* `args` string[] (optional) *Windows* - Defaults to an empty array


Returns `boolean` - Whether the current executable is the default handler for a protocol (aka URI scheme).


**Note:** On macOS, you can use this method to check if the app has been registered as the default protocol handler for a protocol. You can also verify this by checking `~/Library/Preferences/com.apple.LaunchServices.plist` on the macOS machine. Please refer to [Apple's documentation](https://developer.apple.com/library/mac/documentation/Carbon/Reference/LaunchServicesReference/#//apple_ref/c/func/LSCopyDefaultHandlerForURLScheme) for details.


The API uses the Windows Registry and `LSCopyDefaultHandlerForURLScheme` internally.


### 
`app.getApplicationNameForProtocol(url)`[​](#appgetapplicationnameforprotocolurl "Direct link to heading")


* `url` string - a URL with the protocol name to check. Unlike the other methods in this family, this accepts an entire URL, including `://` at a minimum (e.g. `https://`).


Returns `string` - Name of the application handling the protocol, or an empty string if there is no handler. For instance, if Electron is the default handler of the URL, this could be `Electron` on Windows and Mac. However, don't rely on the precise format which is not guaranteed to remain unchanged. Expect a different format on Linux, possibly with a `.desktop` suffix.


This method returns the application name of the default handler for the protocol (aka URI scheme) of a URL.


### 
`app.getApplicationInfoForProtocol(url)` *macOS* *Windows*[​](#appgetapplicationinfoforprotocolurl-macos-windows "Direct link to heading")


* `url` string - a URL with the protocol name to check. Unlike the other methods in this family, this accepts an entire URL, including `://` at a minimum (e.g. `https://`).


Returns `Promise<Object>` - Resolve with an object containing the following:


* `icon` NativeImage - the display icon of the app handling the protocol.
* `path` string - installation path of the app handling the protocol.
* `name` string - display name of the app handling the protocol.


This method returns a promise that contains the application name, icon and path of the default handler for the protocol (aka URI scheme) of a URL.


### 
`app.setUserTasks(tasks)` *Windows*[​](#appsetusertaskstasks-windows "Direct link to heading")


* `tasks` [Task[]](structures/task) - Array of `Task` objects


Adds `tasks` to the [Tasks](https://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#tasks) category of the Jump List on Windows.


`tasks` is an array of [Task](structures/task) objects.


Returns `boolean` - Whether the call succeeded.


**Note:** If you'd like to customize the Jump List even more use `app.setJumpList(categories)` instead.


### 
`app.getJumpListSettings()` *Windows*[​](#appgetjumplistsettings-windows "Direct link to heading")


Returns `Object`:


* `minItems` Integer - The minimum number of items that will be shown in the Jump List (for a more detailed description of this value see the [MSDN docs](https://msdn.microsoft.com/en-us/library/windows/desktop/dd378398(v=vs.85).aspx)).
* `removedItems` [JumpListItem[]](structures/jump-list-item) - Array of `JumpListItem` objects that correspond to items that the user has explicitly removed from custom categories in the Jump List. These items must not be re-added to the Jump List in the **next** call to `app.setJumpList()`, Windows will not display any custom category that contains any of the removed items.


### 
`app.setJumpList(categories)` *Windows*[​](#appsetjumplistcategories-windows "Direct link to heading")


* `categories` [JumpListCategory[]](structures/jump-list-category) | `null` - Array of `JumpListCategory` objects.


Returns `string`


Sets or removes a custom Jump List for the application, and returns one of the following strings:


* `ok` - Nothing went wrong.
* `error` - One or more errors occurred, enable runtime logging to figure out the likely cause.
* `invalidSeparatorError` - An attempt was made to add a separator to a custom category in the Jump List. Separators are only allowed in the standard `Tasks` category.
* `fileTypeRegistrationError` - An attempt was made to add a file link to the Jump List for a file type the app isn't registered to handle.
* `customCategoryAccessDeniedError` - Custom categories can't be added to the Jump List due to user privacy or group policy settings.


If `categories` is `null` the previously set custom Jump List (if any) will be replaced by the standard Jump List for the app (managed by Windows).


**Note:** If a `JumpListCategory` object has neither the `type` nor the `name` property set then its `type` is assumed to be `tasks`. If the `name` property is set but the `type` property is omitted then the `type` is assumed to be `custom`.


**Note:** Users can remove items from custom categories, and Windows will not allow a removed item to be added back into a custom category until **after** the next successful call to `app.setJumpList(categories)`. Any attempt to re-add a removed item to a custom category earlier than that will result in the entire custom category being omitted from the Jump List. The list of removed items can be obtained using `app.getJumpListSettings()`.


**Note:** The maximum length of a Jump List item's `description` property is 260 characters. Beyond this limit, the item will not be added to the Jump List, nor will it be displayed.


Here's a very simple example of creating a custom Jump List:




```
const { app } = require('electron')

app.setJumpList([
  {
    type: 'custom',
    name: 'Recent Projects',
    items: [
      { type: 'file', path: 'C:\\Projects\\project1.proj' },
      { type: 'file', path: 'C:\\Projects\\project2.proj' }
    ]
  },
  { // has a name so `type` is assumed to be "custom"
    name: 'Tools',
    items: [
      {
        type: 'task',
        title: 'Tool A',
        program: process.execPath,
        args: '--run-tool-a',
        icon: process.execPath,
        iconIndex: 0,
        description: 'Runs Tool A'
      },
      {
        type: 'task',
        title: 'Tool B',
        program: process.execPath,
        args: '--run-tool-b',
        icon: process.execPath,
        iconIndex: 0,
        description: 'Runs Tool B'
      }
    ]
  },
  { type: 'frequent' },
  { // has no name and no type so `type` is assumed to be "tasks"
    items: [
      {
        type: 'task',
        title: 'New Project',
        program: process.execPath,
        args: '--new-project',
        description: 'Create a new project.'
      },
      { type: 'separator' },
      {
        type: 'task',
        title: 'Recover Project',
        program: process.execPath,
        args: '--recover-project',
        description: 'Recover Project'
      }
    ]
  }
])
```


### 
`app.requestSingleInstanceLock([additionalData])`[​](#apprequestsingleinstancelockadditionaldata "Direct link to heading")


* `additionalData` Record<any, any> (optional) - A JSON object containing additional data to send to the first instance.


Returns `boolean`


The return value of this method indicates whether or not this instance of your application successfully obtained the lock. If it failed to obtain the lock, you can assume that another instance of your application is already running with the lock and exit immediately.


I.e. This method returns `true` if your process is the primary instance of your application and your app should continue loading. It returns `false` if your process should immediately quit as it has sent its parameters to another instance that has already acquired the lock.


On macOS, the system enforces single instance automatically when users try to open a second instance of your app in Finder, and the `open-file` and `open-url` events will be emitted for that. However when users start your app in command line, the system's single instance mechanism will be bypassed, and you have to use this method to ensure single instance.


An example of activating the window of primary instance when a second instance starts:




```
const { app } = require('electron')
let myWindow = null

const additionalData = { myKey: 'myValue' }
const gotTheLock = app.requestSingleInstanceLock(additionalData)

if (!gotTheLock) {
  app.quit()
} else {
  app.on('second-instance', (event, commandLine, workingDirectory, additionalData) => {
    // Print out data received from the second instance.
    console.log(additionalData)

    // Someone tried to run a second instance, we should focus our window.
    if (myWindow) {
      if (myWindow.isMinimized()) myWindow.restore()
      myWindow.focus()
    }
  })

  // Create myWindow, load the rest of the app, etc...
  app.whenReady().then(() => {
    myWindow = createWindow()
  })
}
```


### 
`app.hasSingleInstanceLock()`[​](#apphassingleinstancelock "Direct link to heading")


Returns `boolean`


This method returns whether or not this instance of your app is currently holding the single instance lock. You can request the lock with `app.requestSingleInstanceLock()` and release with `app.releaseSingleInstanceLock()`


### 
`app.releaseSingleInstanceLock()`[​](#appreleasesingleinstancelock "Direct link to heading")


Releases all locks that were created by `requestSingleInstanceLock`. This will allow multiple instances of the application to once again run side by side.


### 
`app.setUserActivity(type, userInfo[, webpageURL])` *macOS*[​](#appsetuseractivitytype-userinfo-webpageurl-macos "Direct link to heading")


* `type` string - Uniquely identifies the activity. Maps to [`NSUserActivity.activityType`](https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType).
* `userInfo` any - App-specific state to store for use by another device.
* `webpageURL` string (optional) - The webpage to load in a browser if no suitable app is installed on the resuming device. The scheme must be `http` or `https`.


Creates an `NSUserActivity` and sets it as the current activity. The activity is eligible for [Handoff](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html) to another device afterward.


### 
`app.getCurrentActivityType()` *macOS*[​](#appgetcurrentactivitytype-macos "Direct link to heading")


Returns `string` - The type of the currently running activity.


### 
`app.invalidateCurrentActivity()` *macOS*[​](#appinvalidatecurrentactivity-macos "Direct link to heading")


Invalidates the current [Handoff](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html) user activity.


### 
`app.resignCurrentActivity()` *macOS*[​](#appresigncurrentactivity-macos "Direct link to heading")


Marks the current [Handoff](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html) user activity as inactive without invalidating it.


### 
`app.updateCurrentActivity(type, userInfo)` *macOS*[​](#appupdatecurrentactivitytype-userinfo-macos "Direct link to heading")


* `type` string - Uniquely identifies the activity. Maps to [`NSUserActivity.activityType`](https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType).
* `userInfo` any - App-specific state to store for use by another device.


Updates the current activity if its type matches `type`, merging the entries from `userInfo` into its current `userInfo` dictionary.


### 
`app.setAppUserModelId(id)` *Windows*[​](#appsetappusermodelidid-windows "Direct link to heading")


* `id` string


Changes the [Application User Model ID](https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx) to `id`.


### 
`app.setActivationPolicy(policy)` *macOS*[​](#appsetactivationpolicypolicy-macos "Direct link to heading")


* `policy` string - Can be 'regular', 'accessory', or 'prohibited'.


Sets the activation policy for a given app.


Activation policy types:


* 'regular' - The application is an ordinary app that appears in the Dock and may have a user interface.
* 'accessory' - The application doesn’t appear in the Dock and doesn’t have a menu bar, but it may be activated programmatically or by clicking on one of its windows.
* 'prohibited' - The application doesn’t appear in the Dock and may not create windows or be activated.


### 
`app.importCertificate(options, callback)` *Linux*[​](#appimportcertificateoptions-callback-linux "Direct link to heading")


* `options` Object
	+ `certificate` string - Path for the pkcs12 file.
	+ `password` string - Passphrase for the certificate.
* `callback` Function
	+ `result` Integer - Result of import.


Imports the certificate in pkcs12 format into the platform certificate store. `callback` is called with the `result` of import operation, a value of `0` indicates success while any other value indicates failure according to Chromium [net\_error\_list](https://source.chromium.org/chromium/chromium/src/+/main:net/base/net_error_list.h).


### 
`app.configureHostResolver(options)`[​](#appconfigurehostresolveroptions "Direct link to heading")


* `options` Object
	+ `enableBuiltInResolver` boolean (optional) - Whether the built-in host resolver is used in preference to getaddrinfo. When enabled, the built-in resolver will attempt to use the system's DNS settings to do DNS lookups itself. Enabled by default on macOS, disabled by default on Windows and Linux.
	+ `secureDnsMode` string (optional) - Can be "off", "automatic" or "secure". Configures the DNS-over-HTTP mode. When "off", no DoH lookups will be performed. When "automatic", DoH lookups will be performed first if DoH is available, and insecure DNS lookups will be performed as a fallback. When "secure", only DoH lookups will be performed. Defaults to "automatic".
	+ `secureDnsServers` string[] (optional) - A list of DNS-over-HTTP server templates. See [RFC8484 § 3](https://datatracker.ietf.org/doc/html/rfc8484#section-3) for details on the template format. Most servers support the POST method; the template for such servers is simply a URI. Note that for [some DNS providers](https://source.chromium.org/chromium/chromium/src/+/main:net/dns/public/doh_provider_entry.cc;l=31?q=%22DohProviderEntry::GetList()%22&ss=chromium%2Fchromium%2Fsrc), the resolver will automatically upgrade to DoH unless DoH is explicitly disabled, even if there are no DoH servers provided in this list.
	+ `enableAdditionalDnsQueryTypes` boolean (optional) - Controls whether additional DNS query types, e.g. HTTPS (DNS type 65) will be allowed besides the traditional A and AAAA queries when a request is being made via insecure DNS. Has no effect on Secure DNS which always allows additional types. Defaults to true.


Configures host resolution (DNS and DNS-over-HTTPS). By default, the following resolvers will be used, in order:


1. DNS-over-HTTPS, if the [DNS provider supports it](https://source.chromium.org/chromium/chromium/src/+/main:net/dns/public/doh_provider_entry.cc;l=31?q=%22DohProviderEntry::GetList()%22&ss=chromium%2Fchromium%2Fsrc), then
2. the built-in resolver (enabled on macOS only by default), then
3. the system's resolver (e.g. `getaddrinfo`).


This can be configured to either restrict usage of non-encrypted DNS (`secureDnsMode: "secure"`), or disable DNS-over-HTTPS (`secureDnsMode:
"off"`). It is also possible to enable or disable the built-in resolver.


To disable insecure DNS, you can specify a `secureDnsMode` of `"secure"`. If you do so, you should make sure to provide a list of DNS-over-HTTPS servers to use, in case the user's DNS configuration does not include a provider that supports DoH.




```
app.configureHostResolver({
  secureDnsMode: 'secure',
  secureDnsServers: [
    'https://cloudflare-dns.com/dns-query'
  ]
})
```


This API must be called after the `ready` event is emitted.


### 
`app.disableHardwareAcceleration()`[​](#appdisablehardwareacceleration "Direct link to heading")


Disables hardware acceleration for current app.


This method can only be called before app is ready.


### 
`app.disableDomainBlockingFor3DAPIs()`[​](#appdisabledomainblockingfor3dapis "Direct link to heading")


By default, Chromium disables 3D APIs (e.g. WebGL) until restart on a per domain basis if the GPU processes crashes too frequently. This function disables that behavior.


This method can only be called before app is ready.


### 
`app.getAppMetrics()`[​](#appgetappmetrics "Direct link to heading")


Returns [ProcessMetric[]](structures/process-metric): Array of `ProcessMetric` objects that correspond to memory and CPU usage statistics of all the processes associated with the app.


### 
`app.getGPUFeatureStatus()`[​](#appgetgpufeaturestatus "Direct link to heading")


Returns [GPUFeatureStatus](structures/gpu-feature-status) - The Graphics Feature Status from `chrome://gpu/`.


**Note:** This information is only usable after the `gpu-info-update` event is emitted.


### 
`app.getGPUInfo(infoType)`[​](#appgetgpuinfoinfotype "Direct link to heading")


* `infoType` string - Can be `basic` or `complete`.


Returns `Promise<unknown>`


For `infoType` equal to `complete`: Promise is fulfilled with `Object` containing all the GPU Information as in [chromium's GPUInfo object](https://chromium.googlesource.com/chromium/src/+/4178e190e9da409b055e5dff469911ec6f6b716f/gpu/config/gpu_info.cc). This includes the version and driver information that's shown on `chrome://gpu` page.


For `infoType` equal to `basic`: Promise is fulfilled with `Object` containing fewer attributes than when requested with `complete`. Here's an example of basic response:




```
{
  auxAttributes:
   {
     amdSwitchable: true,
     canSupportThreadedTextureMailbox: false,
     directComposition: false,
     directRendering: true,
     glResetNotificationStrategy: 0,
     inProcessGpu: true,
     initializationTime: 0,
     jpegDecodeAcceleratorSupported: false,
     optimus: false,
     passthroughCmdDecoder: false,
     sandboxed: false,
     softwareRendering: false,
     supportsOverlays: false,
     videoDecodeAcceleratorFlags: 0
   },
  gpuDevice:
   [{ active: true, deviceId: 26657, vendorId: 4098 },
     { active: false, deviceId: 3366, vendorId: 32902 }],
  machineModelName: 'MacBookPro',
  machineModelVersion: '11.5'
}
```


Using `basic` should be preferred if only basic information like `vendorId` or `driverId` is needed.


### 
`app.setBadgeCount([count])` *Linux* *macOS*[​](#appsetbadgecountcount-linux-macos "Direct link to heading")


* `count` Integer (optional) - If a value is provided, set the badge to the provided value otherwise, on macOS, display a plain white dot (e.g. unknown number of notifications). On Linux, if a value is not provided the badge will not display.


Returns `boolean` - Whether the call succeeded.


Sets the counter badge for current app. Setting the count to `0` will hide the badge.


On macOS, it shows on the dock icon. On Linux, it only works for Unity launcher.


**Note:** Unity launcher requires a `.desktop` file to work. For more information, please read the [Unity integration documentation](https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher).


### 
`app.getBadgeCount()` *Linux* *macOS*[​](#appgetbadgecount-linux-macos "Direct link to heading")


Returns `Integer` - The current value displayed in the counter badge.


### 
`app.isUnityRunning()` *Linux*[​](#appisunityrunning-linux "Direct link to heading")


Returns `boolean` - Whether the current desktop environment is Unity launcher.


### 
`app.getLoginItemSettings([options])` *macOS* *Windows*[​](#appgetloginitemsettingsoptions-macos-windows "Direct link to heading")


* `options` Object (optional)
	+ `path` string (optional) *Windows* - The executable path to compare against. Defaults to `process.execPath`.
	+ `args` string[] (optional) *Windows* - The command-line arguments to compare against. Defaults to an empty array.


If you provided `path` and `args` options to `app.setLoginItemSettings`, then you need to pass the same arguments here for `openAtLogin` to be set correctly.


Returns `Object`:


* `openAtLogin` boolean - `true` if the app is set to open at login.
* `openAsHidden` boolean *macOS* - `true` if the app is set to open as hidden at login. This setting is not available on [MAS builds](../tutorial/mac-app-store-submission-guide).
* `wasOpenedAtLogin` boolean *macOS* - `true` if the app was opened at login automatically. This setting is not available on [MAS builds](../tutorial/mac-app-store-submission-guide).
* `wasOpenedAsHidden` boolean *macOS* - `true` if the app was opened as a hidden login item. This indicates that the app should not open any windows at startup. This setting is not available on [MAS builds](../tutorial/mac-app-store-submission-guide).
* `restoreState` boolean *macOS* - `true` if the app was opened as a login item that should restore the state from the previous session. This indicates that the app should restore the windows that were open the last time the app was closed. This setting is not available on [MAS builds](../tutorial/mac-app-store-submission-guide).
* `executableWillLaunchAtLogin` boolean *Windows* - `true` if app is set to open at login and its run key is not deactivated. This differs from `openAtLogin` as it ignores the `args` option, this property will be true if the given executable would be launched at login with **any** arguments.
* `launchItems` Object[] *Windows*
	+ `name` string *Windows* - name value of a registry entry.
	+ `path` string *Windows* - The executable to an app that corresponds to a registry entry.
	+ `args` string[] *Windows* - the command-line arguments to pass to the executable.
	+ `scope` string *Windows* - one of `user` or `machine`. Indicates whether the registry entry is under `HKEY_CURRENT USER` or `HKEY_LOCAL_MACHINE`.
	+ `enabled` boolean *Windows* - `true` if the app registry key is startup approved and therefore shows as `enabled` in Task Manager and Windows settings.


### 
`app.setLoginItemSettings(settings)` *macOS* *Windows*[​](#appsetloginitemsettingssettings-macos-windows "Direct link to heading")


* `settings` Object
	+ `openAtLogin` boolean (optional) - `true` to open the app at login, `false` to remove the app as a login item. Defaults to `false`.
	+ `openAsHidden` boolean (optional) *macOS* - `true` to open the app as hidden. Defaults to `false`. The user can edit this setting from the System Preferences so `app.getLoginItemSettings().wasOpenedAsHidden` should be checked when the app is opened to know the current value. This setting is not available on [MAS builds](../tutorial/mac-app-store-submission-guide).
	+ `path` string (optional) *Windows* - The executable to launch at login. Defaults to `process.execPath`.
	+ `args` string[] (optional) *Windows* - The command-line arguments to pass to the executable. Defaults to an empty array. Take care to wrap paths in quotes.
	+ `enabled` boolean (optional) *Windows* - `true` will change the startup approved registry key and `enable / disable` the App in Task Manager and Windows Settings. Defaults to `true`.
	+ `name` string (optional) *Windows* - value name to write into registry. Defaults to the app's AppUserModelId(). Set the app's login item settings.


To work with Electron's `autoUpdater` on Windows, which uses [Squirrel](https://github.com/Squirrel/Squirrel.Windows), you'll want to set the launch path to Update.exe, and pass arguments that specify your application name. For example:




```
const appFolder = path.dirname(process.execPath)
const updateExe = path.resolve(appFolder, '..', 'Update.exe')
const exeName = path.basename(process.execPath)

app.setLoginItemSettings({
  openAtLogin: true,
  path: updateExe,
  args: [
    '--processStart', `"${exeName}"`,
    '--process-start-args', `"--hidden"`
  ]
})
```


### 
`app.isAccessibilitySupportEnabled()` *macOS* *Windows*[​](#appisaccessibilitysupportenabled-macos-windows "Direct link to heading")


Returns `boolean` - `true` if Chrome's accessibility support is enabled, `false` otherwise. This API will return `true` if the use of assistive technologies, such as screen readers, has been detected. See <https://www.chromium.org/developers/design-documents/accessibility> for more details.


### 
`app.setAccessibilitySupportEnabled(enabled)` *macOS* *Windows*[​](#appsetaccessibilitysupportenabledenabled-macos-windows "Direct link to heading")


* `enabled` boolean - Enable or disable [accessibility tree](https://developers.google.com/web/fundamentals/accessibility/semantics-builtin/the-accessibility-tree) rendering


Manually enables Chrome's accessibility support, allowing to expose accessibility switch to users in application settings. See [Chromium's accessibility docs](https://www.chromium.org/developers/design-documents/accessibility) for more details. Disabled by default.


This API must be called after the `ready` event is emitted.


**Note:** Rendering accessibility tree can significantly affect the performance of your app. It should not be enabled by default.


### 
`app.showAboutPanel()`[​](#appshowaboutpanel "Direct link to heading")


Show the app's about panel options. These options can be overridden with `app.setAboutPanelOptions(options)`.


### 
`app.setAboutPanelOptions(options)`[​](#appsetaboutpaneloptionsoptions "Direct link to heading")


* `options` Object
	+ `applicationName` string (optional) - The app's name.
	+ `applicationVersion` string (optional) - The app's version.
	+ `copyright` string (optional) - Copyright information.
	+ `version` string (optional) *macOS* - The app's build version number.
	+ `credits` string (optional) *macOS* *Windows* - Credit information.
	+ `authors` string[] (optional) *Linux* - List of app authors.
	+ `website` string (optional) *Linux* - The app's website.
	+ `iconPath` string (optional) *Linux* *Windows* - Path to the app's icon in a JPEG or PNG file format. On Linux, will be shown as 64x64 pixels while retaining aspect ratio.


Set the about panel options. This will override the values defined in the app's `.plist` file on macOS. See the [Apple docs](https://developer.apple.com/reference/appkit/nsapplication/1428479-orderfrontstandardaboutpanelwith?language=objc) for more details. On Linux, values must be set in order to be shown; there are no defaults.


If you do not set `credits` but still wish to surface them in your app, AppKit will look for a file named "Credits.html", "Credits.rtf", and "Credits.rtfd", in that order, in the bundle returned by the NSBundle class method main. The first file found is used, and if none is found, the info area is left blank. See Apple [documentation](https://developer.apple.com/documentation/appkit/nsaboutpaneloptioncredits?language=objc) for more information.


### 
`app.isEmojiPanelSupported()`[​](#appisemojipanelsupported "Direct link to heading")


Returns `boolean` - whether or not the current OS version allows for native emoji pickers.


### 
`app.showEmojiPanel()` *macOS* *Windows*[​](#appshowemojipanel-macos-windows "Direct link to heading")


Show the platform's native emoji picker.


### 
`app.startAccessingSecurityScopedResource(bookmarkData)` *mas*[​](#appstartaccessingsecurityscopedresourcebookmarkdata-mas "Direct link to heading")


* `bookmarkData` string - The base64 encoded security scoped bookmark data returned by the `dialog.showOpenDialog` or `dialog.showSaveDialog` methods.


Returns `Function` - This function **must** be called once you have finished accessing the security scoped file. If you do not remember to stop accessing the bookmark, [kernel resources will be leaked](https://developer.apple.com/reference/foundation/nsurl/1417051-startaccessingsecurityscopedreso?language=objc) and your app will lose its ability to reach outside the sandbox completely, until your app is restarted.




```
// Start accessing the file.
const stopAccessingSecurityScopedResource = app.startAccessingSecurityScopedResource(data)
// You can now access the file outside of the sandbox 🎉

// Remember to stop accessing the file once you've finished with it.
stopAccessingSecurityScopedResource()
```


Start accessing a security scoped resource. With this method Electron applications that are packaged for the Mac App Store may reach outside their sandbox to access files chosen by the user. See [Apple's documentation](https://developer.apple.com/library/content/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW16) for a description of how this system works.


### 
`app.enableSandbox()`[​](#appenablesandbox "Direct link to heading")


Enables full sandbox mode on the app. This means that all renderers will be launched sandboxed, regardless of the value of the `sandbox` flag in WebPreferences.


This method can only be called before app is ready.


### 
`app.isInApplicationsFolder()` *macOS*[​](#appisinapplicationsfolder-macos "Direct link to heading")


Returns `boolean` - Whether the application is currently running from the systems Application folder. Use in combination with `app.moveToApplicationsFolder()`


### 
`app.moveToApplicationsFolder([options])` *macOS*[​](#appmovetoapplicationsfolderoptions-macos "Direct link to heading")


* `options` Object (optional)
	+ `conflictHandler` Function\<boolean> (optional) - A handler for potential conflict in move failure.
		- `conflictType` string - The type of move conflict encountered by the handler; can be `exists` or `existsAndRunning`, where `exists` means that an app of the same name is present in the Applications directory and `existsAndRunning` means both that it exists and that it's presently running.


Returns `boolean` - Whether the move was successful. Please note that if the move is successful, your application will quit and relaunch.


No confirmation dialog will be presented by default. If you wish to allow the user to confirm the operation, you may do so using the [`dialog`](dialog) API.


**NOTE:** This method throws errors if anything other than the user causes the move to fail. For instance if the user cancels the authorization dialog, this method returns false. If we fail to perform the copy, then this method will throw an error. The message in the error should be informative and tell you exactly what went wrong.


By default, if an app of the same name as the one being moved exists in the Applications directory and is *not* running, the existing app will be trashed and the active app moved into its place. If it *is* running, the pre-existing running app will assume focus and the previously active app will quit itself. This behavior can be changed by providing the optional conflict handler, where the boolean returned by the handler determines whether or not the move conflict is resolved with default behavior. i.e. returning `false` will ensure no further action is taken, returning `true` will result in the default behavior and the method continuing.


For example:




```
app.moveToApplicationsFolder({
  conflictHandler: (conflictType) => {
    if (conflictType === 'exists') {
      return dialog.showMessageBoxSync({
        type: 'question',
        buttons: ['Halt Move', 'Continue Move'],
        defaultId: 0,
        message: 'An app of this name already exists'
      }) === 1
    }
  }
})
```


Would mean that if an app already exists in the user directory, if the user chooses to 'Continue Move' then the function would continue with its default behavior and the existing app will be trashed and the active app moved into its place.


### 
`app.isSecureKeyboardEntryEnabled()` *macOS*[​](#appissecurekeyboardentryenabled-macos "Direct link to heading")


Returns `boolean` - whether `Secure Keyboard Entry` is enabled.


By default this API will return `false`.


### 
`app.setSecureKeyboardEntryEnabled(enabled)` *macOS*[​](#appsetsecurekeyboardentryenabledenabled-macos "Direct link to heading")


* `enabled` boolean - Enable or disable `Secure Keyboard Entry`


Set the `Secure Keyboard Entry` is enabled in your application.


By using this API, important information such as password and other sensitive information can be prevented from being intercepted by other processes.


See [Apple's documentation](https://developer.apple.com/library/archive/technotes/tn2150/_index.html) for more details.


**Note:** Enable `Secure Keyboard Entry` only when it is needed and disable it when it is no longer needed.


Properties[​](#properties "Direct link to heading")
---------------------------------------------------


### 
`app.accessibilitySupportEnabled` *macOS* *Windows*[​](#appaccessibilitysupportenabled-macos-windows "Direct link to heading")


A `boolean` property that's `true` if Chrome's accessibility support is enabled, `false` otherwise. This property will be `true` if the use of assistive technologies, such as screen readers, has been detected. Setting this property to `true` manually enables Chrome's accessibility support, allowing developers to expose accessibility switch to users in application settings.


See [Chromium's accessibility docs](https://www.chromium.org/developers/design-documents/accessibility) for more details. Disabled by default.


This API must be called after the `ready` event is emitted.


**Note:** Rendering accessibility tree can significantly affect the performance of your app. It should not be enabled by default.


### 
`app.applicationMenu`[​](#appapplicationmenu "Direct link to heading")


A `Menu | null` property that returns [`Menu`](menu) if one has been set and `null` otherwise. Users can pass a [Menu](menu) to set this property.


### 
`app.badgeCount` *Linux* *macOS*[​](#appbadgecount-linux-macos "Direct link to heading")


An `Integer` property that returns the badge count for current app. Setting the count to `0` will hide the badge.


On macOS, setting this with any nonzero integer shows on the dock icon. On Linux, this property only works for Unity launcher.


**Note:** Unity launcher requires a `.desktop` file to work. For more information, please read the [Unity integration documentation](https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher).


**Note:** On macOS, you need to ensure that your application has the permission to display notifications for this property to take effect.


### 
`app.commandLine` *Readonly*[​](#appcommandline-readonly "Direct link to heading")


A [`CommandLine`](command-line) object that allows you to read and manipulate the command line arguments that Chromium uses.


### 
`app.dock` *macOS* *Readonly*[​](#appdock-macos-readonly "Direct link to heading")


A [`Dock`](dock) `| undefined` object that allows you to perform actions on your app icon in the user's dock on macOS.


### 
`app.isPackaged` *Readonly*[​](#appispackaged-readonly "Direct link to heading")


A `boolean` property that returns `true` if the app is packaged, `false` otherwise. For many apps, this property can be used to distinguish development and production environments.


### 
`app.name`[​](#appname "Direct link to heading")


A `string` property that indicates the current application's name, which is the name in the application's `package.json` file.


Usually the `name` field of `package.json` is a short lowercase name, according to the npm modules spec. You should usually also specify a `productName` field, which is your application's full capitalized name, and which will be preferred over `name` by Electron.


### 
`app.userAgentFallback`[​](#appuseragentfallback "Direct link to heading")


A `string` which is the user agent string Electron will use as a global fallback.


This is the user agent that will be used when no user agent is set at the `webContents` or `session` level. It is useful for ensuring that your entire app has the same user agent. Set to a custom value as early as possible in your app's initialization to ensure that your overridden value is used.


### 
`app.runningUnderRosettaTranslation` *macOS* *Readonly* *Deprecated*[​](#apprunningunderrosettatranslation-macos-readonly-deprecated "Direct link to heading")


A `boolean` which when `true` indicates that the app is currently running under the [Rosetta Translator Environment](https://en.wikipedia.org/wiki/Rosetta_(software)).


You can use this property to prompt users to download the arm64 version of your application when they are running the x64 version under Rosetta incorrectly.


**Deprecated:** This property is superceded by the `runningUnderARM64Translation` property which detects when the app is being translated to ARM64 in both macOS and Windows.


### 
`app.runningUnderARM64Translation` *Readonly* *macOS* *Windows*[​](#apprunningunderarm64translation-readonly-macos-windows "Direct link to heading")


A `boolean` which when `true` indicates that the app is currently running under an ARM64 translator (like the macOS [Rosetta Translator Environment](https://en.wikipedia.org/wiki/Rosetta_(software)) or Windows [WOW](https://en.wikipedia.org/wiki/Windows_on_Windows)).


You can use this property to prompt users to download the arm64 version of your application when they are running the x64 version under Rosetta incorrectly.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/app>

Advanced Installation Instructions
==================================


To install prebuilt Electron binaries, use [`npm`](https://docs.npmjs.com). The preferred method is to install Electron as a development dependency in your app:




```
npm install electron --save-dev
```


See the [Electron versioning doc](electron-versioning) for info on how to manage Electron versions in your apps.


Running Electron ad-hoc[​](#running-electron-ad-hoc "Direct link to heading")
-----------------------------------------------------------------------------


If you're in a pinch and would prefer to not use `npm install` in your local project, you can also run Electron ad-hoc using the [`npx`](https://docs.npmjs.com/cli/v7/commands/npx) command runner bundled with `npm`:




```
npx electron .
```


The above command will run the current working directory with Electron. Note that any dependencies in your app will not be installed.


Customization[​](#customization "Direct link to heading")
---------------------------------------------------------


If you want to change the architecture that is downloaded (e.g., `ia32` on an `x64` machine), you can use the `--arch` flag with npm install or set the `npm_config_arch` environment variable:




```
npm install --arch=ia32 electron
```


In addition to changing the architecture, you can also specify the platform (e.g., `win32`, `linux`, etc.) using the `--platform` flag:




```
npm install --platform=win32 electron
```


Proxies[​](#proxies "Direct link to heading")
---------------------------------------------


If you need to use an HTTP proxy, you need to set the `ELECTRON_GET_USE_PROXY` variable to any value, plus additional environment variables depending on your host system's Node version:


* [Node 10 and above](https://github.com/gajus/global-agent/blob/v2.1.5/README.md#environment-variables)
* [Before Node 10](https://github.com/np-maintain/global-tunnel/blob/v2.7.1/README.md#auto-config)


Custom Mirrors and Caches[​](#custom-mirrors-and-caches "Direct link to heading")
---------------------------------------------------------------------------------


During installation, the `electron` module will call out to [`@electron/get`](https://github.com/electron/get) to download prebuilt binaries of Electron for your platform. It will do so by contacting GitHub's release download page (`https://github.com/electron/electron/releases/tag/v$VERSION`, where `$VERSION` is the exact version of Electron).


If you are unable to access GitHub or you need to provide a custom build, you can do so by either providing a mirror or an existing cache directory.


#### Mirror[​](#mirror "Direct link to heading")


You can use environment variables to override the base URL, the path at which to look for Electron binaries, and the binary filename. The URL used by `@electron/get` is composed as follows:




```
url = ELECTRON_MIRROR + ELECTRON_CUSTOM_DIR + '/' + ELECTRON_CUSTOM_FILENAME
```


For instance, to use the China CDN mirror:




```
ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
```


By default, `ELECTRON_CUSTOM_DIR` is set to `v$VERSION`. To change the format, use the `{{ version }}` placeholder. For example, `version-{{ version }}` resolves to `version-5.0.0`, `{{ version }}` resolves to `5.0.0`, and `v{{ version }}` is equivalent to the default. As a more concrete example, to use the China non-CDN mirror:




```
ELECTRON_MIRROR="https://npmmirror.com/mirrors/electron/"
ELECTRON_CUSTOM_DIR="{{ version }}"
```


The above configuration will download from URLs such as `https://npmmirror.com/mirrors/electron/8.0.0/electron-v8.0.0-linux-x64.zip`.


If your mirror serves artifacts with different checksums to the official Electron release you may have to set `electron_use_remote_checksums=1` to force Electron to use the remote `SHASUMS256.txt` file to verify the checksum instead of the embedded checksums.


#### Cache[​](#cache "Direct link to heading")


Alternatively, you can override the local cache. `@electron/get` will cache downloaded binaries in a local directory to not stress your network. You can use that cache folder to provide custom builds of Electron or to avoid making contact with the network at all.


* Linux: `$XDG_CACHE_HOME` or `~/.cache/electron/`
* macOS: `~/Library/Caches/electron/`
* Windows: `$LOCALAPPDATA/electron/Cache` or `~/AppData/Local/electron/Cache/`


On environments that have been using older versions of Electron, you might find the cache also in `~/.electron`.


You can also override the local cache location by providing a `electron_config_cache` environment variable.


The cache contains the version's official zip file as well as a checksum, and is stored as `[checksum]/[filename]`. A typical cache might look like this:




```
├── a91b089b5dc5b1279966511344b805ec84869b6cd60af44f800b363bba25b915
│   └── electron-v15.3.1-darwin-x64.zip
```


Skip binary download[​](#skip-binary-download "Direct link to heading")
-----------------------------------------------------------------------


Under the hood, Electron's JavaScript API binds to a binary that contains its implementations. Because this binary is crucial to the function of any Electron app, it is downloaded by default in the `postinstall` step every time you install `electron` from the npm registry.


However, if you want to install your project's dependencies but don't need to use Electron functionality, you can set the `ELECTRON_SKIP_BINARY_DOWNLOAD` environment variable to prevent the binary from being downloaded. For instance, this feature can be useful in continuous integration environments when running unit tests that mock out the `electron` module.



* npm
* Yarn





```
ELECTRON_SKIP_BINARY_DOWNLOAD=1 npm install
```




```
ELECTRON_SKIP_BINARY_DOWNLOAD=1 yarn install
```




Troubleshooting[​](#troubleshooting "Direct link to heading")
-------------------------------------------------------------


When running `npm install electron`, some users occasionally encounter installation errors.


In almost all cases, these errors are the result of network problems and not actual issues with the `electron` npm package. Errors like `ELIFECYCLE`, `EAI_AGAIN`, `ECONNRESET`, and `ETIMEDOUT` are all indications of such network problems. The best resolution is to try switching networks, or wait a bit and try installing again.


You can also attempt to download Electron directly from [electron/electron/releases](https://github.com/electron/electron/releases) if installing via `npm` is failing.


If installation fails with an `EACCESS` error you may need to [fix your npm permissions](https://docs.npmjs.com/getting-started/fixing-npm-permissions).


If the above error persists, the [unsafe-perm](https://docs.npmjs.com/misc/config#unsafe-perm) flag may need to be set to true:




```
sudo npm install electron --unsafe-perm=true
```


On slower networks, it may be advisable to use the `--verbose` flag in order to show download progress:




```
npm install --verbose electron
```


If you need to force a re-download of the asset and the SHASUM file set the `force_no_cache` environment variable to `true`.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/installation>

Security
========




Reporting security issues

For information on how to properly disclose an Electron vulnerability, see [SECURITY.md](https://github.com/electron/electron/tree/main/SECURITY.md).


For upstream Chromium vulnerabilities: Electron keeps up to date with alternating Chromium releases. For more information, see the [Electron Release Timelines](electron-timelines) document.




Preface[​](#preface "Direct link to heading")
---------------------------------------------


As web developers, we usually enjoy the strong security net of the browser — the risks associated with the code we write are relatively small. Our websites are granted limited powers in a sandbox, and we trust that our users enjoy a browser built by a large team of engineers that is able to quickly respond to newly discovered security threats.


When working with Electron, it is important to understand that Electron is not a web browser. It allows you to build feature-rich desktop applications with familiar web technologies, but your code wields much greater power. JavaScript can access the filesystem, user shell, and more. This allows you to build high quality native applications, but the inherent security risks scale with the additional powers granted to your code.


With that in mind, be aware that displaying arbitrary content from untrusted sources poses a severe security risk that Electron is not intended to handle. In fact, the most popular Electron apps (Atom, Slack, Visual Studio Code, etc) display primarily local content (or trusted, secure remote content without Node integration) — if your application executes code from an online source, it is your responsibility to ensure that the code is not malicious.


General guidelines[​](#general-guidelines "Direct link to heading")
-------------------------------------------------------------------


### Security is everyone's responsibility[​](#security-is-everyones-responsibility "Direct link to heading")


It is important to remember that the security of your Electron application is the result of the overall security of the framework foundation (*Chromium*, *Node.js*), Electron itself, all NPM dependencies and your code. As such, it is your responsibility to follow a few important best practices:


* **Keep your application up-to-date with the latest Electron framework release.** When releasing your product, you’re also shipping a bundle composed of Electron, Chromium shared library and Node.js. Vulnerabilities affecting these components may impact the security of your application. By updating Electron to the latest version, you ensure that critical vulnerabilities (such as *nodeIntegration bypasses*) are already patched and cannot be exploited in your application. For more information, see "[Use a current version of Electron](#16-use-a-current-version-of-electron)".
* **Evaluate your dependencies.** While NPM provides half a million reusable packages, it is your responsibility to choose trusted 3rd-party libraries. If you use outdated libraries affected by known vulnerabilities or rely on poorly maintained code, your application security could be in jeopardy.
* **Adopt secure coding practices.** The first line of defense for your application is your own code. Common web vulnerabilities, such as Cross-Site Scripting (XSS), have a higher security impact on Electron applications hence it is highly recommended to adopt secure software development best practices and perform security testing.


### Isolation for untrusted content[​](#isolation-for-untrusted-content "Direct link to heading")


A security issue exists whenever you receive code from an untrusted source (e.g. a remote server) and execute it locally. As an example, consider a remote website being displayed inside a default [`BrowserWindow`](../api/browser-window). If an attacker somehow manages to change said content (either by attacking the source directly, or by sitting between your app and the actual destination), they will be able to execute native code on the user's machine.




danger
Under no circumstances should you load and execute remote code with Node.js integration enabled. Instead, use only local files (packaged together with your application) to execute Node.js code. To display remote content, use the [`<webview>`](../api/webview-tag) tag or [`BrowserView`](../api/browser-view), make sure to disable the `nodeIntegration` and enable `contextIsolation`.





Electron security warnings

Security warnings and recommendations are printed to the developer console. They only show up when the binary's name is Electron, indicating that a developer is currently looking at the console.


You can force-enable or force-disable these warnings by setting `ELECTRON_ENABLE_SECURITY_WARNINGS` or `ELECTRON_DISABLE_SECURITY_WARNINGS` on either `process.env` or the `window` object.




Checklist: Security recommendations[​](#checklist-security-recommendations "Direct link to heading")
----------------------------------------------------------------------------------------------------


You should at least follow these steps to improve the security of your application:


1. [Only load secure content](#1-only-load-secure-content)
2. [Disable the Node.js integration in all renderers that display remote content](#2-do-not-enable-nodejs-integration-for-remote-content)
3. [Enable context isolation in all renderers](#3-enable-context-isolation)
4. [Enable process sandboxing](#4-enable-process-sandboxing)
5. [Use `ses.setPermissionRequestHandler()` in all sessions that load remote content](#5-handle-session-permission-requests-from-remote-content)
6. [Do not disable `webSecurity`](#6-do-not-disable-websecurity)
7. [Define a `Content-Security-Policy`](#7-define-a-content-security-policy) and use restrictive rules (i.e. `script-src 'self'`)
8. [Do not enable `allowRunningInsecureContent`](#8-do-not-enable-allowrunninginsecurecontent)
9. [Do not enable experimental features](#9-do-not-enable-experimental-features)
10. [Do not use `enableBlinkFeatures`](#10-do-not-use-enableblinkfeatures)
11. [`<webview>`: Do not use `allowpopups`](#11-do-not-use-allowpopups-for-webviews)
12. [`<webview>`: Verify options and params](#12-verify-webview-options-before-creation)
13. [Disable or limit navigation](#13-disable-or-limit-navigation)
14. [Disable or limit creation of new windows](#14-disable-or-limit-creation-of-new-windows)
15. [Do not use `shell.openExternal` with untrusted content](#15-do-not-use-shellopenexternal-with-untrusted-content)
16. [Use a current version of Electron](#16-use-a-current-version-of-electron)


To automate the detection of misconfigurations and insecure patterns, it is possible to use [Electronegativity](https://github.com/doyensec/electronegativity). For additional details on potential weaknesses and implementation bugs when developing applications using Electron, please refer to this [guide for developers and auditors](https://doyensec.com/resources/us-17-Carettoni-Electronegativity-A-Study-Of-Electron-Security-wp.pdf).


### 1. Only load secure content[​](#1-only-load-secure-content "Direct link to heading")


Any resources not included with your application should be loaded using a secure protocol like `HTTPS`. In other words, do not use insecure protocols like `HTTP`. Similarly, we recommend the use of `WSS` over `WS`, `FTPS` over `FTP`, and so on.


#### Why?[​](#why "Direct link to heading")


`HTTPS` has three main benefits:


1. It authenticates the remote server, ensuring your app connects to the correct host instead of an impersonator.
2. It ensures data integrity, asserting that the data was not modified while in transit between your application and the host.
3. It encrypts the traffic between your user and the destination host, making it more difficult to eavesdrop on the information sent between your app and the host.


#### How?[​](#how "Direct link to heading")



main.js (Main Process)


```
// Bad
browserWindow.loadURL('http://example.com')

// Good
browserWindow.loadURL('https://example.com')
```




index.html (Renderer Process)


```
<!-- Bad -->
<script crossorigin src="http://example.com/react.js"></script>
<link rel="stylesheet" href="http://example.com/style.css">

<!-- Good -->
<script crossorigin src="https://example.com/react.js"></script>
<link rel="stylesheet" href="https://example.com/style.css">
```



### 2. Do not enable Node.js integration for remote content[​](#2-do-not-enable-nodejs-integration-for-remote-content "Direct link to heading")




info
This recommendation is the default behavior in Electron since 5.0.0.



It is paramount that you do not enable Node.js integration in any renderer ([`BrowserWindow`](../api/browser-window), [`BrowserView`](../api/browser-view), or [`<webview>`](../api/webview-tag)) that loads remote content. The goal is to limit the powers you grant to remote content, thus making it dramatically more difficult for an attacker to harm your users should they gain the ability to execute JavaScript on your website.


After this, you can grant additional permissions for specific hosts. For example, if you are opening a BrowserWindow pointed at `https://example.com/`, you can give that website exactly the abilities it needs, but no more.


#### Why?[​](#why-1 "Direct link to heading")


A cross-site-scripting (XSS) attack is more dangerous if an attacker can jump out of the renderer process and execute code on the user's computer. Cross-site-scripting attacks are fairly common - and while an issue, their power is usually limited to messing with the website that they are executed on. Disabling Node.js integration helps prevent an XSS from being escalated into a so-called "Remote Code Execution" (RCE) attack.


#### How?[​](#how-1 "Direct link to heading")



main.js (Main Process)


```
// Bad
const mainWindow = new BrowserWindow({
  webPreferences: {
    contextIsolation: false,
    nodeIntegration: true,
    nodeIntegrationInWorker: true
  }
})

mainWindow.loadURL('https://example.com')
```




main.js (Main Process)


```
// Good
const mainWindow = new BrowserWindow({
  webPreferences: {
    preload: path.join(app.getAppPath(), 'preload.js')
  }
})

mainWindow.loadURL('https://example.com')
```




index.html (Renderer Process)


```
<!-- Bad -->
<webview nodeIntegration src="page.html"></webview>

<!-- Good -->
<webview src="page.html"></webview>
```



When disabling Node.js integration, you can still expose APIs to your website that do consume Node.js modules or features. Preload scripts continue to have access to `require` and other Node.js features, allowing developers to expose a custom API to remotely loaded content via the [contextBridge API](../api/context-bridge).


### 3. Enable Context Isolation[​](#3-enable-context-isolation "Direct link to heading")




info
This recommendation is the default behavior in Electron since 12.0.0.



Context isolation is an Electron feature that allows developers to run code in preload scripts and in Electron APIs in a dedicated JavaScript context. In practice, that means that global objects like `Array.prototype.push` or `JSON.parse` cannot be modified by scripts running in the renderer process.


Electron uses the same technology as Chromium's [Content Scripts](https://developer.chrome.com/extensions/content_scripts#execution-environment) to enable this behavior.


Even when `nodeIntegration: false` is used, to truly enforce strong isolation and prevent the use of Node primitives `contextIsolation` **must** also be used.




info
For more information on what `contextIsolation` is and how to enable it please see our dedicated [Context Isolation](context-isolation) document.



### 4. Enable process sandboxing[​](#4-enable-process-sandboxing "Direct link to heading")


[Sandboxing](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/design/sandbox.md) is a Chromium feature that uses the operating system to significantly limit what renderer processes have access to. You should enable the sandbox in all renderers. Loading, reading or processing any untrusted content in an unsandboxed process, including the main process, is not advised.




info
For more information on what `contextIsolation` is and how to enable it please see our dedicated [Process Sandboxing](sandbox) document.



### 5. Handle session permission requests from remote content[​](#5-handle-session-permission-requests-from-remote-content "Direct link to heading")


You may have seen permission requests while using Chrome: they pop up whenever the website attempts to use a feature that the user has to manually approve ( like notifications).


The API is based on the [Chromium permissions API](https://developer.chrome.com/extensions/permissions) and implements the same types of permissions.


#### Why?[​](#why-2 "Direct link to heading")


By default, Electron will automatically approve all permission requests unless the developer has manually configured a custom handler. While a solid default, security-conscious developers might want to assume the very opposite.


#### How?[​](#how-2 "Direct link to heading")



main.js (Main Process)


```
const { session } = require('electron')
const URL = require('url').URL

session
  .fromPartition('some-partition')
  .setPermissionRequestHandler((webContents, permission, callback) => {
    const parsedUrl = new URL(webContents.getURL())

    if (permission === 'notifications') {
      // Approves the permissions request
      callback(true)
    }

    // Verify URL
    if (parsedUrl.protocol !== 'https:' || parsedUrl.host !== 'example.com') {
      // Denies the permissions request
      return callback(false)
    }
  })
```



### 6. Do not disable `webSecurity`[​](#6-do-not-disable-websecurity "Direct link to heading")




info
This recommendation is Electron's default.



You may have already guessed that disabling the `webSecurity` property on a renderer process ([`BrowserWindow`](../api/browser-window), [`BrowserView`](../api/browser-view), or [`<webview>`](../api/webview-tag)) disables crucial security features.


Do not disable `webSecurity` in production applications.


#### Why?[​](#why-3 "Direct link to heading")


Disabling `webSecurity` will disable the same-origin policy and set `allowRunningInsecureContent` property to `true`. In other words, it allows the execution of insecure code from different domains.


#### How?[​](#how-3 "Direct link to heading")



main.js (Main Process)


```
// Bad
const mainWindow = new BrowserWindow({
  webPreferences: {
    webSecurity: false
  }
})
```




main.js (Main Process)


```
// Good
const mainWindow = new BrowserWindow()
```




index.html (Renderer Process)


```
<!-- Bad -->
<webview disablewebsecurity src="page.html"></webview>

<!-- Good -->
<webview src="page.html"></webview>
```



### 7. Define a Content Security Policy[​](#7-define-a-content-security-policy "Direct link to heading")


A Content Security Policy (CSP) is an additional layer of protection against cross-site-scripting attacks and data injection attacks. We recommend that they be enabled by any website you load inside Electron.


#### Why?[​](#why-4 "Direct link to heading")


CSP allows the server serving content to restrict and control the resources Electron can load for that given web page. `https://example.com` should be allowed to load scripts from the origins you defined while scripts from `https://evil.attacker.com` should not be allowed to run. Defining a CSP is an easy way to improve your application's security.


#### How?[​](#how-4 "Direct link to heading")


The following CSP will allow Electron to execute scripts from the current website and from `apis.example.com`.




```
// Bad
Content-Security-Policy: '*'

// Good
Content-Security-Policy: script-src 'self' https://apis.example.com
```


#### CSP HTTP headers[​](#csp-http-headers "Direct link to heading")


Electron respects the [`Content-Security-Policy` HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy) which can be set using Electron's [`webRequest.onHeadersReceived`](../api/web-request#webrequestonheadersreceivedfilter-listener) handler:



main.js (Main Process)


```
const { session } = require('electron')

session.defaultSession.webRequest.onHeadersReceived((details, callback) => {
  callback({
    responseHeaders: {
      ...details.responseHeaders,
      'Content-Security-Policy': ['default-src \'none\'']
    }
  })
})
```



#### CSP meta tag[​](#csp-meta-tag "Direct link to heading")


CSP's preferred delivery mechanism is an HTTP header. However, it is not possible to use this method when loading a resource using the `file://` protocol. It can be useful in some cases to set a policy on a page directly in the markup using a `<meta>` tag:



index.html (Renderer Process)


```
<meta http-equiv="Content-Security-Policy" content="default-src 'none'">
```



### 8. Do not enable `allowRunningInsecureContent`[​](#8-do-not-enable-allowrunninginsecurecontent "Direct link to heading")




info
This recommendation is Electron's default.



By default, Electron will not allow websites loaded over `HTTPS` to load and execute scripts, CSS, or plugins from insecure sources (`HTTP`). Setting the property `allowRunningInsecureContent` to `true` disables that protection.


Loading the initial HTML of a website over `HTTPS` and attempting to load subsequent resources via `HTTP` is also known as "mixed content".


#### Why?[​](#why-5 "Direct link to heading")


Loading content over `HTTPS` assures the authenticity and integrity of the loaded resources while encrypting the traffic itself. See the section on [only displaying secure content](#1-only-load-secure-content) for more details.


#### How?[​](#how-5 "Direct link to heading")



main.js (Main Process)


```
// Bad
const mainWindow = new BrowserWindow({
  webPreferences: {
    allowRunningInsecureContent: true
  }
})
```




main.js (Main Process)


```
// Good
const mainWindow = new BrowserWindow({})
```



### 9. Do not enable experimental features[​](#9-do-not-enable-experimental-features "Direct link to heading")




info
This recommendation is Electron's default.



Advanced users of Electron can enable experimental Chromium features using the `experimentalFeatures` property.


#### Why?[​](#why-6 "Direct link to heading")


Experimental features are, as the name suggests, experimental and have not been enabled for all Chromium users. Furthermore, their impact on Electron as a whole has likely not been tested.


Legitimate use cases exist, but unless you know what you are doing, you should not enable this property.


#### How?[​](#how-6 "Direct link to heading")



main.js (Main Process)


```
// Bad
const mainWindow = new BrowserWindow({
  webPreferences: {
    experimentalFeatures: true
  }
})
```




main.js (Main Process)


```
// Good
const mainWindow = new BrowserWindow({})
```



### 10. Do not use `enableBlinkFeatures`[​](#10-do-not-use-enableblinkfeatures "Direct link to heading")




info
This recommendation is Electron's default.



Blink is the name of the rendering engine behind Chromium. As with `experimentalFeatures`, the `enableBlinkFeatures` property allows developers to enable features that have been disabled by default.


#### Why?[​](#why-7 "Direct link to heading")


Generally speaking, there are likely good reasons if a feature was not enabled by default. Legitimate use cases for enabling specific features exist. As a developer, you should know exactly why you need to enable a feature, what the ramifications are, and how it impacts the security of your application. Under no circumstances should you enable features speculatively.


#### How?[​](#how-7 "Direct link to heading")



main.js (Main Process)


```
// Bad
const mainWindow = new BrowserWindow({
  webPreferences: {
    enableBlinkFeatures: 'ExecCommandInJavaScript'
  }
})
```




main.js (Main Process)


```
// Good
const mainWindow = new BrowserWindow()
```



### 11. Do not use `allowpopups` for WebViews[​](#11-do-not-use-allowpopups-for-webviews "Direct link to heading")




info
This recommendation is Electron's default.



If you are using [`<webview>`](../api/webview-tag), you might need the pages and scripts loaded in your `<webview>` tag to open new windows. The `allowpopups` attribute enables them to create new [`BrowserWindows`](../api/browser-window) using the `window.open()` method. `<webview>` tags are otherwise not allowed to create new windows.


#### Why?[​](#why-8 "Direct link to heading")


If you do not need popups, you are better off not allowing the creation of new [`BrowserWindows`](../api/browser-window) by default. This follows the principle of minimally required access: Don't let a website create new popups unless you know it needs that feature.


#### How?[​](#how-8 "Direct link to heading")



index.html (Renderer Process)


```
<!-- Bad -->
<webview allowpopups src="page.html"></webview>

<!-- Good -->
<webview src="page.html"></webview>
```



### 12. Verify WebView options before creation[​](#12-verify-webview-options-before-creation "Direct link to heading")


A WebView created in a renderer process that does not have Node.js integration enabled will not be able to enable integration itself. However, a WebView will always create an independent renderer process with its own `webPreferences`.


It is a good idea to control the creation of new [`<webview>`](../api/webview-tag) tags from the main process and to verify that their webPreferences do not disable security features.


#### Why?[​](#why-9 "Direct link to heading")


Since `<webview>` live in the DOM, they can be created by a script running on your website even if Node.js integration is otherwise disabled.


Electron enables developers to disable various security features that control a renderer process. In most cases, developers do not need to disable any of those features - and you should therefore not allow different configurations for newly created [`<webview>`](../api/webview-tag) tags.


#### How?[​](#how-9 "Direct link to heading")


Before a [`<webview>`](../api/webview-tag) tag is attached, Electron will fire the `will-attach-webview` event on the hosting `webContents`. Use the event to prevent the creation of `webViews` with possibly insecure options.



main.js (Main Process)


```
app.on('web-contents-created', (event, contents) => {
  contents.on('will-attach-webview', (event, webPreferences, params) => {
    // Strip away preload scripts if unused or verify their location is legitimate
    delete webPreferences.preload

    // Disable Node.js integration
    webPreferences.nodeIntegration = false

    // Verify URL being loaded
    if (!params.src.startsWith('https://example.com/')) {
      event.preventDefault()
    }
  })
})
```



Again, this list merely minimizes the risk, but does not remove it. If your goal is to display a website, a browser will be a more secure option.


### 13. Disable or limit navigation[​](#13-disable-or-limit-navigation "Direct link to heading")


If your app has no need to navigate or only needs to navigate to known pages, it is a good idea to limit navigation outright to that known scope, disallowing any other kinds of navigation.


#### Why?[​](#why-10 "Direct link to heading")


Navigation is a common attack vector. If an attacker can convince your app to navigate away from its current page, they can possibly force your app to open web sites on the Internet. Even if your `webContents` are configured to be more secure (like having `nodeIntegration` disabled or `contextIsolation` enabled), getting your app to open a random web site will make the work of exploiting your app a lot easier.


A common attack pattern is that the attacker convinces your app's users to interact with the app in such a way that it navigates to one of the attacker's pages. This is usually done via links, plugins, or other user-generated content.


#### How?[​](#how-10 "Direct link to heading")


If your app has no need for navigation, you can call `event.preventDefault()` in a [`will-navigate`](../api/web-contents#event-will-navigate) handler. If you know which pages your app might navigate to, check the URL in the event handler and only let navigation occur if it matches the URLs you're expecting.


We recommend that you use Node's parser for URLs. Simple string comparisons can sometimes be fooled - a `startsWith('https://example.com')` test would let `https://example.com.attacker.com` through.



main.js (Main Process)


```
const URL = require('url').URL

app.on('web-contents-created', (event, contents) => {
  contents.on('will-navigate', (event, navigationUrl) => {
    const parsedUrl = new URL(navigationUrl)

    if (parsedUrl.origin !== 'https://example.com') {
      event.preventDefault()
    }
  })
})
```



### 14. Disable or limit creation of new windows[​](#14-disable-or-limit-creation-of-new-windows "Direct link to heading")


If you have a known set of windows, it's a good idea to limit the creation of additional windows in your app.


#### Why?[​](#why-11 "Direct link to heading")


Much like navigation, the creation of new `webContents` is a common attack vector. Attackers attempt to convince your app to create new windows, frames, or other renderer processes with more privileges than they had before; or with pages opened that they couldn't open before.


If you have no need to create windows in addition to the ones you know you'll need to create, disabling the creation buys you a little bit of extra security at no cost. This is commonly the case for apps that open one `BrowserWindow` and do not need to open an arbitrary number of additional windows at runtime.


#### How?[​](#how-11 "Direct link to heading")


[`webContents`](../api/web-contents) will delegate to its [window open handler](../api/web-contents#contentssetwindowopenhandlerhandler) before creating new windows. The handler will receive, amongst other parameters, the `url` the window was requested to open and the options used to create it. We recommend that you register a handler to monitor the creation of windows, and deny any unexpected window creation.



main.js (Main Process)


```
const { shell } = require('electron')

app.on('web-contents-created', (event, contents) => {
  contents.setWindowOpenHandler(({ url }) => {
    // In this example, we'll ask the operating system
    // to open this event's url in the default browser.
    //
    // See the following item for considerations regarding what
    // URLs should be allowed through to shell.openExternal.
    if (isSafeForExternalOpen(url)) {
      setImmediate(() => {
        shell.openExternal(url)
      })
    }

    return { action: 'deny' }
  })
})
```



### 15. Do not use `shell.openExternal` with untrusted content[​](#15-do-not-use-shellopenexternal-with-untrusted-content "Direct link to heading")


The shell module's [`openExternal`](../api/shell#shellopenexternalurl-options) API allows opening a given protocol URI with the desktop's native utilities. On macOS, for instance, this function is similar to the `open` terminal command utility and will open the specific application based on the URI and filetype association.


#### Why?[​](#why-12 "Direct link to heading")


Improper use of [`openExternal`](../api/shell#shellopenexternalurl-options) can be leveraged to compromise the user's host. When openExternal is used with untrusted content, it can be leveraged to execute arbitrary commands.


#### How?[​](#how-12 "Direct link to heading")



main.js (Main Process)


```
//  Bad
const { shell } = require('electron')
shell.openExternal(USER_CONTROLLED_DATA_HERE)
```




main.js (Main Process)


```
//  Good
const { shell } = require('electron')
shell.openExternal('https://example.com/index.html')
```



### 16. Use a current version of Electron[​](#16-use-a-current-version-of-electron "Direct link to heading")


You should strive for always using the latest available version of Electron. Whenever a new major version is released, you should attempt to update your app as quickly as possible.


#### Why?[​](#why-13 "Direct link to heading")


An application built with an older version of Electron, Chromium, and Node.js is an easier target than an application that is using more recent versions of those components. Generally speaking, security issues and exploits for older versions of Chromium and Node.js are more widely available.


Both Chromium and Node.js are impressive feats of engineering built by thousands of talented developers. Given their popularity, their security is carefully tested and analyzed by equally skilled security researchers. Many of those researchers [disclose vulnerabilities responsibly](https://en.wikipedia.org/wiki/Responsible_disclosure), which generally means that researchers will give Chromium and Node.js some time to fix issues before publishing them. Your application will be more secure if it is running a recent version of Electron (and thus, Chromium and Node.js) for which potential security issues are not as widely known.


#### How?[​](#how-13 "Direct link to heading")


Migrate your app one major version at a time, while referring to Electron's [Breaking Changes](../breaking-changes) document to see if any code needs to be updated.


### 17. Validate the `sender` of all IPC messages[​](#17-validate-the-sender-of-all-ipc-messages "Direct link to heading")


You should always validate incoming IPC messages `sender` property to ensure you aren't performing actions or sending information to untrusted renderers.


#### Why?[​](#why-14 "Direct link to heading")


All Web Frames can in theory send IPC messages to the main process, including iframes and child windows in some scenarios. If you have an IPC message that returns user data to the sender via `event.reply` or performs privileged actions that the renderer can't natively, you should ensure you aren't listening to third party web frames.


You should be validating the `sender` of **all** IPC messages by default.


#### How?[​](#how-14 "Direct link to heading")



main.js (Main Process)


```
// Bad
ipcMain.handle('get-secrets', () => {
  return getSecrets();
});

// Good
ipcMain.handle('get-secrets', (e) => {
  if (!validateSender(e.senderFrame)) return null;
  return getSecrets();
});

function validateSender(frame) {
  // Value the host of the URL using an actual URL parser and an allowlist
  if ((new URL(frame.url)).host === 'electronjs.org') return true;
  return false;
}
```




 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/security>

Adding Features
===============



Follow along the tutorial

This is **part 4** of the Electron tutorial.


1. [Prerequisites](tutorial-prerequisites)
2. [Building your First App](tutorial-first-app)
3. [Using Preload Scripts](tutorial-preload)
4. **[Adding Features](tutorial-adding-features)**
5. [Packaging Your Application](tutorial-packaging)
6. [Publishing and Updating](tutorial-publishing-updating)




Adding application complexity[​](#adding-application-complexity "Direct link to heading")
-----------------------------------------------------------------------------------------


If you have been following along, you should have a functional Electron application with a static user interface. From this starting point, you can generally progress in developing your app in two broad directions:


1. Adding complexity to your renderer process' web app code
2. Deeper integrations with the operating system and Node.js


It is important to understand the distinction between these two broad concepts. For the first point, Electron-specific resources are not necessary. Building a pretty to-do list in Electron is just pointing your Electron BrowserWindow to a pretty to-do list web app. Ultimately, you are building your renderer's UI using the same tools (HTML, CSS, JavaScript) that you would on the web. Therefore, Electron's docs will not go in-depth on how to use standard web tools.


On the other hand, Electron also provides a rich set of tools that allow you to integrate with the desktop environment, from creating tray icons to adding global shortcuts to displaying native menus. It also gives you all the power of a Node.js environment in the main process. This set of capabilities separates Electron applications from running a website in a browser tab, and are the focus of Electron's documentation.


How-to examples[​](#how-to-examples "Direct link to heading")
-------------------------------------------------------------


Electron's documentation has many tutorials to help you with more advanced topics and deeper operating system integrations. To get started, check out the [How-To Examples](examples) doc.




Let us know if something is missing!
If you can't find what you are looking for, please let us know on [GitHub](https://github.com/electron/electronjs.org-new/issues/new) or in our [Discord server](https://discord.com/invite/APGC3k5yaH)!



What's next?[​](#whats-next "Direct link to heading")
-----------------------------------------------------


For the rest of the tutorial, we will be shifting away from application code and giving you a look at how you can get your app from your developer machine into end users' hands.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/tutorial-adding-features>

Task Object
===========


* `program` string - Path of the program to execute, usually you should specify `process.execPath` which opens the current program.
* `arguments` string - The command line arguments when `program` is executed.
* `title` string - The string to be displayed in a JumpList.
* `description` string - Description of this task.
* `iconPath` string - The absolute path to an icon to be displayed in a JumpList, which can be an arbitrary resource file that contains an icon. You can usually specify `process.execPath` to show the icon of the program.
* `iconIndex` number - The icon index in the icon file. If an icon file consists of two or more icons, set this value to identify the icon. If an icon file consists of one icon, this value is 0.
* `workingDirectory` string (optional) - The working directory. Default is empty.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/task>

Glossary
========


This page defines some terminology that is commonly used in Electron development.


### ASAR[​](#asar "Direct link to heading")


ASAR stands for Atom Shell Archive Format. An [asar](https://github.com/electron/asar) archive is a simple `tar`-like format that concatenates files into a single file. Electron can read arbitrary files from it without unpacking the whole file.


The ASAR format was created primarily to improve performance on Windows when reading large quantities of small files (e.g. when loading your app's JavaScript dependency tree from `node_modules`).


### code signing[​](#code-signing "Direct link to heading")


Code signing is a process where an app developer digitally signs their code to ensure that it hasn't been tampered with after packaging. Both Windows and macOS implement their own version of code signing. As a desktop app developer, it's important that you sign your code if you plan on distributing it to the general public.


For more information, read the [Code Signing](tutorial/code-signing) tutorial.


### context isolation[​](#context-isolation "Direct link to heading")


Context isolation is a security measure in Electron that ensures that your preload script cannot leak privileged Electron or Node.js APIs to the web contents in your renderer process. With context isolation enabled, the only way to expose APIs from your preload script is through the `contextBridge` API.


For more information, read the [Context Isolation](tutorial/context-isolation) tutorial.


See also: [preload script](#preload-script), [renderer process](#renderer-process)


### CRT[​](#crt "Direct link to heading")


The C Runtime Library (CRT) is the part of the C++ Standard Library that incorporates the ISO C99 standard library. The Visual C++ libraries that implement the CRT support native code development, and both mixed native and managed code, and pure managed code for .NET development.


### DMG[​](#dmg "Direct link to heading")


An Apple Disk Image is a packaging format used by macOS. DMG files are commonly used for distributing application "installers".


### IME[​](#ime "Direct link to heading")


Input Method Editor. A program that allows users to enter characters and symbols not found on their keyboard. For example, this allows users of Latin keyboards to input Chinese, Japanese, Korean and Indic characters.


### IDL[​](#idl "Direct link to heading")


Interface description language. Write function signatures and data types in a format that can be used to generate interfaces in Java, C++, JavaScript, etc.


### IPC[​](#ipc "Direct link to heading")


IPC stands for inter-process communication. Electron uses IPC to send serialized JSON messages between the main and renderer processes.


see also: [main process](#main-process), [renderer process](#renderer-process)


### main process[​](#main-process "Direct link to heading")


The main process, commonly a file named `main.js`, is the entry point to every Electron app. It controls the life of the app, from open to close. It also manages native elements such as the Menu, Menu Bar, Dock, Tray, etc. The main process is responsible for creating each new renderer process in the app. The full Node API is built in.


Every app's main process file is specified in the `main` property in `package.json`. This is how `electron .` knows what file to execute at startup.


In Chromium, this process is referred to as the "browser process". It is renamed in Electron to avoid confusion with renderer processes.


See also: [process](#process), [renderer process](#renderer-process)


### MAS[​](#mas "Direct link to heading")


Acronym for Apple's Mac App Store. For details on submitting your app to the MAS, see the [Mac App Store Submission Guide](tutorial/mac-app-store-submission-guide).


### Mojo[​](#mojo "Direct link to heading")


An IPC system for communicating intra- or inter-process, and that's important because Chrome is keen on being able to split its work into separate processes or not, depending on memory pressures etc.


See <https://chromium.googlesource.com/chromium/src/+/main/mojo/README.md>


See also: [IPC](#ipc)


### MSI[​](#msi "Direct link to heading")


On Windows, MSI packages are used by the Windows Installer (also known as Microsoft Installer) service to install and configure applications.


More information can be found in [Microsoft's documentation](https://docs.microsoft.com/en-us/windows/win32/msi/windows-installer-portal).


### native modules[​](#native-modules "Direct link to heading")


Native modules (also called [addons](https://nodejs.org/api/addons.html) in Node.js) are modules written in C or C++ that can be loaded into Node.js or Electron using the require() function, and used as if they were an ordinary Node.js module. They are used primarily to provide an interface between JavaScript running in Node.js and C/C++ libraries.


Native Node modules are supported by Electron, but since Electron is very likely to use a different V8 version from the Node binary installed in your system, you have to manually specify the location of Electron’s headers when building native modules.


For more information, read the [Native Node Modules] tutorial.


### notarization[​](#notarization "Direct link to heading")


Notarization is a macOS-specific process where a developer can send a code-signed app to Apple servers to get verified for malicious components through an automated service.


See also: [code signing](#code-signing)


### OSR[​](#osr "Direct link to heading")


OSR (offscreen rendering) can be used for loading heavy page in background and then displaying it after (it will be much faster). It allows you to render page without showing it on screen.


For more information, read the [Offscreen Rendering][osr] tutorial.


### preload script[​](#preload-script "Direct link to heading")


Preload scripts contain code that executes in a renderer process before its web contents begin loading. These scripts run within the renderer context, but are granted more privileges by having access to Node.js APIs.


See also: [renderer process](#renderer-process), [context isolation](#context-isolation)


### process[​](#process "Direct link to heading")


A process is an instance of a computer program that is being executed. Electron apps that make use of the [main](#main-process) and one or many [renderer](#renderer-process) process are actually running several programs simultaneously.


In Node.js and Electron, each running process has a `process` object. This object is a global that provides information about, and control over, the current process. As a global, it is always available to applications without using require().


See also: [main process](#main-process), [renderer process](#renderer-process)


### renderer process[​](#renderer-process "Direct link to heading")


The renderer process is a browser window in your app. Unlike the main process, there can be multiple of these and each is run in a separate process. They can also be hidden.


See also: [process](#process), [main process](#main-process)


### sandbox[​](#sandbox "Direct link to heading")


The sandbox is a security feature inherited from Chromium that restricts your renderer processes to a limited set of permissions.


For more information, read the [Process Sandboxing](tutorial/sandbox) tutorial.


See also: [process](#process)


### Squirrel[​](#squirrel "Direct link to heading")


Squirrel is an open-source framework that enables Electron apps to update automatically as new versions are released. See the [autoUpdater](api/auto-updater) API for info about getting started with Squirrel.


### userland[​](#userland "Direct link to heading")


This term originated in the Unix community, where "userland" or "userspace" referred to programs that run outside of the operating system kernel. More recently, the term has been popularized in the Node and npm community to distinguish between the features available in "Node core" versus packages published to the npm registry by the much larger "user" community.


Like Node, Electron is focused on having a small set of APIs that provide all the necessary primitives for developing multi-platform desktop applications. This design philosophy allows Electron to remain a flexible tool without being overly prescriptive about how it should be used. Userland enables users to create and share tools that provide additional functionality on top of what is available in "core".


### V8[​](#v8 "Direct link to heading")


V8 is Google's open source JavaScript engine. It is written in C++ and is used in Google Chrome. V8 can run standalone, or can be embedded into any C++ application.


Electron builds V8 as part of Chromium and then points Node to that V8 when building it.


V8's version numbers always correspond to those of Google Chrome. Chrome 59 includes V8 5.9, Chrome 58 includes V8 5.8, etc.


* [v8.dev](https://v8.dev/)
* [nodejs.org/api/v8.html](https://nodejs.org/api/v8.html)
* [docs/development/v8-development.md](development/v8-development)


### webview[​](#webview "Direct link to heading")


`webview` tags are used to embed 'guest' content (such as external web pages) in your Electron app. They are similar to `iframe`s, but differ in that each webview runs in a separate process. It doesn't have the same permissions as your web page and all interactions between your app and embedded content will be asynchronous. This keeps your app safe from the embedded content.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/glossary>

ProcessMetric Object
====================


* `pid` Integer - Process id of the process.
* `type` string - Process type. One of the following values:
	+ `Browser`
	+ `Tab`
	+ `Utility`
	+ `Zygote`
	+ `Sandbox helper`
	+ `GPU`
	+ `Pepper Plugin`
	+ `Pepper Plugin Broker`
	+ `Unknown`
* `serviceName` string (optional) - The non-localized name of the process.
* `name` string (optional) - The name of the process. Examples for utility: `Audio Service`, `Content Decryption Module Service`, `Network Service`, `Video Capture`, etc.
* `cpu` [CPUUsage](cpu-usage) - CPU usage of the process.
* `creationTime` number - Creation time for this process. The time is represented as number of milliseconds since epoch. Since the `pid` can be reused after a process dies, it is useful to use both the `pid` and the `creationTime` to uniquely identify a process.
* `memory` [MemoryInfo](memory-info) - Memory information for the process.
* `sandboxed` boolean (optional) *macOS* *Windows* - Whether the process is sandboxed on OS level.
* `integrityLevel` string (optional) *Windows* - One of the following values:
	+ `untrusted`
	+ `low`
	+ `medium`
	+ `high`
	+ `unknown`



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/process-metric>

Building your First App
=======================



Follow along the tutorial

This is **part 2** of the Electron tutorial.


1. [Prerequisites](tutorial-prerequisites)
2. **[Building your First App](tutorial-first-app)**
3. [Using Preload Scripts](tutorial-preload)
4. [Adding Features](tutorial-adding-features)
5. [Packaging Your Application](tutorial-packaging)
6. [Publishing and Updating](tutorial-publishing-updating)




Learning goals[​](#learning-goals "Direct link to heading")
-----------------------------------------------------------


In this part of the tutorial, you will learn how to set up your Electron project and write a minimal starter application. By the end of this section, you should be able to run a working Electron app in development mode from your terminal.


Setting up your project[​](#setting-up-your-project "Direct link to heading")
-----------------------------------------------------------------------------




Avoid WSL
If you are on a Windows machine, please do not use [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/about#what-is-wsl-2) (WSL) when following this tutorial as you will run into issues when trying to execute the application.



### Initializing your npm project[​](#initializing-your-npm-project "Direct link to heading")


Electron apps are scaffolded using npm, with the package.json file as an entry point. Start by creating a folder and initializing an npm package within it with `npm init`.



* npm
* Yarn





```
mkdir my-electron-app && cd my-electron-app
npm init
```




```
mkdir my-electron-app && cd my-electron-app
yarn init
```




This command will prompt you to configure some fields in your package.json. There are a few rules to follow for the purposes of this tutorial:


* *entry point* should be `main.js` (you will be creating that file soon).
* *author*, *license*, and *description* can be any value, but will be necessary for [packaging](tutorial-packaging) later on.


Then, install Electron into your app's **devDependencies**, which is the list of external development-only package dependencies not required in production.




Why is Electron a devDependency?
This may seem counter-intuitive since your production code is running Electron APIs. However, packaged apps will come bundled with the Electron binary, eliminating the need to specify it as a production dependency.




* npm
* Yarn





```
npm install electron --save-dev
```




```
yarn add electron --dev
```




Your package.json file should look something like this after initializing your package and installing Electron. You should also now have a `node_modules` folder containing the Electron executable, as well as a `package-lock.json` lockfile that specifies the exact dependency versions to install.



package.json


```
{
  "name": "my-electron-app",
  "version": "1.0.0",
  "description": "Hello World!",
  "main": "main.js",
  "author": "Jane Doe",
  "license": "MIT",
  "devDependencies": {
    "electron": "19.0.0"
  }
}
```





Advanced Electron installation steps
If installing Electron directly fails, please refer to our [Advanced Installation](installation) documentation for instructions on download mirrors, proxies, and troubleshooting steps.



### Adding a .gitignore[​](#adding-a-gitignore "Direct link to heading")


The [`.gitignore`](https://git-scm.com/docs/gitignore) file specifies which files and directories to avoid tracking with Git. You should place a copy of [GitHub's Node.js gitignore template](https://github.com/github/gitignore/blob/main/Node.gitignore) into your project's root folder to avoid committing your project's `node_modules` folder.


Running an Electron app[​](#running-an-electron-app "Direct link to heading")
-----------------------------------------------------------------------------




Further reading
Read [Electron's process model](process-model) documentation to better understand how Electron's multiple processes work together.



The [`main`](https://docs.npmjs.com/cli/v7/configuring-npm/package-json#main) script you defined in package.json is the entry point of any Electron application. This script controls the **main process**, which runs in a Node.js environment and is responsible for controlling your app's lifecycle, displaying native interfaces, performing privileged operations, and managing renderer processes (more on that later).


Before creating your first Electron app, you will first use a trivial script to ensure your main process entry point is configured correctly. Create a `main.js` file in the root folder of your project with a single line of code:



main.js


```
console.log(`Hello from Electron 👋`)
```



Because Electron's main process is a Node.js runtime, you can execute arbitrary Node.js code with the `electron` command (you can even use it as a [REPL](repl)). To execute this script, add `electron .` to the `start` command in the [`scripts`](https://docs.npmjs.com/cli/v7/using-npm/scripts) field of your package.json. This command will tell the Electron executable to look for the main script in the current directory and run it in dev mode.



package.json


```
{
  "name": "my-electron-app",
  "version": "1.0.0",
  "description": "Hello World!",
  "main": "main.js",
  "author": "Jane Doe",
  "license": "MIT",
  "scripts": {
    "start": "electron ."
  },
  "devDependencies": {
    "electron": "^19.0.0"
  }
}
```




* npm
* Yarn





```
npm run start
```




```
yarn run start
```




Your terminal should print out `Hello from Electron 👋`. Congratulations, you have executed your first line of code in Electron! Next, you will learn how to create user interfaces with HTML and load that into a native window.


Loading a web page into a BrowserWindow[​](#loading-a-web-page-into-a-browserwindow "Direct link to heading")
-------------------------------------------------------------------------------------------------------------


In Electron, each window displays a web page that can be loaded either from a local HTML file or a remote web address. For this example, you will be loading in a local file. Start by creating a barebones web page in an `index.html` file in the root folder of your project:



index.html


```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'self'; script-src 'self'"
    />
    <meta
      http-equiv="X-Content-Security-Policy"
      content="default-src 'self'; script-src 'self'"
    />
    <title>Hello from Electron renderer!</title>
  </head>
  <body>
    <h1>Hello from Electron renderer!</h1>
    <p>👋</p>
  </body>
</html>
```



Now that you have a web page, you can load it into an Electron [BrowserWindow](../api/browser-window). Replace the contents your `main.js` file with the following code. We will explain each highlighted block separately.



main.js


```
const { app, BrowserWindow } = require('electron')

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
  })

  win.loadFile('index.html')
}

app.whenReady().then(() => {
  createWindow()
})
```



### Importing modules[​](#importing-modules "Direct link to heading")



main.js (Line 1)


```
const { app, BrowserWindow } = require('electron')
```



In the first line, we are importing two Electron modules with CommonJS module syntax:


* [app](../api/app), which controls your application's event lifecycle.
* [BrowserWindow](../api/browser-window), which creates and manages app windows.




Capitalization conventions
You might have noticed the capitalization difference between the **a**pp and **B**rowser**W**indow modules. Electron follows typical JavaScript conventions here, where PascalCase modules are instantiable class constructors (e.g. BrowserWindow, Tray, Notification) whereas camelCase modules are not instantiable (e.g. app, ipcRenderer, webContents).





ES Modules in Electron
[ECMAScript modules](https://nodejs.org/api/esm.html) (i.e. using `import` to load a module) are currently not directly supported in Electron. You can find more information about the state of ESM in Electron in [electron/electron#21457](https://github.com/electron/electron/issues/21457).



### Writing a reusable function to instantiate windows[​](#writing-a-reusable-function-to-instantiate-windows "Direct link to heading")


The `createWindow()` function loads your web page into a new BrowserWindow instance:



main.js (Lines 3-10)


```
const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
  })

  win.loadFile('index.html')
}
```



### Calling your function when the app is ready[​](#calling-your-function-when-the-app-is-ready "Direct link to heading")



main.js (Lines 12-14)


```
app.whenReady().then(() => {
  createWindow()
})
```



Many of Electron's core modules are Node.js [event emitters](https://nodejs.org/api/events.html#events) that adhere to Node's asynchronous event-driven architecture. The app module is one of these emitters.


In Electron, BrowserWindows can only be created after the app module's [`ready`](../api/app#event-ready) event is fired. You can wait for this event by using the [`app.whenReady()`](../api/app#appwhenready) API and calling `createWindow()` once its promise is fulfilled.




info

You typically listen to Node.js events by using an emitter's `.on` function.




```
+ app.on('ready').then(() => {
- app.whenReady().then(() => {
  createWindow()
})
```


However, Electron exposes `app.whenReady()` as a helper specifically for the `ready` event to avoid subtle pitfalls with directly listening to that event in particular. See [electron/electron#21972](https://github.com/electron/electron/pull/21972) for details.




At this point, running your Electron application's `start` command should successfully open a window that displays your web page!


Each web page your app displays in a window will run in a separate process called a **renderer** process (or simply *renderer* for short). Renderer processes have access to the same JavaScript APIs and tooling you use for typical front-end web development, such as using [webpack](https://webpack.js.org) to bundle and minify your code or [React](https://reactjs.org) to build your user interfaces.


Managing your app's window lifecycle[​](#managing-your-apps-window-lifecycle "Direct link to heading")
------------------------------------------------------------------------------------------------------


Application windows behave differently on each operating system. Rather than enforce these conventions by default, Electron gives you the choice to implement them in your app code if you wish to follow them. You can implement basic window conventions by listening for events emitted by the app and BrowserWindow modules.




Process-specific control flow
Checking against Node's [`process.platform`](https://nodejs.org/api/process.html#process_process_platform) variable can help you to run code conditionally on certain platforms. Note that there are only three possible platforms that Electron can run in: `win32` (Windows), `linux` (Linux), and `darwin` (macOS).



### Quit the app when all windows are closed (Windows & Linux)[​](#quit-the-app-when-all-windows-are-closed-windows--linux "Direct link to heading")


On Windows and Linux, closing all windows will generally quit an application entirely. To implement this pattern in your Electron app, listen for the app module's [`window-all-closed`](../api/app#event-window-all-closed) event, and call [`app.quit()`](../api/app#appquit) to exit your app if the user is not on macOS.




```
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})
```


### Open a window if none are open (macOS)[​](#open-a-window-if-none-are-open-macos "Direct link to heading")


In contrast, macOS apps generally continue running even without any windows open. Activating the app when no windows are available should open a new one.


To implement this feature, listen for the app module's [`activate`](../api/app#event-activate-macos) event, and call your existing `createWindow()` method if no BrowserWindows are open.


Because windows cannot be created before the `ready` event, you should only listen for `activate` events after your app is initialized. Do this by only listening for activate events inside your existing `whenReady()` callback.




```
app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})
```


Final starter code[​](#final-starter-code "Direct link to heading")
-------------------------------------------------------------------




[docs/fiddles/tutorial-first-app (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/tutorial-first-app)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/tutorial-first-app)


* main.js
* index.html





```
const { app, BrowserWindow } = require('electron');

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
  });

  win.loadFile('index.html');
};

app.whenReady().then(() => {
  createWindow();

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
    }
  });
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});
```




```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'self'; script-src 'self'"
    />
    <meta
      http-equiv="X-Content-Security-Policy"
      content="default-src 'self'; script-src 'self'"
    />
    <title>Hello from Electron renderer!</title>
  </head>
  <body>
    <h1>Hello from Electron renderer!</h1>
    <p>👋</p>
    <p id="info"></p>
  </body>
  <script src="./renderer.js"></script>
</html>
```





Optional: Debugging from VS Code[​](#optional-debugging-from-vs-code "Direct link to heading")
----------------------------------------------------------------------------------------------


If you want to debug your application using VS Code, you need to attach VS Code to both the main and renderer processes. Here is a sample configuration for you to run. Create a launch.json configuration in a new `.vscode` folder in your project:



.vscode/launch.json


```
{
  "version": "0.2.0",
  "compounds": [
    {
      "name": "Main + renderer",
      "configurations": ["Main", "Renderer"],
      "stopAll": true
    }
  ],
  "configurations": [
    {
      "name": "Renderer",
      "port": 9222,
      "request": "attach",
      "type": "pwa-chrome",
      "webRoot": "${workspaceFolder}"
    },
    {
      "name": "Main",
      "type": "pwa-node",
      "request": "launch",
      "cwd": "${workspaceFolder}",
      "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
      "windows": {
        "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
      },
      "args": [".", "--remote-debugging-port=9222"],
      "outputCapture": "std",
      "console": "integratedTerminal"
    }
  ]
}
```



The "Main + renderer" option will appear when you select "Run and Debug" from the sidebar, allowing you to set breakpoints and inspect all the variables among other things in both the main and renderer processes.


What we have done in the `launch.json` file is to create 3 configurations:


* `Main` is used to start the main process and also expose port 9222 for remote debugging (`--remote-debugging-port=9222`). This is the port that we will use to attach the debugger for the `Renderer`. Because the main process is a Node.js process, the type is set to `pwa-node` (`pwa-` is the prefix that tells VS Code to use the latest JavaScript debugger).
* `Renderer` is used to debug the renderer process. Because the main process is the one that creates the process, we have to "attach" to it (`"request": "attach"`) instead of creating a new one. The renderer process is a web one, so the debugger we have to use is `pwa-chrome`.
* `Main + renderer` is a [compound task](https://code.visualstudio.com/Docs/editor/tasks#_compound-tasks) that executes the previous ones simultaneously.




caution
Because we are attaching to a process in `Renderer`, it is possible that the first lines of your code will be skipped as the debugger will not have had enough time to connect before they are being executed. You can work around this by refreshing the page or setting a timeout before executing the code in development mode.





Further reading

If you want to dig deeper in the debugging area, the following guides provide more information:


* [Application Debugging](application-debugging)
* [DevTools Extensions](devtools-extension)




Summary[​](#summary "Direct link to heading")
---------------------------------------------


Electron applications are set up using npm packages. The Electron executable should be installed in your project's `devDependencies` and can be run in development mode using a script in your package.json file.


The executable runs the JavaScript entry point found in the `main` property of your package.json. This file controls Electron's **main process**, which runs an instance of Node.js and is responsible for your app's lifecycle, displaying native interfaces, performing privileged operations, and managing renderer processes.


**Renderer processes** (or renderers for short) are responsible for display graphical content. You can load a web page into a renderer by pointing it to either a web address or a local HTML file. Renderers behave very similarly to regular web pages and have access to the same web APIs.


In the next section of the tutorial, we will be learning how to augment the renderer process with privileged APIs and how to communicate between processes.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/tutorial-first-app>

Process Model
=============


Electron inherits its multi-process architecture from Chromium, which makes the framework architecturally very similar to a modern web browser. This guide will expand on the concepts applied in the [Tutorial](tutorial-prerequisites).


Why not a single process?[​](#why-not-a-single-process "Direct link to heading")
--------------------------------------------------------------------------------


Web browsers are incredibly complicated applications. Aside from their primary ability to display web content, they have many secondary responsibilities, such as managing multiple windows (or tabs) and loading third-party extensions.


In the earlier days, browsers usually used a single process for all of this functionality. Although this pattern meant less overhead for each tab you had open, it also meant that one website crashing or hanging would affect the entire browser.


The multi-process model[​](#the-multi-process-model "Direct link to heading")
-----------------------------------------------------------------------------


To solve this problem, the Chrome team decided that each tab would render in its own process, limiting the harm that buggy or malicious code on a web page could cause to the app as a whole. A single browser process then controls these processes, as well as the application lifecycle as a whole. This diagram below from the [Chrome Comic](https://www.google.com/googlebooks/chrome/) visualizes this model:


![Chrome&#39;s multi-process architecture]


Electron applications are structured very similarly. As an app developer, you control two types of processes: [main](#the-main-process) and [renderer](#the-renderer-process). These are analogous to Chrome's own browser and renderer processes outlined above.


The main process[​](#the-main-process "Direct link to heading")
---------------------------------------------------------------


Each Electron app has a single main process, which acts as the application's entry point. The main process runs in a Node.js environment, meaning it has the ability to `require` modules and use all of Node.js APIs.


### Window management[​](#window-management "Direct link to heading")


The main process' primary purpose is to create and manage application windows with the [`BrowserWindow`](../api/browser-window) module.


Each instance of the `BrowserWindow` class creates an application window that loads a web page in a separate renderer process. You can interact with this web content from the main process using the window's [`webContents`](../api/web-contents) object.



main.js


```
const { BrowserWindow } = require('electron')

const win = new BrowserWindow({ width: 800, height: 1500 })
win.loadURL('https://github.com')

const contents = win.webContents
console.log(contents)
```




> Note: A renderer process is also created for [web embeds](web-embeds) such as the `BrowserView` module. The `webContents` object is also accessible for embedded web content.
> 
> 


Because the `BrowserWindow` module is an [`EventEmitter`](https://nodejs.org/api/events.html#events_class_eventemitter), you can also add handlers for various user events (for example, minimizing or maximizing your window).


When a `BrowserWindow` instance is destroyed, its corresponding renderer process gets terminated as well.


### Application lifecycle[​](#application-lifecycle "Direct link to heading")


The main process also controls your application's lifecycle through Electron's [`app`](../api/app) module. This module provides a large set of events and methods that you can use to add custom application behaviour (for instance, programatically quitting your application, modifying the application dock, or showing an About panel).


As a practical example, the app shown in the [quick start guide](quick-start#manage-your-windows-lifecycle) uses `app` APIs to create a more native application window experience.



main.js


```
// quitting the app when no windows are open on non-macOS platforms
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})
```



### Native APIs[​](#native-apis "Direct link to heading")


To extend Electron's features beyond being a Chromium wrapper for web contents, the main process also adds custom APIs to interact with the user's operating system. Electron exposes various modules that control native desktop functionality, such as menus, dialogs, and tray icons.


For a full list of Electron's main process modules, check out our API documentation.


The renderer process[​](#the-renderer-process "Direct link to heading")
-----------------------------------------------------------------------


Each Electron app spawns a separate renderer process for each open `BrowserWindow` (and each web embed). As its name implies, a renderer is responsible for *rendering* web content. For all intents and purposes, code ran in renderer processes should behave according to web standards (insofar as Chromium does, at least).


Therefore, all user interfaces and app functionality within a single browser window should be written with the same tools and paradigms that you use on the web.


Although explaining every web spec is out of scope for this guide, the bare minimum to understand is:


* An HTML file is your entry point for the renderer process.
* UI styling is added through Cascading Style Sheets (CSS).
* Executable JavaScript code can be added through `<script>` elements.


Moreover, this also means that the renderer has no direct access to `require` or other Node.js APIs. In order to directly include NPM modules in the renderer, you must use the same bundler toolchains (for example, `webpack` or `parcel`) that you use on the web.




danger
Renderer processes can be spawned with a full Node.js environment for ease of development. Historically, this used to be the default, but this feature was disabled for security reasons.



At this point, you might be wondering how your renderer process user interfaces can interact with Node.js and Electron's native desktop functionality if these features are only accessible from the main process. In fact, there is no direct way to import Electron's content scripts.


Preload scripts[​](#preload-scripts "Direct link to heading")
-------------------------------------------------------------


Preload scripts contain code that executes in a renderer process before its web content begins loading. These scripts run within the renderer context, but are granted more privileges by having access to Node.js APIs.


A preload script can be attached to the main process in the `BrowserWindow` constructor's `webPreferences` option.



main.js


```
const { BrowserWindow } = require('electron')
//...
const win = new BrowserWindow({
  webPreferences: {
    preload: 'path/to/preload.js',
  },
})
//...
```



Because the preload script shares a global [`Window`](https://developer.mozilla.org/en-US/docs/Web/API/Window) interface with the renderers and can access Node.js APIs, it serves to enhance your renderer by exposing arbitrary APIs in the `window` global that your web contents can then consume.


Although preload scripts share a `window` global with the renderer they're attached to, you cannot directly attach any variables from the preload script to `window` because of the [`contextIsolation`](context-isolation) default.



preload.js


```
window.myAPI = {
  desktop: true,
}
```




renderer.js


```
console.log(window.myAPI)
// => undefined
```



Context Isolation means that preload scripts are isolated from the renderer's main world to avoid leaking any privileged APIs into your web content's code.


Instead, use the [`contextBridge`](../api/context-bridge) module to accomplish this securely:



preload.js


```
const { contextBridge } = require('electron')

contextBridge.exposeInMainWorld('myAPI', {
  desktop: true,
})
```




renderer.js


```
console.log(window.myAPI)
// => { desktop: true }
```



This feature is incredibly useful for two main purposes:


* By exposing [`ipcRenderer`](../api/ipc-renderer) helpers to the renderer, you can use inter-process communication (IPC) to trigger main process tasks from the renderer (and vice-versa).
* If you're developing an Electron wrapper for an existing web app hosted on a remote URL, you can add custom properties onto the renderer's `window` global that can be used for desktop-only logic on the web client's side.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/process-model>

GPUFeatureStatus Object
=======================


* `2d_canvas` string - Canvas.
* `flash_3d` string - Flash.
* `flash_stage3d` string - Flash Stage3D.
* `flash_stage3d_baseline` string - Flash Stage3D Baseline profile.
* `gpu_compositing` string - Compositing.
* `multiple_raster_threads` string - Multiple Raster Threads.
* `native_gpu_memory_buffers` string - Native GpuMemoryBuffers.
* `rasterization` string - Rasterization.
* `video_decode` string - Video Decode.
* `video_encode` string - Video Encode.
* `vpx_decode` string - VPx Video Decode.
* `webgl` string - WebGL.
* `webgl2` string - WebGL2.


Possible values:


* `disabled_software` - Software only. Hardware acceleration disabled (yellow)
* `disabled_off` - Disabled (red)
* `disabled_off_ok` - Disabled (yellow)
* `unavailable_software` - Software only, hardware acceleration unavailable (yellow)
* `unavailable_off` - Unavailable (red)
* `unavailable_off_ok` - Unavailable (yellow)
* `enabled_readback` - Hardware accelerated but at reduced performance (yellow)
* `enabled_force` - Hardware accelerated on all pages (green)
* `enabled` - Hardware accelerated (green)
* `enabled_on` - Enabled (green)
* `enabled_force_on` - Force enabled (green)



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/gpu-feature-status>

Using Preload Scripts
=====================



Follow along the tutorial

This is **part 3** of the Electron tutorial.


1. [Prerequisites](tutorial-prerequisites)
2. [Building your First App](tutorial-first-app)
3. **[Using Preload Scripts](tutorial-preload)**
4. [Adding Features](tutorial-adding-features)
5. [Packaging Your Application](tutorial-packaging)
6. [Publishing and Updating](tutorial-publishing-updating)




Learning goals[​](#learning-goals "Direct link to heading")
-----------------------------------------------------------


In this part of the tutorial, you will learn what a preload script is and how to use one to securely expose privileged APIs into the renderer process. You will also learn how to communicate between main and renderer processes with Electron's inter-process communication (IPC) modules.


What is a preload script?[​](#what-is-a-preload-script "Direct link to heading")
--------------------------------------------------------------------------------


Electron's main process is a Node.js environment that has full operating system access. On top of [Electron modules](../api/app), you can also access [Node.js built-ins](https://nodejs.org/dist/latest/docs/api/), as well as any packages installed via npm. On the other hand, renderer processes run web pages and do not run Node.js by default for security reasons.


To bridge Electron's different process types together, we will need to use a special script called a **preload**.


Augmenting the renderer with a preload script[​](#augmenting-the-renderer-with-a-preload-script "Direct link to heading")
-------------------------------------------------------------------------------------------------------------------------


A BrowserWindow's preload script runs in a context that has access to both the HTML DOM and a Node.js environment. Preload scripts are injected before a web page loads in the renderer, similar to a Chrome extension's [content scripts](https://developer.chrome.com/docs/extensions/mv3/content_scripts/). To add features to your renderer that require privileged access, you can define [global](https://developer.mozilla.org/en-US/docs/Glossary/Global_object) objects through the [contextBridge](../api/context-bridge) API.


To demonstrate this concept, you will create a preload script that exposes your app's versions of Chrome, Node, and Electron into the renderer.


Add a new `preload.js` script that exposes selected properties of Electron's `process.versions` object to the renderer process in a `versions` global variable.



preload.js


```
const { contextBridge } = require('electron')

contextBridge.exposeInMainWorld('versions', {
  node: () => process.versions.node,
  chrome: () => process.versions.chrome,
  electron: () => process.versions.electron,
  // we can also expose variables, not just functions
})
```



To attach this script to your renderer process, pass its path to the `webPreferences.preload` option in the BrowserWindow constructor:



main.js


```
const { app, BrowserWindow } = require('electron')
const path = require('path')

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
    },
  })

  win.loadFile('index.html')
}

app.whenReady().then(() => {
  createWindow()
})
```





info

There are two Node.js concepts that are used here:


* The [`__dirname`](https://nodejs.org/api/modules.html#modules_dirname) string points to the path of the currently executing script (in this case, your project's root folder).
* The [`path.join`](https://nodejs.org/api/path.html#path_path_join_paths) API joins multiple path segments together, creating a combined path string that works across all platforms.




At this point, the renderer has access to the `versions` global, so let's display that information in the window. This variable can be accessed via `window.versions` or simply `versions`. Create a `renderer.js` script that uses the [`document.getElementById`](https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById) DOM API to replace the displayed text for the HTML element with `info` as its `id` property.



renderer.js


```
const information = document.getElementById('info')
information.innerText = `This app is using Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), and Electron (v${versions.electron()})`
```



Then, modify your `index.html` by adding a new element with `info` as its `id` property, and attach your `renderer.js` script:



index.html


```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'self'; script-src 'self'"
    />
    <meta
      http-equiv="X-Content-Security-Policy"
      content="default-src 'self'; script-src 'self'"
    />
    <title>Hello from Electron renderer!</title>
  </head>
  <body>
    <h1>Hello from Electron renderer!</h1>
    <p>👋</p>
    <p id="info"></p>
  </body>
  <script src="./renderer.js"></script>
</html>
```



After following the above steps, your app should look something like this:


![Electron app showing This app is using Chrome (v102.0.5005.63), Node.js (v16.14.2), and Electron (v19.0.3)]


And the code should look like this:




[docs/fiddles/tutorial-preload (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/tutorial-preload)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/tutorial-preload)


* main.js
* preload.js
* index.html
* renderer.js





```
const { app, BrowserWindow } = require('electron');
const path = require('path');

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
    },
  });

  win.loadFile('index.html');
};

app.whenReady().then(() => {
  createWindow();

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow();
    }
  });
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});
```




```
const { contextBridge } = require('electron');

contextBridge.exposeInMainWorld('versions', {
  node: () => process.versions.node,
  chrome: () => process.versions.chrome,
  electron: () => process.versions.electron,
});
```




```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <meta
      http-equiv="Content-Security-Policy"
      content="default-src 'self'; script-src 'self'"
    />
    <meta
      http-equiv="X-Content-Security-Policy"
      content="default-src 'self'; script-src 'self'"
    />
    <title>Hello from Electron renderer!</title>
  </head>
  <body>
    <h1>Hello from Electron renderer!</h1>
    <p>👋</p>
    <p id="info"></p>
  </body>
  <script src="./renderer.js"></script>
</html>
```




```
const information = document.getElementById('info');
information.innerText = `This app is using Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), and Electron (v${versions.electron()})`;
```





Communicating between processes[​](#communicating-between-processes "Direct link to heading")
---------------------------------------------------------------------------------------------


As we have mentioned above, Electron's main and renderer process have distinct responsibilities and are not interchangeable. This means it is not possible to access the Node.js APIs directly from the renderer process, nor the HTML Document Object Model (DOM) from the main process.


The solution for this problem is to use Electron's `ipcMain` and `ipcRenderer` modules for inter-process communication (IPC). To send a message from your web page to the main process, you can set up a main process handler with `ipcMain.handle` and then expose a function that calls `ipcRenderer.invoke` to trigger the handler in your preload script.


To illustrate, we will add a global function to the renderer called `ping()` that will return a string from the main process.


First, set up the `invoke` call in your preload script:



preload.js


```
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('versions', {
  node: () => process.versions.node,
  chrome: () => process.versions.chrome,
  electron: () => process.versions.electron,
  ping: () => ipcRenderer.invoke('ping'),
  // we can also expose variables, not just functions
})
```





IPC security
Notice how we wrap the `ipcRenderer.invoke('ping')` call in a helper function rather than expose the `ipcRenderer` module directly via context bridge. You **never** want to directly expose the entire `ipcRenderer` module via preload. This would give your renderer the ability to send arbitrary IPC messages to the main process, which becomes a powerful attack vector for malicious code.



Then, set up your `handle` listener in the main process. We do this *before* loading the HTML file so that the handler is guaranteed to be ready before you send out the `invoke` call from the renderer.



main.js


```
const { ipcMain } = require('electron')

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
    },
  })
  ipcMain.handle('ping', () => 'pong')
  win.loadFile('index.html')
}
```



Once you have the sender and receiver set up, you can now send messages from the renderer to the main process through the `'ping'` channel you just defined.



renderer.js


```
const func = async () => {
  const response = await window.versions.ping()
  console.log(response) // prints out 'pong'
}

func()
```





info
For more in-depth explanations on using the `ipcRenderer` and `ipcMain` modules, check out the full [Inter-Process Communication](ipc) guide.



Summary[​](#summary "Direct link to heading")
---------------------------------------------


A preload script contains code that runs before your web page is loaded into the browser window. It has access to both DOM APIs and Node.js environment, and is often used to expose privileged APIs to the renderer via the `contextBridge` API.


Because the main and renderer processes have very different responsibilities, Electron apps often use the preload script to set up inter-process communication (IPC) interfaces to pass arbitrary messages between the two kinds of processes.


In the next part of the tutorial, we will be showing you resources on adding more functionality to your app, then teaching you distributing your app to users.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/tutorial-preload>

BrowserWindow
=============



> Create and control browser windows.
> 
> 


Process: [Main](../glossary#main-process)


This module cannot be used until the `ready` event of the `app` module is emitted.




```
// In the main process.
const { BrowserWindow } = require('electron')

const win = new BrowserWindow({ width: 800, height: 600 })

// Load a remote URL
win.loadURL('https://github.com')

// Or load a local HTML file
win.loadFile('index.html')
```


Window customization[​](#window-customization "Direct link to heading")
-----------------------------------------------------------------------


The `BrowserWindow` class exposes various ways to modify the look and behavior of your app's windows. For more details, see the [Window Customization](../tutorial/window-customization) tutorial.


Showing the window gracefully[​](#showing-the-window-gracefully "Direct link to heading")
-----------------------------------------------------------------------------------------


When loading a page in the window directly, users may see the page load incrementally, which is not a good experience for a native app. To make the window display without a visual flash, there are two solutions for different situations.


### Using the `ready-to-show` event[​](#using-the-ready-to-show-event "Direct link to heading")


While loading the page, the `ready-to-show` event will be emitted when the renderer process has rendered the page for the first time if the window has not been shown yet. Showing the window after this event will have no visual flash:




```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ show: false })
win.once('ready-to-show', () => {
  win.show()
})
```


This event is usually emitted after the `did-finish-load` event, but for pages with many remote resources, it may be emitted before the `did-finish-load` event.


Please note that using this event implies that the renderer will be considered "visible" and paint even though `show` is false. This event will never fire if you use `paintWhenInitiallyHidden: false`


### Setting the `backgroundColor` property[​](#setting-the-backgroundcolor-property "Direct link to heading")


For a complex app, the `ready-to-show` event could be emitted too late, making the app feel slow. In this case, it is recommended to show the window immediately, and use a `backgroundColor` close to your app's background:




```
const { BrowserWindow } = require('electron')

const win = new BrowserWindow({ backgroundColor: '#2e2c29' })
win.loadURL('https://github.com')
```


Note that even for apps that use `ready-to-show` event, it is still recommended to set `backgroundColor` to make the app feel more native.


Some examples of valid `backgroundColor` values include:




```
const win = new BrowserWindow()
win.setBackgroundColor('hsl(230, 100%, 50%)')
win.setBackgroundColor('rgb(255, 145, 145)')
win.setBackgroundColor('#ff00a3')
win.setBackgroundColor('blueviolet')
```


For more information about these color types see valid options in [win.setBackgroundColor](browser-window#winsetbackgroundcolorbackgroundcolor).


Parent and child windows[​](#parent-and-child-windows "Direct link to heading")
-------------------------------------------------------------------------------


By using `parent` option, you can create child windows:




```
const { BrowserWindow } = require('electron')

const top = new BrowserWindow()
const child = new BrowserWindow({ parent: top })
child.show()
top.show()
```


The `child` window will always show on top of the `top` window.


Modal windows[​](#modal-windows "Direct link to heading")
---------------------------------------------------------


A modal window is a child window that disables parent window, to create a modal window, you have to set both `parent` and `modal` options:




```
const { BrowserWindow } = require('electron')

const child = new BrowserWindow({ parent: top, modal: true, show: false })
child.loadURL('https://github.com')
child.once('ready-to-show', () => {
  child.show()
})
```


Page visibility[​](#page-visibility "Direct link to heading")
-------------------------------------------------------------


The [Page Visibility API](https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API) works as follows:


* On all platforms, the visibility state tracks whether the window is hidden/minimized or not.
* Additionally, on macOS, the visibility state also tracks the window occlusion state. If the window is occluded (i.e. fully covered) by another window, the visibility state will be `hidden`. On other platforms, the visibility state will be `hidden` only when the window is minimized or explicitly hidden with `win.hide()`.
* If a `BrowserWindow` is created with `show: false`, the initial visibility state will be `visible` despite the window actually being hidden.
* If `backgroundThrottling` is disabled, the visibility state will remain `visible` even if the window is minimized, occluded, or hidden.


It is recommended that you pause expensive operations when the visibility state is `hidden` in order to minimize power consumption.


Platform notices[​](#platform-notices "Direct link to heading")
---------------------------------------------------------------


* On macOS modal windows will be displayed as sheets attached to the parent window.
* On macOS the child windows will keep the relative position to parent window when parent window moves, while on Windows and Linux child windows will not move.
* On Linux the type of modal windows will be changed to `dialog`.
* On Linux many desktop environments do not support hiding a modal window.


Class: BrowserWindow[​](#class-browserwindow "Direct link to heading")
----------------------------------------------------------------------



> Create and control browser windows.
> 
> 


Process: [Main](../glossary#main-process)


`BrowserWindow` is an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter).


It creates a new `BrowserWindow` with native properties as set by the `options`.


### 
`new BrowserWindow([options])`[​](#new-browserwindowoptions "Direct link to heading")


* `options` Object (optional)
	+ `width` Integer (optional) - Window's width in pixels. Default is `800`.
	+ `height` Integer (optional) - Window's height in pixels. Default is `600`.
	+ `x` Integer (optional) - (**required** if y is used) Window's left offset from screen. Default is to center the window.
	+ `y` Integer (optional) - (**required** if x is used) Window's top offset from screen. Default is to center the window.
	+ `useContentSize` boolean (optional) - The `width` and `height` would be used as web page's size, which means the actual window's size will include window frame's size and be slightly larger. Default is `false`.
	+ `center` boolean (optional) - Show window in the center of the screen. Default is `false`.
	+ `minWidth` Integer (optional) - Window's minimum width. Default is `0`.
	+ `minHeight` Integer (optional) - Window's minimum height. Default is `0`.
	+ `maxWidth` Integer (optional) - Window's maximum width. Default is no limit.
	+ `maxHeight` Integer (optional) - Window's maximum height. Default is no limit.
	+ `resizable` boolean (optional) - Whether window is resizable. Default is `true`.
	+ `movable` boolean (optional) *macOS* *Windows* - Whether window is movable. This is not implemented on Linux. Default is `true`.
	+ `minimizable` boolean (optional) *macOS* *Windows* - Whether window is minimizable. This is not implemented on Linux. Default is `true`.
	+ `maximizable` boolean (optional) *macOS* *Windows* - Whether window is maximizable. This is not implemented on Linux. Default is `true`.
	+ `closable` boolean (optional) *macOS* *Windows* - Whether window is closable. This is not implemented on Linux. Default is `true`.
	+ `focusable` boolean (optional) - Whether the window can be focused. Default is `true`. On Windows setting `focusable: false` also implies setting `skipTaskbar: true`. On Linux setting `focusable: false` makes the window stop interacting with wm, so the window will always stay on top in all workspaces.
	+ `alwaysOnTop` boolean (optional) - Whether the window should always stay on top of other windows. Default is `false`.
	+ `fullscreen` boolean (optional) - Whether the window should show in fullscreen. When explicitly set to `false` the fullscreen button will be hidden or disabled on macOS. Default is `false`.
	+ `fullscreenable` boolean (optional) - Whether the window can be put into fullscreen mode. On macOS, also whether the maximize/zoom button should toggle full screen mode or maximize window. Default is `true`.
	+ `simpleFullscreen` boolean (optional) *macOS* - Use pre-Lion fullscreen on macOS. Default is `false`.
	+ `skipTaskbar` boolean (optional) *macOS* *Windows* - Whether to show the window in taskbar. Default is `false`.
	+ `kiosk` boolean (optional) - Whether the window is in kiosk mode. Default is `false`.
	+ `title` string (optional) - Default window title. Default is `"Electron"`. If the HTML tag `<title>` is defined in the HTML file loaded by `loadURL()`, this property will be ignored.
	+ `icon` ([NativeImage](native-image) | string) (optional) - The window icon. On Windows it is recommended to use `ICO` icons to get best visual effects, you can also leave it undefined so the executable's icon will be used.
	+ `show` boolean (optional) - Whether window should be shown when created. Default is `true`.
	+ `paintWhenInitiallyHidden` boolean (optional) - Whether the renderer should be active when `show` is `false` and it has just been created. In order for `document.visibilityState` to work correctly on first load with `show: false` you should set this to `false`. Setting this to `false` will cause the `ready-to-show` event to not fire. Default is `true`.
	+ `frame` boolean (optional) - Specify `false` to create a [frameless window](../tutorial/window-customization#create-frameless-windows). Default is `true`.
	+ `parent` BrowserWindow (optional) - Specify parent window. Default is `null`.
	+ `modal` boolean (optional) - Whether this is a modal window. This only works when the window is a child window. Default is `false`.
	+ `acceptFirstMouse` boolean (optional) *macOS* - Whether clicking an inactive window will also click through to the web contents. Default is `false` on macOS. This option is not configurable on other platforms.
	+ `disableAutoHideCursor` boolean (optional) - Whether to hide cursor when typing. Default is `false`.
	+ `autoHideMenuBar` boolean (optional) - Auto hide the menu bar unless the `Alt` key is pressed. Default is `false`.
	+ `enableLargerThanScreen` boolean (optional) *macOS* - Enable the window to be resized larger than screen. Only relevant for macOS, as other OSes allow larger-than-screen windows by default. Default is `false`.
	+ `backgroundColor` string (optional) - The window's background color in Hex, RGB, RGBA, HSL, HSLA or named CSS color format. Alpha in #AARRGGBB format is supported if `transparent` is set to `true`. Default is `#FFF` (white). See [win.setBackgroundColor](browser-window#winsetbackgroundcolorbackgroundcolor) for more information.
	+ `hasShadow` boolean (optional) - Whether window should have a shadow. Default is `true`.
	+ `opacity` number (optional) *macOS* *Windows* - Set the initial opacity of the window, between 0.0 (fully transparent) and 1.0 (fully opaque). This is only implemented on Windows and macOS.
	+ `darkTheme` boolean (optional) - Forces using dark theme for the window, only works on some GTK+3 desktop environments. Default is `false`.
	+ `transparent` boolean (optional) - Makes the window [transparent](../tutorial/window-customization#create-transparent-windows). Default is `false`. On Windows, does not work unless the window is frameless.
	+ `type` string (optional) - The type of window, default is normal window. See more about this below.
	+ `visualEffectState` string (optional) *macOS* - Specify how the material appearance should reflect window activity state on macOS. Must be used with the `vibrancy` property. Possible values are:
		- `followWindow` - The backdrop should automatically appear active when the window is active, and inactive when it is not. This is the default.
		- `active` - The backdrop should always appear active.
		- `inactive` - The backdrop should always appear inactive.
	+ `titleBarStyle` string (optional) *macOS* *Windows* - The style of window title bar. Default is `default`. Possible values are:
		- `default` - Results in the standard title bar for macOS or Windows respectively.
		- `hidden` - Results in a hidden title bar and a full size content window. On macOS, the window still has the standard window controls (“traffic lights”) in the top left. On Windows, when combined with `titleBarOverlay: true` it will activate the Window Controls Overlay (see `titleBarOverlay` for more information), otherwise no window controls will be shown.
		- `hiddenInset` *macOS* - Only on macOS, results in a hidden title bar with an alternative look where the traffic light buttons are slightly more inset from the window edge.
		- `customButtonsOnHover` *macOS* - Only on macOS, results in a hidden title bar and a full size content window, the traffic light buttons will display when being hovered over in the top left of the window. **Note:** This option is currently experimental.
	+ `trafficLightPosition` [Point](structures/point) (optional) *macOS* - Set a custom position for the traffic light buttons in frameless windows.
	+ `roundedCorners` boolean (optional) *macOS* - Whether frameless window should have rounded corners on macOS. Default is `true`. Setting this property to `false` will prevent the window from being fullscreenable.
	+ `fullscreenWindowTitle` boolean (optional) *macOS* *Deprecated* - Shows the title in the title bar in full screen mode on macOS for `hiddenInset` titleBarStyle. Default is `false`.
	+ `thickFrame` boolean (optional) - Use `WS_THICKFRAME` style for frameless windows on Windows, which adds standard window frame. Setting it to `false` will remove window shadow and window animations. Default is `true`.
	+ `vibrancy` string (optional) *macOS* - Add a type of vibrancy effect to the window, only on macOS. Can be `appearance-based`, `light`, `dark`, `titlebar`, `selection`, `menu`, `popover`, `sidebar`, `medium-light`, `ultra-dark`, `header`, `sheet`, `window`, `hud`, `fullscreen-ui`, `tooltip`, `content`, `under-window`, or `under-page`. Please note that `appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` are deprecated and have been removed in macOS Catalina (10.15).
	+ `zoomToPageWidth` boolean (optional) *macOS* - Controls the behavior on macOS when option-clicking the green stoplight button on the toolbar or by clicking the Window > Zoom menu item. If `true`, the window will grow to the preferred width of the web page when zoomed, `false` will cause it to zoom to the width of the screen. This will also affect the behavior when calling `maximize()` directly. Default is `false`.
	+ `tabbingIdentifier` string (optional) *macOS* - Tab group name, allows opening the window as a native tab on macOS 10.12+. Windows with the same tabbing identifier will be grouped together. This also adds a native new tab button to your window's tab bar and allows your `app` and window to receive the `new-window-for-tab` event.
	+ `webPreferences` Object (optional) - Settings of web page's features.
		- `devTools` boolean (optional) - Whether to enable DevTools. If it is set to `false`, can not use `BrowserWindow.webContents.openDevTools()` to open DevTools. Default is `true`.
		- `nodeIntegration` boolean (optional) - Whether node integration is enabled. Default is `false`.
		- `nodeIntegrationInWorker` boolean (optional) - Whether node integration is enabled in web workers. Default is `false`. More about this can be found in [Multithreading](../tutorial/multithreading).
		- `nodeIntegrationInSubFrames` boolean (optional) - Experimental option for enabling Node.js support in sub-frames such as iframes and child windows. All your preloads will load for every iframe, you can use `process.isMainFrame` to determine if you are in the main frame or not.
		- `preload` string (optional) - Specifies a script that will be loaded before other scripts run in the page. This script will always have access to node APIs no matter whether node integration is turned on or off. The value should be the absolute file path to the script. When node integration is turned off, the preload script can reintroduce Node global symbols back to the global scope. See example [here](context-bridge#exposing-node-global-symbols).
		- `sandbox` boolean (optional) - If set, this will sandbox the renderer associated with the window, making it compatible with the Chromium OS-level sandbox and disabling the Node.js engine. This is not the same as the `nodeIntegration` option and the APIs available to the preload script are more limited. Read more about the option [here](../tutorial/sandbox).
		- `session` [Session](session#class-session) (optional) - Sets the session used by the page. Instead of passing the Session object directly, you can also choose to use the `partition` option instead, which accepts a partition string. When both `session` and `partition` are provided, `session` will be preferred. Default is the default session.
		- `partition` string (optional) - Sets the session used by the page according to the session's partition string. If `partition` starts with `persist:`, the page will use a persistent session available to all pages in the app with the same `partition`. If there is no `persist:` prefix, the page will use an in-memory session. By assigning the same `partition`, multiple pages can share the same session. Default is the default session.
		- `zoomFactor` number (optional) - The default zoom factor of the page, `3.0` represents `300%`. Default is `1.0`.
		- `javascript` boolean (optional) - Enables JavaScript support. Default is `true`.
		- `webSecurity` boolean (optional) - When `false`, it will disable the same-origin policy (usually using testing websites by people), and set `allowRunningInsecureContent` to `true` if this options has not been set by user. Default is `true`.
		- `allowRunningInsecureContent` boolean (optional) - Allow an https page to run JavaScript, CSS or plugins from http URLs. Default is `false`.
		- `images` boolean (optional) - Enables image support. Default is `true`.
		- `imageAnimationPolicy` string (optional) - Specifies how to run image animations (E.g. GIFs). Can be `animate`, `animateOnce` or `noAnimation`. Default is `animate`.
		- `textAreasAreResizable` boolean (optional) - Make TextArea elements resizable. Default is `true`.
		- `webgl` boolean (optional) - Enables WebGL support. Default is `true`.
		- `plugins` boolean (optional) - Whether plugins should be enabled. Default is `false`.
		- `experimentalFeatures` boolean (optional) - Enables Chromium's experimental features. Default is `false`.
		- `scrollBounce` boolean (optional) *macOS* - Enables scroll bounce (rubber banding) effect on macOS. Default is `false`.
		- `enableBlinkFeatures` string (optional) - A list of feature strings separated by `,`, like `CSSVariables,KeyboardEventKey` to enable. The full list of supported feature strings can be found in the [RuntimeEnabledFeatures.json5](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5?l=70) file.
		- `disableBlinkFeatures` string (optional) - A list of feature strings separated by `,`, like `CSSVariables,KeyboardEventKey` to disable. The full list of supported feature strings can be found in the [RuntimeEnabledFeatures.json5](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5?l=70) file.
		- `defaultFontFamily` Object (optional) - Sets the default font for the font-family.
			* `standard` string (optional) - Defaults to `Times New Roman`.
			* `serif` string (optional) - Defaults to `Times New Roman`.
			* `sansSerif` string (optional) - Defaults to `Arial`.
			* `monospace` string (optional) - Defaults to `Courier New`.
			* `cursive` string (optional) - Defaults to `Script`.
			* `fantasy` string (optional) - Defaults to `Impact`.
		- `defaultFontSize` Integer (optional) - Defaults to `16`.
		- `defaultMonospaceFontSize` Integer (optional) - Defaults to `13`.
		- `minimumFontSize` Integer (optional) - Defaults to `0`.
		- `defaultEncoding` string (optional) - Defaults to `ISO-8859-1`.
		- `backgroundThrottling` boolean (optional) - Whether to throttle animations and timers when the page becomes background. This also affects the [Page Visibility API](#page-visibility). Defaults to `true`.
		- `offscreen` boolean (optional) - Whether to enable offscreen rendering for the browser window. Defaults to `false`. See the [offscreen rendering tutorial](../tutorial/offscreen-rendering) for more details.
		- `contextIsolation` boolean (optional) - Whether to run Electron APIs and the specified `preload` script in a separate JavaScript context. Defaults to `true`. The context that the `preload` script runs in will only have access to its own dedicated `document` and `window` globals, as well as its own set of JavaScript builtins (`Array`, `Object`, `JSON`, etc.), which are all invisible to the loaded content. The Electron API will only be available in the `preload` script and not the loaded page. This option should be used when loading potentially untrusted remote content to ensure the loaded content cannot tamper with the `preload` script and any Electron APIs being used. This option uses the same technique used by [Chrome Content Scripts](https://developer.chrome.com/extensions/content_scripts#execution-environment). You can access this context in the dev tools by selecting the 'Electron Isolated Context' entry in the combo box at the top of the Console tab.
		- `webviewTag` boolean (optional) - Whether to enable the [`<webview>` tag](webview-tag). Defaults to `false`. **Note:** The `preload` script configured for the `<webview>` will have node integration enabled when it is executed so you should ensure remote/untrusted content is not able to create a `<webview>` tag with a possibly malicious `preload` script. You can use the `will-attach-webview` event on [webContents](web-contents) to strip away the `preload` script and to validate or alter the `<webview>`'s initial settings.
		- `additionalArguments` string[] (optional) - A list of strings that will be appended to `process.argv` in the renderer process of this app. Useful for passing small bits of data down to renderer process preload scripts.
		- `safeDialogs` boolean (optional) - Whether to enable browser style consecutive dialog protection. Default is `false`.
		- `safeDialogsMessage` string (optional) - The message to display when consecutive dialog protection is triggered. If not defined the default message would be used, note that currently the default message is in English and not localized.
		- `disableDialogs` boolean (optional) - Whether to disable dialogs completely. Overrides `safeDialogs`. Default is `false`.
		- `navigateOnDragDrop` boolean (optional) - Whether dragging and dropping a file or link onto the page causes a navigation. Default is `false`.
		- `autoplayPolicy` string (optional) - Autoplay policy to apply to content in the window, can be `no-user-gesture-required`, `user-gesture-required`, `document-user-activation-required`. Defaults to `no-user-gesture-required`.
		- `disableHtmlFullscreenWindowResize` boolean (optional) - Whether to prevent the window from resizing when entering HTML Fullscreen. Default is `false`.
		- `accessibleTitle` string (optional) - An alternative title string provided only to accessibility tools such as screen readers. This string is not directly visible to users.
		- `spellcheck` boolean (optional) - Whether to enable the builtin spellchecker. Default is `true`.
		- `enableWebSQL` boolean (optional) - Whether to enable the [WebSQL api](https://www.w3.org/TR/webdatabase/). Default is `true`.
		- `v8CacheOptions` string (optional) - Enforces the v8 code caching policy used by blink. Accepted values are
			* `none` - Disables code caching
			* `code` - Heuristic based code caching
			* `bypassHeatCheck` - Bypass code caching heuristics but with lazy compilation
			* `bypassHeatCheckAndEagerCompile` - Same as above except compilation is eager. Default policy is `code`.
		- `enablePreferredSizeMode` boolean (optional) - Whether to enable preferred size mode. The preferred size is the minimum size needed to contain the layout of the document—without requiring scrolling. Enabling this will cause the `preferred-size-changed` event to be emitted on the `WebContents` when the preferred size changes. Default is `false`.
	+ `titleBarOverlay` Object | Boolean (optional) - When using a frameless window in conjunction with `win.setWindowButtonVisibility(true)` on macOS or using a `titleBarStyle` so that the standard window controls ("traffic lights" on macOS) are visible, this property enables the Window Controls Overlay [JavaScript APIs](https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#javascript-apis) and [CSS Environment Variables](https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#css-environment-variables). Specifying `true` will result in an overlay with default system colors. Default is `false`.
		- `color` String (optional) *Windows* - The CSS color of the Window Controls Overlay when enabled. Default is the system color.
		- `symbolColor` String (optional) *Windows* - The CSS color of the symbols on the Window Controls Overlay when enabled. Default is the system color.
		- `height` Integer (optional) *macOS* *Windows* - The height of the title bar and Window Controls Overlay in pixels. Default is system height.


When setting minimum or maximum window size with `minWidth`/`maxWidth`/ `minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from passing a size that does not follow size constraints to `setBounds`/`setSize` or to the constructor of `BrowserWindow`.


The possible values and behaviors of the `type` option are platform dependent. Possible values are:


* On Linux, possible types are `desktop`, `dock`, `toolbar`, `splash`, `notification`.
* On macOS, possible types are `desktop`, `textured`, `panel`.
	+ The `textured` type adds metal gradient appearance (`NSWindowStyleMaskTexturedBackground`).
	+ The `desktop` type places the window at the desktop background window level (`kCGDesktopWindowLevel - 1`). Note that desktop window will not receive focus, keyboard or mouse events, but you can use `globalShortcut` to receive input sparingly.
	+ The `panel` type enables the window to float on top of full-screened apps by adding the `NSWindowStyleMaskNonactivatingPanel` style mask,normally reserved for NSPanel, at runtime. Also, the window will appear on all spaces (desktops).
* On Windows, possible type is `toolbar`.


### Instance Events[​](#instance-events "Direct link to heading")


Objects created with `new BrowserWindow` emit the following events:


**Note:** Some events are only available on specific operating systems and are labeled as such.


#### Event: 'page-title-updated'[​](#event-page-title-updated "Direct link to heading")


Returns:


* `event` Event
* `title` string
* `explicitSet` boolean


Emitted when the document changed its title, calling `event.preventDefault()` will prevent the native window's title from changing. `explicitSet` is false when title is synthesized from file URL.


#### Event: 'close'[​](#event-close "Direct link to heading")


Returns:


* `event` Event


Emitted when the window is going to be closed. It's emitted before the `beforeunload` and `unload` event of the DOM. Calling `event.preventDefault()` will cancel the close.


Usually you would want to use the `beforeunload` handler to decide whether the window should be closed, which will also be called when the window is reloaded. In Electron, returning any value other than `undefined` would cancel the close. For example:




```
window.onbeforeunload = (e) => {
  console.log('I do not want to be closed')

  // Unlike usual browsers that a message box will be prompted to users, returning
  // a non-void value will silently cancel the close.
  // It is recommended to use the dialog API to let the user confirm closing the
  // application.
  e.returnValue = false
}
```


***Note**: There is a subtle difference between the behaviors of `window.onbeforeunload = handler` and `window.addEventListener('beforeunload', handler)`. It is recommended to always set the `event.returnValue` explicitly, instead of only returning a value, as the former works more consistently within Electron.*


#### Event: 'closed'[​](#event-closed "Direct link to heading")


Emitted when the window is closed. After you have received this event you should remove the reference to the window and avoid using it any more.


#### Event: 'session-end' *Windows*[​](#event-session-end-windows "Direct link to heading")


Emitted when window session is going to end due to force shutdown or machine restart or session log off.


#### Event: 'unresponsive'[​](#event-unresponsive "Direct link to heading")


Emitted when the web page becomes unresponsive.


#### Event: 'responsive'[​](#event-responsive "Direct link to heading")


Emitted when the unresponsive web page becomes responsive again.


#### Event: 'blur'[​](#event-blur "Direct link to heading")


Emitted when the window loses focus.


#### Event: 'focus'[​](#event-focus "Direct link to heading")


Emitted when the window gains focus.


#### Event: 'show'[​](#event-show "Direct link to heading")


Emitted when the window is shown.


#### Event: 'hide'[​](#event-hide "Direct link to heading")


Emitted when the window is hidden.


#### Event: 'ready-to-show'[​](#event-ready-to-show "Direct link to heading")


Emitted when the web page has been rendered (while not being shown) and window can be displayed without a visual flash.


Please note that using this event implies that the renderer will be considered "visible" and paint even though `show` is false. This event will never fire if you use `paintWhenInitiallyHidden: false`


#### Event: 'maximize'[​](#event-maximize "Direct link to heading")


Emitted when window is maximized.


#### Event: 'unmaximize'[​](#event-unmaximize "Direct link to heading")


Emitted when the window exits from a maximized state.


#### Event: 'minimize'[​](#event-minimize "Direct link to heading")


Emitted when the window is minimized.


#### Event: 'restore'[​](#event-restore "Direct link to heading")


Emitted when the window is restored from a minimized state.


#### Event: 'will-resize' *macOS* *Windows*[​](#event-will-resize-macos-windows "Direct link to heading")


Returns:


* `event` Event
* `newBounds` [Rectangle](structures/rectangle) - Size the window is being resized to.
* `details` Object
	+ `edge` (string) - The edge of the window being dragged for resizing. Can be `bottom`, `left`, `right`, `top-left`, `top-right`, `bottom-left` or `bottom-right`.


Emitted before the window is resized. Calling `event.preventDefault()` will prevent the window from being resized.


Note that this is only emitted when the window is being resized manually. Resizing the window with `setBounds`/`setSize` will not emit this event.


The possible values and behaviors of the `edge` option are platform dependent. Possible values are:


* On Windows, possible values are `bottom`, `top`, `left`, `right`, `top-left`, `top-right`, `bottom-left`, `bottom-right`.
* On macOS, possible values are `bottom` and `right`.
	+ The value `bottom` is used to denote vertical resizing.
	+ The value `right` is used to denote horizontal resizing.


#### Event: 'resize'[​](#event-resize "Direct link to heading")


Emitted after the window has been resized.


#### Event: 'resized' *macOS* *Windows*[​](#event-resized-macos-windows "Direct link to heading")


Emitted once when the window has finished being resized.


This is usually emitted when the window has been resized manually. On macOS, resizing the window with `setBounds`/`setSize` and setting the `animate` parameter to `true` will also emit this event once resizing has finished.


#### Event: 'will-move' *macOS* *Windows*[​](#event-will-move-macos-windows "Direct link to heading")


Returns:


* `event` Event
* `newBounds` [Rectangle](structures/rectangle) - Location the window is being moved to.


Emitted before the window is moved. On Windows, calling `event.preventDefault()` will prevent the window from being moved.


Note that this is only emitted when the window is being moved manually. Moving the window with `setPosition`/`setBounds`/`center` will not emit this event.


#### Event: 'move'[​](#event-move "Direct link to heading")


Emitted when the window is being moved to a new position.


#### Event: 'moved' *macOS* *Windows*[​](#event-moved-macos-windows "Direct link to heading")


Emitted once when the window is moved to a new position.


**Note**: On macOS this event is an alias of `move`.


#### Event: 'enter-full-screen'[​](#event-enter-full-screen "Direct link to heading")


Emitted when the window enters a full-screen state.


#### Event: 'leave-full-screen'[​](#event-leave-full-screen "Direct link to heading")


Emitted when the window leaves a full-screen state.


#### Event: 'enter-html-full-screen'[​](#event-enter-html-full-screen "Direct link to heading")


Emitted when the window enters a full-screen state triggered by HTML API.


#### Event: 'leave-html-full-screen'[​](#event-leave-html-full-screen "Direct link to heading")


Emitted when the window leaves a full-screen state triggered by HTML API.


#### Event: 'always-on-top-changed'[​](#event-always-on-top-changed "Direct link to heading")


Returns:


* `event` Event
* `isAlwaysOnTop` boolean


Emitted when the window is set or unset to show always on top of other windows.


#### Event: 'app-command' *Windows* *Linux*[​](#event-app-command-windows-linux "Direct link to heading")


Returns:


* `event` Event
* `command` string


Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx) is invoked. These are typically related to keyboard media keys or browser commands, as well as the "Back" button built into some mice on Windows.


Commands are lowercased, underscores are replaced with hyphens, and the `APPCOMMAND_` prefix is stripped off. e.g. `APPCOMMAND_BROWSER_BACKWARD` is emitted as `browser-backward`.




```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.on('app-command', (e, cmd) => {
  // Navigate the window back when the user hits their mouse back button
  if (cmd === 'browser-backward' && win.webContents.canGoBack()) {
    win.webContents.goBack()
  }
})
```


The following app commands are explicitly supported on Linux:


* `browser-backward`
* `browser-forward`


#### Event: 'scroll-touch-begin' *macOS*[​](#event-scroll-touch-begin-macos "Direct link to heading")


Emitted when scroll wheel event phase has begun.


#### Event: 'scroll-touch-end' *macOS*[​](#event-scroll-touch-end-macos "Direct link to heading")


Emitted when scroll wheel event phase has ended.


#### Event: 'scroll-touch-edge' *macOS*[​](#event-scroll-touch-edge-macos "Direct link to heading")


Emitted when scroll wheel event phase filed upon reaching the edge of element.


#### Event: 'swipe' *macOS*[​](#event-swipe-macos "Direct link to heading")


Returns:


* `event` Event
* `direction` string


Emitted on 3-finger swipe. Possible directions are `up`, `right`, `down`, `left`.


The method underlying this event is built to handle older macOS-style trackpad swiping, where the content on the screen doesn't move with the swipe. Most macOS trackpads are not configured to allow this kind of swiping anymore, so in order for it to emit properly the 'Swipe between pages' preference in `System Preferences > Trackpad > More Gestures` must be set to 'Swipe with two or three fingers'.


#### Event: 'rotate-gesture' *macOS*[​](#event-rotate-gesture-macos "Direct link to heading")


Returns:


* `event` Event
* `rotation` Float


Emitted on trackpad rotation gesture. Continually emitted until rotation gesture is ended. The `rotation` value on each emission is the angle in degrees rotated since the last emission. The last emitted event upon a rotation gesture will always be of value `0`. Counter-clockwise rotation values are positive, while clockwise ones are negative.


#### Event: 'sheet-begin' *macOS*[​](#event-sheet-begin-macos "Direct link to heading")


Emitted when the window opens a sheet.


#### Event: 'sheet-end' *macOS*[​](#event-sheet-end-macos "Direct link to heading")


Emitted when the window has closed a sheet.


#### Event: 'new-window-for-tab' *macOS*[​](#event-new-window-for-tab-macos "Direct link to heading")


Emitted when the native new tab button is clicked.


#### Event: 'system-context-menu' *Windows*[​](#event-system-context-menu-windows "Direct link to heading")


Returns:


* `event` Event
* `point` [Point](structures/point) - The screen coordinates the context menu was triggered at


Emitted when the system context menu is triggered on the window, this is normally only triggered when the user right clicks on the non-client area of your window. This is the window titlebar or any area you have declared as `-webkit-app-region: drag` in a frameless window.


Calling `event.preventDefault()` will prevent the menu from being displayed.


### Static Methods[​](#static-methods "Direct link to heading")


The `BrowserWindow` class has the following static methods:


#### 
`BrowserWindow.getAllWindows()`[​](#browserwindowgetallwindows "Direct link to heading")


Returns `BrowserWindow[]` - An array of all opened browser windows.


#### 
`BrowserWindow.getFocusedWindow()`[​](#browserwindowgetfocusedwindow "Direct link to heading")


Returns `BrowserWindow | null` - The window that is focused in this application, otherwise returns `null`.


#### 
`BrowserWindow.fromWebContents(webContents)`[​](#browserwindowfromwebcontentswebcontents "Direct link to heading")


* `webContents` [WebContents](web-contents)


Returns `BrowserWindow | null` - The window that owns the given `webContents` or `null` if the contents are not owned by a window.


#### 
`BrowserWindow.fromBrowserView(browserView)`[​](#browserwindowfrombrowserviewbrowserview "Direct link to heading")


* `browserView` [BrowserView](browser-view)


Returns `BrowserWindow | null` - The window that owns the given `browserView`. If the given view is not attached to any window, returns `null`.


#### 
`BrowserWindow.fromId(id)`[​](#browserwindowfromidid "Direct link to heading")


* `id` Integer


Returns `BrowserWindow | null` - The window with the given `id`.


### Instance Properties[​](#instance-properties "Direct link to heading")


Objects created with `new BrowserWindow` have the following properties:




```
const { BrowserWindow } = require('electron')
// In this example `win` is our instance
const win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('https://github.com')
```


#### 
`win.webContents` *Readonly*[​](#winwebcontents-readonly "Direct link to heading")


A `WebContents` object this window owns. All web page related events and operations will be done via it.


See the [`webContents` documentation](web-contents) for its methods and events.


#### 
`win.id` *Readonly*[​](#winid-readonly "Direct link to heading")


A `Integer` property representing the unique ID of the window. Each ID is unique among all `BrowserWindow` instances of the entire Electron application.


#### 
`win.autoHideMenuBar`[​](#winautohidemenubar "Direct link to heading")


A `boolean` property that determines whether the window menu bar should hide itself automatically. Once set, the menu bar will only show when users press the single `Alt` key.


If the menu bar is already visible, setting this property to `true` won't hide it immediately.


#### 
`win.simpleFullScreen`[​](#winsimplefullscreen "Direct link to heading")


A `boolean` property that determines whether the window is in simple (pre-Lion) fullscreen mode.


#### 
`win.fullScreen`[​](#winfullscreen "Direct link to heading")


A `boolean` property that determines whether the window is in fullscreen mode.


#### 
`win.focusable` *Windows* *macOS*[​](#winfocusable-windows-macos "Direct link to heading")


A `boolean` property that determines whether the window is focusable.


#### 
`win.visibleOnAllWorkspaces` *macOS* *Linux*[​](#winvisibleonallworkspaces-macos-linux "Direct link to heading")


A `boolean` property that determines whether the window is visible on all workspaces.


**Note:** Always returns false on Windows.


#### 
`win.shadow`[​](#winshadow "Direct link to heading")


A `boolean` property that determines whether the window has a shadow.


#### 
`win.menuBarVisible` *Windows* *Linux*[​](#winmenubarvisible-windows-linux "Direct link to heading")


A `boolean` property that determines whether the menu bar should be visible.


**Note:** If the menu bar is auto-hide, users can still bring up the menu bar by pressing the single `Alt` key.


#### 
`win.kiosk`[​](#winkiosk "Direct link to heading")


A `boolean` property that determines whether the window is in kiosk mode.


#### 
`win.documentEdited` *macOS*[​](#windocumentedited-macos "Direct link to heading")


A `boolean` property that specifies whether the window’s document has been edited.


The icon in title bar will become gray when set to `true`.


#### 
`win.representedFilename` *macOS*[​](#winrepresentedfilename-macos "Direct link to heading")


A `string` property that determines the pathname of the file the window represents, and the icon of the file will show in window's title bar.


#### 
`win.title`[​](#wintitle "Direct link to heading")


A `string` property that determines the title of the native window.


**Note:** The title of the web page can be different from the title of the native window.


#### 
`win.minimizable` *macOS* *Windows*[​](#winminimizable-macos-windows "Direct link to heading")


A `boolean` property that determines whether the window can be manually minimized by user.


On Linux the setter is a no-op, although the getter returns `true`.


#### 
`win.maximizable` *macOS* *Windows*[​](#winmaximizable-macos-windows "Direct link to heading")


A `boolean` property that determines whether the window can be manually maximized by user.


On Linux the setter is a no-op, although the getter returns `true`.


#### 
`win.fullScreenable`[​](#winfullscreenable "Direct link to heading")


A `boolean` property that determines whether the maximize/zoom window button toggles fullscreen mode or maximizes the window.


#### 
`win.resizable`[​](#winresizable "Direct link to heading")


A `boolean` property that determines whether the window can be manually resized by user.


#### 
`win.closable` *macOS* *Windows*[​](#winclosable-macos-windows "Direct link to heading")


A `boolean` property that determines whether the window can be manually closed by user.


On Linux the setter is a no-op, although the getter returns `true`.


#### 
`win.movable` *macOS* *Windows*[​](#winmovable-macos-windows "Direct link to heading")


A `boolean` property that determines Whether the window can be moved by user.


On Linux the setter is a no-op, although the getter returns `true`.


#### 
`win.excludedFromShownWindowsMenu` *macOS*[​](#winexcludedfromshownwindowsmenu-macos "Direct link to heading")


A `boolean` property that determines whether the window is excluded from the application’s Windows menu. `false` by default.




```
const win = new BrowserWindow({ height: 600, width: 600 })

const template = [
  {
    role: 'windowmenu'
  }
]

win.excludedFromShownWindowsMenu = true

const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
```


#### 
`win.accessibleTitle`[​](#winaccessibletitle "Direct link to heading")


A `string` property that defines an alternative title provided only to accessibility tools such as screen readers. This string is not directly visible to users.


### Instance Methods[​](#instance-methods "Direct link to heading")


Objects created with `new BrowserWindow` have the following instance methods:


**Note:** Some methods are only available on specific operating systems and are labeled as such.


#### 
`win.destroy()`[​](#windestroy "Direct link to heading")


Force closing the window, the `unload` and `beforeunload` event won't be emitted for the web page, and `close` event will also not be emitted for this window, but it guarantees the `closed` event will be emitted.


#### 
`win.close()`[​](#winclose "Direct link to heading")


Try to close the window. This has the same effect as a user manually clicking the close button of the window. The web page may cancel the close though. See the [close event](#event-close).


#### 
`win.focus()`[​](#winfocus "Direct link to heading")


Focuses on the window.


#### 
`win.blur()`[​](#winblur "Direct link to heading")


Removes focus from the window.


#### 
`win.isFocused()`[​](#winisfocused "Direct link to heading")


Returns `boolean` - Whether the window is focused.


#### 
`win.isDestroyed()`[​](#winisdestroyed "Direct link to heading")


Returns `boolean` - Whether the window is destroyed.


#### 
`win.show()`[​](#winshow "Direct link to heading")


Shows and gives focus to the window.


#### 
`win.showInactive()`[​](#winshowinactive "Direct link to heading")


Shows the window but doesn't focus on it.


#### 
`win.hide()`[​](#winhide "Direct link to heading")


Hides the window.


#### 
`win.isVisible()`[​](#winisvisible "Direct link to heading")


Returns `boolean` - Whether the window is visible to the user.


#### 
`win.isModal()`[​](#winismodal "Direct link to heading")


Returns `boolean` - Whether current window is a modal window.


#### 
`win.maximize()`[​](#winmaximize "Direct link to heading")


Maximizes the window. This will also show (but not focus) the window if it isn't being displayed already.


#### 
`win.unmaximize()`[​](#winunmaximize "Direct link to heading")


Unmaximizes the window.


#### 
`win.isMaximized()`[​](#winismaximized "Direct link to heading")


Returns `boolean` - Whether the window is maximized.


#### 
`win.minimize()`[​](#winminimize "Direct link to heading")


Minimizes the window. On some platforms the minimized window will be shown in the Dock.


#### 
`win.restore()`[​](#winrestore "Direct link to heading")


Restores the window from minimized state to its previous state.


#### 
`win.isMinimized()`[​](#winisminimized "Direct link to heading")


Returns `boolean` - Whether the window is minimized.


#### 
`win.setFullScreen(flag)`[​](#winsetfullscreenflag "Direct link to heading")


* `flag` boolean


Sets whether the window should be in fullscreen mode.


#### 
`win.isFullScreen()`[​](#winisfullscreen "Direct link to heading")


Returns `boolean` - Whether the window is in fullscreen mode.


#### 
`win.setSimpleFullScreen(flag)` *macOS*[​](#winsetsimplefullscreenflag-macos "Direct link to heading")


* `flag` boolean


Enters or leaves simple fullscreen mode.


Simple fullscreen mode emulates the native fullscreen behavior found in versions of macOS prior to Lion (10.7).


#### 
`win.isSimpleFullScreen()` *macOS*[​](#winissimplefullscreen-macos "Direct link to heading")


Returns `boolean` - Whether the window is in simple (pre-Lion) fullscreen mode.


#### 
`win.isNormal()`[​](#winisnormal "Direct link to heading")


Returns `boolean` - Whether the window is in normal state (not maximized, not minimized, not in fullscreen mode).


#### 
`win.setAspectRatio(aspectRatio[, extraSize])`[​](#winsetaspectratioaspectratio-extrasize "Direct link to heading")


* `aspectRatio` Float - The aspect ratio to maintain for some portion of the content view.
* `extraSize` [Size](structures/size) (optional) *macOS* - The extra size not to be included while maintaining the aspect ratio.


This will make a window maintain an aspect ratio. The extra size allows a developer to have space, specified in pixels, not included within the aspect ratio calculations. This API already takes into account the difference between a window's size and its content size.


Consider a normal window with an HD video player and associated controls. Perhaps there are 15 pixels of controls on the left edge, 25 pixels of controls on the right edge and 50 pixels of controls below the player. In order to maintain a 16:9 aspect ratio (standard aspect ratio for HD @1920x1080) within the player itself we would call this function with arguments of 16/9 and { width: 40, height: 50 }. The second argument doesn't care where the extra width and height are within the content view--only that they exist. Sum any extra width and height areas you have within the overall content view.


The aspect ratio is not respected when window is resized programmatically with APIs like `win.setSize`.


#### 
`win.setBackgroundColor(backgroundColor)`[​](#winsetbackgroundcolorbackgroundcolor "Direct link to heading")


* `backgroundColor` string - Color in Hex, RGB, RGBA, HSL, HSLA or named CSS color format. The alpha channel is optional for the hex type.


Examples of valid `backgroundColor` values:


* Hex
	+ #fff (shorthand RGB)
	+ #ffff (shorthand ARGB)
	+ #ffffff (RGB)
	+ #ffffffff (ARGB)
* RGB
	+ rgb(([\d]+),\s*([\d]+),\s*([\d]+))
		- e.g. rgb(255, 255, 255)
* RGBA
	+ rgba(([\d]+),\s*([\d]+),\s*([\d]+),\s\*([\d.]+))
		- e.g. rgba(255, 255, 255, 1.0)
* HSL
	+ hsl((-?[\d.]+),\s*([\d.]+)%,\s*([\d.]+)%)
		- e.g. hsl(200, 20%, 50%)
* HSLA
	+ hsla((-?[\d.]+),\s*([\d.]+)%,\s*([\d.]+)%,\s\*([\d.]+))
		- e.g. hsla(200, 20%, 50%, 0.5)
* Color name
	+ Options are listed in [SkParseColor.cpp](https://source.chromium.org/chromium/chromium/src/+/main:third_party/skia/src/utils/SkParseColor.cpp;l=11-152;drc=eea4bf52cb0d55e2a39c828b017c80a5ee054148)
	+ Similar to CSS Color Module Level 3 keywords, but case-sensitive.
		- e.g. `blueviolet` or `red`


Sets the background color of the window. See [Setting `backgroundColor`](#setting-the-backgroundcolor-property).


#### 
`win.previewFile(path[, displayName])` *macOS*[​](#winpreviewfilepath-displayname-macos "Direct link to heading")


* `path` string - The absolute path to the file to preview with QuickLook. This is important as Quick Look uses the file name and file extension on the path to determine the content type of the file to open.
* `displayName` string (optional) - The name of the file to display on the Quick Look modal view. This is purely visual and does not affect the content type of the file. Defaults to `path`.


Uses [Quick Look](https://en.wikipedia.org/wiki/Quick_Look) to preview a file at a given path.


#### 
`win.closeFilePreview()` *macOS*[​](#winclosefilepreview-macos "Direct link to heading")


Closes the currently open [Quick Look](https://en.wikipedia.org/wiki/Quick_Look) panel.


#### 
`win.setBounds(bounds[, animate])`[​](#winsetboundsbounds-animate "Direct link to heading")


* `bounds` Partial<[Rectangle](structures/rectangle)>
* `animate` boolean (optional) *macOS*


Resizes and moves the window to the supplied bounds. Any properties that are not supplied will default to their current values.




```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()

// set all bounds properties
win.setBounds({ x: 440, y: 225, width: 800, height: 600 })

// set a single bounds property
win.setBounds({ width: 100 })

// { x: 440, y: 225, width: 100, height: 600 }
console.log(win.getBounds())
```


#### 
`win.getBounds()`[​](#wingetbounds "Direct link to heading")


Returns [Rectangle](structures/rectangle) - The `bounds` of the window as `Object`.


#### 
`win.getBackgroundColor()`[​](#wingetbackgroundcolor "Direct link to heading")


Returns `string` - Gets the background color of the window in Hex (`#RRGGBB`) format.


See [Setting `backgroundColor`](#setting-the-backgroundcolor-property).


**Note:** The alpha value is *not* returned alongside the red, green, and blue values.


#### 
`win.setContentBounds(bounds[, animate])`[​](#winsetcontentboundsbounds-animate "Direct link to heading")


* `bounds` [Rectangle](structures/rectangle)
* `animate` boolean (optional) *macOS*


Resizes and moves the window's client area (e.g. the web page) to the supplied bounds.


#### 
`win.getContentBounds()`[​](#wingetcontentbounds "Direct link to heading")


Returns [Rectangle](structures/rectangle) - The `bounds` of the window's client area as `Object`.


#### 
`win.getNormalBounds()`[​](#wingetnormalbounds "Direct link to heading")


Returns [Rectangle](structures/rectangle) - Contains the window bounds of the normal state


**Note:** whatever the current state of the window : maximized, minimized or in fullscreen, this function always returns the position and size of the window in normal state. In normal state, getBounds and getNormalBounds returns the same [Rectangle](structures/rectangle).


#### 
`win.setEnabled(enable)`[​](#winsetenabledenable "Direct link to heading")


* `enable` boolean


Disable or enable the window.


#### 
`win.isEnabled()`[​](#winisenabled "Direct link to heading")


Returns `boolean` - whether the window is enabled.


#### 
`win.setSize(width, height[, animate])`[​](#winsetsizewidth-height-animate "Direct link to heading")


* `width` Integer
* `height` Integer
* `animate` boolean (optional) *macOS*


Resizes the window to `width` and `height`. If `width` or `height` are below any set minimum size constraints the window will snap to its minimum size.


#### 
`win.getSize()`[​](#wingetsize "Direct link to heading")


Returns `Integer[]` - Contains the window's width and height.


#### 
`win.setContentSize(width, height[, animate])`[​](#winsetcontentsizewidth-height-animate "Direct link to heading")


* `width` Integer
* `height` Integer
* `animate` boolean (optional) *macOS*


Resizes the window's client area (e.g. the web page) to `width` and `height`.


#### 
`win.getContentSize()`[​](#wingetcontentsize "Direct link to heading")


Returns `Integer[]` - Contains the window's client area's width and height.


#### 
`win.setMinimumSize(width, height)`[​](#winsetminimumsizewidth-height "Direct link to heading")


* `width` Integer
* `height` Integer


Sets the minimum size of window to `width` and `height`.


#### 
`win.getMinimumSize()`[​](#wingetminimumsize "Direct link to heading")


Returns `Integer[]` - Contains the window's minimum width and height.


#### 
`win.setMaximumSize(width, height)`[​](#winsetmaximumsizewidth-height "Direct link to heading")


* `width` Integer
* `height` Integer


Sets the maximum size of window to `width` and `height`.


#### 
`win.getMaximumSize()`[​](#wingetmaximumsize "Direct link to heading")


Returns `Integer[]` - Contains the window's maximum width and height.


#### 
`win.setResizable(resizable)`[​](#winsetresizableresizable "Direct link to heading")


* `resizable` boolean


Sets whether the window can be manually resized by the user.


#### 
`win.isResizable()`[​](#winisresizable "Direct link to heading")


Returns `boolean` - Whether the window can be manually resized by the user.


#### 
`win.setMovable(movable)` *macOS* *Windows*[​](#winsetmovablemovable-macos-windows "Direct link to heading")


* `movable` boolean


Sets whether the window can be moved by user. On Linux does nothing.


#### 
`win.isMovable()` *macOS* *Windows*[​](#winismovable-macos-windows "Direct link to heading")


Returns `boolean` - Whether the window can be moved by user.


On Linux always returns `true`.


#### 
`win.setMinimizable(minimizable)` *macOS* *Windows*[​](#winsetminimizableminimizable-macos-windows "Direct link to heading")


* `minimizable` boolean


Sets whether the window can be manually minimized by user. On Linux does nothing.


#### 
`win.isMinimizable()` *macOS* *Windows*[​](#winisminimizable-macos-windows "Direct link to heading")


Returns `boolean` - Whether the window can be manually minimized by the user.


On Linux always returns `true`.


#### 
`win.setMaximizable(maximizable)` *macOS* *Windows*[​](#winsetmaximizablemaximizable-macos-windows "Direct link to heading")


* `maximizable` boolean


Sets whether the window can be manually maximized by user. On Linux does nothing.


#### 
`win.isMaximizable()` *macOS* *Windows*[​](#winismaximizable-macos-windows "Direct link to heading")


Returns `boolean` - Whether the window can be manually maximized by user.


On Linux always returns `true`.


#### 
`win.setFullScreenable(fullscreenable)`[​](#winsetfullscreenablefullscreenable "Direct link to heading")


* `fullscreenable` boolean


Sets whether the maximize/zoom window button toggles fullscreen mode or maximizes the window.


#### 
`win.isFullScreenable()`[​](#winisfullscreenable "Direct link to heading")


Returns `boolean` - Whether the maximize/zoom window button toggles fullscreen mode or maximizes the window.


#### 
`win.setClosable(closable)` *macOS* *Windows*[​](#winsetclosableclosable-macos-windows "Direct link to heading")


* `closable` boolean


Sets whether the window can be manually closed by user. On Linux does nothing.


#### 
`win.isClosable()` *macOS* *Windows*[​](#winisclosable-macos-windows "Direct link to heading")


Returns `boolean` - Whether the window can be manually closed by user.


On Linux always returns `true`.


#### 
`win.setAlwaysOnTop(flag[, level][, relativeLevel])`[​](#winsetalwaysontopflag-level-relativelevel "Direct link to heading")


* `flag` boolean
* `level` string (optional) *macOS* *Windows* - Values include `normal`, `floating`, `torn-off-menu`, `modal-panel`, `main-menu`, `status`, `pop-up-menu`, `screen-saver`, and ~~`dock`~~ (Deprecated). The default is `floating` when `flag` is true. The `level` is reset to `normal` when the flag is false. Note that from `floating` to `status` included, the window is placed below the Dock on macOS and below the taskbar on Windows. From `pop-up-menu` to a higher it is shown above the Dock on macOS and above the taskbar on Windows. See the [macOS docs](https://developer.apple.com/documentation/appkit/nswindow/level) for more details.
* `relativeLevel` Integer (optional) *macOS* - The number of layers higher to set this window relative to the given `level`. The default is `0`. Note that Apple discourages setting levels higher than 1 above `screen-saver`.


Sets whether the window should show always on top of other windows. After setting this, the window is still a normal window, not a toolbox window which can not be focused on.


#### 
`win.isAlwaysOnTop()`[​](#winisalwaysontop "Direct link to heading")


Returns `boolean` - Whether the window is always on top of other windows.


#### 
`win.moveAbove(mediaSourceId)`[​](#winmoveabovemediasourceid "Direct link to heading")


* `mediaSourceId` string - Window id in the format of DesktopCapturerSource's id. For example "window:1869:0".


Moves window above the source window in the sense of z-order. If the `mediaSourceId` is not of type window or if the window does not exist then this method throws an error.


#### 
`win.moveTop()`[​](#winmovetop "Direct link to heading")


Moves window to top(z-order) regardless of focus


#### 
`win.center()`[​](#wincenter "Direct link to heading")


Moves window to the center of the screen.


#### 
`win.setPosition(x, y[, animate])`[​](#winsetpositionx-y-animate "Direct link to heading")


* `x` Integer
* `y` Integer
* `animate` boolean (optional) *macOS*


Moves window to `x` and `y`.


#### 
`win.getPosition()`[​](#wingetposition "Direct link to heading")


Returns `Integer[]` - Contains the window's current position.


#### 
`win.setTitle(title)`[​](#winsettitletitle "Direct link to heading")


* `title` string


Changes the title of native window to `title`.


#### 
`win.getTitle()`[​](#wingettitle "Direct link to heading")


Returns `string` - The title of the native window.


**Note:** The title of the web page can be different from the title of the native window.


#### 
`win.setSheetOffset(offsetY[, offsetX])` *macOS*[​](#winsetsheetoffsetoffsety-offsetx-macos "Direct link to heading")


* `offsetY` Float
* `offsetX` Float (optional)


Changes the attachment point for sheets on macOS. By default, sheets are attached just below the window frame, but you may want to display them beneath a HTML-rendered toolbar. For example:




```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()

const toolbarRect = document.getElementById('toolbar').getBoundingClientRect()
win.setSheetOffset(toolbarRect.height)
```


#### 
`win.flashFrame(flag)`[​](#winflashframeflag "Direct link to heading")


* `flag` boolean


Starts or stops flashing the window to attract user's attention.


#### 
`win.setSkipTaskbar(skip)` *macOS* *Windows*[​](#winsetskiptaskbarskip-macos-windows "Direct link to heading")


* `skip` boolean


Makes the window not show in the taskbar.


#### 
`win.setKiosk(flag)`[​](#winsetkioskflag "Direct link to heading")


* `flag` boolean


Enters or leaves kiosk mode.


#### 
`win.isKiosk()`[​](#winiskiosk "Direct link to heading")


Returns `boolean` - Whether the window is in kiosk mode.


#### 
`win.isTabletMode()` *Windows*[​](#winistabletmode-windows "Direct link to heading")


Returns `boolean` - Whether the window is in Windows 10 tablet mode.


Since Windows 10 users can [use their PC as tablet](https://support.microsoft.com/en-us/help/17210/windows-10-use-your-pc-like-a-tablet), under this mode apps can choose to optimize their UI for tablets, such as enlarging the titlebar and hiding titlebar buttons.


This API returns whether the window is in tablet mode, and the `resize` event can be be used to listen to changes to tablet mode.


#### 
`win.getMediaSourceId()`[​](#wingetmediasourceid "Direct link to heading")


Returns `string` - Window id in the format of DesktopCapturerSource's id. For example "window:1324:0".


More precisely the format is `window:id:other_id` where `id` is `HWND` on Windows, `CGWindowID` (`uint64_t`) on macOS and `Window` (`unsigned long`) on Linux. `other_id` is used to identify web contents (tabs) so within the same top level window.


#### 
`win.getNativeWindowHandle()`[​](#wingetnativewindowhandle "Direct link to heading")


Returns `Buffer` - The platform-specific handle of the window.


The native type of the handle is `HWND` on Windows, `NSView*` on macOS, and `Window` (`unsigned long`) on Linux.


#### 
`win.hookWindowMessage(message, callback)` *Windows*[​](#winhookwindowmessagemessage-callback-windows "Direct link to heading")


* `message` Integer
* `callback` Function
	+ `wParam` any - The `wParam` provided to the WndProc
	+ `lParam` any - The `lParam` provided to the WndProc


Hooks a windows message. The `callback` is called when the message is received in the WndProc.


#### 
`win.isWindowMessageHooked(message)` *Windows*[​](#winiswindowmessagehookedmessage-windows "Direct link to heading")


* `message` Integer


Returns `boolean` - `true` or `false` depending on whether the message is hooked.


#### 
`win.unhookWindowMessage(message)` *Windows*[​](#winunhookwindowmessagemessage-windows "Direct link to heading")


* `message` Integer


Unhook the window message.


#### 
`win.unhookAllWindowMessages()` *Windows*[​](#winunhookallwindowmessages-windows "Direct link to heading")


Unhooks all of the window messages.


#### 
`win.setRepresentedFilename(filename)` *macOS*[​](#winsetrepresentedfilenamefilename-macos "Direct link to heading")


* `filename` string


Sets the pathname of the file the window represents, and the icon of the file will show in window's title bar.


#### 
`win.getRepresentedFilename()` *macOS*[​](#wingetrepresentedfilename-macos "Direct link to heading")


Returns `string` - The pathname of the file the window represents.


#### 
`win.setDocumentEdited(edited)` *macOS*[​](#winsetdocumenteditededited-macos "Direct link to heading")


* `edited` boolean


Specifies whether the window’s document has been edited, and the icon in title bar will become gray when set to `true`.


#### 
`win.isDocumentEdited()` *macOS*[​](#winisdocumentedited-macos "Direct link to heading")


Returns `boolean` - Whether the window's document has been edited.


#### 
`win.focusOnWebView()`[​](#winfocusonwebview "Direct link to heading")


#### 
`win.blurWebView()`[​](#winblurwebview "Direct link to heading")


#### 
`win.capturePage([rect])`[​](#wincapturepagerect "Direct link to heading")


* `rect` [Rectangle](structures/rectangle) (optional) - The bounds to capture


Returns `Promise<NativeImage>` - Resolves with a [NativeImage](native-image)


Captures a snapshot of the page within `rect`. Omitting `rect` will capture the whole visible page. If the page is not visible, `rect` may be empty.


#### 
`win.loadURL(url[, options])`[​](#winloadurlurl-options "Direct link to heading")


* `url` string
* `options` Object (optional)
	+ `httpReferrer` (string | [Referrer](structures/referrer)) (optional) - An HTTP Referrer URL.
	+ `userAgent` string (optional) - A user agent originating the request.
	+ `extraHeaders` string (optional) - Extra headers separated by "\n"
	+ `postData` ([UploadRawData](structures/upload-raw-data) | [UploadFile](structures/upload-file))[] (optional)
	+ `baseURLForDataURL` string (optional) - Base URL (with trailing path separator) for files to be loaded by the data URL. This is needed only if the specified `url` is a data URL and needs to load other files.


Returns `Promise<void>` - the promise will resolve when the page has finished loading (see [`did-finish-load`](web-contents#event-did-finish-load)), and rejects if the page fails to load (see [`did-fail-load`](web-contents#event-did-fail-load)).


Same as [`webContents.loadURL(url[, options])`](web-contents#contentsloadurlurl-options).


The `url` can be a remote address (e.g. `http://`) or a path to a local HTML file using the `file://` protocol.


To ensure that file URLs are properly formatted, it is recommended to use Node's [`url.format`](https://nodejs.org/api/url.html#url_url_format_urlobject) method:




```
const url = require('url').format({
  protocol: 'file',
  slashes: true,
  pathname: require('path').join(__dirname, 'index.html')
})

win.loadURL(url)
```


You can load a URL using a `POST` request with URL-encoded data by doing the following:




```
win.loadURL('http://localhost:8000/post', {
  postData: [{
    type: 'rawData',
    bytes: Buffer.from('hello=world')
  }],
  extraHeaders: 'Content-Type: application/x-www-form-urlencoded'
})
```


#### 
`win.loadFile(filePath[, options])`[​](#winloadfilefilepath-options "Direct link to heading")


* `filePath` string
* `options` Object (optional)
	+ `query` Record<string, string> (optional) - Passed to `url.format()`.
	+ `search` string (optional) - Passed to `url.format()`.
	+ `hash` string (optional) - Passed to `url.format()`.


Returns `Promise<void>` - the promise will resolve when the page has finished loading (see [`did-finish-load`](web-contents#event-did-finish-load)), and rejects if the page fails to load (see [`did-fail-load`](web-contents#event-did-fail-load)).


Same as `webContents.loadFile`, `filePath` should be a path to an HTML file relative to the root of your application. See the `webContents` docs for more information.


#### 
`win.reload()`[​](#winreload "Direct link to heading")


Same as `webContents.reload`.


#### 
`win.setMenu(menu)` *Linux* *Windows*[​](#winsetmenumenu-linux-windows "Direct link to heading")


* `menu` Menu | null


Sets the `menu` as the window's menu bar.


#### 
`win.removeMenu()` *Linux* *Windows*[​](#winremovemenu-linux-windows "Direct link to heading")


Remove the window's menu bar.


#### 
`win.setProgressBar(progress[, options])`[​](#winsetprogressbarprogress-options "Direct link to heading")


* `progress` Double
* `options` Object (optional)
	+ `mode` string *Windows* - Mode for the progress bar. Can be `none`, `normal`, `indeterminate`, `error` or `paused`.


Sets progress value in progress bar. Valid range is [0, 1.0].


Remove progress bar when progress < 0; Change to indeterminate mode when progress > 1.


On Linux platform, only supports Unity desktop environment, you need to specify the `*.desktop` file name to `desktopName` field in `package.json`. By default, it will assume `{app.name}.desktop`.


On Windows, a mode can be passed. Accepted values are `none`, `normal`, `indeterminate`, `error`, and `paused`. If you call `setProgressBar` without a mode set (but with a value within the valid range), `normal` will be assumed.


#### 
`win.setOverlayIcon(overlay, description)` *Windows*[​](#winsetoverlayiconoverlay-description-windows "Direct link to heading")


* `overlay` [NativeImage](native-image) | null - the icon to display on the bottom right corner of the taskbar icon. If this parameter is `null`, the overlay is cleared
* `description` string - a description that will be provided to Accessibility screen readers


Sets a 16 x 16 pixel overlay onto the current taskbar icon, usually used to convey some sort of application status or to passively notify the user.


#### 
`win.setHasShadow(hasShadow)`[​](#winsethasshadowhasshadow "Direct link to heading")


* `hasShadow` boolean


Sets whether the window should have a shadow.


#### 
`win.hasShadow()`[​](#winhasshadow "Direct link to heading")


Returns `boolean` - Whether the window has a shadow.


#### 
`win.setOpacity(opacity)` *Windows* *macOS*[​](#winsetopacityopacity-windows-macos "Direct link to heading")


* `opacity` number - between 0.0 (fully transparent) and 1.0 (fully opaque)


Sets the opacity of the window. On Linux, does nothing. Out of bound number values are clamped to the [0, 1] range.


#### 
`win.getOpacity()`[​](#wingetopacity "Direct link to heading")


Returns `number` - between 0.0 (fully transparent) and 1.0 (fully opaque). On Linux, always returns 1.


#### 
`win.setShape(rects)` *Windows* *Linux* *Experimental*[​](#winsetshaperects-windows-linux-experimental "Direct link to heading")


* `rects` [Rectangle[]](structures/rectangle) - Sets a shape on the window. Passing an empty list reverts the window to being rectangular.


Setting a window shape determines the area within the window where the system permits drawing and user interaction. Outside of the given region, no pixels will be drawn and no mouse events will be registered. Mouse events outside of the region will not be received by that window, but will fall through to whatever is behind the window.


#### 
`win.setThumbarButtons(buttons)` *Windows*[​](#winsetthumbarbuttonsbuttons-windows "Direct link to heading")


* `buttons` [ThumbarButton[]](structures/thumbar-button)


Returns `boolean` - Whether the buttons were added successfully


Add a thumbnail toolbar with a specified set of buttons to the thumbnail image of a window in a taskbar button layout. Returns a `boolean` object indicates whether the thumbnail has been added successfully.


The number of buttons in thumbnail toolbar should be no greater than 7 due to the limited room. Once you setup the thumbnail toolbar, the toolbar cannot be removed due to the platform's limitation. But you can call the API with an empty array to clean the buttons.


The `buttons` is an array of `Button` objects:


* `Button` Object
	+ `icon` [NativeImage](native-image) - The icon showing in thumbnail toolbar.
	+ `click` Function
	+ `tooltip` string (optional) - The text of the button's tooltip.
	+ `flags` string[] (optional) - Control specific states and behaviors of the button. By default, it is `['enabled']`.


The `flags` is an array that can include following `string`s:


* `enabled` - The button is active and available to the user.
* `disabled` - The button is disabled. It is present, but has a visual state indicating it will not respond to user action.
* `dismissonclick` - When the button is clicked, the thumbnail window closes immediately.
* `nobackground` - Do not draw a button border, use only the image.
* `hidden` - The button is not shown to the user.
* `noninteractive` - The button is enabled but not interactive; no pressed button state is drawn. This value is intended for instances where the button is used in a notification.


#### 
`win.setThumbnailClip(region)` *Windows*[​](#winsetthumbnailclipregion-windows "Direct link to heading")


* `region` [Rectangle](structures/rectangle) - Region of the window


Sets the region of the window to show as the thumbnail image displayed when hovering over the window in the taskbar. You can reset the thumbnail to be the entire window by specifying an empty region: `{ x: 0, y: 0, width: 0, height: 0 }`.


#### 
`win.setThumbnailToolTip(toolTip)` *Windows*[​](#winsetthumbnailtooltiptooltip-windows "Direct link to heading")


* `toolTip` string


Sets the toolTip that is displayed when hovering over the window thumbnail in the taskbar.


#### 
`win.setAppDetails(options)` *Windows*[​](#winsetappdetailsoptions-windows "Direct link to heading")


* `options` Object
	+ `appId` string (optional) - Window's [App User Model ID](https://msdn.microsoft.com/en-us/library/windows/desktop/dd391569(v=vs.85).aspx). It has to be set, otherwise the other options will have no effect.
	+ `appIconPath` string (optional) - Window's [Relaunch Icon](https://msdn.microsoft.com/en-us/library/windows/desktop/dd391573(v=vs.85).aspx).
	+ `appIconIndex` Integer (optional) - Index of the icon in `appIconPath`. Ignored when `appIconPath` is not set. Default is `0`.
	+ `relaunchCommand` string (optional) - Window's [Relaunch Command](https://msdn.microsoft.com/en-us/library/windows/desktop/dd391571(v=vs.85).aspx).
	+ `relaunchDisplayName` string (optional) - Window's [Relaunch Display Name](https://msdn.microsoft.com/en-us/library/windows/desktop/dd391572(v=vs.85).aspx).


Sets the properties for the window's taskbar button.


**Note:** `relaunchCommand` and `relaunchDisplayName` must always be set together. If one of those properties is not set, then neither will be used.


#### 
`win.showDefinitionForSelection()` *macOS*[​](#winshowdefinitionforselection-macos "Direct link to heading")


Same as `webContents.showDefinitionForSelection()`.


#### 
`win.setIcon(icon)` *Windows* *Linux*[​](#winseticonicon-windows-linux "Direct link to heading")


* `icon` [NativeImage](native-image) | string


Changes window icon.


#### 
`win.setWindowButtonVisibility(visible)` *macOS*[​](#winsetwindowbuttonvisibilityvisible-macos "Direct link to heading")


* `visible` boolean


Sets whether the window traffic light buttons should be visible.


#### 
`win.setAutoHideMenuBar(hide)` *Windows* *Linux*[​](#winsetautohidemenubarhide-windows-linux "Direct link to heading")


* `hide` boolean


Sets whether the window menu bar should hide itself automatically. Once set the menu bar will only show when users press the single `Alt` key.


If the menu bar is already visible, calling `setAutoHideMenuBar(true)` won't hide it immediately.


#### 
`win.isMenuBarAutoHide()` *Windows* *Linux*[​](#winismenubarautohide-windows-linux "Direct link to heading")


Returns `boolean` - Whether menu bar automatically hides itself.


#### 
`win.setMenuBarVisibility(visible)` *Windows* *Linux*[​](#winsetmenubarvisibilityvisible-windows-linux "Direct link to heading")


* `visible` boolean


Sets whether the menu bar should be visible. If the menu bar is auto-hide, users can still bring up the menu bar by pressing the single `Alt` key.


#### 
`win.isMenuBarVisible()` *Windows* *Linux*[​](#winismenubarvisible-windows-linux "Direct link to heading")


Returns `boolean` - Whether the menu bar is visible.


#### 
`win.setVisibleOnAllWorkspaces(visible[, options])` *macOS* *Linux*[​](#winsetvisibleonallworkspacesvisible-options-macos-linux "Direct link to heading")


* `visible` boolean
* `options` Object (optional)
	+ `visibleOnFullScreen` boolean (optional) *macOS* - Sets whether the window should be visible above fullscreen windows.
	+ `skipTransformProcessType` boolean (optional) *macOS* - Calling setVisibleOnAllWorkspaces will by default transform the process type between UIElementApplication and ForegroundApplication to ensure the correct behavior. However, this will hide the window and dock for a short time every time it is called. If your window is already of type UIElementApplication, you can bypass this transformation by passing true to skipTransformProcessType.


Sets whether the window should be visible on all workspaces.


**Note:** This API does nothing on Windows.


#### 
`win.isVisibleOnAllWorkspaces()` *macOS* *Linux*[​](#winisvisibleonallworkspaces-macos-linux "Direct link to heading")


Returns `boolean` - Whether the window is visible on all workspaces.


**Note:** This API always returns false on Windows.


#### 
`win.setIgnoreMouseEvents(ignore[, options])`[​](#winsetignoremouseeventsignore-options "Direct link to heading")


* `ignore` boolean
* `options` Object (optional)
	+ `forward` boolean (optional) *macOS* *Windows* - If true, forwards mouse move messages to Chromium, enabling mouse related events such as `mouseleave`. Only used when `ignore` is true. If `ignore` is false, forwarding is always disabled regardless of this value.


Makes the window ignore all mouse events.


All mouse events happened in this window will be passed to the window below this window, but if this window has focus, it will still receive keyboard events.


#### 
`win.setContentProtection(enable)` *macOS* *Windows*[​](#winsetcontentprotectionenable-macos-windows "Direct link to heading")


* `enable` boolean


Prevents the window contents from being captured by other apps.


On macOS it sets the NSWindow's sharingType to NSWindowSharingNone. On Windows it calls SetWindowDisplayAffinity with `WDA_EXCLUDEFROMCAPTURE`. For Windows 10 version 2004 and up the window will be removed from capture entirely, older Windows versions behave as if `WDA_MONITOR` is applied capturing a black window.


#### 
`win.setFocusable(focusable)` *macOS* *Windows*[​](#winsetfocusablefocusable-macos-windows "Direct link to heading")


* `focusable` boolean


Changes whether the window can be focused.


On macOS it does not remove the focus from the window.


#### 
`win.isFocusable()` *macOS* *Windows*[​](#winisfocusable-macos-windows "Direct link to heading")


Returns whether the window can be focused.


#### 
`win.setParentWindow(parent)`[​](#winsetparentwindowparent "Direct link to heading")


* `parent` BrowserWindow | null


Sets `parent` as current window's parent window, passing `null` will turn current window into a top-level window.


#### 
`win.getParentWindow()`[​](#wingetparentwindow "Direct link to heading")


Returns `BrowserWindow | null` - The parent window or `null` if there is no parent.


#### 
`win.getChildWindows()`[​](#wingetchildwindows "Direct link to heading")


Returns `BrowserWindow[]` - All child windows.


#### 
`win.setAutoHideCursor(autoHide)` *macOS*[​](#winsetautohidecursorautohide-macos "Direct link to heading")


* `autoHide` boolean


Controls whether to hide cursor when typing.


#### 
`win.selectPreviousTab()` *macOS*[​](#winselectprevioustab-macos "Direct link to heading")


Selects the previous tab when native tabs are enabled and there are other tabs in the window.


#### 
`win.selectNextTab()` *macOS*[​](#winselectnexttab-macos "Direct link to heading")


Selects the next tab when native tabs are enabled and there are other tabs in the window.


#### 
`win.mergeAllWindows()` *macOS*[​](#winmergeallwindows-macos "Direct link to heading")


Merges all windows into one window with multiple tabs when native tabs are enabled and there is more than one open window.


#### 
`win.moveTabToNewWindow()` *macOS*[​](#winmovetabtonewwindow-macos "Direct link to heading")


Moves the current tab into a new window if native tabs are enabled and there is more than one tab in the current window.


#### 
`win.toggleTabBar()` *macOS*[​](#wintoggletabbar-macos "Direct link to heading")


Toggles the visibility of the tab bar if native tabs are enabled and there is only one tab in the current window.


#### 
`win.addTabbedWindow(browserWindow)` *macOS*[​](#winaddtabbedwindowbrowserwindow-macos "Direct link to heading")


* `browserWindow` BrowserWindow


Adds a window as a tab on this window, after the tab for the window instance.


#### 
`win.setVibrancy(type)` *macOS*[​](#winsetvibrancytype-macos "Direct link to heading")


* `type` string | null - Can be `appearance-based`, `light`, `dark`, `titlebar`, `selection`, `menu`, `popover`, `sidebar`, `medium-light`, `ultra-dark`, `header`, `sheet`, `window`, `hud`, `fullscreen-ui`, `tooltip`, `content`, `under-window`, or `under-page`. See the [macOS documentation](https://developer.apple.com/documentation/appkit/nsvisualeffectview?preferredLanguage=objc) for more details.


Adds a vibrancy effect to the browser window. Passing `null` or an empty string will remove the vibrancy effect on the window.


Note that `appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` have been deprecated and will be removed in an upcoming version of macOS.


#### 
`win.setTrafficLightPosition(position)` *macOS*[​](#winsettrafficlightpositionposition-macos "Direct link to heading")


* `position` [Point](structures/point)


Set a custom position for the traffic light buttons in frameless window.


#### 
`win.getTrafficLightPosition()` *macOS*[​](#wingettrafficlightposition-macos "Direct link to heading")


Returns `Point` - The custom position for the traffic light buttons in frameless window.


#### 
`win.setTouchBar(touchBar)` *macOS*[​](#winsettouchbartouchbar-macos "Direct link to heading")


* `touchBar` TouchBar | null


Sets the touchBar layout for the current window. Specifying `null` or `undefined` clears the touch bar. This method only has an effect if the machine has a touch bar and is running on macOS 10.12.1+.


**Note:** The TouchBar API is currently experimental and may change or be removed in future Electron releases.


#### 
`win.setBrowserView(browserView)` *Experimental*[​](#winsetbrowserviewbrowserview-experimental "Direct link to heading")


* `browserView` [BrowserView](browser-view) | null - Attach `browserView` to `win`. If there are other `BrowserView`s attached, they will be removed from this window.


#### 
`win.getBrowserView()` *Experimental*[​](#wingetbrowserview-experimental "Direct link to heading")


Returns `BrowserView | null` - The `BrowserView` attached to `win`. Returns `null` if one is not attached. Throws an error if multiple `BrowserView`s are attached.


#### 
`win.addBrowserView(browserView)` *Experimental*[​](#winaddbrowserviewbrowserview-experimental "Direct link to heading")


* `browserView` [BrowserView](browser-view)


Replacement API for setBrowserView supporting work with multi browser views.


#### 
`win.removeBrowserView(browserView)` *Experimental*[​](#winremovebrowserviewbrowserview-experimental "Direct link to heading")


* `browserView` [BrowserView](browser-view)


#### 
`win.setTopBrowserView(browserView)` *Experimental*[​](#winsettopbrowserviewbrowserview-experimental "Direct link to heading")


* `browserView` [BrowserView](browser-view)


Raises `browserView` above other `BrowserView`s attached to `win`. Throws an error if `browserView` is not attached to `win`.


#### 
`win.getBrowserViews()` *Experimental*[​](#wingetbrowserviews-experimental "Direct link to heading")


Returns `BrowserView[]` - an array of all BrowserViews that have been attached with `addBrowserView` or `setBrowserView`.


**Note:** The BrowserView API is currently experimental and may change or be removed in future Electron releases.


#### 
`win.setTitleBarOverlay(options)` *Windows*[​](#winsettitlebaroverlayoptions-windows "Direct link to heading")


* `options` Object
	+ `color` String (optional) *Windows* - The CSS color of the Window Controls Overlay when enabled.
	+ `symbolColor` String (optional) *Windows* - The CSS color of the symbols on the Window Controls Overlay when enabled.
	+ `height` Integer (optional) *Windows* - The height of the title bar and Window Controls Overlay in pixels.


On a Window with Window Controls Overlay already enabled, this method updates the style of the title bar overlay.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/browser-window>

Packaging Your Application
==========================



Follow along the tutorial

This is **part 5** of the Electron tutorial.


1. [Prerequisites](tutorial-prerequisites)
2. [Building your First App](tutorial-first-app)
3. [Using Preload Scripts](tutorial-preload)
4. [Adding Features](tutorial-adding-features)
5. **[Packaging Your Application](tutorial-packaging)**
6. [Publishing and Updating](tutorial-publishing-updating)




Learning goals[​](#learning-goals "Direct link to heading")
-----------------------------------------------------------


In this part of the tutorial, we'll be going over the basics of packaging and distributing your app with [Electron Forge](https://www.electronforge.io).


Using Electron Forge[​](#using-electron-forge "Direct link to heading")
-----------------------------------------------------------------------


Electron does not have any tooling for packaging and distribution bundled into its core modules. Once you have a working Electron app in dev mode, you need to use additional tooling to create a packaged app you can distribute to your users (also known as a **distributable**). Distributables can be either installers (e.g. MSI on Windows) or portable executable files (e.g. `.app` on macOS).


Electron Forge is an all-in-one tool that handles the packaging and distribution of Electron apps. Under the hood, it combines a lot of existing Electron tools (e.g. [`electron-packager`](https://github.com/electron/electron-packager), [`@electron/osx-sign`](https://github.com/electron/osx-sign), [`electron-winstaller`](https://github.com/electron/windows-installer), etc.) into a single interface so you do not have to worry about wiring them all together.


### Importing your project into Forge[​](#importing-your-project-into-forge "Direct link to heading")


You can install Electron Forge's CLI in your project's `devDependencies` and import your existing project with a handy conversion script.



* npm
* Yarn





```
npm install --save-dev @electron-forge/cli
npx electron-forge import
```




```
yarn add --dev @electron-forge/cli
npx electron-forge import
```




Once the conversion script is done, Forge should have added a few scripts to your `package.json` file.



package.json


```
  //...
  "scripts": {
    "start": "electron-forge start",
    "package": "electron-forge package",
    "make": "electron-forge make"
  },
  //...
```





CLI documentation
For more information on `make` and other Forge APIs, check out the [Electron Forge CLI documentation](https://www.electronforge.io/cli#commands).



You should also notice that your package.json now has a few more packages installed under your `devDependencies`, and contains an added `config.forge` field with an array of makers configured. **Makers** are Forge plugins that create distributables from your source code. You should see multiple makers in the pre-populated configuration, one for each target platform.


### Creating a distributable[​](#creating-a-distributable "Direct link to heading")


To create a distributable, use your project's new `make` script, which runs the `electron-forge make` command.



* npm
* Yarn





```
npm run make
```




```
yarn run make
```




This `make` command contains two steps:


1. It will first run `electron-forge package` under the hood, which bundles your app code together with the Electron binary. The packaged code is generated into a folder.
2. It will then use this packaged app folder to create a separate distributable for each configured maker.


After the script runs, you should see an `out` folder containing both the distributable and a folder containing the packaged application code.



macOS output example


```
out/
├── out/make/zip/darwin/x64/my-electron-app-darwin-x64-1.0.0.zip
├── ...
└── out/my-electron-app-darwin-x64/my-electron-app.app/Contents/MacOS/my-electron-app
```



The distributable in the `out/make` folder should be ready to launch! You have now created your first bundled Electron application.




Distributable formats
Electron Forge can be configured to create distributables in different OS-specific formats (e.g. DMG, deb, MSI, etc.). See Forge's [Makers](https://www.electronforge.io/config/makers) documentation for all configuration options.





Packaging without Electron Forge
If you want to manually package your code, or if you're just interested understanding the mechanics behind packaging an Electron app, check out the full [Application Packaging](application-distribution) documentation.



Important: signing your code[​](#important-signing-your-code "Direct link to heading")
--------------------------------------------------------------------------------------


In order to distribute desktop applications to end users, we *highly recommended* for you to **code sign** your Electron app. Code signing is an important part of shipping desktop applications, and is mandatory for the auto-update step in the final part of the tutorial.


Code signing is a security technology that you use to certify that a desktop app was created by a known source. Windows and macOS have their own OS-specific code signing systems that will make it difficult for users to download or launch unsigned applications.


If you already have code signing certificates for Windows and macOS, you can set your credentials in your Forge configuration. Otherwise, please refer to the full [Code Signing](code-signing) documentation to learn how to purchase a certificate and for more information on the desktop app code signing process.


On macOS, code signing is done at the app packaging level. On Windows, distributable installers are signed instead.



* macOS
* Windows




package.json


```
{
  //...
  "config": {
    "forge": {
      //...
      "packagerConfig": {
        "osxSign": {
          "identity": "Developer ID Application: Felix Rieseberg (LT94ZKYDCJ)",
          "hardened-runtime": true,
          "entitlements": "entitlements.plist",
          "entitlements-inherit": "entitlements.plist",
          "signature-flags": "library"
        },
        "osxNotarize": {
          "appleId": "felix@felix.fun",
          "appleIdPassword": "this-is-a-secret"
        }
      }
      //...
    }
  }
  //...
}
```




package.json


```
{
  //...
  "config": {
    "forge": {
      //...
      "makers": [
        {
          "name": "@electron-forge/maker-squirrel",
          "config": {
            "certificateFile": "./cert.pfx",
            "certificatePassword": "this-is-a-secret"
          }
        }
      ]
      //...
    }
  }
  //...
}
```





Summary[​](#summary "Direct link to heading")
---------------------------------------------


Electron applications need to be packaged to be distributed to users. In this tutorial, you imported your app into Electron Forge and configured it to package your app and generate installers.


In order for your application to be trusted by the user's system, you need to digitally certify that the distributable is authentic and untampered by code signing it. Your app can be signed through Forge once you configure it to use your code signing certificate information.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/tutorial-packaging>

Publishing and Updating
=======================



Follow along the tutorial

This is **part 6** of the Electron tutorial.


1. [Prerequisites](tutorial-prerequisites)
2. [Building your First App](tutorial-first-app)
3. [Using Preload Scripts](tutorial-preload)
4. [Adding Features](tutorial-adding-features)
5. [Packaging Your Application](tutorial-packaging)
6. **[Publishing and Updating](tutorial-publishing-updating)**




Learning goals[​](#learning-goals "Direct link to heading")
-----------------------------------------------------------


If you've been following along, this is the last step of the tutorial! In this part, you will publish your app to GitHub releases and integrate automatic updates into your app code.


Using update.electronjs.org[​](#using-updateelectronjsorg "Direct link to heading")
-----------------------------------------------------------------------------------


The Electron maintainers provide a free auto-updating service for open-source apps at <https://update.electronjs.org.> Its requirements are:


* Your app runs on macOS or Windows
* Your app has a public GitHub repository
* Builds are published to [GitHub releases](https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository)
* Builds are [code signed](code-signing)


At this point, we'll assume that you have already pushed all your code to a public GitHub repository.




Alternative update services
If you're using an alternate repository host (e.g. GitLab or Bitbucket) or if you need to keep your code repository private, please refer to our [step-by-step guide](updates) on hosting your own Electron update server.



Publishing a GitHub release[​](#publishing-a-github-release "Direct link to heading")
-------------------------------------------------------------------------------------


Electron Forge has [Publisher](https://www.electronforge.io/config/publishers) plugins that can automate the distribution of your packaged application to various sources. In this tutorial, we will be using the GitHub Publisher, which will allow us to publish our code to GitHub releases.


### Generating a personal access token[​](#generating-a-personal-access-token "Direct link to heading")


Forge cannot publish to any repository on GitHub without permission. You need to pass in an authenticated token that gives Forge access to your GitHub releases. The easiest way to do this is to [create a new personal access token (PAT)](https://github.com/settings/tokens/new) with the `public_repo` scope, which gives write access to your public repositories. **Make sure to keep this token a secret.**


### Setting up the GitHub Publisher[​](#setting-up-the-github-publisher "Direct link to heading")


#### Installing the module[​](#installing-the-module "Direct link to heading")


Forge's [GitHub Publisher](https://www.electronforge.io/config/publishers/github) is a plugin that needs to be installed in your project's `devDependencies`:



* npm
* Yarn





```
npm install --save-dev @electron-forge/publisher-github
```




```
yarn add --dev @electron-forge/publisher-github
```




#### Configuring the publisher in Forge[​](#configuring-the-publisher-in-forge "Direct link to heading")


Once you have it installed, you need to set it up in your Forge configuration. A full list of options is documented in the Forge's [`PublisherGitHubConfig`](https://js.electronforge.io/publisher/github/interfaces/publishergithubconfig) API docs.



package.json


```
{
  //...
  "config": {
    "forge": {
      "publishers": [
        {
          "name": "@electron-forge/publisher-github",
          "config": {
            "repository": {
              "owner": "github-user-name",
              "name": "github-repo-name"
            },
            "prerelease": false,
            "draft": true
          }
        }
      ]
    }
  }
  //...
}
```





Drafting releases before publishing
Notice that you have configured Forge to publish your release as a draft. This will allow you to see the release with its generated artifacts without actually publishing it to your end users. You can manually publish your releases via GitHub after writing release notes and double-checking that your distributables work.



#### Setting up your authentication token[​](#setting-up-your-authentication-token "Direct link to heading")


You also need to make the Publisher aware of your authentication token. By default, it will use the value stored in the `GITHUB_TOKEN` environment variable.


### Running the publish command[​](#running-the-publish-command "Direct link to heading")


Add Forge's [publish command](https://www.electronforge.io/cli#publish) to your npm scripts.



package.json


```
  //...
  "scripts": {
    "start": "electron-forge start",
    "package": "electron-forge package",
    "make": "electron-forge make",
    "publish": "electron-forge publish"
  },
  //...
```



This command will run your configured makers and publish the output distributables to a new GitHub release.



* npm
* Yarn





```
npm run publish
```




```
yarn run publish
```




By default, this will only publish a single distributable for your host operating system and architecture. You can publish for different architectures by passing in the `--arch` flag to your Forge commands.


The name of this release will correspond to the `version` field in your project's package.json file.




Tagging releases
Optionally, you can also [tag your releases in Git][git-tag] so that your release is associated with a labeled point in your code history. npm comes with a handy [`npm version`](https://docs.npmjs.com/cli/v8/commands/npm-version) command that can handle the version bumping and tagging for you.



#### Bonus: Publishing in GitHub Actions[​](#bonus-publishing-in-github-actions "Direct link to heading")


Publishing locally can be painful, especially because you can only create distributables for your host operating system (i.e. you can't publish a Window `.exe` file from macOS).


A solution for this would be to publish your app via automation workflows such as [GitHub Actions](https://github.com/features/actions), which can run tasks in the cloud on Ubuntu, macOS, and Windows. This is the exact approach taken by [Electron Fiddle](https://electronjs.org/fiddle). You can refer to Fiddle's [Build and Release pipeline](https://github.com/electron/fiddle/blob/master/.github/workflows/build.yaml) and [Forge configuration](https://github.com/electron/fiddle/blob/master/forge.config.js) for more details.


Instrumenting your updater code[​](#instrumenting-your-updater-code "Direct link to heading")
---------------------------------------------------------------------------------------------


Now that we have a functional release system via GitHub releases, we now need to tell our Electron app to download an update whenever a new release is out. Electron apps do this via the [autoUpdater](../api/auto-updater) module, which reads from an update server feed to check if a new version is available for download.


The update.electronjs.org service provides an updater-compatible feed. For example, Electron Fiddle v0.28.0 will check the endpoint at <https://update.electronjs.org/electron/fiddle/darwin/v0.28.0> to see if a newer GitHub release is available.


After your release is published to GitHub, the update.electronjs.org service should work for your application. The only step left is to configure the feed with the autoUpdater module.


To make this process easier, the Electron team maintains the [`update-electron-app`](https://github.com/electron/update-electron-app) module, which sets up the autoUpdater boilerplate for update.electronjs.org in one function call — no configuration required. This module will search for the update.electronjs.org feed that matches your project's package.json `"repository"` field.


First, install the module as a runtime dependency.



* npm
* Yarn





```
npm install update-electron-app
```




```
yarn add update-electron-app
```




Then, import the module and call it immediately in the main process.



main.js


```
require('update-electron-app')()
```



And that is all it takes! Once your application is packaged, it will update itself for each new GitHub release that you publish.


Summary[​](#summary "Direct link to heading")
---------------------------------------------


In this tutorial, we configured Electron Forge's GitHub Publisher to upload your app's distributables to GitHub releases. Since distributables cannot always be generated between platforms, we recommend setting up your building and publishing flow in a Continuous Integration pipeline if you do not have access to machines.


Electron applications can self-update by pointing the autoUpdater module to an update server feed. update.electronjs.org is a free update server provided by Electron for open-source applications published on GitHub releases. Configuring your Electron app to use this service is as easy as installing and importing the `update-electron-app` module.


If your application is not eligible for update.electronjs.org, you should instead deploy your own update server and configure the autoUpdater module yourself.




🌟 You're done!
From here, you have officially completed our tutorial to Electron. Feel free to explore the rest of our docs and happy developing! If you have questions, please stop by our community [Discord server](https://discord.com/invite/APGC3k5yaH).




 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/tutorial-publishing-updating>

Class: CommandLine
==================

Class: CommandLine[​](#class-commandline "Direct link to heading")
------------------------------------------------------------------



> Manipulate the command line arguments for your app that Chromium reads
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


The following example shows how to check if the `--disable-gpu` flag is set.




```
const { app } = require('electron')
app.commandLine.hasSwitch('disable-gpu')
```


For more information on what kinds of flags and switches you can use, check out the [Command Line Switches](command-line-switches) document.


### Instance Methods[​](#instance-methods "Direct link to heading")


#### 
`commandLine.appendSwitch(switch[, value])`[​](#commandlineappendswitchswitch-value "Direct link to heading")


* `switch` string - A command-line switch, without the leading `--`
* `value` string (optional) - A value for the given switch


Append a switch (with optional `value`) to Chromium's command line.


**Note:** This will not affect `process.argv`. The intended usage of this function is to control Chromium's behavior.


#### 
`commandLine.appendArgument(value)`[​](#commandlineappendargumentvalue "Direct link to heading")


* `value` string - The argument to append to the command line


Append an argument to Chromium's command line. The argument will be quoted correctly. Switches will precede arguments regardless of appending order.


If you're appending an argument like `--switch=value`, consider using `appendSwitch('switch', 'value')` instead.


**Note:** This will not affect `process.argv`. The intended usage of this function is to control Chromium's behavior.


#### 
`commandLine.hasSwitch(switch)`[​](#commandlinehasswitchswitch "Direct link to heading")


* `switch` string - A command-line switch


Returns `boolean` - Whether the command-line switch is present.


#### 
`commandLine.getSwitchValue(switch)`[​](#commandlinegetswitchvalueswitch "Direct link to heading")


* `switch` string - A command-line switch


Returns `string` - The command-line switch value.


**Note:** When the switch is not present or has no value, it returns empty string.


#### 
`commandLine.removeSwitch(switch)`[​](#commandlineremoveswitchswitch "Direct link to heading")


* `switch` string - A command-line switch


Removes the specified switch from Chromium's command line.


**Note:** This will not affect `process.argv`. The intended usage of this function is to control Chromium's behavior.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/command-line>

Class: Dock
===========

Class: Dock[​](#class-dock "Direct link to heading")
----------------------------------------------------



> Control your app in the macOS dock
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


The following example shows how to bounce your icon on the dock.




```
const { app } = require('electron')
app.dock.bounce()
```


### Instance Methods[​](#instance-methods "Direct link to heading")


#### 
`dock.bounce([type])` *macOS*[​](#dockbouncetype-macos "Direct link to heading")


* `type` string (optional) - Can be `critical` or `informational`. The default is `informational`


Returns `Integer` - an ID representing the request.


When `critical` is passed, the dock icon will bounce until either the application becomes active or the request is canceled.


When `informational` is passed, the dock icon will bounce for one second. However, the request remains active until either the application becomes active or the request is canceled.


**Note:** This method can only be used while the app is not focused; when the app is focused it will return -1.


#### 
`dock.cancelBounce(id)` *macOS*[​](#dockcancelbounceid-macos "Direct link to heading")


* `id` Integer


Cancel the bounce of `id`.


#### 
`dock.downloadFinished(filePath)` *macOS*[​](#dockdownloadfinishedfilepath-macos "Direct link to heading")


* `filePath` string


Bounces the Downloads stack if the filePath is inside the Downloads folder.


#### 
`dock.setBadge(text)` *macOS*[​](#docksetbadgetext-macos "Direct link to heading")


* `text` string


Sets the string to be displayed in the dock’s badging area.


#### 
`dock.getBadge()` *macOS*[​](#dockgetbadge-macos "Direct link to heading")


Returns `string` - The badge string of the dock.


#### 
`dock.hide()` *macOS*[​](#dockhide-macos "Direct link to heading")


Hides the dock icon.


#### 
`dock.show()` *macOS*[​](#dockshow-macos "Direct link to heading")


Returns `Promise<void>` - Resolves when the dock icon is shown.


#### 
`dock.isVisible()` *macOS*[​](#dockisvisible-macos "Direct link to heading")


Returns `boolean` - Whether the dock icon is visible.


#### 
`dock.setMenu(menu)` *macOS*[​](#docksetmenumenu-macos "Direct link to heading")


* `menu` [Menu](menu)


Sets the application's [dock menu][dock-menu].


#### 
`dock.getMenu()` *macOS*[​](#dockgetmenu-macos "Direct link to heading")


Returns `Menu | null` - The application's [dock menu][dock-menu].


#### 
`dock.setIcon(image)` *macOS*[​](#dockseticonimage-macos "Direct link to heading")


* `image` ([NativeImage](native-image) | string)


Sets the `image` associated with this dock icon.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/dock>

autoUpdater
===========



> Enable apps to automatically update themselves.
> 
> 


Process: [Main](../glossary#main-process)


**See also: [A detailed guide about how to implement updates in your application](../tutorial/updates).**


`autoUpdater` is an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter).


Platform Notices[​](#platform-notices "Direct link to heading")
---------------------------------------------------------------


Currently, only macOS and Windows are supported. There is no built-in support for auto-updater on Linux, so it is recommended to use the distribution's package manager to update your app.


In addition, there are some subtle differences on each platform:


### macOS[​](#macos "Direct link to heading")


On macOS, the `autoUpdater` module is built upon [Squirrel.Mac](https://github.com/Squirrel/Squirrel.Mac), meaning you don't need any special setup to make it work. For server-side requirements, you can read [Server Support](https://github.com/Squirrel/Squirrel.Mac#server-support). Note that [App Transport Security](https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW35) (ATS) applies to all requests made as part of the update process. Apps that need to disable ATS can add the `NSAllowsArbitraryLoads` key to their app's plist.


**Note:** Your application must be signed for automatic updates on macOS. This is a requirement of `Squirrel.Mac`.


### Windows[​](#windows "Direct link to heading")


On Windows, you have to install your app into a user's machine before you can use the `autoUpdater`, so it is recommended that you use the [electron-winstaller](https://github.com/electron/windows-installer), [electron-forge](https://github.com/electron-userland/electron-forge) or the [grunt-electron-installer](https://github.com/electron/grunt-electron-installer) package to generate a Windows installer.


When using [electron-winstaller](https://github.com/electron/windows-installer) or [electron-forge](https://github.com/electron-userland/electron-forge) make sure you do not try to update your app [the first time it runs](https://github.com/electron/windows-installer#handling-squirrel-events) (Also see [this issue for more info](https://github.com/electron/electron/issues/7155)). It's also recommended to use [electron-squirrel-startup](https://github.com/mongodb-js/electron-squirrel-startup) to get desktop shortcuts for your app.


The installer generated with Squirrel will create a shortcut icon with an [Application User Model ID](https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx) in the format of `com.squirrel.PACKAGE_ID.YOUR_EXE_WITHOUT_DOT_EXE`, examples are `com.squirrel.slack.Slack` and `com.squirrel.code.Code`. You have to use the same ID for your app with `app.setAppUserModelId` API, otherwise Windows will not be able to pin your app properly in task bar.


Like Squirrel.Mac, Windows can host updates on S3 or any other static file host. You can read the documents of [Squirrel.Windows](https://github.com/Squirrel/Squirrel.Windows) to get more details about how Squirrel.Windows works.


Events[​](#events "Direct link to heading")
-------------------------------------------


The `autoUpdater` object emits the following events:


### Event: 'error'[​](#event-error "Direct link to heading")


Returns:


* `error` Error


Emitted when there is an error while updating.


### Event: 'checking-for-update'[​](#event-checking-for-update "Direct link to heading")


Emitted when checking if an update has started.


### Event: 'update-available'[​](#event-update-available "Direct link to heading")


Emitted when there is an available update. The update is downloaded automatically.


### Event: 'update-not-available'[​](#event-update-not-available "Direct link to heading")


Emitted when there is no available update.


### Event: 'update-downloaded'[​](#event-update-downloaded "Direct link to heading")


Returns:


* `event` Event
* `releaseNotes` string
* `releaseName` string
* `releaseDate` Date
* `updateURL` string


Emitted when an update has been downloaded.


On Windows only `releaseName` is available.


**Note:** It is not strictly necessary to handle this event. A successfully downloaded update will still be applied the next time the application starts.


### Event: 'before-quit-for-update'[​](#event-before-quit-for-update "Direct link to heading")


This event is emitted after a user calls `quitAndInstall()`.


When this API is called, the `before-quit` event is not emitted before all windows are closed. As a result you should listen to this event if you wish to perform actions before the windows are closed while a process is quitting, as well as listening to `before-quit`.


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `autoUpdater` object has the following methods:


### 
`autoUpdater.setFeedURL(options)`[​](#autoupdatersetfeedurloptions "Direct link to heading")


* `options` Object
	+ `url` string
	+ `headers` Record<string, string> (optional) *macOS* - HTTP request headers.
	+ `serverType` string (optional) *macOS* - Can be `json` or `default`, see the [Squirrel.Mac](https://github.com/Squirrel/Squirrel.Mac) README for more information.


Sets the `url` and initialize the auto updater.


### 
`autoUpdater.getFeedURL()`[​](#autoupdatergetfeedurl "Direct link to heading")


Returns `string` - The current update feed URL.


### 
`autoUpdater.checkForUpdates()`[​](#autoupdatercheckforupdates "Direct link to heading")


Asks the server whether there is an update. You must call `setFeedURL` before using this API.


**Note:** If an update is available it will be downloaded automatically. Calling `autoUpdater.checkForUpdates()` twice will download the update two times.


### 
`autoUpdater.quitAndInstall()`[​](#autoupdaterquitandinstall "Direct link to heading")


Restarts the app and installs the update after it has been downloaded. It should only be called after `update-downloaded` has been emitted.


Under the hood calling `autoUpdater.quitAndInstall()` will close all application windows first, and automatically call `app.quit()` after all windows have been closed.


**Note:** It is not strictly necessary to call this function to apply an update, as a successfully downloaded update will always be applied the next time the application starts.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/auto-updater>

Dark Mode
=========


Overview[​](#overview "Direct link to heading")
-----------------------------------------------


### Automatically update the native interfaces[​](#automatically-update-the-native-interfaces "Direct link to heading")


"Native interfaces" include the file picker, window border, dialogs, context menus, and more - anything where the UI comes from your operating system and not from your app. The default behavior is to opt into this automatic theming from the OS.


### Automatically update your own interfaces[​](#automatically-update-your-own-interfaces "Direct link to heading")


If your app has its own dark mode, you should toggle it on and off in sync with the system's dark mode setting. You can do this by using the [prefer-color-scheme] CSS media query.


### Manually update your own interfaces[​](#manually-update-your-own-interfaces "Direct link to heading")


If you want to manually switch between light/dark modes, you can do this by setting the desired mode in the [themeSource](../api/native-theme#nativethemethemesource) property of the `nativeTheme` module. This property's value will be propagated to your Renderer process. Any CSS rules related to `prefers-color-scheme` will be updated accordingly.


macOS settings[​](#macos-settings "Direct link to heading")
-----------------------------------------------------------


In macOS 10.14 Mojave, Apple introduced a new [system-wide dark mode](https://developer.apple.com/design/human-interface-guidelines/macos/visual-design/dark-mode/) for all macOS computers. If your Electron app has a dark mode, you can make it follow the system-wide dark mode setting using [the `nativeTheme` api](../api/native-theme).


In macOS 10.15 Catalina, Apple introduced a new "automatic" dark mode option for all macOS computers. In order for the `nativeTheme.shouldUseDarkColors` and `Tray` APIs to work correctly in this mode on Catalina, you need to use Electron `>=7.0.0`, or set `NSRequiresAquaSystemAppearance` to `false` in your `Info.plist` file for older versions. Both [Electron Packager](https://github.com/electron/electron-packager) and [Electron Forge](https://www.electronforge.io/) have a [`darwinDarkModeSupport` option](https://electron.github.io/electron-packager/main/interfaces/electronpackager.options.html#darwindarkmodesupport) to automate the `Info.plist` changes during app build time.


If you wish to opt-out while using Electron > 8.0.0, you must set the `NSRequiresAquaSystemAppearance` key in the `Info.plist` file to `true`. Please note that Electron 8.0.0 and above will not let you opt-out of this theming, due to the use of the macOS 10.14 SDK.


Example[​](#example "Direct link to heading")
---------------------------------------------


This example demonstrates an Electron application that derives its theme colors from the `nativeTheme`. Additionally, it provides theme toggle and reset controls using IPC channels.




[docs/fiddles/features/macos-dark-mode (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/features/macos-dark-mode)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/features/macos-dark-mode)


* main.js
* preload.js
* index.html
* renderer.js
* styles.css





```
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron')
const path = require('path')

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  win.loadFile('index.html')

  ipcMain.handle('dark-mode:toggle', () => {
    if (nativeTheme.shouldUseDarkColors) {
      nativeTheme.themeSource = 'light'
    } else {
      nativeTheme.themeSource = 'dark'
    }
    return nativeTheme.shouldUseDarkColors
  })

  ipcMain.handle('dark-mode:system', () => {
    nativeTheme.themeSource = 'system'
  })
}

app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow()
    }
  })
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})
```




```
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('darkMode', {
  toggle: () => ipcRenderer.invoke('dark-mode:toggle'),
  system: () => ipcRenderer.invoke('dark-mode:system')
})
```




```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
    <link rel="stylesheet" type="text/css" href="./styles.css">
</head>
<body>
    <h1>Hello World!</h1>
    <p>Current theme source: <strong id="theme-source">System</strong></p>

    <button id="toggle-dark-mode">Toggle Dark Mode</button>
    <button id="reset-to-system">Reset to System Theme</button>

    <script src="renderer.js"></script>
  </body>
</body>
</html>
```




```
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
  const isDarkMode = await window.darkMode.toggle()
  document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'
})

document.getElementById('reset-to-system').addEventListener('click', async () => {
  await window.darkMode.system()
  document.getElementById('theme-source').innerHTML = 'System'
})
```




```
@media (prefers-color-scheme: dark) {
  body { background: #333; color: white; }
}

@media (prefers-color-scheme: light) {
  body { background: #ddd; color: black; }
}
```





### How does this work?[​](#how-does-this-work "Direct link to heading")


Starting with the `index.html` file:



index.html


```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
    <link rel="stylesheet" type="text/css" href="./styles.css">
</head>
<body>
    <h1>Hello World!</h1>
    <p>Current theme source: <strong id="theme-source">System</strong></p>

    <button id="toggle-dark-mode">Toggle Dark Mode</button>
    <button id="reset-to-system">Reset to System Theme</button>

    <script src="renderer.js"></script>
  </body>
</body>
</html>
```



And the `styles.css` file:



styles.css


```
@media (prefers-color-scheme: dark) {
  body { background: #333; color: white; }
}

@media (prefers-color-scheme: light) {
  body { background: #ddd; color: black; }
}
```



The example renders an HTML page with a couple elements. The `<strong id="theme-source">` element shows which theme is currently selected, and the two `<button>` elements are the controls. The CSS file uses the [`prefers-color-scheme`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) media query to set the `<body>` element background and text colors.


The `preload.js` script adds a new API to the `window` object called `darkMode`. This API exposes two IPC channels to the renderer process, `'dark-mode:toggle'` and `'dark-mode:system'`. It also assigns two methods, `toggle` and `system`, which pass messages from the renderer to the main process.



preload.js


```
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('darkMode', {
  toggle: () => ipcRenderer.invoke('dark-mode:toggle'),
  system: () => ipcRenderer.invoke('dark-mode:system')
})
```



Now the renderer process can communicate with the main process securely and perform the necessary mutations to the `nativeTheme` object.


The `renderer.js` file is responsible for controlling the `<button>` functionality.



renderer.js


```
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
  const isDarkMode = await window.darkMode.toggle()
  document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'
})

document.getElementById('reset-to-system').addEventListener('click', async () => {
  await window.darkMode.system()
  document.getElementById('theme-source').innerHTML = 'System'
})
```



Using `addEventListener`, the `renderer.js` file adds `'click'` [event listeners](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener) to each button element. Each event listener handler makes calls to the respective `window.darkMode` API methods.


Finally, the `main.js` file represents the main process and contains the actual `nativeTheme` API.




```
const { app, BrowserWindow, ipcMain, nativeTheme } = require('electron')
const path = require('path')

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  win.loadFile('index.html')

  ipcMain.handle('dark-mode:toggle', () => {
    if (nativeTheme.shouldUseDarkColors) {
      nativeTheme.themeSource = 'light'
    } else {
      nativeTheme.themeSource = 'dark'
    }
    return nativeTheme.shouldUseDarkColors
  })

  ipcMain.handle('dark-mode:system', () => {
    nativeTheme.themeSource = 'system'
  })
}

app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow()
    }
  })
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})
```


The `ipcMain.handle` methods are how the main process responds to the click events from the buttons on the HTML page.


The `'dark-mode:toggle'` IPC channel handler method checks the `shouldUseDarkColors` boolean property, sets the corresponding `themeSource`, and then returns the current `shouldUseDarkColors` property. Looking back on the renderer process event listener for this IPC channel, the return value from this handler is utilized to assign the correct text to the `<strong id='theme-source'>` element.


The `'dark-mode:system'` IPC channel handler method assigns the string `'system'` to the `themeSource` and returns nothing. This also corresponds with the relative renderer process event listener as the method is awaited with no return value expected.


Run the example using Electron Fiddle and then click the "Toggle Dark Mode" button; the app should start alternating between a light and dark background color.


![Dark Mode](https://www.electronjs.org/assets/images/dark_mode-495e2c44ffc3f1b3a03219255e438870.gif)



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/dark-mode>

Menu
====


Class: Menu[​](#class-menu "Direct link to heading")
----------------------------------------------------



> Create native application menus and context menus.
> 
> 


Process: [Main](../glossary#main-process)


### 
`new Menu()`[​](#new-menu "Direct link to heading")


Creates a new menu.


### Static Methods[​](#static-methods "Direct link to heading")


The `Menu` class has the following static methods:


#### 
`Menu.setApplicationMenu(menu)`[​](#menusetapplicationmenumenu "Direct link to heading")


* `menu` Menu | null


Sets `menu` as the application menu on macOS. On Windows and Linux, the `menu` will be set as each window's top menu.


Also on Windows and Linux, you can use a `&` in the top-level item name to indicate which letter should get a generated accelerator. For example, using `&File` for the file menu would result in a generated `Alt-F` accelerator that opens the associated menu. The indicated character in the button label then gets an underline, and the `&` character is not displayed on the button label.


In order to escape the `&` character in an item name, add a proceeding `&`. For example, `&&File` would result in `&File` displayed on the button label.


Passing `null` will suppress the default menu. On Windows and Linux, this has the additional effect of removing the menu bar from the window.


**Note:** The default menu will be created automatically if the app does not set one. It contains standard items such as `File`, `Edit`, `View`, `Window` and `Help`.


#### 
`Menu.getApplicationMenu()`[​](#menugetapplicationmenu "Direct link to heading")


Returns `Menu | null` - The application menu, if set, or `null`, if not set.


**Note:** The returned `Menu` instance doesn't support dynamic addition or removal of menu items. [Instance properties](#instance-properties) can still be dynamically modified.


#### 
`Menu.sendActionToFirstResponder(action)` *macOS*[​](#menusendactiontofirstresponderaction-macos "Direct link to heading")


* `action` string


Sends the `action` to the first responder of application. This is used for emulating default macOS menu behaviors. Usually you would use the [`role`](menu-item#roles) property of a [`MenuItem`](menu-item).


See the [macOS Cocoa Event Handling Guide](https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/EventOverview/EventArchitecture/EventArchitecture.html#//apple_ref/doc/uid/10000060i-CH3-SW7) for more information on macOS' native actions.


#### 
`Menu.buildFromTemplate(template)`[​](#menubuildfromtemplatetemplate "Direct link to heading")


* `template` (MenuItemConstructorOptions | MenuItem)[]


Returns `Menu`


Generally, the `template` is an array of `options` for constructing a [MenuItem](menu-item). The usage can be referenced above.


You can also attach other fields to the element of the `template` and they will become properties of the constructed menu items.


### Instance Methods[​](#instance-methods "Direct link to heading")


The `menu` object has the following instance methods:


#### 
`menu.popup([options])`[​](#menupopupoptions "Direct link to heading")


* `options` Object (optional)
	+ `window` [BrowserWindow](browser-window) (optional) - Default is the focused window.
	+ `x` number (optional) - Default is the current mouse cursor position. Must be declared if `y` is declared.
	+ `y` number (optional) - Default is the current mouse cursor position. Must be declared if `x` is declared.
	+ `positioningItem` number (optional) *macOS* - The index of the menu item to be positioned under the mouse cursor at the specified coordinates. Default is -1.
	+ `callback` Function (optional) - Called when menu is closed.


Pops up this menu as a context menu in the [`BrowserWindow`](browser-window).


#### 
`menu.closePopup([browserWindow])`[​](#menuclosepopupbrowserwindow "Direct link to heading")


* `browserWindow` [BrowserWindow](browser-window) (optional) - Default is the focused window.


Closes the context menu in the `browserWindow`.


#### 
`menu.append(menuItem)`[​](#menuappendmenuitem "Direct link to heading")


* `menuItem` [MenuItem](menu-item)


Appends the `menuItem` to the menu.


#### 
`menu.getMenuItemById(id)`[​](#menugetmenuitembyidid "Direct link to heading")


* `id` string


Returns `MenuItem | null` the item with the specified `id`


#### 
`menu.insert(pos, menuItem)`[​](#menuinsertpos-menuitem "Direct link to heading")


* `pos` Integer
* `menuItem` [MenuItem](menu-item)


Inserts the `menuItem` to the `pos` position of the menu.


### Instance Events[​](#instance-events "Direct link to heading")


Objects created with `new Menu` or returned by `Menu.buildFromTemplate` emit the following events:


**Note:** Some events are only available on specific operating systems and are labeled as such.


#### Event: 'menu-will-show'[​](#event-menu-will-show "Direct link to heading")


Returns:


* `event` Event


Emitted when `menu.popup()` is called.


#### Event: 'menu-will-close'[​](#event-menu-will-close "Direct link to heading")


Returns:


* `event` Event


Emitted when a popup is closed either manually or with `menu.closePopup()`.


### Instance Properties[​](#instance-properties "Direct link to heading")


`menu` objects also have the following properties:


#### 
`menu.items`[​](#menuitems "Direct link to heading")


A `MenuItem[]` array containing the menu's items.


Each `Menu` consists of multiple [`MenuItem`](menu-item)s and each `MenuItem` can have a submenu.


Examples[​](#examples "Direct link to heading")
-----------------------------------------------


An example of creating the application menu with the simple template API:




```
const { app, Menu } = require('electron')

const isMac = process.platform === 'darwin'

const template = [
  // { role: 'appMenu' }
  ...(isMac ? [{
    label: app.name,
    submenu: [
      { role: 'about' },
      { type: 'separator' },
      { role: 'services' },
      { type: 'separator' },
      { role: 'hide' },
      { role: 'hideOthers' },
      { role: 'unhide' },
      { type: 'separator' },
      { role: 'quit' }
    ]
  }] : []),
  // { role: 'fileMenu' }
  {
    label: 'File',
    submenu: [
      isMac ? { role: 'close' } : { role: 'quit' }
    ]
  },
  // { role: 'editMenu' }
  {
    label: 'Edit',
    submenu: [
      { role: 'undo' },
      { role: 'redo' },
      { type: 'separator' },
      { role: 'cut' },
      { role: 'copy' },
      { role: 'paste' },
      ...(isMac ? [
        { role: 'pasteAndMatchStyle' },
        { role: 'delete' },
        { role: 'selectAll' },
        { type: 'separator' },
        {
          label: 'Speech',
          submenu: [
            { role: 'startSpeaking' },
            { role: 'stopSpeaking' }
          ]
        }
      ] : [
        { role: 'delete' },
        { type: 'separator' },
        { role: 'selectAll' }
      ])
    ]
  },
  // { role: 'viewMenu' }
  {
    label: 'View',
    submenu: [
      { role: 'reload' },
      { role: 'forceReload' },
      { role: 'toggleDevTools' },
      { type: 'separator' },
      { role: 'resetZoom' },
      { role: 'zoomIn' },
      { role: 'zoomOut' },
      { type: 'separator' },
      { role: 'togglefullscreen' }
    ]
  },
  // { role: 'windowMenu' }
  {
    label: 'Window',
    submenu: [
      { role: 'minimize' },
      { role: 'zoom' },
      ...(isMac ? [
        { type: 'separator' },
        { role: 'front' },
        { type: 'separator' },
        { role: 'window' }
      ] : [
        { role: 'close' }
      ])
    ]
  },
  {
    role: 'help',
    submenu: [
      {
        label: 'Learn More',
        click: async () => {
          const { shell } = require('electron')
          await shell.openExternal('https://electronjs.org')
        }
      }
    ]
  }
]

const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
```


### Render process[​](#render-process "Direct link to heading")


To create menus initiated by the renderer process, send the required information to the main process using IPC and have the main process display the menu on behalf of the renderer.


Below is an example of showing a menu when the user right clicks the page:




```
// renderer
window.addEventListener('contextmenu', (e) => {
  e.preventDefault()
  ipcRenderer.send('show-context-menu')
})

ipcRenderer.on('context-menu-command', (e, command) => {
  // ...
})

// main
ipcMain.on('show-context-menu', (event) => {
  const template = [
    {
      label: 'Menu Item 1',
      click: () => { event.sender.send('context-menu-command', 'menu-item-1') }
    },
    { type: 'separator' },
    { label: 'Menu Item 2', type: 'checkbox', checked: true }
  ]
  const menu = Menu.buildFromTemplate(template)
  menu.popup(BrowserWindow.fromWebContents(event.sender))
})
```


Notes on macOS Application Menu[​](#notes-on-macos-application-menu "Direct link to heading")
---------------------------------------------------------------------------------------------


macOS has a completely different style of application menu from Windows and Linux. Here are some notes on making your app's menu more native-like.


### Standard Menus[​](#standard-menus "Direct link to heading")


On macOS there are many system-defined standard menus, like the [`Services`](https://developer.apple.com/documentation/appkit/nsapplication/1428608-servicesmenu?language=objc) and `Windows` menus. To make your menu a standard menu, you should set your menu's `role` to one of the following and Electron will recognize them and make them become standard menus:


* `window`
* `help`
* `services`


### Standard Menu Item Actions[​](#standard-menu-item-actions "Direct link to heading")


macOS has provided standard actions for some menu items, like `About xxx`, `Hide xxx`, and `Hide Others`. To set the action of a menu item to a standard action, you should set the `role` attribute of the menu item.


### Main Menu's Name[​](#main-menus-name "Direct link to heading")


On macOS the label of the application menu's first item is always your app's name, no matter what label you set. To change it, modify your app bundle's `Info.plist` file. See [About Information Property List Files](https://developer.apple.com/library/ios/documentation/general/Reference/InfoPlistKeyReference/Articles/AboutInformationPropertyListFiles.html) for more information.


Setting Menu for Specific Browser Window (*Linux* *Windows*)[​](#setting-menu-for-specific-browser-window-linux-windows "Direct link to heading")
-------------------------------------------------------------------------------------------------------------------------------------------------


The [`setMenu` method](browser-window#winsetmenumenu-linux-windows) of browser windows can set the menu of certain browser windows.


Menu Item Position[​](#menu-item-position "Direct link to heading")
-------------------------------------------------------------------


You can make use of `before`, `after`, `beforeGroupContaining`, `afterGroupContaining` and `id` to control how the item will be placed when building a menu with `Menu.buildFromTemplate`.


* `before` - Inserts this item before the item with the specified label. If the referenced item doesn't exist the item will be inserted at the end of the menu. Also implies that the menu item in question should be placed in the same “group” as the item.
* `after` - Inserts this item after the item with the specified label. If the referenced item doesn't exist the item will be inserted at the end of the menu. Also implies that the menu item in question should be placed in the same “group” as the item.
* `beforeGroupContaining` - Provides a means for a single context menu to declare the placement of their containing group before the containing group of the item with the specified label.
* `afterGroupContaining` - Provides a means for a single context menu to declare the placement of their containing group after the containing group of the item with the specified label.


By default, items will be inserted in the order they exist in the template unless one of the specified positioning keywords is used.


### Examples[​](#examples-1 "Direct link to heading")


Template:




```
[
  { id: '1', label: 'one' },
  { id: '2', label: 'two' },
  { id: '3', label: 'three' },
  { id: '4', label: 'four' }
]
```


Menu:




```
- 1
- 2
- 3
- 4
```


Template:




```
[
  { id: '1', label: 'one' },
  { type: 'separator' },
  { id: '3', label: 'three', beforeGroupContaining: ['1'] },
  { id: '4', label: 'four', afterGroupContaining: ['2'] },
  { type: 'separator' },
  { id: '2', label: 'two' }
]
```


Menu:




```
- 3
- 4
- ---
- 1
- ---
- 2
```


Template:




```
[
  { id: '1', label: 'one', after: ['3'] },
  { id: '2', label: 'two', before: ['1'] },
  { id: '3', label: 'three' }
]
```


Menu:




```
- ---
- 3
- 2
- 1
```



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/menu>

Electron Releases
=================


Electron frequently releases major versions alongside every other Chromium release. This document focuses on the release cadence and version support policy. For a more in-depth guide on our git branches and how Electron uses semantic versions, check out our [Electron Versioning](electron-versioning) doc.


Timeline[​](#timeline "Direct link to heading")
-----------------------------------------------




| Electron | Alpha | Beta | Stable | Chrome | Node | Supported |
| --- | --- | --- | --- | --- | --- | --- |
| 2.0.0 | -- | 2018-Feb-21 | 2018-May-01 | M61 | v8.9 | 🚫 |
| 3.0.0 | -- | 2018-Jun-21 | 2018-Sep-18 | M66 | v10.2 | 🚫 |
| 4.0.0 | -- | 2018-Oct-11 | 2018-Dec-20 | M69 | v10.11 | 🚫 |
| 5.0.0 | -- | 2019-Jan-22 | 2019-Apr-24 | M73 | v12.0 | 🚫 |
| 6.0.0 | -- | 2019-May-01 | 2019-Jul-30 | M76 | v12.4 | 🚫 |
| 7.0.0 | -- | 2019-Aug-01 | 2019-Oct-22 | M78 | v12.8 | 🚫 |
| 8.0.0 | -- | 2019-Oct-24 | 2020-Feb-04 | M80 | v12.13 | 🚫 |
| 9.0.0 | -- | 2020-Feb-06 | 2020-May-19 | M83 | v12.14 | 🚫 |
| 10.0.0 | -- | 2020-May-21 | 2020-Aug-25 | M85 | v12.16 | 🚫 |
| 11.0.0 | -- | 2020-Aug-27 | 2020-Nov-17 | M87 | v12.18 | 🚫 |
| 12.0.0 | -- | 2020-Nov-19 | 2021-Mar-02 | M89 | v14.16 | 🚫 |
| 13.0.0 | -- | 2021-Mar-04 | 2021-May-25 | M91 | v14.16 | 🚫 |
| 14.0.0 | -- | 2021-May-27 | 2021-Aug-31 | M93 | v14.17 | 🚫 |
| 15.0.0 | 2021-Jul-20 | 2021-Sep-01 | 2021-Sep-21 | M94 | v16.5 | 🚫 |
| 16.0.0 | 2021-Sep-23 | 2021-Oct-20 | 2021-Nov-16 | M96 | v16.9 | 🚫 |
| 17.0.0 | 2021-Nov-18 | 2022-Jan-06 | 2022-Feb-01 | M98 | v16.13 | 🚫 |
| 18.0.0 | 2022-Feb-03 | 2022-Mar-03 | 2022-Mar-29 | M100 | v16.13 | ✅ |
| 19.0.0 | 2022-Mar-31 | 2022-Apr-26 | 2022-May-24 | M102 | v16.14 | ✅ |
| 20.0.0 | 2022-May-26 | 2022-Jun-21 | 2022-Aug-02 | M104 | v16.15 | ✅ |
| 21.0.0 | 2022-Aug-04 | 2022-Aug-30 | 2022-Sep-27 | M106 | TBD | ✅ |


**Notes:**


* The `-alpha.1`, `-beta.1`, and `stable` dates are our solid release dates.
* We strive for weekly alpha/beta releases, but we often release more than scheduled.
* All dates are our goals but there may be reasons for adjusting the stable deadline, such as security bugs.


**Historical changes:**


* Since Electron 5, Electron has been publicizing its release dates ([see blog post](https://electronjs.org/blog/electron-5-0-timeline)).
* Since Electron 6, Electron major versions have been targeting every other Chromium major version. Each Electron stable should happen on the same day as Chrome stable ([see blog post](https://www.electronjs.org/blog/12-week-cadence)).
* Since Electron 16, Electron has been releasing major versions on an 8-week cadence in accordance to Chrome's change to a 4-week release cadence ([see blog post](https://www.electronjs.org/blog/8-week-cadence)).




Chrome release dates
Chromium has the own public release schedule [here](https://chromiumdash.appspot.com/schedule).



Version support policy[​](#version-support-policy "Direct link to heading")
---------------------------------------------------------------------------




info
Beginning in September 2021 (Electron 15), the Electron team will temporarily support the latest **four** stable major versions. This extended support is intended to help Electron developers transition to the [new 8-week release cadence](https://electronjs.org/blog/8-week-cadence), and will continue until the release of Electron 19. At that time, the Electron team will drop support back to the latest three stable major versions.



The latest three *stable* major versions are supported by the Electron team. For example, if the latest release is 6.1.x, then the 5.0.x as well as the 4.2.x series are supported. We only support the latest minor release for each stable release series. This means that in the case of a security fix, 6.1.x will receive the fix, but we will not release a new version of 6.0.x.


The latest stable release unilaterally receives all fixes from `main`, and the version prior to that receives the vast majority of those fixes as time and bandwidth warrants. The oldest supported release line will receive only security fixes directly.


### Breaking API changes[​](#breaking-api-changes "Direct link to heading")


When an API is changed or removed in a way that breaks existing functionality, the previous functionality will be supported for a minimum of two major versions when possible before being removed. For example, if a function takes three arguments, and that number is reduced to two in major version 10, the three-argument version would continue to work until, at minimum, major version 12. Past the minimum two-version threshold, we will attempt to support backwards compatibility beyond two versions until the maintainers feel the maintenance burden is too high to continue doing so.


### End-of-life[​](#end-of-life "Direct link to heading")


When a release branch reaches the end of its support cycle, the series will be deprecated in NPM and a final end-of-support release will be made. This release will add a warning to inform that an unsupported version of Electron is in use.


These steps are to help app developers learn when a branch they're using becomes unsupported, but without being excessively intrusive to end users.


If an application has exceptional circumstances and needs to stay on an unsupported series of Electron, developers can silence the end-of-support warning by omitting the final release from the app's `package.json` `devDependencies`. For example, since the 1-6-x series ended with an end-of-support 1.6.18 release, developers could choose to stay in the 1-6-x series without warnings with `devDependency` of `"electron": 1.6.0 - 1.6.17`.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/electron-timelines>

Electron Versioning
===================



> A detailed look at our versioning policy and implementation.
> 
> 


As of version 2.0.0, Electron follows the [SemVer](#semver) spec. The following command will install the most recent stable build of Electron:



* npm
* Yarn





```
npm install --save-dev electron
```




```
yarn add --dev electron
```




To update an existing project to use the latest stable version:



* npm
* Yarn





```
npm install --save-dev electron@latest
```




```
yarn add --dev electron@latest
```




Versioning scheme[​](#versioning-scheme "Direct link to heading")
-----------------------------------------------------------------


There are several major changes from our 1.x strategy outlined below. Each change is intended to satisfy the needs and priorities of developers/maintainers and app developers.


1. Strict use of the the [SemVer](#semver) spec
2. Introduction of semver-compliant `-beta` tags
3. Introduction of [conventional commit messages](https://conventionalcommits.org/)
4. Well-defined stabilization branches
5. The `main` branch is versionless; only stabilization branches contain version information


We will cover in detail how git branching works, how npm tagging works, what developers should expect to see, and how one can backport changes.


SemVer[​](#semver "Direct link to heading")
-------------------------------------------


Below is a table explicitly mapping types of changes to their corresponding category of SemVer (e.g. Major, Minor, Patch).




| Major Version Increments | Minor Version Increments | Patch Version Increments |
| --- | --- | --- |
| Electron breaking API changes | Electron non-breaking API changes | Electron bug fixes |
| Node.js major version updates | Node.js minor version updates | Node.js patch version updates |
| Chromium version updates |  | fix-related chromium patches |


For more information, see the [Semantic Versioning 2.0.0](https://semver.org/) spec.


Note that most Chromium updates will be considered breaking. Fixes that can be backported will likely be cherry-picked as patches.


Stabilization branches[​](#stabilization-branches "Direct link to heading")
---------------------------------------------------------------------------


Stabilization branches are branches that run parallel to `main`, taking in only cherry-picked commits that are related to security or stability. These branches are never merged back to `main`.


![Stabilization Branches]


Since Electron 8, stabilization branches are always **major** version lines, and named against the following template `$MAJOR-x-y` e.g. `8-x-y`. Prior to that we used **minor** version lines and named them as `$MAJOR-$MINOR-x` e.g. `2-0-x`.


We allow for multiple stabilization branches to exist simultaneously, one for each supported version. For more details on which versions are supported, see our [Electron Releases](electron-timelines) doc.


![Multiple Stability Branches]


Older lines will not be supported by the Electron project, but other groups can take ownership and backport stability and security fixes on their own. We discourage this, but recognize that it makes life easier for many app developers.


Beta releases and bug fixes[​](#beta-releases-and-bug-fixes "Direct link to heading")
-------------------------------------------------------------------------------------


Developers want to know which releases are *safe* to use. Even seemingly innocent features can introduce regressions in complex applications. At the same time, locking to a fixed version is dangerous because you’re ignoring security patches and bug fixes that may have come out since your version. Our goal is to allow the following standard semver ranges in `package.json` :


* Use `~2.0.0` to admit only stability or security related fixes to your `2.0.0` release.
* Use `^2.0.0` to admit non-breaking *reasonably stable* feature work as well as security and bug fixes.


What’s important about the second point is that apps using `^` should still be able to expect a reasonable level of stability. To accomplish this, SemVer allows for a *pre-release identifier* to indicate a particular version is not yet *safe* or *stable*.


Whatever you choose, you will periodically have to bump the version in your `package.json` as breaking changes are a fact of Chromium life.


The process is as follows:


1. All new major and minor releases lines begin with a beta series indicated by SemVer prerelease tags of `beta.N`, e.g. `2.0.0-beta.1`. After the first beta, subsequent beta releases must meet all of the following conditions:
	1. The change is backwards API-compatible (deprecations are allowed)
	2. The risk to meeting our stability timeline must be low.
2. If allowed changes need to be made once a release is beta, they are applied and the prerelease tag is incremented, e.g. `2.0.0-beta.2`.
3. If a particular beta release is *generally regarded* as stable, it will be re-released as a stable build, changing only the version information. e.g. `2.0.0`. After the first stable, all changes must be backwards-compatible bug or security fixes.
4. If future bug fixes or security patches need to be made once a release is stable, they are applied and the *patch* version is incremented e.g. `2.0.1`.


Specifically, the above means:


1. Admitting non-breaking-API changes before Week 3 in the beta cycle is okay, even if those changes have the potential to cause moderate side-effects.
2. Admitting feature-flagged changes, that do not otherwise alter existing code paths, at most points in the beta cycle is okay. Users can explicitly enable those flags in their apps.
3. Admitting features of any sort after Week 3 in the beta cycle is 👎 without a very good reason.


For each major and minor bump, you should expect to see something like the following:




```
2.0.0-beta.1
2.0.0-beta.2
2.0.0-beta.3
2.0.0
2.0.1
2.0.2
```


An example lifecycle in pictures:


* A new release branch is created that includes the latest set of features. It is published as `2.0.0-beta.1`. ![New Release Branch]
* A bug fix comes into master that can be backported to the release branch. The patch is applied, and a new beta is published as `2.0.0-beta.2`. ![Bugfix Backport to Beta]
* The beta is considered *generally stable* and it is published again as a non-beta under `2.0.0`. ![Beta to Stable]
* Later, a zero-day exploit is revealed and a fix is applied to master. We backport the fix to the `2-0-x` line and release `2.0.1`. ![Security Backports]


A few examples of how various SemVer ranges will pick up new releases:


![Semvers and Releases]


### Backport request process[​](#backport-request-process "Direct link to heading")


All supported release lines will accept external pull requests to backport fixes previously merged to `main`, though this may be on a case-by-case basis for some older supported lines. All contested decisions around release line backports will be resolved by the [Releases Working Group](https://github.com/electron/governance/tree/main/wg-releases) as an agenda item at their weekly meeting the week the backport PR is raised.


Feature flags[​](#feature-flags "Direct link to heading")
---------------------------------------------------------


Feature flags are a common practice in Chromium, and are well-established in the web-development ecosystem. In the context of Electron, a feature flag or **soft branch** must have the following properties:


* it is enabled/disabled either at runtime, or build-time; we do not support the concept of a request-scoped feature flag
* it completely segments new and old code paths; refactoring old code to support a new feature *violates* the feature-flag contract
* feature flags are eventually removed after the feature is released


Semantic commits[​](#semantic-commits "Direct link to heading")
---------------------------------------------------------------


All pull requests must adhere to the [Conventional Commits](https://conventionalcommits.org/) spec, which can be summarized as follows:


* Commits that would result in a SemVer **major** bump must start their body with `BREAKING CHANGE:`.
* Commits that would result in a SemVer **minor** bump must start with `feat:`.
* Commits that would result in a SemVer **patch** bump must start with `fix:`.


The `electron/electron` repository also enforces squash merging, so you only need to make sure that your pull request has the correct title prefix.


Versioned `main` branch[​](#versioned-main-branch "Direct link to heading")
---------------------------------------------------------------------------


* The `main` branch will always contain the next major version `X.0.0-nightly.DATE` in its `package.json`.
* Release branches are never merged back to `main`.
* Release branches *do* contain the correct version in their `package.json`.
* As soon as a release branch is cut for a major, `main` must be bumped to the next major (i.e. `main` is always versioned as the next theoretical release branch).


Historical versioning (Electron 1.X)[​](#historical-versioning-electron-1x "Direct link to heading")
----------------------------------------------------------------------------------------------------


Electron versions *< 2.0* did not conform to the [SemVer](https://semver.org) spec: major versions corresponded to end-user API changes, minor versions corresponded to Chromium major releases, and patch versions corresponded to new features and bug fixes. While convenient for developers merging features, it creates problems for developers of client-facing applications. The QA testing cycles of major apps like Slack, Teams, Skype, VS Code, and GitHub Desktop can be lengthy and stability is a highly desired outcome. There is a high risk in adopting new features while trying to absorb bug fixes.


Here is an example of the 1.x strategy:


![1.x Versioning]


An app developed with `1.8.1` cannot take the `1.8.3` bug fix without either absorbing the `1.8.2` feature, or by backporting the fix and maintaining a new release line.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/electron-versioning>

BrowserView
===========


A `BrowserView` can be used to embed additional web content into a [`BrowserWindow`](browser-window). It is like a child window, except that it is positioned relative to its owning window. It is meant to be an alternative to the `webview` tag.


Class: BrowserView[​](#class-browserview "Direct link to heading")
------------------------------------------------------------------



> Create and control views.
> 
> 


Process: [Main](../glossary#main-process)


This module cannot be used until the `ready` event of the `app` module is emitted.


### Example[​](#example "Direct link to heading")




```
// In the main process.
const { app, BrowserView, BrowserWindow } = require('electron')

app.whenReady().then(() => {
  const win = new BrowserWindow({ width: 800, height: 600 })

  const view = new BrowserView()
  win.setBrowserView(view)
  view.setBounds({ x: 0, y: 0, width: 300, height: 300 })
  view.webContents.loadURL('https://electronjs.org')
})
```


### 
`new BrowserView([options])` *Experimental*[​](#new-browserviewoptions-experimental "Direct link to heading")


* `options` Object (optional)
	+ `webPreferences` Object (optional) - See [BrowserWindow](browser-window).


### Instance Properties[​](#instance-properties "Direct link to heading")


Objects created with `new BrowserView` have the following properties:


#### 
`view.webContents` *Experimental*[​](#viewwebcontents-experimental "Direct link to heading")


A [`WebContents`](web-contents) object owned by this view.


### Instance Methods[​](#instance-methods "Direct link to heading")


Objects created with `new BrowserView` have the following instance methods:


#### 
`view.setAutoResize(options)` *Experimental*[​](#viewsetautoresizeoptions-experimental "Direct link to heading")


* `options` Object
	+ `width` boolean (optional) - If `true`, the view's width will grow and shrink together with the window. `false` by default.
	+ `height` boolean (optional) - If `true`, the view's height will grow and shrink together with the window. `false` by default.
	+ `horizontal` boolean (optional) - If `true`, the view's x position and width will grow and shrink proportionally with the window. `false` by default.
	+ `vertical` boolean (optional) - If `true`, the view's y position and height will grow and shrink proportionally with the window. `false` by default.


#### 
`view.setBounds(bounds)` *Experimental*[​](#viewsetboundsbounds-experimental "Direct link to heading")


* `bounds` [Rectangle](structures/rectangle)


Resizes and moves the view to the supplied bounds relative to the window.


#### 
`view.getBounds()` *Experimental*[​](#viewgetbounds-experimental "Direct link to heading")


Returns [Rectangle](structures/rectangle)


The `bounds` of this BrowserView instance as `Object`.


#### 
`view.setBackgroundColor(color)` *Experimental*[​](#viewsetbackgroundcolorcolor-experimental "Direct link to heading")


* `color` string - Color in Hex, RGB, ARGB, HSL, HSLA or named CSS color format. The alpha channel is optional for the hex type.


Examples of valid `color` values:


* Hex
	+ #fff (RGB)
	+ #ffff (ARGB)
	+ #ffffff (RRGGBB)
	+ #ffffffff (AARRGGBB)
* RGB
	+ rgb(([\d]+),\s*([\d]+),\s*([\d]+))
		- e.g. rgb(255, 255, 255)
* RGBA
	+ rgba(([\d]+),\s*([\d]+),\s*([\d]+),\s\*([\d.]+))
		- e.g. rgba(255, 255, 255, 1.0)
* HSL
	+ hsl((-?[\d.]+),\s*([\d.]+)%,\s*([\d.]+)%)
		- e.g. hsl(200, 20%, 50%)
* HSLA
	+ hsla((-?[\d.]+),\s*([\d.]+)%,\s*([\d.]+)%,\s\*([\d.]+))
		- e.g. hsla(200, 20%, 50%, 0.5)
* Color name
	+ Options are listed in [SkParseColor.cpp](https://source.chromium.org/chromium/chromium/src/+/main:third_party/skia/src/utils/SkParseColor.cpp;l=11-152;drc=eea4bf52cb0d55e2a39c828b017c80a5ee054148)
	+ Similar to CSS Color Module Level 3 keywords, but case-sensitive.
		- e.g. `blueviolet` or `red`


**Note:** Hex format with alpha takes `AARRGGBB` or `ARGB`, *not* `RRGGBBA` or `RGA`.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/browser-view>

Process Sandboxing
==================


One key security feature in Chromium is that processes can be executed within a sandbox. The sandbox limits the harm that malicious code can cause by limiting access to most system resources — sandboxed processes can only freely use CPU cycles and memory. In order to perform operations requiring additional privilege, sandboxed processes use dedicated communication channels to delegate tasks to more privileged processes.


In Chromium, sandboxing is applied to most processes other than the main process. This includes renderer processes, as well as utility processes such as the audio service, the GPU service and the network service.


See Chromium's [Sandbox design document](https://chromium.googlesource.com/chromium/src/+/main/docs/design/sandbox.md) for more information.


Electron's sandboxing policies[​](#electrons-sandboxing-policies "Direct link to heading")
------------------------------------------------------------------------------------------


Electron comes with a mixed sandbox environment, meaning sandboxed processes can run alongside privileged ones. By default, renderer processes are not sandboxed, but utility processes are. Note that as in Chromium, the main (browser) process is privileged and cannot be sandboxed.


Historically, this mixed sandbox approach was established because having Node.js available in the renderer is an extremely powerful tool for app developers. Unfortunately, this feature is also an equally massive security vulnerability.


Theoretically, unsandboxed renderers are not a problem for desktop applications that only display trusted code, but they make Electron less secure than Chromium for displaying untrusted web content. However, even purportedly trusted code may be dangerous — there are countless attack vectors that malicious actors can use, from cross-site scripting to content injection to man-in-the-middle attacks on remotely loaded websites, just to name a few. For this reason, we recommend enabling renderer sandboxing for the vast majority of cases under an abundance of caution.


Note that there is an active discussion in the issue tracker to enable renderer sandboxing by default. See [#28466](https://github.com/electron/electron/issues/28466)) for details.


Sandbox behaviour in Electron[​](#sandbox-behaviour-in-electron "Direct link to heading")
-----------------------------------------------------------------------------------------


Sandboxed processes in Electron behave *mostly* in the same way as Chromium's do, but Electron has a few additional concepts to consider because it interfaces with Node.js.


### Renderer processes[​](#renderer-processes "Direct link to heading")


When renderer processes in Electron are sandboxed, they behave in the same way as a regular Chrome renderer would. A sandboxed renderer won't have a Node.js environment initialized.


Therefore, when the sandbox is enabled, renderer processes can only perform privileged tasks (such as interacting with the filesystem, making changes to the system, or spawning subprocesses) by delegating these tasks to the main process via inter-process communication (IPC).


### Preload scripts[​](#preload-scripts "Direct link to heading")


In order to allow renderer processes to communicate with the main process, preload scripts attached to sandboxed renderers will still have a polyfilled subset of Node.js APIs available. A `require` function similar to Node's `require` module is exposed, but can only import a subset of Electron and Node's built-in modules:


* `electron` (only renderer process modules)
* [`events`](https://nodejs.org/api/events.html)
* [`timers`](https://nodejs.org/api/timers.html)
* [`url`](https://nodejs.org/api/url.html)


In addition, the preload script also polyfills certain Node.js primitives as globals:


* [`Buffer`](https://nodejs.org/api/Buffer.html)
* [`process`](../api/process)
* [`clearImmediate`](https://nodejs.org/api/timers.html#timers_clearimmediate_immediate)
* [`setImmediate`](https://nodejs.org/api/timers.html#timers_setimmediate_callback_args)


Because the `require` function is a polyfill with limited functionality, you will not be able to use [CommonJS modules](https://nodejs.org/api/modules.html#modules_modules_commonjs_modules) to separate your preload script into multiple files. If you need to split your preload code, use a bundler such as [webpack](https://webpack.js.org/) or [Parcel](https://parceljs.org/).


Note that because the environment presented to the `preload` script is substantially more privileged than that of a sandboxed renderer, it is still possible to leak privileged APIs to untrusted code running in the renderer process unless [`contextIsolation`](context-isolation) is enabled.


Configuring the sandbox[​](#configuring-the-sandbox "Direct link to heading")
-----------------------------------------------------------------------------


### Enabling the sandbox for a single process[​](#enabling-the-sandbox-for-a-single-process "Direct link to heading")


In Electron, renderer sandboxing can be enabled on a per-process basis with the `sandbox: true` preference in the [`BrowserWindow`](../api/browser-window) constructor.




```
// main.js
app.whenReady().then(() => {
  const win = new BrowserWindow({
    webPreferences: {
      sandbox: true
    }
  })
  win.loadURL('https://google.com')
})
```


### Enabling the sandbox globally[​](#enabling-the-sandbox-globally "Direct link to heading")


If you want to force sandboxing for all renderers, you can also use the [`app.enableSandbox`](../api/app#appenablesandbox) API. Note that this API has to be called before the app's `ready` event.




```
// main.js
app.enableSandbox()
app.whenReady().then(() => {
  // no need to pass `sandbox: true` since `app.enableSandbox()` was called.
  const win = new BrowserWindow()
  win.loadURL('https://google.com')
})
```


### Disabling Chromium's sandbox (testing only)[​](#disabling-chromiums-sandbox-testing-only "Direct link to heading")


You can also disable Chromium's sandbox entirely with the [`--no-sandbox`](../api/command-line-switches#--no-sandbox) CLI flag, which will disable the sandbox for all processes (including utility processes). We highly recommend that you only use this flag for testing purposes, and **never** in production.


Note that the `sandbox: true` option will still disable the renderer's Node.js environment.


A note on rendering untrusted content[​](#a-note-on-rendering-untrusted-content "Direct link to heading")
---------------------------------------------------------------------------------------------------------


Rendering untrusted content in Electron is still somewhat uncharted territory, though some apps are finding success (e.g. [Beaker Browser](https://github.com/beakerbrowser/beaker)). Our goal is to get as close to Chrome as we can in terms of the security of sandboxed content, but ultimately we will always be behind due to a few fundamental issues:


1. We do not have the dedicated resources or expertise that Chromium has to apply to the security of its product. We do our best to make use of what we have, to inherit everything we can from Chromium, and to respond quickly to security issues, but Electron cannot be as secure as Chromium without the resources that Chromium is able to dedicate.
2. Some security features in Chrome (such as Safe Browsing and Certificate Transparency) require a centralized authority and dedicated servers, both of which run counter to the goals of the Electron project. As such, we disable those features in Electron, at the cost of the associated security they would otherwise bring.
3. There is only one Chromium, whereas there are many thousands of apps built on Electron, all of which behave slightly differently. Accounting for those differences can yield a huge possibility space, and make it challenging to ensure the security of the platform in unusual use cases.
4. We can't push security updates to users directly, so we rely on app vendors to upgrade the version of Electron underlying their app in order for security updates to reach users.


While we make our best effort to backport Chromium security fixes to older versions of Electron, we do not make a guarantee that every fix will be backported. Your best chance at staying secure is to be on the latest stable version of Electron.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/sandbox>

NotificationResponse Object
===========================


* `actionIdentifier` string - The identifier string of the action that the user selected.
* `date` number - The delivery date of the notification.
* `identifier` string - The unique identifier for this notification request.
* `userInfo` Record<string, any> - A dictionary of custom information associated with the notification.
* `userText` string (optional) - The text entered or chosen by the user.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/notification-response>

Certificate Object
==================


* `data` string - PEM encoded data
* `issuer` [CertificatePrincipal](certificate-principal) - Issuer principal
* `issuerName` string - Issuer's Common Name
* `issuerCert` Certificate - Issuer certificate (if not self-signed)
* `subject` [CertificatePrincipal](certificate-principal) - Subject principal
* `subjectName` string - Subject's Common Name
* `serialNumber` string - Hex value represented string
* `validStart` number - Start date of the certificate being valid in seconds
* `validExpiry` number - End date of the certificate being valid in seconds
* `fingerprint` string - Fingerprint of the certificate



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/certificate>

JumpListCategory Object
=======================


* `type` string (optional) - One of the following:
	+ `tasks` - Items in this category will be placed into the standard `Tasks` category. There can be only one such category, and it will always be displayed at the bottom of the Jump List.
	+ `frequent` - Displays a list of files frequently opened by the app, the name of the category and its items are set by Windows.
	+ `recent` - Displays a list of files recently opened by the app, the name of the category and its items are set by Windows. Items may be added to this category indirectly using `app.addRecentDocument(path)`.
	+ `custom` - Displays tasks or file links, `name` must be set by the app.
* `name` string (optional) - Must be set if `type` is `custom`, otherwise it should be omitted.
* `items` JumpListItem[] (optional) - Array of [JumpListItem](jump-list-item) objects if `type` is `tasks` or `custom`, otherwise it should be omitted.


**Note:** If a `JumpListCategory` object has neither the `type` nor the `name` property set then its `type` is assumed to be `tasks`. If the `name` property is set but the `type` property is omitted then the `type` is assumed to be `custom`.


**Note:** The maximum length of a Jump List item's `description` property is 260 characters. Beyond this limit, the item will not be added to the Jump List, nor will it be displayed.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/jump-list-category>

Mac App Store Submission Guide
==============================


This guide provides information on:


* How to sign Electron apps on macOS;
* How to submit Electron apps to Mac App Store (MAS);
* The limitations of the MAS build.


Requirements[​](#requirements "Direct link to heading")
-------------------------------------------------------


To sign Electron apps, the following tools must be installed first:


* Xcode 11 or above.
* The [electron-osx-sign](https://github.com/electron/electron-osx-sign) npm module.


You also have to register an Apple Developer account and join the [Apple Developer Program](https://developer.apple.com/support/compare-memberships/).


Sign Electron apps[​](#sign-electron-apps "Direct link to heading")
-------------------------------------------------------------------


Electron apps can be distributed through Mac App Store or outside it. Each way requires different ways of signing and testing. This guide focuses on distribution via Mac App Store, but will also mention other methods.


The following steps describe how to get the certificates from Apple, how to sign Electron apps, and how to test them.


### Get certificates[​](#get-certificates "Direct link to heading")


The simplest way to get signing certificates is to use Xcode:


1. Open Xcode and open "Accounts" preferences;
2. Sign in with your Apple account;
3. Select a team and click "Manage Certificates";
4. In the lower-left corner of the signing certificates sheet, click the Add button (+), and add following certificates:
	* "Apple Development"
	* "Apple Distribution"


The "Apple Development" certificate is used to sign apps for development and testing, on machines that have been registered on Apple Developer website. The method of registration will be described in [Prepare provisioning profile](#prepare-provisioning-profile).


Apps signed with the "Apple Development" certificate cannot be submitted to Mac App Store. For that purpose, apps must be signed with the "Apple Distribution" certificate instead. But note that apps signed with the "Apple Distribution" certificate cannot run directly, they must be re-signed by Apple to be able to run, which will only be possible after being downloaded from the Mac App Store.


#### Other certificates[​](#other-certificates "Direct link to heading")


You may notice that there are also other kinds of certificates.


The "Developer ID Application" certificate is used to sign apps before distributing them outside the Mac App Store.


The "Developer ID Installer" and "Mac Installer Distribution" certificates are used to sign the Mac Installer Package instead of the app itself. Most Electron apps do not use Mac Installer Package so they are generally not needed.


The full list of certificate types can be found [here](https://help.apple.com/xcode/mac/current/#/dev80c6204ec).


Apps signed with "Apple Development" and "Apple Distribution" certificates can only run under [App Sandbox](https://developer.apple.com/app-sandboxing/), so they must use the MAS build of Electron. However, the "Developer ID Application" certificate does not have this restrictions, so apps signed with it can use either the normal build or the MAS build of Electron.


#### Legacy certificate names[​](#legacy-certificate-names "Direct link to heading")


Apple has been changing the names of certificates during past years, you might encounter them when reading old documentations, and some utilities are still using one of the old names.


* The "Apple Distribution" certificate was also named as "3rd Party Mac Developer Application" and "Mac App Distribution".
* The "Apple Development" certificate was also named as "Mac Developer" and "Development".


### Prepare provisioning profile[​](#prepare-provisioning-profile "Direct link to heading")


If you want to test your app on your local machine before submitting your app to the Mac App Store, you have to sign the app with the "Apple Development" certificate with the provisioning profile embedded in the app bundle.


To [create a provisioning profile](https://help.apple.com/developer-account/#/devf2eb157f8), you can follow the below steps:


1. Open the "Certificates, Identifiers & Profiles" page on the [Apple Developer](https://developer.apple.com/account) website.
2. Add a new App ID for your app in the "Identifiers" page.
3. Register your local machine in the "Devices" page. You can find your machine's "Device ID" in the "Hardware" page of the "System Information" app.
4. Register a new Provisioning Profile in the "Profiles" page, and download it to `/path/to/yourapp.provisionprofile`.


### Enable Apple's App Sandbox[​](#enable-apples-app-sandbox "Direct link to heading")


Apps submitted to the Mac App Store must run under Apple's [App Sandbox](https://developer.apple.com/app-sandboxing/), and only the MAS build of Electron can run with the App Sandbox. The standard darwin build of Electron will fail to launch when run under App Sandbox.


When signing the app with `electron-osx-sign`, it will automatically add the necessary entitlements to your app's entitlements, but if you are using custom entitlements, you must ensure App Sandbox capacity is added:




```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
  </dict>
</plist>
```


#### Extra steps without `electron-osx-sign`[​](#extra-steps-without-electron-osx-sign "Direct link to heading")


If you are signing your app without using `electron-osx-sign`, you must ensure the app bundle's entitlements have at least following keys:




```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
    <key>com.apple.security.application-groups</key>
    <array>
      <string>TEAM_ID.your.bundle.id</string>
    </array>
  </dict>
</plist>
```


The `TEAM_ID` should be replaced with your Apple Developer account's Team ID, and the `your.bundle.id` should be replaced with the App ID of the app.


And the following entitlements must be added to the binaries and helpers in the app's bundle:




```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>com.apple.security.app-sandbox</key>
    <true/>
    <key>com.apple.security.inherit</key>
    <true/>
  </dict>
</plist>
```


And the app bundle's `Info.plist` must include `ElectronTeamID` key, which has your Apple Developer account's Team ID as its value:




```
<plist version="1.0">
<dict>
  ...
  <key>ElectronTeamID</key>
  <string>TEAM_ID</string>
</dict>
</plist>
```


When using `electron-osx-sign` the `ElectronTeamID` key will be added automatically by extracting the Team ID from the certificate's name. You may need to manually add this key if `electron-osx-sign` could not find the correct Team ID.


### Sign apps for development[​](#sign-apps-for-development "Direct link to heading")


To sign an app that can run on your development machine, you must sign it with the "Apple Development" certificate and pass the provisioning profile to `electron-osx-sign`.




```
electron-osx-sign YourApp.app --identity='Apple Development' --provisioning-profile=/path/to/yourapp.provisionprofile
```


If you are signing without `electron-osx-sign`, you must place the provisioning profile to `YourApp.app/Contents/embedded.provisionprofile`.


The signed app can only run on the machines that registered by the provisioning profile, and this is the only way to test the signed app before submitting to Mac App Store.


### Sign apps for submitting to the Mac App Store[​](#sign-apps-for-submitting-to-the-mac-app-store "Direct link to heading")


To sign an app that will be submitted to Mac App Store, you must sign it with the "Apple Distribution" certificate. Note that apps signed with this certificate will not run anywhere, unless it is downloaded from Mac App Store.




```
electron-osx-sign YourApp.app --identity='Apple Distribution'
```


### Sign apps for distribution outside the Mac App Store[​](#sign-apps-for-distribution-outside-the-mac-app-store "Direct link to heading")


If you don't plan to submit the app to Mac App Store, you can sign it the "Developer ID Application" certificate. In this way there is no requirement on App Sandbox, and you should use the normal darwin build of Electron if you don't use App Sandbox.




```
electron-osx-sign YourApp.app --identity='Developer ID Application' --no-gatekeeper-assess
```


By passing `--no-gatekeeper-assess`, the `electron-osx-sign` will skip the macOS GateKeeper check as your app usually has not been notarized yet by this step.


This guide does not cover [App Notarization](https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution), but you might want to do it otherwise Apple may prevent users from using your app outside Mac App Store.


Submit Apps to the Mac App Store[​](#submit-apps-to-the-mac-app-store "Direct link to heading")
-----------------------------------------------------------------------------------------------


After signing the app with the "Apple Distribution" certificate, you can continue to submit it to Mac App Store.


However, this guide do not ensure your app will be approved by Apple; you still need to read Apple's [Submitting Your App](https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html) guide on how to meet the Mac App Store requirements.


### Upload[​](#upload "Direct link to heading")


The Application Loader should be used to upload the signed app to iTunes Connect for processing, making sure you have [created a record](https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/CreatingiTunesConnectRecord.html) before uploading.


If you are seeing errors like private APIs uses, you should check if the app is using the MAS build of Electron.


### Submit for review[​](#submit-for-review "Direct link to heading")


After uploading, you should [submit your app for review](https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/SubmittingTheApp.html).


Limitations of MAS Build[​](#limitations-of-mas-build "Direct link to heading")
-------------------------------------------------------------------------------


In order to satisfy all requirements for app sandboxing, the following modules have been disabled in the MAS build:


* `crashReporter`
* `autoUpdater`


and the following behaviors have been changed:


* Video capture may not work for some machines.
* Certain accessibility features may not work.
* Apps will not be aware of DNS changes.


Also, due to the usage of app sandboxing, the resources which can be accessed by the app are strictly limited; you can read [App Sandboxing](https://developer.apple.com/app-sandboxing/) for more information.


### Additional entitlements[​](#additional-entitlements "Direct link to heading")


Depending on which Electron APIs your app uses, you may need to add additional entitlements to your app's entitlements file. Otherwise, the App Sandbox may prevent you from using them.


#### Network access[​](#network-access "Direct link to heading")


Enable outgoing network connections to allow your app to connect to a server:




```
<key>com.apple.security.network.client</key>
<true/>
```


Enable incoming network connections to allow your app to open a network listening socket:




```
<key>com.apple.security.network.server</key>
<true/>
```


See the [Enabling Network Access documentation](https://developer.apple.com/library/ios/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW9) for more details.


#### dialog.showOpenDialog[​](#dialogshowopendialog "Direct link to heading")




```
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
```


See the [Enabling User-Selected File Access documentation](https://developer.apple.com/library/mac/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW6) for more details.


#### dialog.showSaveDialog[​](#dialogshowsavedialog "Direct link to heading")




```
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
```


See the [Enabling User-Selected File Access documentation](https://developer.apple.com/library/mac/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW6) for more details.


Cryptographic Algorithms Used by Electron[​](#cryptographic-algorithms-used-by-electron "Direct link to heading")
-----------------------------------------------------------------------------------------------------------------


Depending on the countries in which you are releasing your app, you may be required to provide information on the cryptographic algorithms used in your software. See the [encryption export compliance docs](https://help.apple.com/app-store-connect/#/devc3f64248f) for more information.


Electron uses following cryptographic algorithms:


* AES - [NIST SP 800-38A](https://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf), [NIST SP 800-38D](https://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf), [RFC 3394](https://www.ietf.org/rfc/rfc3394.txt)
* HMAC - [FIPS 198-1](https://csrc.nist.gov/publications/fips/fips198-1/FIPS-198-1_final.pdf)
* ECDSA - ANS X9.62–2005
* ECDH - ANS X9.63–2001
* HKDF - [NIST SP 800-56C](https://csrc.nist.gov/publications/nistpubs/800-56C/SP-800-56C.pdf)
* PBKDF2 - [RFC 2898](https://tools.ietf.org/html/rfc2898)
* RSA - [RFC 3447](https://www.ietf.org/rfc/rfc3447)
* SHA - [FIPS 180-4](https://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf)
* Blowfish - <https://www.schneier.com/cryptography/blowfish/>
* CAST - [RFC 2144](https://tools.ietf.org/html/rfc2144), [RFC 2612](https://tools.ietf.org/html/rfc2612)
* DES - [FIPS 46-3](https://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf)
* DH - [RFC 2631](https://tools.ietf.org/html/rfc2631)
* DSA - [ANSI X9.30](https://webstore.ansi.org/RecordDetail.aspx?sku=ANSI+X9.30-1%3A1997)
* EC - [SEC 1](https://www.secg.org/sec1-v2.pdf)
* IDEA - "On the Design and Security of Block Ciphers" book by X. Lai
* MD2 - [RFC 1319](https://tools.ietf.org/html/rfc1319)
* MD4 - [RFC 6150](https://tools.ietf.org/html/rfc6150)
* MD5 - [RFC 1321](https://tools.ietf.org/html/rfc1321)
* MDC2 - [ISO/IEC 10118-2](https://wiki.openssl.org/index.php/Manual:Mdc2(3))
* RC2 - [RFC 2268](https://tools.ietf.org/html/rfc2268)
* RC4 - [RFC 4345](https://tools.ietf.org/html/rfc4345)
* RC5 - <https://people.csail.mit.edu/rivest/Rivest-rc5rev.pdf>
* RIPEMD - [ISO/IEC 10118-3](https://webstore.ansi.org/RecordDetail.aspx?sku=ISO%2FIEC%2010118-3:2004)



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/mac-app-store-submission-guide>

contextBridge
=============



> Create a safe, bi-directional, synchronous bridge across isolated contexts
> 
> 


Process: [Renderer](../glossary#renderer-process)


An example of exposing an API to a renderer from an isolated preload script is given below:




```
// Preload (Isolated World)
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld(
  'electron',
  {
    doThing: () => ipcRenderer.send('do-a-thing')
  }
)
```




```
// Renderer (Main World)

window.electron.doThing()
```


Glossary[​](#glossary "Direct link to heading")
-----------------------------------------------


### Main World[​](#main-world "Direct link to heading")


The "Main World" is the JavaScript context that your main renderer code runs in. By default, the page you load in your renderer executes code in this world.


### Isolated World[​](#isolated-world "Direct link to heading")


When `contextIsolation` is enabled in your `webPreferences` (this is the default behavior since Electron 12.0.0), your `preload` scripts run in an "Isolated World". You can read more about context isolation and what it affects in the [security](../tutorial/security#3-enable-context-isolation) docs.


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `contextBridge` module has the following methods:


### 
`contextBridge.exposeInMainWorld(apiKey, api)`[​](#contextbridgeexposeinmainworldapikey-api "Direct link to heading")


* `apiKey` string - The key to inject the API onto `window` with. The API will be accessible on `window[apiKey]`.
* `api` any - Your API, more information on what this API can be and how it works is available below.


Usage[​](#usage "Direct link to heading")
-----------------------------------------


### API[​](#api "Direct link to heading")


The `api` provided to [`exposeInMainWorld`](#contextbridgeexposeinmainworldapikey-api) must be a `Function`, `string`, `number`, `Array`, `boolean`, or an object whose keys are strings and values are a `Function`, `string`, `number`, `Array`, `boolean`, or another nested object that meets the same conditions.


`Function` values are proxied to the other context and all other values are **copied** and **frozen**. Any data / primitives sent in the API become immutable and updates on either side of the bridge do not result in an update on the other side.


An example of a complex API is shown below:




```
const { contextBridge } = require('electron')

contextBridge.exposeInMainWorld(
  'electron',
  {
    doThing: () => ipcRenderer.send('do-a-thing'),
    myPromises: [Promise.resolve(), Promise.reject(new Error('whoops'))],
    anAsyncFunction: async () => 123,
    data: {
      myFlags: ['a', 'b', 'c'],
      bootTime: 1234
    },
    nestedAPI: {
      evenDeeper: {
        youCanDoThisAsMuchAsYouWant: {
          fn: () => ({
            returnData: 123
          })
        }
      }
    }
  }
)
```


### API Functions[​](#api-functions "Direct link to heading")


`Function` values that you bind through the `contextBridge` are proxied through Electron to ensure that contexts remain isolated. This results in some key limitations that we've outlined below.


#### Parameter / Error / Return Type support[​](#parameter--error--return-type-support "Direct link to heading")


Because parameters, errors and return values are **copied** when they are sent over the bridge, there are only certain types that can be used. At a high level, if the type you want to use can be serialized and deserialized into the same object it will work. A table of type support has been included below for completeness:




| Type | Complexity | Parameter Support | Return Value Support | Limitations |
| --- | --- | --- | --- | --- |
| `string` | Simple | ✅ | ✅ | N/A |
| `number` | Simple | ✅ | ✅ | N/A |
| `boolean` | Simple | ✅ | ✅ | N/A |
| `Object` | Complex | ✅ | ✅ | Keys must be supported using only "Simple" types in this table. Values must be supported in this table. Prototype modifications are dropped. Sending custom classes will copy values but not the prototype. |
| `Array` | Complex | ✅ | ✅ | Same limitations as the `Object` type |
| `Error` | Complex | ✅ | ✅ | Errors that are thrown are also copied, this can result in the message and stack trace of the error changing slightly due to being thrown in a different context, and any custom properties on the Error object [will be lost](https://github.com/electron/electron/issues/25596) |
| `Promise` | Complex | ✅ | ✅ | N/A |
| `Function` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending classes or constructors will not work. |
| [Cloneable Types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) | Simple | ✅ | ✅ | See the linked document on cloneable types |
| `Element` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending custom elements will not work. |
| `Blob` | Complex | ✅ | ✅ | N/A |
| `Symbol` | N/A | ❌ | ❌ | Symbols cannot be copied across contexts so they are dropped |


If the type you care about is not in the above table, it is probably not supported.


### Exposing Node Global Symbols[​](#exposing-node-global-symbols "Direct link to heading")


The `contextBridge` can be used by the preload script to give your renderer access to Node APIs. The table of supported types described above also applies to Node APIs that you expose through `contextBridge`. Please note that many Node APIs grant access to local system resources. Be very cautious about which globals and APIs you expose to untrusted remote content.




```
const { contextBridge } = require('electron')
const crypto = require('crypto')
contextBridge.exposeInMainWorld('nodeCrypto', {
  sha256sum (data) {
    const hash = crypto.createHash('sha256')
    hash.update(data)
    return hash.digest('hex')
  }
})
```



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/context-bridge>

Context Isolation
=================


What is it?[​](#what-is-it "Direct link to heading")
----------------------------------------------------


Context Isolation is a feature that ensures that both your `preload` scripts and Electron's internal logic run in a separate context to the website you load in a [`webContents`](../api/web-contents). This is important for security purposes as it helps prevent the website from accessing Electron internals or the powerful APIs your preload script has access to.


This means that the `window` object that your preload script has access to is actually a **different** object than the website would have access to. For example, if you set `window.hello = 'wave'` in your preload script and context isolation is enabled, `window.hello` will be undefined if the website tries to access it.


Context isolation has been enabled by default since Electron 12, and it is a recommended security setting for *all applications*.


Migration[​](#migration "Direct link to heading")
-------------------------------------------------



> Without context isolation, I used to provide APIs from my preload script using `window.X = apiObject`. Now what?
> 
> 


### Before: context isolation disabled[​](#before-context-isolation-disabled "Direct link to heading")


Exposing APIs from your preload script to a loaded website in the renderer process is a common use-case. With context isolation disabled, your preload script would share a common global `window` object with the renderer. You could then attach arbitrary properties to a preload script:



preload.js


```
// preload with contextIsolation disabled
window.myAPI = {
  doAThing: () => {}
}
```



The `doAThing()` function could then be used directly in the renderer process:



renderer.js


```
// use the exposed API in the renderer
window.myAPI.doAThing()
```



### After: context isolation enabled[​](#after-context-isolation-enabled "Direct link to heading")


There is a dedicated module in Electron to help you do this in a painless way. The [`contextBridge`](../api/context-bridge) module can be used to **safely** expose APIs from your preload script's isolated context to the context the website is running in. The API will also be accessible from the website on `window.myAPI` just like it was before.



preload.js


```
// preload with contextIsolation enabled
const { contextBridge } = require('electron')

contextBridge.exposeInMainWorld('myAPI', {
  doAThing: () => {}
})
```




renderer.js


```
// use the exposed API in the renderer
window.myAPI.doAThing()
```



Please read the `contextBridge` documentation linked above to fully understand its limitations. For instance, you can't send custom prototypes or symbols over the bridge.


Security considerations[​](#security-considerations "Direct link to heading")
-----------------------------------------------------------------------------


Just enabling `contextIsolation` and using `contextBridge` does not automatically mean that everything you do is safe. For instance, this code is **unsafe**.



preload.js


```
// ❌ Bad code
contextBridge.exposeInMainWorld('myAPI', {
  send: ipcRenderer.send
})
```



It directly exposes a powerful API without any kind of argument filtering. This would allow any website to send arbitrary IPC messages, which you do not want to be possible. The correct way to expose IPC-based APIs would instead be to provide one method per IPC message.



preload.js


```
// ✅ Good code
contextBridge.exposeInMainWorld('myAPI', {
  loadPreferences: () => ipcRenderer.invoke('load-prefs')
})
```



Usage with TypeScript[​](#usage-with-typescript "Direct link to heading")
-------------------------------------------------------------------------


If you're building your Electron app with TypeScript, you'll want to add types to your APIs exposed over the context bridge. The renderer's `window` object won't have the correct typings unless you extend the types with a [declaration file](https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html).


For example, given this `preload.ts` script:



preload.ts


```
contextBridge.exposeInMainWorld('electronAPI', {
  loadPreferences: () => ipcRenderer.invoke('load-prefs')
})
```



You can create a `renderer.d.ts` declaration file and globally augment the `Window` interface:



renderer.d.ts


```
export interface IElectronAPI {
  loadPreferences: () => Promise<void>,
}

declare global {
  interface Window {
    electronAPI: IElectronAPI
  }
}
```



Doing so will ensure that the TypeScript compiler will know about the `electronAPI` property on your global `window` object when writing scripts in your renderer process:



renderer.ts


```
window.electronAPI.loadPreferences()
```




 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/context-isolation>

Class: WebRequest
=================

Class: WebRequest[​](#class-webrequest "Direct link to heading")
----------------------------------------------------------------



> Intercept and modify the contents of a request at various stages of its lifetime.
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


Instances of the `WebRequest` class are accessed by using the `webRequest` property of a `Session`.


The methods of `WebRequest` accept an optional `filter` and a `listener`. The `listener` will be called with `listener(details)` when the API's event has happened. The `details` object describes the request.


⚠️ Only the last attached `listener` will be used. Passing `null` as `listener` will unsubscribe from the event.


The `filter` object has a `urls` property which is an Array of URL patterns that will be used to filter out the requests that do not match the URL patterns. If the `filter` is omitted then all requests will be matched.


For certain events the `listener` is passed with a `callback`, which should be called with a `response` object when `listener` has done its work.


An example of adding `User-Agent` header for requests:




```
const { session } = require('electron')

// Modify the user agent for all requests to the following urls.
const filter = {
  urls: ['https://*.github.com/*', '*://electron.github.io']
}

session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => {
  details.requestHeaders['User-Agent'] = 'MyAgent'
  callback({ requestHeaders: details.requestHeaders })
})
```


### Instance Methods[​](#instance-methods "Direct link to heading")


The following methods are available on instances of `WebRequest`:


#### 
`webRequest.onBeforeRequest([filter, ]listener)`[​](#webrequestonbeforerequestfilter-listener "Direct link to heading")


* `filter` [WebRequestFilter](structures/web-request-filter) (optional)
* `listener` Function | null
	+ `details` Object
		- `id` Integer
		- `url` string
		- `method` string
		- `webContentsId` Integer (optional)
		- `webContents` WebContents (optional)
		- `frame` WebFrameMain (optional)
		- `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
		- `referrer` string
		- `timestamp` Double
		- `uploadData` [UploadData[]](structures/upload-data)
	+ `callback` Function
		- `response` Object
			* `cancel` boolean (optional)
			* `redirectURL` string (optional) - The original request is prevented from being sent or completed and is instead redirected to the given URL.


The `listener` will be called with `listener(details, callback)` when a request is about to occur.


The `uploadData` is an array of `UploadData` objects.


The `callback` has to be called with an `response` object.


Some examples of valid `urls`:




```
'http://foo:1234/'
'http://foo.com/'
'http://foo:1234/bar'
'*://*/*'
'*://example.com/*'
'*://example.com/foo/*'
'http://*.foo:1234/'
'file://foo:1234/bar'
'http://foo:*/'
'*://www.foo.com/'
```


#### 
`webRequest.onBeforeSendHeaders([filter, ]listener)`[​](#webrequestonbeforesendheadersfilter-listener "Direct link to heading")


* `filter` [WebRequestFilter](structures/web-request-filter) (optional)
* `listener` Function | null
	+ `details` Object
		- `id` Integer
		- `url` string
		- `method` string
		- `webContentsId` Integer (optional)
		- `webContents` WebContents (optional)
		- `frame` WebFrameMain (optional)
		- `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
		- `referrer` string
		- `timestamp` Double
		- `uploadData` [UploadData[]](structures/upload-data) (optional)
		- `requestHeaders` Record<string, string>
	+ `callback` Function
		- `beforeSendResponse` Object
		
		```
		* `cancel` boolean (optional)
		* `requestHeaders` Record<string, string | string[]&#62; (optional) - When provided, request will be made
		```
		
		with these headers.


The `listener` will be called with `listener(details, callback)` before sending an HTTP request, once the request headers are available. This may occur after a TCP connection is made to the server, but before any http data is sent.


The `callback` has to be called with a `response` object.


#### 
`webRequest.onSendHeaders([filter, ]listener)`[​](#webrequestonsendheadersfilter-listener "Direct link to heading")


* `filter` [WebRequestFilter](structures/web-request-filter) (optional)
* `listener` Function | null
	+ `details` Object
		- `id` Integer
		- `url` string
		- `method` string
		- `webContentsId` Integer (optional)
		- `webContents` WebContents (optional)
		- `frame` WebFrameMain (optional)
		- `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
		- `referrer` string
		- `timestamp` Double
		- `requestHeaders` Record<string, string>


The `listener` will be called with `listener(details)` just before a request is going to be sent to the server, modifications of previous `onBeforeSendHeaders` response are visible by the time this listener is fired.


#### 
`webRequest.onHeadersReceived([filter, ]listener)`[​](#webrequestonheadersreceivedfilter-listener "Direct link to heading")


* `filter` [WebRequestFilter](structures/web-request-filter) (optional)
* `listener` Function | null
	+ `details` Object
		- `id` Integer
		- `url` string
		- `method` string
		- `webContentsId` Integer (optional)
		- `webContents` WebContents (optional)
		- `frame` WebFrameMain (optional)
		- `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
		- `referrer` string
		- `timestamp` Double
		- `statusLine` string
		- `statusCode` Integer
		- `responseHeaders` Record<string, string[]> (optional)
	+ `callback` Function
		- `headersReceivedResponse` Object
			* `cancel` boolean (optional)
			* `responseHeaders` Record<string, string | string[]> (optional) - When provided, the server is assumed to have responded with these headers.
			* `statusLine` string (optional) - Should be provided when overriding `responseHeaders` to change header status otherwise original response header's status will be used.


The `listener` will be called with `listener(details, callback)` when HTTP response headers of a request have been received.


The `callback` has to be called with a `response` object.


#### 
`webRequest.onResponseStarted([filter, ]listener)`[​](#webrequestonresponsestartedfilter-listener "Direct link to heading")


* `filter` [WebRequestFilter](structures/web-request-filter) (optional)
* `listener` Function | null
	+ `details` Object
		- `id` Integer
		- `url` string
		- `method` string
		- `webContentsId` Integer (optional)
		- `webContents` WebContents (optional)
		- `frame` WebFrameMain (optional)
		- `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
		- `referrer` string
		- `timestamp` Double
		- `responseHeaders` Record<string, string[]> (optional)
		- `fromCache` boolean - Indicates whether the response was fetched from disk cache.
		- `statusCode` Integer
		- `statusLine` string


The `listener` will be called with `listener(details)` when first byte of the response body is received. For HTTP requests, this means that the status line and response headers are available.


#### 
`webRequest.onBeforeRedirect([filter, ]listener)`[​](#webrequestonbeforeredirectfilter-listener "Direct link to heading")


* `filter` [WebRequestFilter](structures/web-request-filter) (optional)
* `listener` Function | null
	+ `details` Object
		- `id` Integer
		- `url` string
		- `method` string
		- `webContentsId` Integer (optional)
		- `webContents` WebContents (optional)
		- `frame` WebFrameMain (optional)
		- `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
		- `referrer` string
		- `timestamp` Double
		- `redirectURL` string
		- `statusCode` Integer
		- `statusLine` string
		- `ip` string (optional) - The server IP address that the request was actually sent to.
		- `fromCache` boolean
		- `responseHeaders` Record<string, string[]> (optional)


The `listener` will be called with `listener(details)` when a server initiated redirect is about to occur.


#### 
`webRequest.onCompleted([filter, ]listener)`[​](#webrequestoncompletedfilter-listener "Direct link to heading")


* `filter` [WebRequestFilter](structures/web-request-filter) (optional)
* `listener` Function | null
	+ `details` Object
		- `id` Integer
		- `url` string
		- `method` string
		- `webContentsId` Integer (optional)
		- `webContents` WebContents (optional)
		- `frame` WebFrameMain (optional)
		- `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
		- `referrer` string
		- `timestamp` Double
		- `responseHeaders` Record<string, string[]> (optional)
		- `fromCache` boolean
		- `statusCode` Integer
		- `statusLine` string
		- `error` string


The `listener` will be called with `listener(details)` when a request is completed.


#### 
`webRequest.onErrorOccurred([filter, ]listener)`[​](#webrequestonerroroccurredfilter-listener "Direct link to heading")


* `filter` [WebRequestFilter](structures/web-request-filter) (optional)
* `listener` Function | null
	+ `details` Object
		- `id` Integer
		- `url` string
		- `method` string
		- `webContentsId` Integer (optional)
		- `webContents` WebContents (optional)
		- `frame` WebFrameMain (optional)
		- `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
		- `referrer` string
		- `timestamp` Double
		- `fromCache` boolean
		- `error` string - The error description.


The `listener` will be called with `listener(details)` when an error occurs.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/web-request>

JumpListItem Object
===================


* `type` string (optional) - One of the following:
	+ `task` - A task will launch an app with specific arguments.
	+ `separator` - Can be used to separate items in the standard `Tasks` category.
	+ `file` - A file link will open a file using the app that created the Jump List, for this to work the app must be registered as a handler for the file type (though it doesn't have to be the default handler).
* `path` string (optional) - Path of the file to open, should only be set if `type` is `file`.
* `program` string (optional) - Path of the program to execute, usually you should specify `process.execPath` which opens the current program. Should only be set if `type` is `task`.
* `args` string (optional) - The command line arguments when `program` is executed. Should only be set if `type` is `task`.
* `title` string (optional) - The text to be displayed for the item in the Jump List. Should only be set if `type` is `task`.
* `description` string (optional) - Description of the task (displayed in a tooltip). Should only be set if `type` is `task`. Maximum length 260 characters.
* `iconPath` string (optional) - The absolute path to an icon to be displayed in a Jump List, which can be an arbitrary resource file that contains an icon (e.g. `.ico`, `.exe`, `.dll`). You can usually specify `process.execPath` to show the program icon.
* `iconIndex` number (optional) - The index of the icon in the resource file. If a resource file contains multiple icons this value can be used to specify the zero-based index of the icon that should be displayed for this task. If a resource file contains only one icon, this property should be set to zero.
* `workingDirectory` string (optional) - The working directory. Default is empty.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/jump-list-item>

dialog
======



> Display native system dialogs for opening and saving files, alerting, etc.
> 
> 


Process: [Main](../glossary#main-process)


An example of showing a dialog to select multiple files:




```
const { dialog } = require('electron')
console.log(dialog.showOpenDialog({ properties: ['openFile', 'multiSelections'] }))
```


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `dialog` module has the following methods:


### 
`dialog.showOpenDialogSync([browserWindow, ]options)`[​](#dialogshowopendialogsyncbrowserwindow-options "Direct link to heading")


* `browserWindow` [BrowserWindow](browser-window) (optional)
* `options` Object
	+ `title` string (optional)
	+ `defaultPath` string (optional)
	+ `buttonLabel` string (optional) - Custom label for the confirmation button, when left empty the default label will be used.
	+ `filters` [FileFilter[]](structures/file-filter) (optional)
	+ `properties` string[] (optional) - Contains which features the dialog should use. The following values are supported:
		- `openFile` - Allow files to be selected.
		- `openDirectory` - Allow directories to be selected.
		- `multiSelections` - Allow multiple paths to be selected.
		- `showHiddenFiles` - Show hidden files in dialog.
		- `createDirectory` *macOS* - Allow creating new directories from dialog.
		- `promptToCreate` *Windows* - Prompt for creation if the file path entered in the dialog does not exist. This does not actually create the file at the path but allows non-existent paths to be returned that should be created by the application.
		- `noResolveAliases` *macOS* - Disable the automatic alias (symlink) path resolution. Selected aliases will now return the alias path instead of their target path.
		- `treatPackageAsDirectory` *macOS* - Treat packages, such as `.app` folders, as a directory instead of a file.
		- `dontAddToRecent` *Windows* - Do not add the item being opened to the recent documents list.
	+ `message` string (optional) *macOS* - Message to display above input boxes.
	+ `securityScopedBookmarks` boolean (optional) *macOS* *mas* - Create [security scoped bookmarks](https://developer.apple.com/library/content/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW16) when packaged for the Mac App Store.


Returns `string[] | undefined`, the file paths chosen by the user; if the dialog is cancelled it returns `undefined`.


The `browserWindow` argument allows the dialog to attach itself to a parent window, making it modal.


The `filters` specifies an array of file types that can be displayed or selected when you want to limit the user to a specific type. For example:




```
{
  filters: [
    { name: 'Images', extensions: ['jpg', 'png', 'gif'] },
    { name: 'Movies', extensions: ['mkv', 'avi', 'mp4'] },
    { name: 'Custom File Type', extensions: ['as'] },
    { name: 'All Files', extensions: ['*'] }
  ]
}
```


The `extensions` array should contain extensions without wildcards or dots (e.g. `'png'` is good but `'.png'` and `'*.png'` are bad). To show all files, use the `'*'` wildcard (no other wildcard is supported).


**Note:** On Windows and Linux an open dialog can not be both a file selector and a directory selector, so if you set `properties` to `['openFile', 'openDirectory']` on these platforms, a directory selector will be shown.




```
dialog.showOpenDialogSync(mainWindow, {
  properties: ['openFile', 'openDirectory']
})
```


### 
`dialog.showOpenDialog([browserWindow, ]options)`[​](#dialogshowopendialogbrowserwindow-options "Direct link to heading")


* `browserWindow` [BrowserWindow](browser-window) (optional)
* `options` Object
	+ `title` string (optional)
	+ `defaultPath` string (optional)
	+ `buttonLabel` string (optional) - Custom label for the confirmation button, when left empty the default label will be used.
	+ `filters` [FileFilter[]](structures/file-filter) (optional)
	+ `properties` string[] (optional) - Contains which features the dialog should use. The following values are supported:
		- `openFile` - Allow files to be selected.
		- `openDirectory` - Allow directories to be selected.
		- `multiSelections` - Allow multiple paths to be selected.
		- `showHiddenFiles` - Show hidden files in dialog.
		- `createDirectory` *macOS* - Allow creating new directories from dialog.
		- `promptToCreate` *Windows* - Prompt for creation if the file path entered in the dialog does not exist. This does not actually create the file at the path but allows non-existent paths to be returned that should be created by the application.
		- `noResolveAliases` *macOS* - Disable the automatic alias (symlink) path resolution. Selected aliases will now return the alias path instead of their target path.
		- `treatPackageAsDirectory` *macOS* - Treat packages, such as `.app` folders, as a directory instead of a file.
		- `dontAddToRecent` *Windows* - Do not add the item being opened to the recent documents list.
	+ `message` string (optional) *macOS* - Message to display above input boxes.
	+ `securityScopedBookmarks` boolean (optional) *macOS* *mas* - Create [security scoped bookmarks](https://developer.apple.com/library/content/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW16) when packaged for the Mac App Store.


Returns `Promise<Object>` - Resolve with an object containing the following:


* `canceled` boolean - whether or not the dialog was canceled.
* `filePaths` string[] - An array of file paths chosen by the user. If the dialog is cancelled this will be an empty array.
* `bookmarks` string[] (optional) *macOS* *mas* - An array matching the `filePaths` array of base64 encoded strings which contains security scoped bookmark data. `securityScopedBookmarks` must be enabled for this to be populated. (For return values, see [table here](#bookmarks-array).)


The `browserWindow` argument allows the dialog to attach itself to a parent window, making it modal.


The `filters` specifies an array of file types that can be displayed or selected when you want to limit the user to a specific type. For example:




```
{
  filters: [
    { name: 'Images', extensions: ['jpg', 'png', 'gif'] },
    { name: 'Movies', extensions: ['mkv', 'avi', 'mp4'] },
    { name: 'Custom File Type', extensions: ['as'] },
    { name: 'All Files', extensions: ['*'] }
  ]
}
```


The `extensions` array should contain extensions without wildcards or dots (e.g. `'png'` is good but `'.png'` and `'*.png'` are bad). To show all files, use the `'*'` wildcard (no other wildcard is supported).


**Note:** On Windows and Linux an open dialog can not be both a file selector and a directory selector, so if you set `properties` to `['openFile', 'openDirectory']` on these platforms, a directory selector will be shown.




```
dialog.showOpenDialog(mainWindow, {
  properties: ['openFile', 'openDirectory']
}).then(result => {
  console.log(result.canceled)
  console.log(result.filePaths)
}).catch(err => {
  console.log(err)
})
```


### 
`dialog.showSaveDialogSync([browserWindow, ]options)`[​](#dialogshowsavedialogsyncbrowserwindow-options "Direct link to heading")


* `browserWindow` [BrowserWindow](browser-window) (optional)
* `options` Object
	+ `title` string (optional) - The dialog title. Cannot be displayed on some *Linux* desktop environments.
	+ `defaultPath` string (optional) - Absolute directory path, absolute file path, or file name to use by default.
	+ `buttonLabel` string (optional) - Custom label for the confirmation button, when left empty the default label will be used.
	+ `filters` [FileFilter[]](structures/file-filter) (optional)
	+ `message` string (optional) *macOS* - Message to display above text fields.
	+ `nameFieldLabel` string (optional) *macOS* - Custom label for the text displayed in front of the filename text field.
	+ `showsTagField` boolean (optional) *macOS* - Show the tags input box, defaults to `true`.
	+ `properties` string[] (optional)
		- `showHiddenFiles` - Show hidden files in dialog.
		- `createDirectory` *macOS* - Allow creating new directories from dialog.
		- `treatPackageAsDirectory` *macOS* - Treat packages, such as `.app` folders, as a directory instead of a file.
		- `showOverwriteConfirmation` *Linux* - Sets whether the user will be presented a confirmation dialog if the user types a file name that already exists.
		- `dontAddToRecent` *Windows* - Do not add the item being saved to the recent documents list.
	+ `securityScopedBookmarks` boolean (optional) *macOS* *mas* - Create a [security scoped bookmark](https://developer.apple.com/library/content/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW16) when packaged for the Mac App Store. If this option is enabled and the file doesn't already exist a blank file will be created at the chosen path.


Returns `string | undefined`, the path of the file chosen by the user; if the dialog is cancelled it returns `undefined`.


The `browserWindow` argument allows the dialog to attach itself to a parent window, making it modal.


The `filters` specifies an array of file types that can be displayed, see `dialog.showOpenDialog` for an example.


### 
`dialog.showSaveDialog([browserWindow, ]options)`[​](#dialogshowsavedialogbrowserwindow-options "Direct link to heading")


* `browserWindow` [BrowserWindow](browser-window) (optional)
* `options` Object
	+ `title` string (optional) - The dialog title. Cannot be displayed on some *Linux* desktop environments.
	+ `defaultPath` string (optional) - Absolute directory path, absolute file path, or file name to use by default.
	+ `buttonLabel` string (optional) - Custom label for the confirmation button, when left empty the default label will be used.
	+ `filters` [FileFilter[]](structures/file-filter) (optional)
	+ `message` string (optional) *macOS* - Message to display above text fields.
	+ `nameFieldLabel` string (optional) *macOS* - Custom label for the text displayed in front of the filename text field.
	+ `showsTagField` boolean (optional) *macOS* - Show the tags input box, defaults to `true`.
	+ `properties` string[] (optional)
		- `showHiddenFiles` - Show hidden files in dialog.
		- `createDirectory` *macOS* - Allow creating new directories from dialog.
		- `treatPackageAsDirectory` *macOS* - Treat packages, such as `.app` folders, as a directory instead of a file.
		- `showOverwriteConfirmation` *Linux* - Sets whether the user will be presented a confirmation dialog if the user types a file name that already exists.
		- `dontAddToRecent` *Windows* - Do not add the item being saved to the recent documents list.
	+ `securityScopedBookmarks` boolean (optional) *macOS* *mas* - Create a [security scoped bookmark](https://developer.apple.com/library/content/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW16) when packaged for the Mac App Store. If this option is enabled and the file doesn't already exist a blank file will be created at the chosen path.


Returns `Promise<Object>` - Resolve with an object containing the following:


* `canceled` boolean - whether or not the dialog was canceled.
* `filePath` string (optional) - If the dialog is canceled, this will be `undefined`.
* `bookmark` string (optional) *macOS* *mas* - Base64 encoded string which contains the security scoped bookmark data for the saved file. `securityScopedBookmarks` must be enabled for this to be present. (For return values, see [table here](#bookmarks-array).)


The `browserWindow` argument allows the dialog to attach itself to a parent window, making it modal.


The `filters` specifies an array of file types that can be displayed, see `dialog.showOpenDialog` for an example.


**Note:** On macOS, using the asynchronous version is recommended to avoid issues when expanding and collapsing the dialog.


### 
`dialog.showMessageBoxSync([browserWindow, ]options)`[​](#dialogshowmessageboxsyncbrowserwindow-options "Direct link to heading")


* `browserWindow` [BrowserWindow](browser-window) (optional)
* `options` Object
	+ `message` string - Content of the message box.
	+ `type` string (optional) - Can be `"none"`, `"info"`, `"error"`, `"question"` or `"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless you set an icon using the `"icon"` option. On macOS, both `"warning"` and `"error"` display the same warning icon.
	+ `buttons` string[] (optional) - Array of texts for buttons. On Windows, an empty array will result in one button labeled "OK".
	+ `defaultId` Integer (optional) - Index of the button in the buttons array which will be selected by default when the message box opens.
	+ `title` string (optional) - Title of the message box, some platforms will not show it.
	+ `detail` string (optional) - Extra information of the message.
	+ `icon` ([NativeImage](native-image) | string) (optional)
	+ `textWidth` Integer (optional) *macOS* - Custom width of the text in the message box.
	+ `cancelId` Integer (optional) - The index of the button to be used to cancel the dialog, via the `Esc` key. By default this is assigned to the first button with "cancel" or "no" as the label. If no such labeled buttons exist and this option is not set, `0` will be used as the return value.
	+ `noLink` boolean (optional) - On Windows Electron will try to figure out which one of the `buttons` are common buttons (like "Cancel" or "Yes"), and show the others as command links in the dialog. This can make the dialog appear in the style of modern Windows apps. If you don't like this behavior, you can set `noLink` to `true`.
	+ `normalizeAccessKeys` boolean (optional) - Normalize the keyboard access keys across platforms. Default is `false`. Enabling this assumes `&` is used in the button labels for the placement of the keyboard shortcut access key and labels will be converted so they work correctly on each platform, `&` characters are removed on macOS, converted to `_` on Linux, and left untouched on Windows. For example, a button label of `Vie&w` will be converted to `Vie_w` on Linux and `View` on macOS and can be selected via `Alt-W` on Windows and Linux.


Returns `Integer` - the index of the clicked button.


Shows a message box, it will block the process until the message box is closed. It returns the index of the clicked button.


The `browserWindow` argument allows the dialog to attach itself to a parent window, making it modal. If `browserWindow` is not shown dialog will not be attached to it. In such case it will be displayed as an independent window.


### 
`dialog.showMessageBox([browserWindow, ]options)`[​](#dialogshowmessageboxbrowserwindow-options "Direct link to heading")


* `browserWindow` [BrowserWindow](browser-window) (optional)
* `options` Object
	+ `message` string - Content of the message box.
	+ `type` string (optional) - Can be `"none"`, `"info"`, `"error"`, `"question"` or `"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless you set an icon using the `"icon"` option. On macOS, both `"warning"` and `"error"` display the same warning icon.
	+ `buttons` string[] (optional) - Array of texts for buttons. On Windows, an empty array will result in one button labeled "OK".
	+ `defaultId` Integer (optional) - Index of the button in the buttons array which will be selected by default when the message box opens.
	+ `signal` AbortSignal (optional) - Pass an instance of [AbortSignal](https://nodejs.org/api/globals.html#globals_class_abortsignal) to optionally close the message box, the message box will behave as if it was cancelled by the user. On macOS, `signal` does not work with message boxes that do not have a parent window, since those message boxes run synchronously due to platform limitations.
	+ `title` string (optional) - Title of the message box, some platforms will not show it.
	+ `detail` string (optional) - Extra information of the message.
	+ `checkboxLabel` string (optional) - If provided, the message box will include a checkbox with the given label.
	+ `checkboxChecked` boolean (optional) - Initial checked state of the checkbox. `false` by default.
	+ `icon` ([NativeImage](native-image) | string) (optional)
	+ `textWidth` Integer (optional) *macOS* - Custom width of the text in the message box.
	+ `cancelId` Integer (optional) - The index of the button to be used to cancel the dialog, via the `Esc` key. By default this is assigned to the first button with "cancel" or "no" as the label. If no such labeled buttons exist and this option is not set, `0` will be used as the return value.
	+ `noLink` boolean (optional) - On Windows Electron will try to figure out which one of the `buttons` are common buttons (like "Cancel" or "Yes"), and show the others as command links in the dialog. This can make the dialog appear in the style of modern Windows apps. If you don't like this behavior, you can set `noLink` to `true`.
	+ `normalizeAccessKeys` boolean (optional) - Normalize the keyboard access keys across platforms. Default is `false`. Enabling this assumes `&` is used in the button labels for the placement of the keyboard shortcut access key and labels will be converted so they work correctly on each platform, `&` characters are removed on macOS, converted to `_` on Linux, and left untouched on Windows. For example, a button label of `Vie&w` will be converted to `Vie_w` on Linux and `View` on macOS and can be selected via `Alt-W` on Windows and Linux.


Returns `Promise<Object>` - resolves with a promise containing the following properties:


* `response` number - The index of the clicked button.
* `checkboxChecked` boolean - The checked state of the checkbox if `checkboxLabel` was set. Otherwise `false`.


Shows a message box.


The `browserWindow` argument allows the dialog to attach itself to a parent window, making it modal.


### 
`dialog.showErrorBox(title, content)`[​](#dialogshowerrorboxtitle-content "Direct link to heading")


* `title` string - The title to display in the error box.
* `content` string - The text content to display in the error box.


Displays a modal dialog that shows an error message.


This API can be called safely before the `ready` event the `app` module emits, it is usually used to report errors in early stage of startup. If called before the app `ready`event on Linux, the message will be emitted to stderr, and no GUI dialog will appear.


### 
`dialog.showCertificateTrustDialog([browserWindow, ]options)` *macOS* *Windows*[​](#dialogshowcertificatetrustdialogbrowserwindow-options-macos-windows "Direct link to heading")


* `browserWindow` [BrowserWindow](browser-window) (optional)
* `options` Object
	+ `certificate` [Certificate](structures/certificate) - The certificate to trust/import.
	+ `message` string - The message to display to the user.


Returns `Promise<void>` - resolves when the certificate trust dialog is shown.


On macOS, this displays a modal dialog that shows a message and certificate information, and gives the user the option of trusting/importing the certificate. If you provide a `browserWindow` argument the dialog will be attached to the parent window, making it modal.


On Windows the options are more limited, due to the Win32 APIs used:


* The `message` argument is not used, as the OS provides its own confirmation dialog.
* The `browserWindow` argument is ignored since it is not possible to make this confirmation dialog modal.


Bookmarks array[​](#bookmarks-array "Direct link to heading")
-------------------------------------------------------------


`showOpenDialog`, `showOpenDialogSync`, `showSaveDialog`, and `showSaveDialogSync` will return a `bookmarks` array.




| Build Type | securityScopedBookmarks boolean | Return Type | Return Value |
| --- | --- | --- | --- |
| macOS mas | True | Success | `['LONGBOOKMARKSTRING']` |
| macOS mas | True | Error | `['']` (array of empty string) |
| macOS mas | False | NA | `[]` (empty array) |
| non mas | any | NA | `[]` (empty array) |


Sheets[​](#sheets "Direct link to heading")
-------------------------------------------


On macOS, dialogs are presented as sheets attached to a window if you provide a [`BrowserWindow`](browser-window) reference in the `browserWindow` parameter, or modals if no window is provided.


You can call `BrowserWindow.getCurrentWindow().setSheetOffset(offset)` to change the offset from the window frame where sheets are attached.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/dialog>

shell
=====



> Manage files and URLs using their default applications.
> 
> 


Process: [Main](../glossary#main-process), [Renderer](../glossary#renderer-process) (non-sandboxed only)


The `shell` module provides functions related to desktop integration.


An example of opening a URL in the user's default browser:




```
const { shell } = require('electron')

shell.openExternal('https://github.com')
```


**Note:** While the `shell` module can be used in the renderer process, it will not function in a sandboxed renderer.


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `shell` module has the following methods:


### 
`shell.showItemInFolder(fullPath)`[​](#shellshowiteminfolderfullpath "Direct link to heading")


* `fullPath` string


Show the given file in a file manager. If possible, select the file.


### 
`shell.openPath(path)`[​](#shellopenpathpath "Direct link to heading")


* `path` string


Returns `Promise<string>` - Resolves with a string containing the error message corresponding to the failure if a failure occurred, otherwise "".


Open the given file in the desktop's default manner.


### 
`shell.openExternal(url[, options])`[​](#shellopenexternalurl-options "Direct link to heading")


* `url` string - Max 2081 characters on windows.
* `options` Object (optional)
	+ `activate` boolean (optional) *macOS* - `true` to bring the opened application to the foreground. The default is `true`.
	+ `workingDirectory` string (optional) *Windows* - The working directory.


Returns `Promise<void>`


Open the given external protocol URL in the desktop's default manner. (For example, mailto: URLs in the user's default mail agent).


### 
`shell.trashItem(path)`[​](#shelltrashitempath "Direct link to heading")


* `path` string - path to the item to be moved to the trash.


Returns `Promise<void>` - Resolves when the operation has been completed. Rejects if there was an error while deleting the requested item.


This moves a path to the OS-specific trash location (Trash on macOS, Recycle Bin on Windows, and a desktop-environment-specific location on Linux).


### 
`shell.beep()`[​](#shellbeep "Direct link to heading")


Play the beep sound.


### 
`shell.writeShortcutLink(shortcutPath[, operation], options)` *Windows*[​](#shellwriteshortcutlinkshortcutpath-operation-options-windows "Direct link to heading")


* `shortcutPath` string
* `operation` string (optional) - Default is `create`, can be one of following:
	+ `create` - Creates a new shortcut, overwriting if necessary.
	+ `update` - Updates specified properties only on an existing shortcut.
	+ `replace` - Overwrites an existing shortcut, fails if the shortcut doesn't exist.
* `options` [ShortcutDetails](structures/shortcut-details)


Returns `boolean` - Whether the shortcut was created successfully.


Creates or updates a shortcut link at `shortcutPath`.


### 
`shell.readShortcutLink(shortcutPath)` *Windows*[​](#shellreadshortcutlinkshortcutpath-windows "Direct link to heading")


* `shortcutPath` string


Returns [ShortcutDetails](structures/shortcut-details)


Resolves the shortcut link at `shortcutPath`.


An exception will be thrown when any error happens.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/shell>

Performance
===========


Developers frequently ask about strategies to optimize the performance of Electron applications. Software engineers, consumers, and framework developers do not always agree on one single definition of what "performance" means. This document outlines some of the Electron maintainers' favorite ways to reduce the amount of memory, CPU, and disk resources being used while ensuring that your app is responsive to user input and completes operations as quickly as possible. Furthermore, we want all performance strategies to maintain a high standard for your app's security.


Wisdom and information about how to build performant websites with JavaScript generally applies to Electron apps, too. To a certain extent, resources discussing how to build performant Node.js applications also apply, but be careful to understand that the term "performance" means different things for a Node.js backend than it does for an application running on a client.


This list is provided for your convenience – and is, much like our [security checklist](security) – not meant to exhaustive. It is probably possible to build a slow Electron app that follows all the steps outlined below. Electron is a powerful development platform that enables you, the developer, to do more or less whatever you want. All that freedom means that performance is largely your responsibility.


Measure, Measure, Measure[​](#measure-measure-measure "Direct link to heading")
-------------------------------------------------------------------------------


The list below contains a number of steps that are fairly straightforward and easy to implement. However, building the most performant version of your app will require you to go beyond a number of steps. Instead, you will have to closely examine all the code running in your app by carefully profiling and measuring. Where are the bottlenecks? When the user clicks a button, what operations take up the brunt of the time? While the app is simply idling, which objects take up the most memory?


Time and time again, we have seen that the most successful strategy for building a performant Electron app is to profile the running code, find the most resource-hungry piece of it, and to optimize it. Repeating this seemingly laborious process over and over again will dramatically increase your app's performance. Experience from working with major apps like Visual Studio Code or Slack has shown that this practice is by far the most reliable strategy to improve performance.


To learn more about how to profile your app's code, familiarize yourself with the Chrome Developer Tools. For advanced analysis looking at multiple processes at once, consider the [Chrome Tracing](https://www.chromium.org/developers/how-tos/trace-event-profiling-tool) tool.


### Recommended Reading[​](#recommended-reading "Direct link to heading")


* [Get Started With Analyzing Runtime Performance](https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/)
* [Talk: "Visual Studio Code - The First Second"](https://www.youtube.com/watch?v=r0OeHRUCCb4)


Checklist: Performance recommendations[​](#checklist-performance-recommendations "Direct link to heading")
----------------------------------------------------------------------------------------------------------


Chances are that your app could be a little leaner, faster, and generally less resource-hungry if you attempt these steps.


1. [Carelessly including modules](#1-carelessly-including-modules)
2. [Loading and running code too soon](#2-loading-and-running-code-too-soon)
3. [Blocking the main process](#3-blocking-the-main-process)
4. [Blocking the renderer process](#4-blocking-the-renderer-process)
5. [Unnecessary polyfills](#5-unnecessary-polyfills)
6. [Unnecessary or blocking network requests](#6-unnecessary-or-blocking-network-requests)
7. [Bundle your code](#7-bundle-your-code)


### 1. Carelessly including modules[​](#1-carelessly-including-modules "Direct link to heading")


Before adding a Node.js module to your application, examine said module. How many dependencies does that module include? What kind of resources does it need to simply be called in a `require()` statement? You might find that the module with the most downloads on the NPM package registry or the most stars on GitHub is not in fact the leanest or smallest one available.


#### Why?[​](#why "Direct link to heading")


The reasoning behind this recommendation is best illustrated with a real-world example. During the early days of Electron, reliable detection of network connectivity was a problem, resulting many apps to use a module that exposed a simple `isOnline()` method.


That module detected your network connectivity by attempting to reach out to a number of well-known endpoints. For the list of those endpoints, it depended on a different module, which also contained a list of well-known ports. This dependency itself relied on a module containing information about ports, which came in the form of a JSON file with more than 100,000 lines of content. Whenever the module was loaded (usually in a `require('module')` statement), it would load all its dependencies and eventually read and parse this JSON file. Parsing many thousands lines of JSON is a very expensive operation. On a slow machine it can take up whole seconds of time.


In many server contexts, startup time is virtually irrelevant. A Node.js server that requires information about all ports is likely actually "more performant" if it loads all required information into memory whenever the server boots at the benefit of serving requests faster. The module discussed in this example is not a "bad" module. Electron apps, however, should not be loading, parsing, and storing in memory information that it does not actually need.


In short, a seemingly excellent module written primarily for Node.js servers running Linux might be bad news for your app's performance. In this particular example, the correct solution was to use no module at all, and to instead use connectivity checks included in later versions of Chromium.


#### How?[​](#how "Direct link to heading")


When considering a module, we recommend that you check:


1. the size of dependencies included
2. the resources required to load (`require()`) it
3. the resources required to perform the action you're interested in


Generating a CPU profile and a heap memory profile for loading a module can be done with a single command on the command line. In the example below, we're looking at the popular module `request`.




```
node --cpu-prof --heap-prof -e "require('request')"
```


Executing this command results in a `.cpuprofile` file and a `.heapprofile` file in the directory you executed it in. Both files can be analyzed using the Chrome Developer Tools, using the `Performance` and `Memory` tabs respectively.


![Performance CPU Profile](https://www.electronjs.org/assets/images/performance-cpu-prof-ac389f8f3dfd6fbcb08245a6d02f346f.png)


![Performance Heap Memory Profile](https://www.electronjs.org/assets/images/performance-heap-prof-97e432676b7357425aa67f73eeef0d1f.png)


In this example, on the author's machine, we saw that loading `request` took almost half a second, whereas `node-fetch` took dramatically less memory and less than 50ms.


### 2. Loading and running code too soon[​](#2-loading-and-running-code-too-soon "Direct link to heading")


If you have expensive setup operations, consider deferring those. Inspect all the work being executed right after the application starts. Instead of firing off all operations right away, consider staggering them in a sequence more closely aligned with the user's journey.


In traditional Node.js development, we're used to putting all our `require()` statements at the top. If you're currently writing your Electron application using the same strategy *and* are using sizable modules that you do not immediately need, apply the same strategy and defer loading to a more opportune time.


#### Why?[​](#why-1 "Direct link to heading")


Loading modules is a surprisingly expensive operation, especially on Windows. When your app starts, it should not make users wait for operations that are currently not necessary.


This might seem obvious, but many applications tend to do a large amount of work immediately after the app has launched - like checking for updates, downloading content used in a later flow, or performing heavy disk I/O operations.


Let's consider Visual Studio Code as an example. When you open a file, it will immediately display the file to you without any code highlighting, prioritizing your ability to interact with the text. Once it has done that work, it will move on to code highlighting.


#### How?[​](#how-1 "Direct link to heading")


Let's consider an example and assume that your application is parsing files in the fictitious `.foo` format. In order to do that, it relies on the equally fictitious `foo-parser` module. In traditional Node.js development, you might write code that eagerly loads dependencies:



parser.js


```
const fs = require('fs')
const fooParser = require('foo-parser')

class Parser {
  constructor () {
    this.files = fs.readdirSync('.')
  }

  getParsedFiles () {
    return fooParser.parse(this.files)
  }
}

const parser = new Parser()

module.exports = { parser }
```



In the above example, we're doing a lot of work that's being executed as soon as the file is loaded. Do we need to get parsed files right away? Could we do this work a little later, when `getParsedFiles()` is actually called?



parser.js


```
// "fs" is likely already being loaded, so the `require()` call is cheap
const fs = require('fs')

class Parser {
  async getFiles () {
    // Touch the disk as soon as `getFiles` is called, not sooner.
    // Also, ensure that we're not blocking other operations by using
    // the asynchronous version.
    this.files = this.files || await fs.readdir('.')

    return this.files
  }

  async getParsedFiles () {
    // Our fictitious foo-parser is a big and expensive module to load, so
    // defer that work until we actually need to parse files.
    // Since `require()` comes with a module cache, the `require()` call
    // will only be expensive once - subsequent calls of `getParsedFiles()`
    // will be faster.
    const fooParser = require('foo-parser')
    const files = await this.getFiles()

    return fooParser.parse(files)
  }
}

// This operation is now a lot cheaper than in our previous example
const parser = new Parser()

module.exports = { parser }
```



In short, allocate resources "just in time" rather than allocating them all when your app starts.


### 3. Blocking the main process[​](#3-blocking-the-main-process "Direct link to heading")


Electron's main process (sometimes called "browser process") is special: It is the parent process to all your app's other processes and the primary process the operating system interacts with. It handles windows, interactions, and the communication between various components inside your app. It also houses the UI thread.


Under no circumstances should you block this process and the UI thread with long-running operations. Blocking the UI thread means that your entire app will freeze until the main process is ready to continue processing.


#### Why?[​](#why-2 "Direct link to heading")


The main process and its UI thread are essentially the control tower for major operations inside your app. When the operating system tells your app about a mouse click, it'll go through the main process before it reaches your window. If your window is rendering a buttery-smooth animation, it'll need to talk to the GPU process about that – once again going through the main process.


Electron and Chromium are careful to put heavy disk I/O and CPU-bound operations onto new threads to avoid blocking the UI thread. You should do the same.


#### How?[​](#how-2 "Direct link to heading")


Electron's powerful multi-process architecture stands ready to assist you with your long-running tasks, but also includes a small number of performance traps.


1. For long running CPU-heavy tasks, make use of [worker threads](https://nodejs.org/api/worker_threads.html), consider moving them to the BrowserWindow, or (as a last resort) spawn a dedicated process.
2. Avoid using the synchronous IPC and the `@electron/remote` module as much as possible. While there are legitimate use cases, it is far too easy to unknowingly block the UI thread.
3. Avoid using blocking I/O operations in the main process. In short, whenever core Node.js modules (like `fs` or `child_process`) offer a synchronous or an asynchronous version, you should prefer the asynchronous and non-blocking variant.


### 4. Blocking the renderer process[​](#4-blocking-the-renderer-process "Direct link to heading")


Since Electron ships with a current version of Chrome, you can make use of the latest and greatest features the Web Platform offers to defer or offload heavy operations in a way that keeps your app smooth and responsive.


#### Why?[​](#why-3 "Direct link to heading")


Your app probably has a lot of JavaScript to run in the renderer process. The trick is to execute operations as quickly as possible without taking away resources needed to keep scrolling smooth, respond to user input, or animations at 60fps.


Orchestrating the flow of operations in your renderer's code is particularly useful if users complain about your app sometimes "stuttering".


#### How?[​](#how-3 "Direct link to heading")


Generally speaking, all advice for building performant web apps for modern browsers apply to Electron's renderers, too. The two primary tools at your disposal are currently `requestIdleCallback()` for small operations and `Web Workers` for long-running operations.


*`requestIdleCallback()`* allows developers to queue up a function to be executed as soon as the process is entering an idle period. It enables you to perform low-priority or background work without impacting the user experience. For more information about how to use it, [check out its documentation on MDN](https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback).


*Web Workers* are a powerful tool to run code on a separate thread. There are some caveats to consider – consult Electron's [multithreading documentation](multithreading) and the [MDN documentation for Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers). They're an ideal solution for any operation that requires a lot of CPU power for an extended period of time.


### 5. Unnecessary polyfills[​](#5-unnecessary-polyfills "Direct link to heading")


One of Electron's great benefits is that you know exactly which engine will parse your JavaScript, HTML, and CSS. If you're re-purposing code that was written for the web at large, make sure to not polyfill features included in Electron.


#### Why?[​](#why-4 "Direct link to heading")


When building a web application for today's Internet, the oldest environments dictate what features you can and cannot use. Even though Electron supports well-performing CSS filters and animations, an older browser might not. Where you could use WebGL, your developers may have chosen a more resource-hungry solution to support older phones.


When it comes to JavaScript, you may have included toolkit libraries like jQuery for DOM selectors or polyfills like the `regenerator-runtime` to support `async/await`.


It is rare for a JavaScript-based polyfill to be faster than the equivalent native feature in Electron. Do not slow down your Electron app by shipping your own version of standard web platform features.


#### How?[​](#how-4 "Direct link to heading")


Operate under the assumption that polyfills in current versions of Electron are unnecessary. If you have doubts, check [caniuse.com](https://caniuse.com/) and check if the [version of Chromium used in your Electron version](../api/process#processversionschrome-readonly) supports the feature you desire.


In addition, carefully examine the libraries you use. Are they really necessary? `jQuery`, for example, was such a success that many of its features are now part of the [standard JavaScript feature set available](http://youmightnotneedjquery.com/).


If you're using a transpiler/compiler like TypeScript, examine its configuration and ensure that you're targeting the latest ECMAScript version supported by Electron.


### 6. Unnecessary or blocking network requests[​](#6-unnecessary-or-blocking-network-requests "Direct link to heading")


Avoid fetching rarely changing resources from the internet if they could easily be bundled with your application.


#### Why?[​](#why-5 "Direct link to heading")


Many users of Electron start with an entirely web-based app that they're turning into a desktop application. As web developers, we are used to loading resources from a variety of content delivery networks. Now that you are shipping a proper desktop application, attempt to "cut the cord" where possible and avoid letting your users wait for resources that never change and could easily be included in your app.


A typical example is Google Fonts. Many developers make use of Google's impressive collection of free fonts, which comes with a content delivery network. The pitch is straightforward: Include a few lines of CSS and Google will take care of the rest.


When building an Electron app, your users are better served if you download the fonts and include them in your app's bundle.


#### How?[​](#how-5 "Direct link to heading")


In an ideal world, your application wouldn't need the network to operate at all. To get there, you must understand what resources your app is downloading - and how large those resources are.


To do so, open up the developer tools. Navigate to the `Network` tab and check the `Disable cache` option. Then, reload your renderer. Unless your app prohibits such reloads, you can usually trigger a reload by hitting `Cmd + R` or `Ctrl + R` with the developer tools in focus.


The tools will now meticulously record all network requests. In a first pass, take stock of all the resources being downloaded, focusing on the larger files first. Are any of them images, fonts, or media files that don't change and could be included with your bundle? If so, include them.


As a next step, enable `Network Throttling`. Find the drop-down that currently reads `Online` and select a slower speed such as `Fast 3G`. Reload your renderer and see if there are any resources that your app is unnecessarily waiting for. In many cases, an app will wait for a network request to complete despite not actually needing the involved resource.


As a tip, loading resources from the Internet that you might want to change without shipping an application update is a powerful strategy. For advanced control over how resources are being loaded, consider investing in [Service Workers](https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API).


### 7. Bundle your code[​](#7-bundle-your-code "Direct link to heading")


As already pointed out in "[Loading and running code too soon](#2-loading-and-running-code-too-soon)", calling `require()` is an expensive operation. If you are able to do so, bundle your application's code into a single file.


#### Why?[​](#why-6 "Direct link to heading")


Modern JavaScript development usually involves many files and modules. While that's perfectly fine for developing with Electron, we heavily recommend that you bundle all your code into one single file to ensure that the overhead included in calling `require()` is only paid once when your application loads.


#### How?[​](#how-6 "Direct link to heading")


There are numerous JavaScript bundlers out there and we know better than to anger the community by recommending one tool over another. We do however recommend that you use a bundler that is able to handle Electron's unique environment that needs to handle both Node.js and browser environments.


As of writing this article, the popular choices include [Webpack](https://webpack.js.org/), [Parcel](https://parceljs.org/), and [rollup.js](https://rollupjs.org/).



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/performance>

ThumbarButton Object
====================


* `icon` [NativeImage](../native-image) - The icon showing in thumbnail toolbar.
* `click` Function
* `tooltip` string (optional) - The text of the button's tooltip.
* `flags` string[] (optional) - Control specific states and behaviors of the button. By default, it is `['enabled']`.


The `flags` is an array that can include following `string`s:


* `enabled` - The button is active and available to the user.
* `disabled` - The button is disabled. It is present, but has a visual state indicating it will not respond to user action.
* `dismissonclick` - When the button is clicked, the thumbnail window closes immediately.
* `nobackground` - Do not draw a button border, use only the image.
* `hidden` - The button is not shown to the user.
* `noninteractive` - The button is enabled but not interactive; no pressed button state is drawn. This value is intended for instances where the button is used in a notification.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/thumbar-button>

V8 Development
==============



> A collection of resources for learning and using V8
> 
> 


* [V8 Tracing](https://v8.dev/docs/trace)
* [V8 Profiler](https://v8.dev/docs/profile) - Profiler combinations which are useful for profiling: `--prof`, `--trace-ic`, `--trace-opt`, `--trace-deopt`, `--print-bytecode`, `--print-opt-code`
* [V8 Interpreter Design](https://docs.google.com/document/d/11T2CRex9hXxoJwbYqVQ32yIPMh0uouUZLdyrtmMoL44/edit?ts=56f27d9d#heading=h.6jz9dj3bnr8t)
* [Optimizing compiler](https://v8.dev/docs/turbofan)
* [V8 GDB Debugging](https://v8.dev/docs/gdb-jit)


See also [Chromium Development](chromium-development)



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/v8-development>

Application Debugging
=====================


Whenever your Electron application is not behaving the way you wanted it to, an array of debugging tools might help you find coding errors, performance bottlenecks, or optimization opportunities.


Renderer Process[​](#renderer-process "Direct link to heading")
---------------------------------------------------------------


The most comprehensive tool to debug individual renderer processes is the Chromium Developer Toolset. It is available for all renderer processes, including instances of `BrowserWindow`, `BrowserView`, and `WebView`. You can open them programmatically by calling the `openDevTools()` API on the `webContents` of the instance:




```
const { BrowserWindow } = require('electron')

const win = new BrowserWindow()
win.webContents.openDevTools()
```


Google offers [excellent documentation for their developer tools](https://developer.chrome.com/devtools). We recommend that you make yourself familiar with them - they are usually one of the most powerful utilities in any Electron Developer's tool belt.


Main Process[​](#main-process "Direct link to heading")
-------------------------------------------------------


Debugging the main process is a bit trickier, since you cannot open developer tools for them. The Chromium Developer Tools can [be used to debug Electron's main process](https://nodejs.org/en/docs/inspector/) thanks to a closer collaboration between Google / Chrome and Node.js, but you might encounter oddities like `require` not being present in the console.


For more information, see the [Debugging the Main Process documentation](debugging-main-process).


V8 Crashes[​](#v8-crashes "Direct link to heading")
---------------------------------------------------


If the V8 context crashes, the DevTools will display this message.


`DevTools was disconnected from the page. Once page is reloaded, DevTools will automatically reconnect.`


Chromium logs can be enabled via the `ELECTRON_ENABLE_LOGGING` environment variable. For more information, see the [environment variables documentation](../api/environment-variables#electron_enable_logging).


Alternatively, the command line argument `--enable-logging` can be passed. More information is available in the [command line switches documentation](../api/command-line-switches#--enable-loggingfile).



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/application-debugging>

`<webview>` Tag
================


Warning[​](#warning "Direct link to heading")
---------------------------------------------


Electron's `webview` tag is based on [Chromium's `webview`](https://developer.chrome.com/docs/extensions/reference/webviewTag/), which is undergoing dramatic architectural changes. This impacts the stability of `webviews`, including rendering, navigation, and event routing. We currently recommend to not use the `webview` tag and to consider alternatives, like `iframe`, [Electron's `BrowserView`](browser-view), or an architecture that avoids embedded content altogether.


Enabling[​](#enabling "Direct link to heading")
-----------------------------------------------


By default the `webview` tag is disabled in Electron >= 5. You need to enable the tag by setting the `webviewTag` webPreferences option when constructing your `BrowserWindow`. For more information see the [BrowserWindow constructor docs](browser-window).


Overview[​](#overview "Direct link to heading")
-----------------------------------------------



> Display external web content in an isolated frame and process.
> 
> 


Process: [Renderer](../glossary#renderer-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


Use the `webview` tag to embed 'guest' content (such as web pages) in your Electron app. The guest content is contained within the `webview` container. An embedded page within your app controls how the guest content is laid out and rendered.


Unlike an `iframe`, the `webview` runs in a separate process than your app. It doesn't have the same permissions as your web page and all interactions between your app and embedded content will be asynchronous. This keeps your app safe from the embedded content. **Note:** Most methods called on the webview from the host page require a synchronous call to the main process.


Example[​](#example "Direct link to heading")
---------------------------------------------


To embed a web page in your app, add the `webview` tag to your app's embedder page (this is the app page that will display the guest content). In its simplest form, the `webview` tag includes the `src` of the web page and css styles that control the appearance of the `webview` container:




```
<webview id="foo" src="https://www.github.com/" style="display:inline-flex; width:640px; height:480px"></webview>
```


If you want to control the guest content in any way, you can write JavaScript that listens for `webview` events and responds to those events using the `webview` methods. Here's sample code with two event listeners: one that listens for the web page to start loading, the other for the web page to stop loading, and displays a "loading..." message during the load time:




```
<script>
  onload = () => {
    const webview = document.querySelector('webview')
    const indicator = document.querySelector('.indicator')

    const loadstart = () => {
      indicator.innerText = 'loading...'
    }

    const loadstop = () => {
      indicator.innerText = ''
    }

    webview.addEventListener('did-start-loading', loadstart)
    webview.addEventListener('did-stop-loading', loadstop)
  }
</script>
```


Internal implementation[​](#internal-implementation "Direct link to heading")
-----------------------------------------------------------------------------


Under the hood `webview` is implemented with [Out-of-Process iframes (OOPIFs)](https://www.chromium.org/developers/design-documents/oop-iframes). The `webview` tag is essentially a custom element using shadow DOM to wrap an `iframe` element inside it.


So the behavior of `webview` is very similar to a cross-domain `iframe`, as examples:


* When clicking into a `webview`, the page focus will move from the embedder frame to `webview`.
* You can not add keyboard, mouse, and scroll event listeners to `webview`.
* All reactions between the embedder frame and `webview` are asynchronous.


CSS Styling Notes[​](#css-styling-notes "Direct link to heading")
-----------------------------------------------------------------


Please note that the `webview` tag's style uses `display:flex;` internally to ensure the child `iframe` element fills the full height and width of its `webview` container when used with traditional and flexbox layouts. Please do not overwrite the default `display:flex;` CSS property, unless specifying `display:inline-flex;` for inline layout.


Tag Attributes[​](#tag-attributes "Direct link to heading")
-----------------------------------------------------------


The `webview` tag has the following attributes:


### 
`src`[​](#src "Direct link to heading")




```
<webview src="https://www.github.com/"></webview>
```


A `string` representing the visible URL. Writing to this attribute initiates top-level navigation.


Assigning `src` its own value will reload the current page.


The `src` attribute can also accept data URLs, such as `data:text/plain,Hello, world!`.


### 
`nodeintegration`[​](#nodeintegration "Direct link to heading")




```
<webview src="http://www.google.com/" nodeintegration></webview>
```


A `boolean`. When this attribute is present the guest page in `webview` will have node integration and can use node APIs like `require` and `process` to access low level system resources. Node integration is disabled by default in the guest page.


### 
`nodeintegrationinsubframes`[​](#nodeintegrationinsubframes "Direct link to heading")




```
<webview src="http://www.google.com/" nodeintegrationinsubframes></webview>
```


A `boolean` for the experimental option for enabling NodeJS support in sub-frames such as iframes inside the `webview`. All your preloads will load for every iframe, you can use `process.isMainFrame` to determine if you are in the main frame or not. This option is disabled by default in the guest page.


### 
`plugins`[​](#plugins "Direct link to heading")




```
<webview src="https://www.github.com/" plugins></webview>
```


A `boolean`. When this attribute is present the guest page in `webview` will be able to use browser plugins. Plugins are disabled by default.


### 
`preload`[​](#preload "Direct link to heading")




```
<!-- from a file -->
<webview src="https://www.github.com/" preload="./test.js"></webview>
<!-- or if you want to load from an asar archive -->
<webview src="https://www.github.com/" preload="./app.asar/test.js"></webview>
```


A `string` that specifies a script that will be loaded before other scripts run in the guest page. The protocol of script's URL must be `file:` (even when using `asar:` archives) because it will be loaded by Node's `require` under the hood, which treats `asar:` archives as virtual directories.


When the guest page doesn't have node integration this script will still have access to all Node APIs, but global objects injected by Node will be deleted after this script has finished executing.


### 
`httpreferrer`[​](#httpreferrer "Direct link to heading")




```
<webview src="https://www.github.com/" httpreferrer="http://cheng.guru"></webview>
```


A `string` that sets the referrer URL for the guest page.


### 
`useragent`[​](#useragent "Direct link to heading")




```
<webview src="https://www.github.com/" useragent="Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; AS; rv:11.0) like Gecko"></webview>
```


A `string` that sets the user agent for the guest page before the page is navigated to. Once the page is loaded, use the `setUserAgent` method to change the user agent.


### 
`disablewebsecurity`[​](#disablewebsecurity "Direct link to heading")




```
<webview src="https://www.github.com/" disablewebsecurity></webview>
```


A `boolean`. When this attribute is present the guest page will have web security disabled. Web security is enabled by default.


### 
`partition`[​](#partition "Direct link to heading")




```
<webview src="https://github.com" partition="persist:github"></webview>
<webview src="https://electronjs.org" partition="electron"></webview>
```


A `string` that sets the session used by the page. If `partition` starts with `persist:`, the page will use a persistent session available to all pages in the app with the same `partition`. if there is no `persist:` prefix, the page will use an in-memory session. By assigning the same `partition`, multiple pages can share the same session. If the `partition` is unset then default session of the app will be used.


This value can only be modified before the first navigation, since the session of an active renderer process cannot change. Subsequent attempts to modify the value will fail with a DOM exception.


### 
`allowpopups`[​](#allowpopups "Direct link to heading")




```
<webview src="https://www.github.com/" allowpopups></webview>
```


A `boolean`. When this attribute is present the guest page will be allowed to open new windows. Popups are disabled by default.


### 
`webpreferences`[​](#webpreferences "Direct link to heading")




```
<webview src="https://github.com" webpreferences="allowRunningInsecureContent, javascript=no"></webview>
```


A `string` which is a comma separated list of strings which specifies the web preferences to be set on the webview. The full list of supported preference strings can be found in [BrowserWindow](browser-window#new-browserwindowoptions).


The string follows the same format as the features string in `window.open`. A name by itself is given a `true` boolean value. A preference can be set to another value by including an `=`, followed by the value. Special values `yes` and `1` are interpreted as `true`, while `no` and `0` are interpreted as `false`.


### 
`enableblinkfeatures`[​](#enableblinkfeatures "Direct link to heading")




```
<webview src="https://www.github.com/" enableblinkfeatures="PreciseMemoryInfo, CSSVariables"></webview>
```


A `string` which is a list of strings which specifies the blink features to be enabled separated by `,`. The full list of supported feature strings can be found in the [RuntimeEnabledFeatures.json5](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5?l=70) file.


### 
`disableblinkfeatures`[​](#disableblinkfeatures "Direct link to heading")




```
<webview src="https://www.github.com/" disableblinkfeatures="PreciseMemoryInfo, CSSVariables"></webview>
```


A `string` which is a list of strings which specifies the blink features to be disabled separated by `,`. The full list of supported feature strings can be found in the [RuntimeEnabledFeatures.json5](https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5?l=70) file.


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `webview` tag has the following methods:


**Note:** The webview element must be loaded before using the methods.


**Example**




```
const webview = document.querySelector('webview')
webview.addEventListener('dom-ready', () => {
  webview.openDevTools()
})
```


### 
`<webview>.loadURL(url[, options])`[​](#webviewloadurlurl-options "Direct link to heading")


* `url` URL
* `options` Object (optional)
	+ `httpReferrer` (string | [Referrer](structures/referrer)) (optional) - An HTTP Referrer url.
	+ `userAgent` string (optional) - A user agent originating the request.
	+ `extraHeaders` string (optional) - Extra headers separated by "\n"
	+ `postData` ([UploadRawData](structures/upload-raw-data) | [UploadFile](structures/upload-file))[] (optional)
	+ `baseURLForDataURL` string (optional) - Base url (with trailing path separator) for files to be loaded by the data url. This is needed only if the specified `url` is a data url and needs to load other files.


Returns `Promise<void>` - The promise will resolve when the page has finished loading (see [`did-finish-load`](webview-tag#event-did-finish-load)), and rejects if the page fails to load (see [`did-fail-load`](webview-tag#event-did-fail-load)).


Loads the `url` in the webview, the `url` must contain the protocol prefix, e.g. the `http://` or `file://`.


### 
`<webview>.downloadURL(url)`[​](#webviewdownloadurlurl "Direct link to heading")


* `url` string


Initiates a download of the resource at `url` without navigating.


### 
`<webview>.getURL()`[​](#webviewgeturl "Direct link to heading")


Returns `string` - The URL of guest page.


### 
`<webview>.getTitle()`[​](#webviewgettitle "Direct link to heading")


Returns `string` - The title of guest page.


### 
`<webview>.isLoading()`[​](#webviewisloading "Direct link to heading")


Returns `boolean` - Whether guest page is still loading resources.


### 
`<webview>.isLoadingMainFrame()`[​](#webviewisloadingmainframe "Direct link to heading")


Returns `boolean` - Whether the main frame (and not just iframes or frames within it) is still loading.


### 
`<webview>.isWaitingForResponse()`[​](#webviewiswaitingforresponse "Direct link to heading")


Returns `boolean` - Whether the guest page is waiting for a first-response for the main resource of the page.


### 
`<webview>.stop()`[​](#webviewstop "Direct link to heading")


Stops any pending navigation.


### 
`<webview>.reload()`[​](#webviewreload "Direct link to heading")


Reloads the guest page.


### 
`<webview>.reloadIgnoringCache()`[​](#webviewreloadignoringcache "Direct link to heading")


Reloads the guest page and ignores cache.


### 
`<webview>.canGoBack()`[​](#webviewcangoback "Direct link to heading")


Returns `boolean` - Whether the guest page can go back.


### 
`<webview>.canGoForward()`[​](#webviewcangoforward "Direct link to heading")


Returns `boolean` - Whether the guest page can go forward.


### 
`<webview>.canGoToOffset(offset)`[​](#webviewcangotooffsetoffset "Direct link to heading")


* `offset` Integer


Returns `boolean` - Whether the guest page can go to `offset`.


### 
`<webview>.clearHistory()`[​](#webviewclearhistory "Direct link to heading")


Clears the navigation history.


### 
`<webview>.goBack()`[​](#webviewgoback "Direct link to heading")


Makes the guest page go back.


### 
`<webview>.goForward()`[​](#webviewgoforward "Direct link to heading")


Makes the guest page go forward.


### 
`<webview>.goToIndex(index)`[​](#webviewgotoindexindex "Direct link to heading")


* `index` Integer


Navigates to the specified absolute index.


### 
`<webview>.goToOffset(offset)`[​](#webviewgotooffsetoffset "Direct link to heading")


* `offset` Integer


Navigates to the specified offset from the "current entry".


### 
`<webview>.isCrashed()`[​](#webviewiscrashed "Direct link to heading")


Returns `boolean` - Whether the renderer process has crashed.


### 
`<webview>.setUserAgent(userAgent)`[​](#webviewsetuseragentuseragent "Direct link to heading")


* `userAgent` string


Overrides the user agent for the guest page.


### 
`<webview>.getUserAgent()`[​](#webviewgetuseragent "Direct link to heading")


Returns `string` - The user agent for guest page.


### 
`<webview>.insertCSS(css)`[​](#webviewinsertcsscss "Direct link to heading")


* `css` string


Returns `Promise<string>` - A promise that resolves with a key for the inserted CSS that can later be used to remove the CSS via `<webview>.removeInsertedCSS(key)`.


Injects CSS into the current web page and returns a unique key for the inserted stylesheet.


### 
`<webview>.removeInsertedCSS(key)`[​](#webviewremoveinsertedcsskey "Direct link to heading")


* `key` string


Returns `Promise<void>` - Resolves if the removal was successful.


Removes the inserted CSS from the current web page. The stylesheet is identified by its key, which is returned from `<webview>.insertCSS(css)`.


### 
`<webview>.executeJavaScript(code[, userGesture])`[​](#webviewexecutejavascriptcode-usergesture "Direct link to heading")


* `code` string
* `userGesture` boolean (optional) - Default `false`.


Returns `Promise<any>` - A promise that resolves with the result of the executed code or is rejected if the result of the code is a rejected promise.


Evaluates `code` in page. If `userGesture` is set, it will create the user gesture context in the page. HTML APIs like `requestFullScreen`, which require user action, can take advantage of this option for automation.


### 
`<webview>.openDevTools()`[​](#webviewopendevtools "Direct link to heading")


Opens a DevTools window for guest page.


### 
`<webview>.closeDevTools()`[​](#webviewclosedevtools "Direct link to heading")


Closes the DevTools window of guest page.


### 
`<webview>.isDevToolsOpened()`[​](#webviewisdevtoolsopened "Direct link to heading")


Returns `boolean` - Whether guest page has a DevTools window attached.


### 
`<webview>.isDevToolsFocused()`[​](#webviewisdevtoolsfocused "Direct link to heading")


Returns `boolean` - Whether DevTools window of guest page is focused.


### 
`<webview>.inspectElement(x, y)`[​](#webviewinspectelementx-y "Direct link to heading")


* `x` Integer
* `y` Integer


Starts inspecting element at position (`x`, `y`) of guest page.


### 
`<webview>.inspectSharedWorker()`[​](#webviewinspectsharedworker "Direct link to heading")


Opens the DevTools for the shared worker context present in the guest page.


### 
`<webview>.inspectServiceWorker()`[​](#webviewinspectserviceworker "Direct link to heading")


Opens the DevTools for the service worker context present in the guest page.


### 
`<webview>.setAudioMuted(muted)`[​](#webviewsetaudiomutedmuted "Direct link to heading")


* `muted` boolean


Set guest page muted.


### 
`<webview>.isAudioMuted()`[​](#webviewisaudiomuted "Direct link to heading")


Returns `boolean` - Whether guest page has been muted.


### 
`<webview>.isCurrentlyAudible()`[​](#webviewiscurrentlyaudible "Direct link to heading")


Returns `boolean` - Whether audio is currently playing.


### 
`<webview>.undo()`[​](#webviewundo "Direct link to heading")


Executes editing command `undo` in page.


### 
`<webview>.redo()`[​](#webviewredo "Direct link to heading")


Executes editing command `redo` in page.


### 
`<webview>.cut()`[​](#webviewcut "Direct link to heading")


Executes editing command `cut` in page.


### 
`<webview>.copy()`[​](#webviewcopy "Direct link to heading")


Executes editing command `copy` in page.


### 
`<webview>.paste()`[​](#webviewpaste "Direct link to heading")


Executes editing command `paste` in page.


### 
`<webview>.pasteAndMatchStyle()`[​](#webviewpasteandmatchstyle "Direct link to heading")


Executes editing command `pasteAndMatchStyle` in page.


### 
`<webview>.delete()`[​](#webviewdelete "Direct link to heading")


Executes editing command `delete` in page.


### 
`<webview>.selectAll()`[​](#webviewselectall "Direct link to heading")


Executes editing command `selectAll` in page.


### 
`<webview>.unselect()`[​](#webviewunselect "Direct link to heading")


Executes editing command `unselect` in page.


### 
`<webview>.replace(text)`[​](#webviewreplacetext "Direct link to heading")


* `text` string


Executes editing command `replace` in page.


### 
`<webview>.replaceMisspelling(text)`[​](#webviewreplacemisspellingtext "Direct link to heading")


* `text` string


Executes editing command `replaceMisspelling` in page.


### 
`<webview>.insertText(text)`[​](#webviewinserttexttext "Direct link to heading")


* `text` string


Returns `Promise<void>`


Inserts `text` to the focused element.


### 
`<webview>.findInPage(text[, options])`[​](#webviewfindinpagetext-options "Direct link to heading")


* `text` string - Content to be searched, must not be empty.
* `options` Object (optional)
	+ `forward` boolean (optional) - Whether to search forward or backward, defaults to `true`.
	+ `findNext` boolean (optional) - Whether to begin a new text finding session with this request. Should be `true` for initial requests, and `false` for follow-up requests. Defaults to `false`.
	+ `matchCase` boolean (optional) - Whether search should be case-sensitive, defaults to `false`.


Returns `Integer` - The request id used for the request.


Starts a request to find all matches for the `text` in the web page. The result of the request can be obtained by subscribing to [`found-in-page`](webview-tag#event-found-in-page) event.


### 
`<webview>.stopFindInPage(action)`[​](#webviewstopfindinpageaction "Direct link to heading")


* `action` string - Specifies the action to take place when ending [`<webview>.findInPage`](#webviewfindinpagetext-options) request.
	+ `clearSelection` - Clear the selection.
	+ `keepSelection` - Translate the selection into a normal selection.
	+ `activateSelection` - Focus and click the selection node.


Stops any `findInPage` request for the `webview` with the provided `action`.


### 
`<webview>.print([options])`[​](#webviewprintoptions "Direct link to heading")


* `options` Object (optional)
	+ `silent` boolean (optional) - Don't ask user for print settings. Default is `false`.
	+ `printBackground` boolean (optional) - Prints the background color and image of the web page. Default is `false`.
	+ `deviceName` string (optional) - Set the printer device name to use. Must be the system-defined name and not the 'friendly' name, e.g 'Brother\_QL\_820NWB' and not 'Brother QL-820NWB'.
	+ `color` boolean (optional) - Set whether the printed web page will be in color or grayscale. Default is `true`.
	+ `margins` Object (optional)
		- `marginType` string (optional) - Can be `default`, `none`, `printableArea`, or `custom`. If `custom` is chosen, you will also need to specify `top`, `bottom`, `left`, and `right`.
		- `top` number (optional) - The top margin of the printed web page, in pixels.
		- `bottom` number (optional) - The bottom margin of the printed web page, in pixels.
		- `left` number (optional) - The left margin of the printed web page, in pixels.
		- `right` number (optional) - The right margin of the printed web page, in pixels.
	+ `landscape` boolean (optional) - Whether the web page should be printed in landscape mode. Default is `false`.
	+ `scaleFactor` number (optional) - The scale factor of the web page.
	+ `pagesPerSheet` number (optional) - The number of pages to print per page sheet.
	+ `collate` boolean (optional) - Whether the web page should be collated.
	+ `copies` number (optional) - The number of copies of the web page to print.
	+ `pageRanges` Object[] (optional) - The page range to print.
		- `from` number - Index of the first page to print (0-based).
		- `to` number - Index of the last page to print (inclusive) (0-based).
	+ `duplexMode` string (optional) - Set the duplex mode of the printed web page. Can be `simplex`, `shortEdge`, or `longEdge`.
	+ `dpi` Record<string, number> (optional)
		- `horizontal` number (optional) - The horizontal dpi.
		- `vertical` number (optional) - The vertical dpi.
	+ `header` string (optional) - string to be printed as page header.
	+ `footer` string (optional) - string to be printed as page footer.
	+ `pageSize` string | Size (optional) - Specify page size of the printed document. Can be `A3`, `A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` in microns.


Returns `Promise<void>`


Prints `webview`'s web page. Same as `webContents.print([options])`.


### 
`<webview>.printToPDF(options)`[​](#webviewprinttopdfoptions "Direct link to heading")


* `options` Object
	+ `headerFooter` Record<string, string> (optional) - the header and footer for the PDF.
		- `title` string - The title for the PDF header.
		- `url` string - the url for the PDF footer.
	+ `landscape` boolean (optional) - `true` for landscape, `false` for portrait.
	+ `marginsType` Integer (optional) - Specifies the type of margins to use. Uses 0 for default margin, 1 for no margin, and 2 for minimum margin. and `width` in microns.
	+ `scaleFactor` number (optional) - The scale factor of the web page. Can range from 0 to 100.
	+ `pageRanges` Record<string, number> (optional) - The page range to print. On macOS, only the first range is honored.
		- `from` number - Index of the first page to print (0-based).
		- `to` number - Index of the last page to print (inclusive) (0-based).
	+ `pageSize` string | Size (optional) - Specify page size of the generated PDF. Can be `A3`, `A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`
	+ `printBackground` boolean (optional) - Whether to print CSS backgrounds.
	+ `printSelectionOnly` boolean (optional) - Whether to print selection only.


Returns `Promise<Uint8Array>` - Resolves with the generated PDF data.


Prints `webview`'s web page as PDF, Same as `webContents.printToPDF(options)`.


### 
`<webview>.capturePage([rect])`[​](#webviewcapturepagerect "Direct link to heading")


* `rect` [Rectangle](structures/rectangle) (optional) - The area of the page to be captured.


Returns `Promise<NativeImage>` - Resolves with a [NativeImage](native-image)


Captures a snapshot of the page within `rect`. Omitting `rect` will capture the whole visible page.


### 
`<webview>.send(channel, ...args)`[​](#webviewsendchannel-args "Direct link to heading")


* `channel` string
* `...args` any[]


Returns `Promise<void>`


Send an asynchronous message to renderer process via `channel`, you can also send arbitrary arguments. The renderer process can handle the message by listening to the `channel` event with the [`ipcRenderer`](ipc-renderer) module.


See [webContents.send](web-contents#contentssendchannel-args) for examples.


### 
`<webview>.sendToFrame(frameId, channel, ...args)`[​](#webviewsendtoframeframeid-channel-args "Direct link to heading")


* `frameId` [number, number] - `[processId, frameId]`
* `channel` string
* `...args` any[]


Returns `Promise<void>`


Send an asynchronous message to renderer process via `channel`, you can also send arbitrary arguments. The renderer process can handle the message by listening to the `channel` event with the [`ipcRenderer`](ipc-renderer) module.


See [webContents.sendToFrame](web-contents#contentssendtoframeframeid-channel-args) for examples.


### 
`<webview>.sendInputEvent(event)`[​](#webviewsendinputeventevent "Direct link to heading")


* `event` [MouseInputEvent](structures/mouse-input-event) | [MouseWheelInputEvent](structures/mouse-wheel-input-event) | [KeyboardInputEvent](structures/keyboard-input-event)


Returns `Promise<void>`


Sends an input `event` to the page.


See [webContents.sendInputEvent](web-contents#contentssendinputeventinputevent) for detailed description of `event` object.


### 
`<webview>.setZoomFactor(factor)`[​](#webviewsetzoomfactorfactor "Direct link to heading")


* `factor` number - Zoom factor.


Changes the zoom factor to the specified factor. Zoom factor is zoom percent divided by 100, so 300% = 3.0.


### 
`<webview>.setZoomLevel(level)`[​](#webviewsetzoomlevellevel "Direct link to heading")


* `level` number - Zoom level.


Changes the zoom level to the specified level. The original size is 0 and each increment above or below represents zooming 20% larger or smaller to default limits of 300% and 50% of original size, respectively. The formula for this is `scale := 1.2 ^ level`.



> **NOTE**: The zoom policy at the Chromium level is same-origin, meaning that the zoom level for a specific domain propagates across all instances of windows with the same domain. Differentiating the window URLs will make zoom work per-window.
> 
> 


### 
`<webview>.getZoomFactor()`[​](#webviewgetzoomfactor "Direct link to heading")


Returns `number` - the current zoom factor.


### 
`<webview>.getZoomLevel()`[​](#webviewgetzoomlevel "Direct link to heading")


Returns `number` - the current zoom level.


### 
`<webview>.setVisualZoomLevelLimits(minimumLevel, maximumLevel)`[​](#webviewsetvisualzoomlevellimitsminimumlevel-maximumlevel "Direct link to heading")


* `minimumLevel` number
* `maximumLevel` number


Returns `Promise<void>`


Sets the maximum and minimum pinch-to-zoom level.


### 
`<webview>.showDefinitionForSelection()` *macOS*[​](#webviewshowdefinitionforselection-macos "Direct link to heading")


Shows pop-up dictionary that searches the selected word on the page.


### 
`<webview>.getWebContentsId()`[​](#webviewgetwebcontentsid "Direct link to heading")


Returns `number` - The WebContents ID of this `webview`.


DOM Events[​](#dom-events "Direct link to heading")
---------------------------------------------------


The following DOM events are available to the `webview` tag:


### Event: 'load-commit'[​](#event-load-commit "Direct link to heading")


Returns:


* `url` string
* `isMainFrame` boolean


Fired when a load has committed. This includes navigation within the current document as well as subframe document-level loads, but does not include asynchronous resource loads.


### Event: 'did-finish-load'[​](#event-did-finish-load "Direct link to heading")


Fired when the navigation is done, i.e. the spinner of the tab will stop spinning, and the `onload` event is dispatched.


### Event: 'did-fail-load'[​](#event-did-fail-load "Direct link to heading")


Returns:


* `errorCode` Integer
* `errorDescription` string
* `validatedURL` string
* `isMainFrame` boolean


This event is like `did-finish-load`, but fired when the load failed or was cancelled, e.g. `window.stop()` is invoked.


### Event: 'did-frame-finish-load'[​](#event-did-frame-finish-load "Direct link to heading")


Returns:


* `isMainFrame` boolean


Fired when a frame has done navigation.


### Event: 'did-start-loading'[​](#event-did-start-loading "Direct link to heading")


Corresponds to the points in time when the spinner of the tab starts spinning.


### Event: 'did-stop-loading'[​](#event-did-stop-loading "Direct link to heading")


Corresponds to the points in time when the spinner of the tab stops spinning.


### Event: 'did-attach'[​](#event-did-attach "Direct link to heading")


Fired when attached to the embedder web contents.


### Event: 'dom-ready'[​](#event-dom-ready "Direct link to heading")


Fired when document in the given frame is loaded.


### Event: 'page-title-updated'[​](#event-page-title-updated "Direct link to heading")


Returns:


* `title` string
* `explicitSet` boolean


Fired when page title is set during navigation. `explicitSet` is false when title is synthesized from file url.


### Event: 'page-favicon-updated'[​](#event-page-favicon-updated "Direct link to heading")


Returns:


* `favicons` string[] - Array of URLs.


Fired when page receives favicon urls.


### Event: 'enter-html-full-screen'[​](#event-enter-html-full-screen "Direct link to heading")


Fired when page enters fullscreen triggered by HTML API.


### Event: 'leave-html-full-screen'[​](#event-leave-html-full-screen "Direct link to heading")


Fired when page leaves fullscreen triggered by HTML API.


### Event: 'console-message'[​](#event-console-message "Direct link to heading")


Returns:


* `level` Integer - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
* `message` string - The actual console message
* `line` Integer - The line number of the source that triggered this console message
* `sourceId` string


Fired when the guest window logs a console message.


The following example code forwards all log messages to the embedder's console without regard for log level or other properties.




```
const webview = document.querySelector('webview')
webview.addEventListener('console-message', (e) => {
  console.log('Guest page logged a message:', e.message)
})
```


### Event: 'found-in-page'[​](#event-found-in-page "Direct link to heading")


Returns:


* `result` Object
	+ `requestId` Integer
	+ `activeMatchOrdinal` Integer - Position of the active match.
	+ `matches` Integer - Number of Matches.
	+ `selectionArea` Rectangle - Coordinates of first match region.
	+ `finalUpdate` boolean


Fired when a result is available for [`webview.findInPage`](#webviewfindinpagetext-options) request.




```
const webview = document.querySelector('webview')
webview.addEventListener('found-in-page', (e) => {
  webview.stopFindInPage('keepSelection')
})

const requestId = webview.findInPage('test')
console.log(requestId)
```


### Event: 'new-window'[​](#event-new-window "Direct link to heading")


Returns:


* `url` string
* `frameName` string
* `disposition` string - Can be `default`, `foreground-tab`, `background-tab`, `new-window`, `save-to-disk` and `other`.
* `options` BrowserWindowConstructorOptions - The options which should be used for creating the new [`BrowserWindow`](browser-window).


Fired when the guest page attempts to open a new browser window.


The following example code opens the new url in system's default browser.




```
const { shell } = require('electron')
const webview = document.querySelector('webview')

webview.addEventListener('new-window', async (e) => {
  const protocol = (new URL(e.url)).protocol
  if (protocol === 'http:' || protocol === 'https:') {
    await shell.openExternal(e.url)
  }
})
```


### Event: 'will-navigate'[​](#event-will-navigate "Direct link to heading")


Returns:


* `url` string


Emitted when a user or the page wants to start navigation. It can happen when the `window.location` object is changed or a user clicks a link in the page.


This event will not emit when the navigation is started programmatically with APIs like `<webview>.loadURL` and `<webview>.back`.


It is also not emitted during in-page navigation, such as clicking anchor links or updating the `window.location.hash`. Use `did-navigate-in-page` event for this purpose.


Calling `event.preventDefault()` does **NOT** have any effect.


### Event: 'did-start-navigation'[​](#event-did-start-navigation "Direct link to heading")


Returns:


* `url` string
* `isInPlace` boolean
* `isMainFrame` boolean
* `frameProcessId` Integer
* `frameRoutingId` Integer


Emitted when any frame (including main) starts navigating. `isInPlace` will be `true` for in-page navigations.


### Event: 'did-redirect-navigation'[​](#event-did-redirect-navigation "Direct link to heading")


Returns:


* `url` string
* `isInPlace` boolean
* `isMainFrame` boolean
* `frameProcessId` Integer
* `frameRoutingId` Integer


Emitted after a server side redirect occurs during navigation. For example a 302 redirect.


### Event: 'did-navigate'[​](#event-did-navigate "Direct link to heading")


Returns:


* `url` string


Emitted when a navigation is done.


This event is not emitted for in-page navigations, such as clicking anchor links or updating the `window.location.hash`. Use `did-navigate-in-page` event for this purpose.


### Event: 'did-frame-navigate'[​](#event-did-frame-navigate "Direct link to heading")


Returns:


* `url` string
* `httpResponseCode` Integer - -1 for non HTTP navigations
* `httpStatusText` string - empty for non HTTP navigations,
* `isMainFrame` boolean
* `frameProcessId` Integer
* `frameRoutingId` Integer


Emitted when any frame navigation is done.


This event is not emitted for in-page navigations, such as clicking anchor links or updating the `window.location.hash`. Use `did-navigate-in-page` event for this purpose.


### Event: 'did-navigate-in-page'[​](#event-did-navigate-in-page "Direct link to heading")


Returns:


* `isMainFrame` boolean
* `url` string


Emitted when an in-page navigation happened.


When in-page navigation happens, the page URL changes but does not cause navigation outside of the page. Examples of this occurring are when anchor links are clicked or when the DOM `hashchange` event is triggered.


### Event: 'close'[​](#event-close "Direct link to heading")


Fired when the guest page attempts to close itself.


The following example code navigates the `webview` to `about:blank` when the guest attempts to close itself.




```
const webview = document.querySelector('webview')
webview.addEventListener('close', () => {
  webview.src = 'about:blank'
})
```


### Event: 'ipc-message'[​](#event-ipc-message "Direct link to heading")


Returns:


* `frameId` [number, number] - pair of `[processId, frameId]`.
* `channel` string
* `args` any[]


Fired when the guest page has sent an asynchronous message to embedder page.


With `sendToHost` method and `ipc-message` event you can communicate between guest page and embedder page:




```
// In embedder page.
const webview = document.querySelector('webview')
webview.addEventListener('ipc-message', (event) => {
  console.log(event.channel)
  // Prints "pong"
})
webview.send('ping')
```




```
// In guest page.
const { ipcRenderer } = require('electron')
ipcRenderer.on('ping', () => {
  ipcRenderer.sendToHost('pong')
})
```


### Event: 'crashed'[​](#event-crashed "Direct link to heading")


Fired when the renderer process is crashed.


### Event: 'plugin-crashed'[​](#event-plugin-crashed "Direct link to heading")


Returns:


* `name` string
* `version` string


Fired when a plugin process is crashed.


### Event: 'destroyed'[​](#event-destroyed "Direct link to heading")


Fired when the WebContents is destroyed.


### Event: 'media-started-playing'[​](#event-media-started-playing "Direct link to heading")


Emitted when media starts playing.


### Event: 'media-paused'[​](#event-media-paused "Direct link to heading")


Emitted when media is paused or done playing.


### Event: 'did-change-theme-color'[​](#event-did-change-theme-color "Direct link to heading")


Returns:


* `themeColor` string


Emitted when a page's theme color changes. This is usually due to encountering a meta tag:




```
<meta name='theme-color' content='#ff0000'>
```


### Event: 'update-target-url'[​](#event-update-target-url "Direct link to heading")


Returns:


* `url` string


Emitted when mouse moves over a link or the keyboard moves the focus to a link.


### Event: 'devtools-opened'[​](#event-devtools-opened "Direct link to heading")


Emitted when DevTools is opened.


### Event: 'devtools-closed'[​](#event-devtools-closed "Direct link to heading")


Emitted when DevTools is closed.


### Event: 'devtools-focused'[​](#event-devtools-focused "Direct link to heading")


Emitted when DevTools is focused / opened.


### Event: 'context-menu'[​](#event-context-menu "Direct link to heading")


Returns:


* `params` Object
	+ `x` Integer - x coordinate.
	+ `y` Integer - y coordinate.
	+ `linkURL` string - URL of the link that encloses the node the context menu was invoked on.
	+ `linkText` string - Text associated with the link. May be an empty string if the contents of the link are an image.
	+ `pageURL` string - URL of the top level page that the context menu was invoked on.
	+ `frameURL` string - URL of the subframe that the context menu was invoked on.
	+ `srcURL` string - Source URL for the element that the context menu was invoked on. Elements with source URLs are images, audio and video.
	+ `mediaType` string - Type of the node the context menu was invoked on. Can be `none`, `image`, `audio`, `video`, `canvas`, `file` or `plugin`.
	+ `hasImageContents` boolean - Whether the context menu was invoked on an image which has non-empty contents.
	+ `isEditable` boolean - Whether the context is editable.
	+ `selectionText` string - Text of the selection that the context menu was invoked on.
	+ `titleText` string - Title text of the selection that the context menu was invoked on.
	+ `altText` string - Alt text of the selection that the context menu was invoked on.
	+ `suggestedFilename` string - Suggested filename to be used when saving file through 'Save Link As' option of context menu.
	+ `selectionRect` [Rectangle](structures/rectangle) - Rect representing the coordinates in the document space of the selection.
	+ `selectionStartOffset` number - Start position of the selection text.
	+ `referrerPolicy` [Referrer](structures/referrer) - The referrer policy of the frame on which the menu is invoked.
	+ `misspelledWord` string - The misspelled word under the cursor, if any.
	+ `dictionarySuggestions` string[] - An array of suggested words to show the user to replace the `misspelledWord`. Only available if there is a misspelled word and spellchecker is enabled.
	+ `frameCharset` string - The character encoding of the frame on which the menu was invoked.
	+ `inputFieldType` string - If the context menu was invoked on an input field, the type of that field. Possible values are `none`, `plainText`, `password`, `other`.
	+ `spellcheckEnabled` boolean - If the context is editable, whether or not spellchecking is enabled.
	+ `menuSourceType` string - Input source that invoked the context menu. Can be `none`, `mouse`, `keyboard`, `touch`, `touchMenu`, `longPress`, `longTap`, `touchHandle`, `stylus`, `adjustSelection`, or `adjustSelectionReset`.
	+ `mediaFlags` Object - The flags for the media element the context menu was invoked on.
		- `inError` boolean - Whether the media element has crashed.
		- `isPaused` boolean - Whether the media element is paused.
		- `isMuted` boolean - Whether the media element is muted.
		- `hasAudio` boolean - Whether the media element has audio.
		- `isLooping` boolean - Whether the media element is looping.
		- `isControlsVisible` boolean - Whether the media element's controls are visible.
		- `canToggleControls` boolean - Whether the media element's controls are toggleable.
		- `canPrint` boolean - Whether the media element can be printed.
		- `canSave` boolean - Whether or not the media element can be downloaded.
		- `canShowPictureInPicture` boolean - Whether the media element can show picture-in-picture.
		- `isShowingPictureInPicture` boolean - Whether the media element is currently showing picture-in-picture.
		- `canRotate` boolean - Whether the media element can be rotated.
		- `canLoop` boolean - Whether the media element can be looped.
	+ `editFlags` Object - These flags indicate whether the renderer believes it is able to perform the corresponding action.
		- `canUndo` boolean - Whether the renderer believes it can undo.
		- `canRedo` boolean - Whether the renderer believes it can redo.
		- `canCut` boolean - Whether the renderer believes it can cut.
		- `canCopy` boolean - Whether the renderer believes it can copy.
		- `canPaste` boolean - Whether the renderer believes it can paste.
		- `canDelete` boolean - Whether the renderer believes it can delete.
		- `canSelectAll` boolean - Whether the renderer believes it can select all.
		- `canEditRichly` boolean - Whether the renderer believes it can edit text richly.


Emitted when there is a new context menu that needs to be handled.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/webview-tag>

Size Object
===========


* `width` number
* `height` number



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/size>

CPUUsage Object
===============


* `percentCPUUsage` number - Percentage of CPU used since the last call to getCPUUsage. First call returns 0.
* `idleWakeupsPerSecond` number - The number of average idle CPU wakeups per second since the last call to getCPUUsage. First call returns 0. Will always return 0 on Windows.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/cpu-usage>

DevTools Extension
==================


Electron supports [Chrome DevTools extensions](https://developer.chrome.com/extensions/devtools), which can be used to extend the ability of Chrome's developer tools for debugging popular web frameworks.


Loading a DevTools extension with tooling[​](#loading-a-devtools-extension-with-tooling "Direct link to heading")
-----------------------------------------------------------------------------------------------------------------


The easiest way to load a DevTools extension is to use third-party tooling to automate the process for you. [electron-devtools-installer](https://github.com/MarshallOfSound/electron-devtools-installer) is a popular NPM package that does just that.


Manually loading a DevTools extension[​](#manually-loading-a-devtools-extension "Direct link to heading")
---------------------------------------------------------------------------------------------------------


If you don't want to use the tooling approach, you can also do all of the necessary operations by hand. To load an extension in Electron, you need to download it via Chrome, locate its filesystem path, and then load it into your [Session](../api/session) by calling the [`ses.loadExtension`] API.


Using the [React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi) as an example:


1. Install the extension in Google Chrome.
2. Navigate to `chrome://extensions`, and find its extension ID, which is a hash string like `fmkadmapgofadopljbjfkapdkoienihi`.
3. Find out the filesystem location used by Chrome for storing extensions:


	* on Windows it is `%LOCALAPPDATA%\Google\Chrome\User Data\Default\Extensions`;
	* on Linux it could be:
		+ `~/.config/google-chrome/Default/Extensions/`
		+ `~/.config/google-chrome-beta/Default/Extensions/`
		+ `~/.config/google-chrome-canary/Default/Extensions/`
		+ `~/.config/chromium/Default/Extensions/`
	* on macOS it is `~/Library/Application Support/Google/Chrome/Default/Extensions`.
4. Pass the location of the extension to the [`ses.loadExtension`](../api/session#sesloadextensionpath-options) API. For React Developer Tools `v4.9.0`, it looks something like:




```
 const { app, session } = require('electron')
 const path = require('path')
 const os = require('os')

 // on macOS
 const reactDevToolsPath = path.join(
   os.homedir(),
   '/Library/Application Support/Google/Chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.9.0_0'
 )

 app.whenReady().then(async () => {
   await session.defaultSession.loadExtension(reactDevToolsPath)
 })
```


**Notes:**


* `loadExtension` returns a Promise with an [Extension object](../api/structures/extension), which contains metadata about the extension that was loaded. This promise needs to resolve (e.g. with an `await` expression) before loading a page. Otherwise, the extension won't be guaranteed to load.
* `loadExtension` cannot be called before the `ready` event of the `app` module is emitted, nor can it be called on in-memory (non-persistent) sessions.
* `loadExtension` must be called on every boot of your app if you want the extension to be loaded.


### Removing a DevTools extension[​](#removing-a-devtools-extension "Direct link to heading")


You can pass the extension's ID to the [`ses.removeExtension`](../api/session#sesremoveextensionextensionid) API to remove it from your Session. Loaded extensions are not persisted between app launches.


DevTools extension support[​](#devtools-extension-support "Direct link to heading")
-----------------------------------------------------------------------------------


Electron only supports [a limited set of `chrome.*` APIs](../api/extensions), so extensions using unsupported `chrome.*` APIs under the hood may not work.


The following Devtools extensions have been tested to work in Electron:


* [Ember Inspector](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi)
* [React Developer Tools](https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi)
* [Backbone Debugger](https://chrome.google.com/webstore/detail/backbone-debugger/bhljhndlimiafopmmhjlgfpnnchjjbhd)
* [jQuery Debugger](https://chrome.google.com/webstore/detail/jquery-debugger/dbhhnnnpaeobfddmlalhnehgclcmjimi)
* [AngularJS Batarang](https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk)
* [Vue.js devtools](https://chrome.google.com/webstore/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd)
* [Cerebral Debugger](https://cerebraljs.com/docs/introduction/devtools.html)
* [Redux DevTools Extension](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd)
* [MobX Developer Tools](https://chrome.google.com/webstore/detail/mobx-developer-tools/pfgnfdagidkfgccljigdamigbcnndkod)


### What should I do if a DevTools extension is not working?[​](#what-should-i-do-if-a-devtools-extension-is-not-working "Direct link to heading")


First, please make sure the extension is still being maintained and is compatible with the latest version of Google Chrome. We cannot provide additional support for unsupported extensions.


If the extension works on Chrome but not on Electron, file a bug in Electron's [issue tracker](https://github.com/electron/electron/issues) and describe which part of the extension is not working as expected.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/devtools-extension>

Electron FAQ
============


Why am I having trouble installing Electron?[​](#why-am-i-having-trouble-installing-electron "Direct link to heading")
----------------------------------------------------------------------------------------------------------------------


When running `npm install electron`, some users occasionally encounter installation errors.


In almost all cases, these errors are the result of network problems and not actual issues with the `electron` npm package. Errors like `ELIFECYCLE`, `EAI_AGAIN`, `ECONNRESET`, and `ETIMEDOUT` are all indications of such network problems. The best resolution is to try switching networks, or wait a bit and try installing again.


You can also attempt to download Electron directly from [electron/electron/releases](https://github.com/electron/electron/releases) if installing via `npm` is failing.


When will Electron upgrade to latest Chrome?[​](#when-will-electron-upgrade-to-latest-chrome "Direct link to heading")
----------------------------------------------------------------------------------------------------------------------


The Chrome version of Electron is usually bumped within one or two weeks after a new stable Chrome version gets released. This estimate is not guaranteed and depends on the amount of work involved with upgrading.


Only the stable channel of Chrome is used. If an important fix is in beta or dev channel, we will back-port it.


For more information, please see the [security introduction](tutorial/security).


When will Electron upgrade to latest Node.js?[​](#when-will-electron-upgrade-to-latest-nodejs "Direct link to heading")
-----------------------------------------------------------------------------------------------------------------------


When a new version of Node.js gets released, we usually wait for about a month before upgrading the one in Electron. So we can avoid getting affected by bugs introduced in new Node.js versions, which happens very often.


New features of Node.js are usually brought by V8 upgrades, since Electron is using the V8 shipped by Chrome browser, the shiny new JavaScript feature of a new Node.js version is usually already in Electron.


How to share data between web pages?[​](#how-to-share-data-between-web-pages "Direct link to heading")
------------------------------------------------------------------------------------------------------


To share data between web pages (the renderer processes) the simplest way is to use HTML5 APIs which are already available in browsers. Good candidates are [Storage API](https://developer.mozilla.org/en-US/docs/Web/API/Storage), [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage), [`sessionStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage), and [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API).


Alternatively, you can use the IPC primitives that are provided by Electron. To share data between the main and renderer processes, you can use the [`ipcMain`](api/ipc-main) and [`ipcRenderer`](api/ipc-renderer) modules. To communicate directly between web pages, you can send a [`MessagePort`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort) from one to the other, possibly via the main process using [`ipcRenderer.postMessage()`](api/ipc-renderer#ipcrendererpostmessagechannel-message-transfer). Subsequent communication over message ports is direct and does not detour through the main process.


My app's tray disappeared after a few minutes.[​](#my-apps-tray-disappeared-after-a-few-minutes "Direct link to heading")
-------------------------------------------------------------------------------------------------------------------------


This happens when the variable which is used to store the tray gets garbage collected.


If you encounter this problem, the following articles may prove helpful:


* [Memory Management](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management)
* [Variable Scope](https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx)


If you want a quick fix, you can make the variables global by changing your code from this:




```
const { app, Tray } = require('electron')
app.whenReady().then(() => {
  const tray = new Tray('/path/to/icon.png')
  tray.setTitle('hello world')
})
```


to this:




```
const { app, Tray } = require('electron')
let tray = null
app.whenReady().then(() => {
  tray = new Tray('/path/to/icon.png')
  tray.setTitle('hello world')
})
```


I can not use jQuery/RequireJS/Meteor/AngularJS in Electron.[​](#i-can-not-use-jqueryrequirejsmeteorangularjs-in-electron "Direct link to heading")
---------------------------------------------------------------------------------------------------------------------------------------------------


Due to the Node.js integration of Electron, there are some extra symbols inserted into the DOM like `module`, `exports`, `require`. This causes problems for some libraries since they want to insert the symbols with the same names.


To solve this, you can turn off node integration in Electron:




```
// In the main process.
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
  webPreferences: {
    nodeIntegration: false
  }
})
win.show()
```


But if you want to keep the abilities of using Node.js and Electron APIs, you have to rename the symbols in the page before including other libraries:




```
<head>
<script>
window.nodeRequire = require;
delete window.require;
delete window.exports;
delete window.module;
</script>
<script type="text/javascript" src="jquery.js"></script>
</head>
```



`require('electron').xxx` is undefined.[​](#requireelectronxxx-is-undefined "Direct link to heading")
------------------------------------------------------------------------------------------------------


When using Electron's built-in module you might encounter an error like this:




```
> require('electron').webFrame.setZoomFactor(1.0)
Uncaught TypeError: Cannot read property 'setZoomLevel' of undefined
```


It is very likely you are using the module in the wrong process. For example `electron.app` can only be used in the main process, while `electron.webFrame` is only available in renderer processes.


The font looks blurry, what is this and what can I do?[​](#the-font-looks-blurry-what-is-this-and-what-can-i-do "Direct link to heading")
-----------------------------------------------------------------------------------------------------------------------------------------


If [sub-pixel anti-aliasing](https://alienryderflex.com/sub_pixel/) is deactivated, then fonts on LCD screens can look blurry. Example:


![subpixel rendering example](https://www.electronjs.org/docs/latest/images/subpixel-rendering-screenshot.gif)


Sub-pixel anti-aliasing needs a non-transparent background of the layer containing the font glyphs. (See [this issue](https://github.com/electron/electron/issues/6344#issuecomment-420371918) for more info).


To achieve this goal, set the background in the constructor for [BrowserWindow](api/browser-window):




```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
  backgroundColor: '#fff'
})
```


The effect is visible only on (some?) LCD screens. Even if you don't see a difference, some of your users may. It is best to always set the background this way, unless you have reasons not to do so.


Notice that just setting the background in the CSS does not have the desired effect.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/faq>

Build Instructions
==================


Follow the guidelines below for building **Electron itself**, for the purposes of creating custom Electron binaries. For bundling and distributing your app code with the prebuilt Electron binaries, see the [application distribution](../tutorial/application-distribution) guide.


Platform prerequisites[​](#platform-prerequisites "Direct link to heading")
---------------------------------------------------------------------------


Check the build prerequisites for your platform before proceeding


* [macOS](build-instructions-macos#prerequisites)
* [Linux](build-instructions-linux#prerequisites)
* [Windows](build-instructions-windows#prerequisites)


Build Tools[​](#build-tools "Direct link to heading")
-----------------------------------------------------


[Electron's Build Tools](https://github.com/electron/build-tools) automate much of the setup for compiling Electron from source with different configurations and build targets. If you wish to set up the environment manually, the instructions are listed below.


Electron uses [GN](https://gn.googlesource.com/gn) for project generation and [ninja](https://ninja-build.org/) for building. Project configurations can be found in the `.gn` and `.gni` files.


GN Files[​](#gn-files "Direct link to heading")
-----------------------------------------------


The following `gn` files contain the main rules for building Electron:


* `BUILD.gn` defines how Electron itself is built and includes the default configurations for linking with Chromium.
* `build/args/{testing,release,all}.gn` contain the default build arguments for building Electron.


GN prerequisites[​](#gn-prerequisites "Direct link to heading")
---------------------------------------------------------------


You'll need to install [`depot_tools`](https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html#_setting_up), the toolset used for fetching Chromium and its dependencies.


Also, on Windows, you'll need to set the environment variable `DEPOT_TOOLS_WIN_TOOLCHAIN=0`. To do so, open `Control Panel` → `System and
Security` → `System` → `Advanced system settings` and add a system variable `DEPOT_TOOLS_WIN_TOOLCHAIN` with value `0`. This tells `depot_tools` to use your locally installed version of Visual Studio (by default, `depot_tools` will try to download a Google-internal version that only Googlers have access to).


### Setting up the git cache[​](#setting-up-the-git-cache "Direct link to heading")


If you plan on checking out Electron more than once (for example, to have multiple parallel directories checked out to different branches), using the git cache will speed up subsequent calls to `gclient`. To do this, set a `GIT_CACHE_PATH` environment variable:




```
$ export GIT_CACHE_PATH="${HOME}/.git_cache"
$ mkdir -p "${GIT_CACHE_PATH}"
# This will use about 16G.
```


Getting the code[​](#getting-the-code "Direct link to heading")
---------------------------------------------------------------




```
$ mkdir electron && cd electron
$ gclient config --name "src/electron" --unmanaged https://github.com/electron/electron
$ gclient sync --with_branch_heads --with_tags
# This will take a while, go get a coffee.
```



> Instead of `https://github.com/electron/electron`, you can use your own fork here (something like `https://github.com/<username>/electron`).
> 
> 


### A note on pulling/pushing[​](#a-note-on-pullingpushing "Direct link to heading")


If you intend to `git pull` or `git push` from the official `electron` repository in the future, you now need to update the respective folder's origin URLs.




```
$ cd src/electron
$ git remote remove origin
$ git remote add origin https://github.com/electron/electron
$ git checkout main
$ git branch --set-upstream-to=origin/main
$ cd -
```


📝 `gclient` works by checking a file called `DEPS` inside the `src/electron` folder for dependencies (like Chromium or Node.js). Running `gclient sync -f` ensures that all dependencies required to build Electron match that file.


So, in order to pull, you'd run the following commands:




```
$ cd src/electron
$ git pull
$ gclient sync -f
```


Building[​](#building "Direct link to heading")
-----------------------------------------------


**Set the environment variable for chromium build tools**


On Linux & MacOS




```
$ cd src
$ export CHROMIUM_BUILDTOOLS_PATH=`pwd`/buildtools
```


On Windows:




```
$ cd src
$ set CHROMIUM_BUILDTOOLS_PATH=%cd%\buildtools
```


**To generate Testing build config of Electron:**




```
$ gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\")"
```


**To generate Release build config of Electron:**




```
$ gn gen out/Release --args="import(\"//electron/build/args/release.gn\")"
```


**Note:** This will generate a `out/Testing` or `out/Release` build directory under `src/` with the testing or release build depending upon the configuration passed above. You can replace `Testing|Release` with another names, but it should be a subdirectory of `out`.


Also you shouldn't have to run `gn gen` again—if you want to change the build arguments, you can run `gn args out/Testing` to bring up an editor. To see the list of available build configuration options, run `gn args out/Testing --list`.


**To build, run `ninja` with the `electron` target:** Note: This will also take a while and probably heat up your lap.


For the testing configuration:




```
$ ninja -C out/Testing electron
```


For the release configuration:




```
$ ninja -C out/Release electron
```


This will build all of what was previously 'libchromiumcontent' (i.e. the `content/` directory of `chromium` and its dependencies, incl. WebKit and V8), so it will take a while.


The built executable will be under `./out/Testing`:




```
$ ./out/Testing/Electron.app/Contents/MacOS/Electron
# or, on Windows
$ ./out/Testing/electron.exe
# or, on Linux
$ ./out/Testing/electron
```


### Packaging[​](#packaging "Direct link to heading")


On linux, first strip the debugging and symbol information:




```
$ electron/script/strip-binaries.py -d out/Release
```


To package the electron build as a distributable zip file:




```
$ ninja -C out/Release electron:electron_dist_zip
```


### Cross-compiling[​](#cross-compiling "Direct link to heading")


To compile for a platform that isn't the same as the one you're building on, set the `target_cpu` and `target_os` GN arguments. For example, to compile an x86 target from an x64 host, specify `target_cpu = "x86"` in `gn args`.




```
$ gn gen out/Testing-x86 --args='... target_cpu = "x86"'
```


Not all combinations of source and target CPU/OS are supported by Chromium.




| Host | Target | Status |
| --- | --- | --- |
| Windows x64 | Windows arm64 | Experimental |
| Windows x64 | Windows x86 | Automatically tested |
| Linux x64 | Linux x86 | Automatically tested |


If you test other combinations and find them to work, please update this document :)


See the GN reference for allowable values of [`target_os`](https://gn.googlesource.com/gn/+/main/docs/reference.md#built_in-predefined-variables-target_os_the-desired-operating-system-for-the-build-possible-values) and [`target_cpu`](https://gn.googlesource.com/gn/+/main/docs/reference.md#built_in-predefined-variables-target_cpu_the-desired-cpu-architecture-for-the-build-possible-values).


#### Windows on Arm (experimental)[​](#windows-on-arm-experimental "Direct link to heading")


To cross-compile for Windows on Arm, [follow Chromium's guide](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/windows_build_instructions.md#Visual-Studio) to get the necessary dependencies, SDK and libraries, then build with `ELECTRON_BUILDING_WOA=1` in your environment before running `gclient sync`.




```
set ELECTRON_BUILDING_WOA=1
gclient sync -f --with_branch_heads --with_tags
```


Or (if using PowerShell):




```
$env:ELECTRON_BUILDING_WOA=1
gclient sync -f --with_branch_heads --with_tags
```


Next, run `gn gen` as above with `target_cpu="arm64"`.


Tests[​](#tests "Direct link to heading")
-----------------------------------------


To run the tests, you'll first need to build the test modules against the same version of Node.js that was built as part of the build process. To generate build headers for the modules to compile against, run the following under `src/` directory.




```
$ ninja -C out/Testing third_party/electron_node:headers
```


You can now [run the tests](testing#unit-tests).


If you're debugging something, it can be helpful to pass some extra flags to the Electron binary:




```
$ npm run test -- \
  --enable-logging -g 'BrowserWindow module'
```


Sharing the git cache between multiple machines[​](#sharing-the-git-cache-between-multiple-machines "Direct link to heading")
-----------------------------------------------------------------------------------------------------------------------------


It is possible to share the gclient git cache with other machines by exporting it as SMB share on linux, but only one process/machine can be using the cache at a time. The locks created by git-cache script will try to prevent this, but it may not work perfectly in a network.


On Windows, SMBv2 has a directory cache that will cause problems with the git cache script, so it is necessary to disable it by setting the registry key




```
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Lanmanworkstation\Parameters\DirectoryCacheLifetime
```


to 0. More information: <https://stackoverflow.com/a/9935126>


This can be set quickly in powershell (ran as administrator):




```
New-ItemProperty -Path "HKLM:\System\CurrentControlSet\Services\Lanmanworkstation\Parameters" -Name DirectoryCacheLifetime -Value 0 -PropertyType DWORD -Force
```


Troubleshooting[​](#troubleshooting "Direct link to heading")
-------------------------------------------------------------


### gclient sync complains about rebase[​](#gclient-sync-complains-about-rebase "Direct link to heading")


If `gclient sync` is interrupted the git tree may be left in a bad state, leading to a cryptic message when running `gclient sync` in the future:




```
2> Conflict while rebasing this branch.
2> Fix the conflict and run gclient again.
2> See man git-rebase for details.
```


If there are no git conflicts or rebases in `src/electron`, you may need to abort a `git am` in `src`:




```
$ cd ../
$ git am --abort
$ cd electron
$ gclient sync -f
```


### I'm being asked for a username/password for chromium-internal.googlesource.com[​](#im-being-asked-for-a-usernamepassword-for-chromium-internalgooglesourcecom "Direct link to heading")


If you see a prompt for `Username for 'https://chrome-internal.googlesource.com':` when running `gclient sync` on Windows, it's probably because the `DEPOT_TOOLS_WIN_TOOLCHAIN` environment variable is not set to 0. Open `Control Panel` → `System and Security` → `System` → `Advanced system settings` and add a system variable `DEPOT_TOOLS_WIN_TOOLCHAIN` with value `0`. This tells `depot_tools` to use your locally installed version of Visual Studio (by default, `depot_tools` will try to download a Google-internal version that only Googlers have access to).



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/build-instructions-gn>

Supported Command Line Switches
===============================



> Command line switches supported by Electron.
> 
> 


You can use [app.commandLine.appendSwitch](command-line#commandlineappendswitchswitch-value) to append them in your app's main script before the [ready](app#event-ready) event of the <app> module is emitted:




```
const { app } = require('electron')
app.commandLine.appendSwitch('remote-debugging-port', '8315')
app.commandLine.appendSwitch('host-rules', 'MAP * 127.0.0.1')

app.whenReady().then(() => {
  // Your code here
})
```


Electron CLI Flags[​](#electron-cli-flags "Direct link to heading")
-------------------------------------------------------------------


### --auth-server-whitelist=`url`[​](#--auth-server-whitelisturl "Direct link to heading")


A comma-separated list of servers for which integrated authentication is enabled.


For example:




```
--auth-server-whitelist='*example.com, *foobar.com, *baz'
```


then any `url` ending with `example.com`, `foobar.com`, `baz` will be considered for integrated authentication. Without `*` prefix the URL has to match exactly.


### --auth-negotiate-delegate-whitelist=`url`[​](#--auth-negotiate-delegate-whitelisturl "Direct link to heading")


A comma-separated list of servers for which delegation of user credentials is required. Without `*` prefix the URL has to match exactly.


### --disable-ntlm-v2[​](#--disable-ntlm-v2 "Direct link to heading")


Disables NTLM v2 for posix platforms, no effect elsewhere.


### --disable-http-cache[​](#--disable-http-cache "Direct link to heading")


Disables the disk cache for HTTP requests.


### --disable-http2[​](#--disable-http2 "Direct link to heading")


Disable HTTP/2 and SPDY/3.1 protocols.


### --disable-renderer-backgrounding[​](#--disable-renderer-backgrounding "Direct link to heading")


Prevents Chromium from lowering the priority of invisible pages' renderer processes.


This flag is global to all renderer processes, if you only want to disable throttling in one window, you can take the hack of [playing silent audio](https://github.com/atom/atom/pull/9485/files).


### --disk-cache-size=`size`[​](#--disk-cache-sizesize "Direct link to heading")


Forces the maximum disk space to be used by the disk cache, in bytes.


### --enable-logging[=file][​](#--enable-loggingfile "Direct link to heading")


Prints Chromium's logging to stderr (or a log file).


The `ELECTRON_ENABLE_LOGGING` environment variable has the same effect as passing `--enable-logging`.


Passing `--enable-logging` will result in logs being printed on stderr. Passing `--enable-logging=file` will result in logs being saved to the file specified by `--log-file=...`, or to `electron_debug.log` in the user-data directory if `--log-file` is not specified.



> **Note:** On Windows, logs from child processes cannot be sent to stderr. Logging to a file is the most reliable way to collect logs on Windows.
> 
> 


See also `--log-file`, `--log-level`, `--v`, and `--vmodule`.


### --force-fieldtrials=`trials`[​](#--force-fieldtrialstrials "Direct link to heading")


Field trials to be forcefully enabled or disabled.


For example: `WebRTC-Audio-Red-For-Opus/Enabled/`


### --host-rules=`rules`[​](#--host-rulesrules "Direct link to heading")


A comma-separated list of `rules` that control how hostnames are mapped.


For example:


* `MAP * 127.0.0.1` Forces all hostnames to be mapped to 127.0.0.1
* `MAP *.google.com proxy` Forces all google.com subdomains to be resolved to "proxy".
* `MAP test.com [::1]:77` Forces "test.com" to resolve to IPv6 loopback. Will also force the port of the resulting socket address to be 77.
* `MAP * baz, EXCLUDE www.google.com` Remaps everything to "baz", except for "[www.google.com"](http://www.google.com%22).


These mappings apply to the endpoint host in a net request (the TCP connect and host resolver in a direct connection, and the `CONNECT` in an HTTP proxy connection, and the endpoint host in a `SOCKS` proxy connection).


### --host-resolver-rules=`rules`[​](#--host-resolver-rulesrules "Direct link to heading")


Like `--host-rules` but these `rules` only apply to the host resolver.


### --ignore-certificate-errors[​](#--ignore-certificate-errors "Direct link to heading")


Ignores certificate related errors.


### --ignore-connections-limit=`domains`[​](#--ignore-connections-limitdomains "Direct link to heading")


Ignore the connections limit for `domains` list separated by `,`.


### --js-flags=`flags`[​](#--js-flagsflags "Direct link to heading")


Specifies the flags passed to the Node.js engine. It has to be passed when starting Electron if you want to enable the `flags` in the main process.




```
$ electron --js-flags="--harmony_proxies --harmony_collections" your-app
```


See the [Node.js documentation](https://nodejs.org/api/cli.html) or run `node --help` in your terminal for a list of available flags. Additionally, run `node --v8-options` to see a list of flags that specifically refer to Node.js's V8 JavaScript engine.


### --lang[​](#--lang "Direct link to heading")


Set a custom locale.


### --log-file=`path`[​](#--log-filepath "Direct link to heading")


If `--enable-logging` is specified, logs will be written to the given path. The parent directory must exist.


Setting the `ELECTRON_LOG_FILE` environment variable is equivalent to passing this flag. If both are present, the command-line switch takes precedence.


### --log-net-log=`path`[​](#--log-net-logpath "Direct link to heading")


Enables net log events to be saved and writes them to `path`.


### --log-level=`N`[​](#--log-leveln "Direct link to heading")


Sets the verbosity of logging when used together with `--enable-logging`. `N` should be one of [Chrome's LogSeverities](https://source.chromium.org/chromium/chromium/src/+/main:base/logging.h?q=logging::LogSeverity&ss=chromium).


Note that two complimentary logging mechanisms in Chromium -- `LOG()` and `VLOG()` -- are controlled by different switches. `--log-level` controls `LOG()` messages, while `--v` and `--vmodule` control `VLOG()` messages. So you may want to use a combination of these three switches depending on the granularity you want and what logging calls are made by the code you're trying to watch.


See [Chromium Logging source](https://source.chromium.org/chromium/chromium/src/+/main:base/logging.h) for more information on how `LOG()` and `VLOG()` interact. Loosely speaking, `VLOG()` can be thought of as sub-levels / per-module levels inside `LOG(INFO)` to control the firehose of `LOG(INFO)` data.


See also `--enable-logging`, `--log-level`, `--v`, and `--vmodule`.


### --no-proxy-server[​](#--no-proxy-server "Direct link to heading")


Don't use a proxy server and always make direct connections. Overrides any other proxy server flags that are passed.


### --no-sandbox[​](#--no-sandbox "Direct link to heading")


Disables the Chromium [sandbox](https://www.chromium.org/developers/design-documents/sandbox). Forces renderer process and Chromium helper processes to run un-sandboxed. Should only be used for testing.


### --proxy-bypass-list=`hosts`[​](#--proxy-bypass-listhosts "Direct link to heading")


Instructs Electron to bypass the proxy server for the given semi-colon-separated list of hosts. This flag has an effect only if used in tandem with `--proxy-server`.


For example:




```
const { app } = require('electron')
app.commandLine.appendSwitch('proxy-bypass-list', '<local>;*.google.com;*foo.com;1.2.3.4:5678')
```


Will use the proxy server for all hosts except for local addresses (`localhost`, `127.0.0.1` etc.), `google.com` subdomains, hosts that contain the suffix `foo.com` and anything at `1.2.3.4:5678`.


### --proxy-pac-url=`url`[​](#--proxy-pac-urlurl "Direct link to heading")


Uses the PAC script at the specified `url`.


### --proxy-server=`address:port`[​](#--proxy-serveraddressport "Direct link to heading")


Use a specified proxy server, which overrides the system setting. This switch only affects requests with HTTP protocol, including HTTPS and WebSocket requests. It is also noteworthy that not all proxy servers support HTTPS and WebSocket requests. The proxy URL does not support username and password authentication [per Chromium issue](https://bugs.chromium.org/p/chromium/issues/detail?id=615947).


### --remote-debugging-port=`port`[​](#--remote-debugging-portport "Direct link to heading")


Enables remote debugging over HTTP on the specified `port`.


### --v=`log_level`[​](#--vlog_level "Direct link to heading")


Gives the default maximal active V-logging level; 0 is the default. Normally positive values are used for V-logging levels.


This switch only works when `--enable-logging` is also passed.


See also `--enable-logging`, `--log-level`, and `--vmodule`.


### --vmodule=`pattern`[​](#--vmodulepattern "Direct link to heading")


Gives the per-module maximal V-logging levels to override the value given by `--v`. E.g. `my_module=2,foo*=3` would change the logging level for all code in source files `my_module.*` and `foo*.*`.


Any pattern containing a forward or backward slash will be tested against the whole pathname and not only the module. E.g. `*/foo/bar/*=2` would change the logging level for all code in the source files under a `foo/bar` directory.


This switch only works when `--enable-logging` is also passed.


See also `--enable-logging`, `--log-level`, and `--v`.


### --force\_high\_performance\_gpu[​](#--force_high_performance_gpu "Direct link to heading")


Force using discrete GPU when there are multiple GPUs available.


### --force\_low\_power\_gpu[​](#--force_low_power_gpu "Direct link to heading")


Force using integrated GPU when there are multiple GPUs available.


Node.js Flags[​](#nodejs-flags "Direct link to heading")
--------------------------------------------------------


Electron supports some of the [CLI flags](https://nodejs.org/api/cli.html) supported by Node.js.


**Note:** Passing unsupported command line switches to Electron when it is not running in `ELECTRON_RUN_AS_NODE` will have no effect.


### --inspect-brk[=[host:]port][​](#--inspect-brkhostport "Direct link to heading")


Activate inspector on host:port and break at start of user script. Default host:port is 127.0.0.1:9229.


Aliased to `--debug-brk=[host:]port`.


### --inspect-port=[host:]port[​](#--inspect-porthostport "Direct link to heading")


Set the `host:port` to be used when the inspector is activated. Useful when activating the inspector by sending the SIGUSR1 signal. Default host is `127.0.0.1`.


Aliased to `--debug-port=[host:]port`.


### --inspect[=[host:]port][​](#--inspecthostport "Direct link to heading")


Activate inspector on `host:port`. Default is `127.0.0.1:9229`.


V8 inspector integration allows tools such as Chrome DevTools and IDEs to debug and profile Electron instances. The tools attach to Electron instances via a TCP port and communicate using the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/).


See the [Debugging the Main Process](../tutorial/debugging-main-process) guide for more details.


Aliased to `--debug[=[host:]port`.


### --inspect-publish-uid=stderr,http[​](#--inspect-publish-uidstderrhttp "Direct link to heading")


Specify ways of the inspector web socket url exposure.


By default inspector websocket url is available in stderr and under /json/list endpoint on http://host:port/json/list.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/command-line-switches>

Code Signing
============

Code signing is a security technology that you use to certify that an app was created by you. You should sign your application so it does not trigger any operating system security checks.


On macOS, the system can detect any change to the app, whether the change is introduced accidentally or by malicious code.


On Windows, the system assigns a trust level to your code signing certificate which if you don't have, or if your trust level is low, will cause security dialogs to appear when users start using your application. Trust level builds over time so it's better to start code signing as early as possible.


While it is possible to distribute unsigned apps, it is not recommended. Both Windows and macOS will, by default, prevent either the download or the execution of unsigned applications. Starting with macOS Catalina (version 10.15), users have to go through multiple manual steps to open unsigned applications.


![macOS Catalina Gatekeeper warning: The app cannot be opened because the developer cannot be verified]


As you can see, users get two options: Move the app straight to the trash or cancel running it. You don't want your users to see that dialog.


If you are building an Electron app that you intend to package and distribute, it should be code signed.


Signing & notarizing macOS builds[​](#signing--notarizing-macos-builds "Direct link to heading")
------------------------------------------------------------------------------------------------


Properly preparing macOS applications for release requires two steps. First, the app needs to be code signed. Then, the app needs to be uploaded to Apple for a process called **notarization**, where automated systems will further verify that your app isn't doing anything to endanger its users.


To start the process, ensure that you fulfill the requirements for signing and notarizing your app:


1. Enroll in the [Apple Developer Program](https://developer.apple.com/programs/) (requires an annual fee)
2. Download and install [Xcode](https://developer.apple.com/xcode) - this requires a computer running macOS
3. Generate, download, and install [signing certificates](https://github.com/electron/electron-osx-sign/wiki/1.-Getting-Started#certificates)


Electron's ecosystem favors configuration and freedom, so there are multiple ways to get your application signed and notarized.


### Using Electron Forge[​](#using-electron-forge "Direct link to heading")


If you're using Electron's favorite build tool, getting your application signed and notarized requires a few additions to your configuration. [Forge](https://electronforge.io) is a collection of the official Electron tools, using [`electron-packager`](https://github.com/electron/electron-packager), [`electron-osx-sign`](https://github.com/electron-userland/electron-osx-sign), and [`electron-notarize`](https://github.com/electron/electron-notarize) under the hood.


Let's take a look at an example `package.json` configuration with all required fields. Not all of them are required: the tools will be clever enough to automatically find a suitable `identity`, for instance, but we recommend that you are explicit.



package.json


```
{
  "name": "my-app",
  "version": "0.0.1",
  "config": {
    "forge": {
      "packagerConfig": {
        "osxSign": {
          "identity": "Developer ID Application: Felix Rieseberg (LT94ZKYDCJ)",
          "hardened-runtime": true,
          "entitlements": "entitlements.plist",
          "entitlements-inherit": "entitlements.plist",
          "signature-flags": "library"
        },
        "osxNotarize": {
          "appleId": "felix@felix.fun",
          "appleIdPassword": "my-apple-id-password"
        }
      }
    }
  }
}
```



The `entitlements.plist` file referenced here needs the following macOS-specific entitlements to assure the Apple security mechanisms that your app is doing these things without meaning any harm:



entitlements.plist


```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>com.apple.security.cs.allow-jit</key>
    <true/>
    <key>com.apple.security.cs.debugger</key>
    <true/>
  </dict>
</plist>
```



Note that up until Electron 12, the `com.apple.security.cs.allow-unsigned-executable-memory` entitlement was required as well. However, it should not be used anymore if it can be avoided.


To see all of this in action, check out Electron Fiddle's source code, [especially its `electron-forge` configuration file](https://github.com/electron/fiddle/blob/master/forge.config.js).


If you plan to access the microphone or camera within your app using Electron's APIs, you'll also need to add the following entitlements:



entitlements.plist


```
<key>com.apple.security.device.audio-input</key>
<true/>
<key>com.apple.security.device.camera</key>
<true/>
```



If these are not present in your app's entitlements when you invoke, for example:



main.js


```
const { systemPreferences } = require('electron')
const microphone = systemPreferences.askForMediaAccess('microphone')
```



Your app may crash. See the Resource Access section in [Hardened Runtime](https://developer.apple.com/documentation/security/hardened_runtime) for more information and entitlements you may need.


### Using Electron Builder[​](#using-electron-builder "Direct link to heading")


Electron Builder comes with a custom solution for signing your application. You can find [its documentation here](https://www.electron.build/code-signing).


### Using Electron Packager[​](#using-electron-packager "Direct link to heading")


If you're not using an integrated build pipeline like Forge or Builder, you are likely using [`electron-packager`](https://github.com/electron/electron-packager), which includes [`electron-osx-sign`](https://github.com/electron-userland/electron-osx-sign) and [`electron-notarize`](https://github.com/electron/electron-notarize).


If you're using Packager's API, you can pass [in configuration that both signs and notarizes your application](https://electron.github.io/electron-packager/main/interfaces/electronpackager.options.html).




```
const packager = require('electron-packager')

packager({
  dir: '/path/to/my/app',
  osxSign: {
    identity: 'Developer ID Application: Felix Rieseberg (LT94ZKYDCJ)',
    'hardened-runtime': true,
    entitlements: 'entitlements.plist',
    'entitlements-inherit': 'entitlements.plist',
    'signature-flags': 'library'
  },
  osxNotarize: {
    appleId: 'felix@felix.fun',
    appleIdPassword: 'my-apple-id-password'
  }
})
```


The `entitlements.plist` file referenced here needs the following macOS-specific entitlements to assure the Apple security mechanisms that your app is doing these things without meaning any harm:



entitlements.plist


```
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>com.apple.security.cs.allow-jit</key>
    <true/>
    <key>com.apple.security.cs.debugger</key>
    <true/>
  </dict>
</plist>
```



Up until Electron 12, the `com.apple.security.cs.allow-unsigned-executable-memory` entitlement was required as well. However, it should not be used anymore if it can be avoided.


### Signing Mac App Store applications[​](#signing-mac-app-store-applications "Direct link to heading")


See the [Mac App Store Guide](mac-app-store-submission-guide).


Signing Windows builds[​](#signing-windows-builds "Direct link to heading")
---------------------------------------------------------------------------


Before signing Windows builds, you must do the following:


1. Get a Windows Authenticode code signing certificate (requires an annual fee)
2. Install Visual Studio to get the signing utility (the free [Community Edition](https://visualstudio.microsoft.com/vs/community/) is enough)


You can get a code signing certificate from a lot of resellers. Prices vary, so it may be worth your time to shop around. Popular resellers include:


* [digicert](https://www.digicert.com/code-signing/microsoft-authenticode.htm)
* [Sectigo](https://sectigo.com/ssl-certificates-tls/code-signing)
* Amongst others, please shop around to find one that suits your needs! 😄




Keep your certificate password private
Your certificate password should be a **secret**. Do not share it publicly or commit it to your source code.



### Using Electron Forge[​](#using-electron-forge-1 "Direct link to heading")


Once you have a code signing certificate file (`.pfx`), you can sign [Squirrel.Windows](https://www.electronforge.io/config/makers/squirrel.windows) and [MSI](https://www.electronforge.io/config/makers/wix-msi) installers in Electron Forge with the `certificateFile` and `certificatePassword` fields in their respective configuration objects.


For example, if you keep your Forge config in your `package.json` file and are creating a Squirrel.Windows installer:



package.json


```
{
  "name": "my-app",
  "version": "0.0.1",
  //...
  "config": {
    "forge": {
      "packagerConfig": {},
      "makers": [
        {
          "name": "@electron-forge/maker-squirrel",
          "config": {
            "certificateFile": "./cert.pfx",
            "certificatePassword": "this-is-a-secret"
          }
        }
      ]
    }
  }
  //...
}
```



### Using electron-winstaller (Squirrel.Windows)[​](#using-electron-winstaller-squirrelwindows "Direct link to heading")


[`electron-winstaller`](https://github.com/electron/windows-installer) is a package that can generate Squirrel.Windows installers for your Electron app. This is the tool used under the hood by Electron Forge's [Squirrel.Windows Maker](https://www.electronforge.io/config/makers/squirrel.windows). If you're not using Electron Forge and want to use `electron-winstaller` directly, use the `certificateFile` and `certificatePassword` configuration options when creating your installer.




```
const electronInstaller = require('electron-winstaller')
// NB: Use this syntax within an async function, Node does not have support for
//     top-level await as of Node 12.
try {
  await electronInstaller.createWindowsInstaller({
    appDirectory: '/tmp/build/my-app-64',
    outputDirectory: '/tmp/build/installer64',
    authors: 'My App Inc.',
    exe: 'myapp.exe',
    certificateFile: './cert.pfx',
    certificatePassword: 'this-is-a-secret',
  })
  console.log('It worked!')
} catch (e) {
  console.log(`No dice: ${e.message}`)
}
```


For full configuration options, check out the [`electron-winstaller`](https://github.com/electron/windows-installer) repository!


### Using electron-wix-msi (WiX MSI)[​](#using-electron-wix-msi-wix-msi "Direct link to heading")


[`electron-wix-msi`](https://github.com/felixrieseberg/electron-wix-msi) is a package that can generate MSI installers for your Electron app. This is the tool used under the hood by Electron Forge's [MSI Maker](https://www.electronforge.io/config/makers/wix-msi).


If you're not using Electron Forge and want to use `electron-wix-msi` directly, use the `certificateFile` and `certificatePassword` configuration options or pass in parameters directly to [SignTool.exe](https://docs.microsoft.com/en-us/dotnet/framework/tools/signtool-exe) with the `signWithParams` option.




```
import { MSICreator } from 'electron-wix-msi'

// Step 1: Instantiate the MSICreator
const msiCreator = new MSICreator({
  appDirectory: '/path/to/built/app',
  description: 'My amazing Kitten simulator',
  exe: 'kittens',
  name: 'Kittens',
  manufacturer: 'Kitten Technologies',
  version: '1.1.2',
  outputDirectory: '/path/to/output/folder',
  certificateFile: './cert.pfx',
  certificatePassword: 'this-is-a-secret',
})

// Step 2: Create a .wxs template file
const supportBinaries = await msiCreator.create()

// 🆕 Step 2a: optionally sign support binaries if you
// sign you binaries as part of of your packaging script
supportBinaries.forEach(async (binary) => {
  // Binaries are the new stub executable and optionally
  // the Squirrel auto updater.
  await signFile(binary)
})

// Step 3: Compile the template to a .msi file
await msiCreator.compile()
```


For full configuration options, check out the [`electron-wix-msi`](https://github.com/felixrieseberg/electron-wix-msi) repository!


### Using Electron Builder[​](#using-electron-builder-1 "Direct link to heading")


Electron Builder comes with a custom solution for signing your application. You can find [its documentation here](https://www.electron.build/code-signing).


### Signing Windows Store applications[​](#signing-windows-store-applications "Direct link to heading")


See the [Windows Store Guide](windows-store-guide).



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/code-signing>

nativeImage
===========



> Create tray, dock, and application icons using PNG or JPG files.
> 
> 


Process: [Main](../glossary#main-process), [Renderer](../glossary#renderer-process)


In Electron, for the APIs that take images, you can pass either file paths or `NativeImage` instances. An empty image will be used when `null` is passed.


For example, when creating a tray or setting a window's icon, you can pass an image file path as a `string`:




```
const { BrowserWindow, Tray } = require('electron')

const appIcon = new Tray('/Users/somebody/images/icon.png')
const win = new BrowserWindow({ icon: '/Users/somebody/images/window.png' })
console.log(appIcon, win)
```


Or read the image from the clipboard, which returns a `NativeImage`:




```
const { clipboard, Tray } = require('electron')
const image = clipboard.readImage()
const appIcon = new Tray(image)
console.log(appIcon)
```


Supported Formats[​](#supported-formats "Direct link to heading")
-----------------------------------------------------------------


Currently `PNG` and `JPEG` image formats are supported. `PNG` is recommended because of its support for transparency and lossless compression.


On Windows, you can also load `ICO` icons from file paths. For best visual quality, it is recommended to include at least the following sizes in the:


* Small icon
	+ 16x16 (100% DPI scale)
	+ 20x20 (125% DPI scale)
	+ 24x24 (150% DPI scale)
	+ 32x32 (200% DPI scale)
* Large icon
	+ 32x32 (100% DPI scale)
	+ 40x40 (125% DPI scale)
	+ 48x48 (150% DPI scale)
	+ 64x64 (200% DPI scale)
	+ 256x256


Check the *Size requirements* section in [this article](https://msdn.microsoft.com/en-us/library/windows/desktop/dn742485(v=vs.85).aspx).


High Resolution Image[​](#high-resolution-image "Direct link to heading")
-------------------------------------------------------------------------


On platforms that have high-DPI support such as Apple Retina displays, you can append `@2x` after image's base filename to mark it as a high resolution image.


For example, if `icon.png` is a normal image that has standard resolution, then `icon@2x.png` will be treated as a high resolution image that has double DPI density.


If you want to support displays with different DPI densities at the same time, you can put images with different sizes in the same folder and use the filename without DPI suffixes. For example:




```
images/
├── icon.png
├── icon@2x.png
└── icon@3x.png
```




```
const { Tray } = require('electron')
const appIcon = new Tray('/Users/somebody/images/icon.png')
console.log(appIcon)
```


The following suffixes for DPI are also supported:


* `@1x`
* `@1.25x`
* `@1.33x`
* `@1.4x`
* `@1.5x`
* `@1.8x`
* `@2x`
* `@2.5x`
* `@3x`
* `@4x`
* `@5x`


Template Image[​](#template-image "Direct link to heading")
-----------------------------------------------------------


Template images consist of black and an alpha channel. Template images are not intended to be used as standalone images and are usually mixed with other content to create the desired final appearance.


The most common case is to use template images for a menu bar icon, so it can adapt to both light and dark menu bars.


**Note:** Template image is only supported on macOS.


To mark an image as a template image, its filename should end with the word `Template`. For example:


* `xxxTemplate.png`
* `xxxTemplate@2x.png`


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `nativeImage` module has the following methods, all of which return an instance of the `NativeImage` class:


### 
`nativeImage.createEmpty()`[​](#nativeimagecreateempty "Direct link to heading")


Returns `NativeImage`


Creates an empty `NativeImage` instance.


### 
`nativeImage.createThumbnailFromPath(path, maxSize)` *macOS* *Windows*[​](#nativeimagecreatethumbnailfrompathpath-maxsize-macos-windows "Direct link to heading")


* `path` string - path to a file that we intend to construct a thumbnail out of.
* `maxSize` [Size](structures/size) - the maximum width and height (positive numbers) the thumbnail returned can be. The Windows implementation will ignore `maxSize.height` and scale the height according to `maxSize.width`.


Returns `Promise<NativeImage>` - fulfilled with the file's thumbnail preview image, which is a [NativeImage](native-image).


### 
`nativeImage.createFromPath(path)`[​](#nativeimagecreatefrompathpath "Direct link to heading")


* `path` string


Returns `NativeImage`


Creates a new `NativeImage` instance from a file located at `path`. This method returns an empty image if the `path` does not exist, cannot be read, or is not a valid image.




```
const nativeImage = require('electron').nativeImage

const image = nativeImage.createFromPath('/Users/somebody/images/icon.png')
console.log(image)
```


### 
`nativeImage.createFromBitmap(buffer, options)`[​](#nativeimagecreatefrombitmapbuffer-options "Direct link to heading")


* `buffer` [Buffer](https://nodejs.org/api/buffer.html#buffer_class_buffer)
* `options` Object
	+ `width` Integer
	+ `height` Integer
	+ `scaleFactor` Double (optional) - Defaults to 1.0.


Returns `NativeImage`


Creates a new `NativeImage` instance from `buffer` that contains the raw bitmap pixel data returned by `toBitmap()`. The specific format is platform-dependent.


### 
`nativeImage.createFromBuffer(buffer[, options])`[​](#nativeimagecreatefrombufferbuffer-options "Direct link to heading")


* `buffer` [Buffer](https://nodejs.org/api/buffer.html#buffer_class_buffer)
* `options` Object (optional)
	+ `width` Integer (optional) - Required for bitmap buffers.
	+ `height` Integer (optional) - Required for bitmap buffers.
	+ `scaleFactor` Double (optional) - Defaults to 1.0.


Returns `NativeImage`


Creates a new `NativeImage` instance from `buffer`. Tries to decode as PNG or JPEG first.


### 
`nativeImage.createFromDataURL(dataURL)`[​](#nativeimagecreatefromdataurldataurl "Direct link to heading")


* `dataURL` string


Returns `NativeImage`


Creates a new `NativeImage` instance from `dataURL`.


### 
`nativeImage.createFromNamedImage(imageName[, hslShift])` *macOS*[​](#nativeimagecreatefromnamedimageimagename-hslshift-macos "Direct link to heading")


* `imageName` string
* `hslShift` number[] (optional)


Returns `NativeImage`


Creates a new `NativeImage` instance from the NSImage that maps to the given image name. See [`System Icons`](https://developer.apple.com/design/human-interface-guidelines/macos/icons-and-images/system-icons/) for a list of possible values.


The `hslShift` is applied to the image with the following rules:


* `hsl_shift[0]` (hue): The absolute hue value for the image - 0 and 1 map to 0 and 360 on the hue color wheel (red).
* `hsl_shift[1]` (saturation): A saturation shift for the image, with the following key values: 0 = remove all color. 0.5 = leave unchanged. 1 = fully saturate the image.
* `hsl_shift[2]` (lightness): A lightness shift for the image, with the following key values: 0 = remove all lightness (make all pixels black). 0.5 = leave unchanged. 1 = full lightness (make all pixels white).


This means that `[-1, 0, 1]` will make the image completely white and `[-1, 1, 0]` will make the image completely black.


In some cases, the `NSImageName` doesn't match its string representation; one example of this is `NSFolderImageName`, whose string representation would actually be `NSFolder`. Therefore, you'll need to determine the correct string representation for your image before passing it in. This can be done with the following:


`echo -e '#import <Cocoa/Cocoa.h>\nint main() { NSLog(@"%@", SYSTEM_IMAGE_NAME); }' | clang -otest -x objective-c -framework Cocoa - && ./test`


where `SYSTEM_IMAGE_NAME` should be replaced with any value from [this list](https://developer.apple.com/documentation/appkit/nsimagename?language=objc).


Class: NativeImage[​](#class-nativeimage "Direct link to heading")
------------------------------------------------------------------



> Natively wrap images such as tray, dock, and application icons.
> 
> 


Process: [Main](../glossary#main-process), [Renderer](../glossary#renderer-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


### Instance Methods[​](#instance-methods "Direct link to heading")


The following methods are available on instances of the `NativeImage` class:


#### 
`image.toPNG([options])`[​](#imagetopngoptions "Direct link to heading")


* `options` Object (optional)
	+ `scaleFactor` Double (optional) - Defaults to 1.0.


Returns `Buffer` - A [Buffer](https://nodejs.org/api/buffer.html#buffer_class_buffer) that contains the image's `PNG` encoded data.


#### 
`image.toJPEG(quality)`[​](#imagetojpegquality "Direct link to heading")


* `quality` Integer - Between 0 - 100.


Returns `Buffer` - A [Buffer](https://nodejs.org/api/buffer.html#buffer_class_buffer) that contains the image's `JPEG` encoded data.


#### 
`image.toBitmap([options])`[​](#imagetobitmapoptions "Direct link to heading")


* `options` Object (optional)
	+ `scaleFactor` Double (optional) - Defaults to 1.0.


Returns `Buffer` - A [Buffer](https://nodejs.org/api/buffer.html#buffer_class_buffer) that contains a copy of the image's raw bitmap pixel data.


#### 
`image.toDataURL([options])`[​](#imagetodataurloptions "Direct link to heading")


* `options` Object (optional)
	+ `scaleFactor` Double (optional) - Defaults to 1.0.


Returns `string` - The data URL of the image.


#### 
`image.getBitmap([options])`[​](#imagegetbitmapoptions "Direct link to heading")


* `options` Object (optional)
	+ `scaleFactor` Double (optional) - Defaults to 1.0.


Returns `Buffer` - A [Buffer](https://nodejs.org/api/buffer.html#buffer_class_buffer) that contains the image's raw bitmap pixel data.


The difference between `getBitmap()` and `toBitmap()` is that `getBitmap()` does not copy the bitmap data, so you have to use the returned Buffer immediately in current event loop tick; otherwise the data might be changed or destroyed.


#### 
`image.getNativeHandle()` *macOS*[​](#imagegetnativehandle-macos "Direct link to heading")


Returns `Buffer` - A [Buffer](https://nodejs.org/api/buffer.html#buffer_class_buffer) that stores C pointer to underlying native handle of the image. On macOS, a pointer to `NSImage` instance would be returned.


Notice that the returned pointer is a weak pointer to the underlying native image instead of a copy, so you *must* ensure that the associated `nativeImage` instance is kept around.


#### 
`image.isEmpty()`[​](#imageisempty "Direct link to heading")


Returns `boolean` - Whether the image is empty.


#### 
`image.getSize([scaleFactor])`[​](#imagegetsizescalefactor "Direct link to heading")


* `scaleFactor` Double (optional) - Defaults to 1.0.


Returns [Size](structures/size).


If `scaleFactor` is passed, this will return the size corresponding to the image representation most closely matching the passed value.


#### 
`image.setTemplateImage(option)`[​](#imagesettemplateimageoption "Direct link to heading")


* `option` boolean


Marks the image as a template image.


#### 
`image.isTemplateImage()`[​](#imageistemplateimage "Direct link to heading")


Returns `boolean` - Whether the image is a template image.


#### 
`image.crop(rect)`[​](#imagecroprect "Direct link to heading")


* `rect` [Rectangle](structures/rectangle) - The area of the image to crop.


Returns `NativeImage` - The cropped image.


#### 
`image.resize(options)`[​](#imageresizeoptions "Direct link to heading")


* `options` Object
	+ `width` Integer (optional) - Defaults to the image's width.
	+ `height` Integer (optional) - Defaults to the image's height.
	+ `quality` string (optional) - The desired quality of the resize image. Possible values are `good`, `better`, or `best`. The default is `best`. These values express a desired quality/speed tradeoff. They are translated into an algorithm-specific method that depends on the capabilities (CPU, GPU) of the underlying platform. It is possible for all three methods to be mapped to the same algorithm on a given platform.


Returns `NativeImage` - The resized image.


If only the `height` or the `width` are specified then the current aspect ratio will be preserved in the resized image.


#### 
`image.getAspectRatio([scaleFactor])`[​](#imagegetaspectratioscalefactor "Direct link to heading")


* `scaleFactor` Double (optional) - Defaults to 1.0.


Returns `Float` - The image's aspect ratio.


If `scaleFactor` is passed, this will return the aspect ratio corresponding to the image representation most closely matching the passed value.


#### 
`image.getScaleFactors()`[​](#imagegetscalefactors "Direct link to heading")


Returns `Float[]` - An array of all scale factors corresponding to representations for a given nativeImage.


#### 
`image.addRepresentation(options)`[​](#imageaddrepresentationoptions "Direct link to heading")


* `options` Object
	+ `scaleFactor` Double - The scale factor to add the image representation for.
	+ `width` Integer (optional) - Defaults to 0. Required if a bitmap buffer is specified as `buffer`.
	+ `height` Integer (optional) - Defaults to 0. Required if a bitmap buffer is specified as `buffer`.
	+ `buffer` Buffer (optional) - The buffer containing the raw image data.
	+ `dataURL` string (optional) - The data URL containing either a base 64 encoded PNG or JPEG image.


Add an image representation for a specific scale factor. This can be used to explicitly add different scale factor representations to an image. This can be called on empty images.


### Instance Properties[​](#instance-properties "Direct link to heading")


#### 
`nativeImage.isMacTemplateImage` *macOS*[​](#nativeimageismactemplateimage-macos "Direct link to heading")


A `boolean` property that determines whether the image is considered a [template image](https://developer.apple.com/documentation/appkit/nsimage/1520017-template).


Please note that this property only has an effect on macOS.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/native-image>

Web Embeds
==========


Overview[​](#overview "Direct link to heading")
-----------------------------------------------


If you want to embed (third-party) web content in an Electron `BrowserWindow`, there are three options available to you: `<iframe>` tags, `<webview>` tags, and `BrowserViews`. Each one offers slightly different functionality and is useful in different situations. To help you choose between these, this guide explains the differences and capabilities of each option.


### Iframes[​](#iframes "Direct link to heading")


Iframes in Electron behave like iframes in regular browsers. An `<iframe>` element in your page can show external web pages, provided that their [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) allows it. To limit the number of capabilities of a site in an `<iframe>` tag, it is recommended to use the [`sandbox` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#attr-sandbox) and only allow the capabilities you want to support.


### WebViews[​](#webviews "Direct link to heading")



> Important Note: [we do not recommend you to use WebViews](../api/webview-tag#warning), as this tag undergoes dramatic architectural changes that may affect stability of your application. Consider switching to alternatives, like `iframe` and Electron's `BrowserView`, or an architecture that avoids embedded content by design.
> 
> 


[WebViews](../api/webview-tag) are based on Chromium's WebViews and are not explicitly supported by Electron. We do not guarantee that the WebView API will remain available in future versions of Electron. To use `<webview>` tags, you will need to set `webviewTag` to `true` in the `webPreferences` of your `BrowserWindow`.


WebView is a custom element (`<webview>`) that will only work inside Electron. They are implemented as an "out-of-process iframe". This means that all communication with the `<webview>` is done asynchronously using IPC. The `<webview>` element has many custom methods and events, similar to `webContents`, that provide you with greater control over the content.


Compared to an `<iframe>`, `<webview>` tends to be slightly slower but offers much greater control in loading and communicating with the third-party content and handling various events.


### BrowserViews[​](#browserviews "Direct link to heading")


[BrowserViews](../api/browser-view) are not a part of the DOM - instead, they are created in and controlled by your Main process. They are simply another layer of web content on top of your existing window. This means that they are completely separate from your own `BrowserWindow` content and their position is not controlled by the DOM or CSS. Instead, it is controlled by setting the bounds in the Main process.


`BrowserViews` offer the greatest control over their contents, since they implement the `webContents` similarly to how the `BrowserWindow` does it. However, as `BrowserViews` are not a part of your DOM, but are rather overlaid on top of them, you will have to manage their position manually.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/web-embeds>

ipcRenderer
===========



> Communicate asynchronously from a renderer process to the main process.
> 
> 


Process: [Renderer](../glossary#renderer-process)


The `ipcRenderer` module is an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter). It provides a few methods so you can send synchronous and asynchronous messages from the render process (web page) to the main process. You can also receive replies from the main process.


See [IPC tutorial](../tutorial/ipc) for code examples.


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `ipcRenderer` module has the following method to listen for events and send messages:


### 
`ipcRenderer.on(channel, listener)`[​](#ipcrendereronchannel-listener "Direct link to heading")


* `channel` string
* `listener` Function
	+ `event` IpcRendererEvent
	+ `...args` any[]


Listens to `channel`, when a new message arrives `listener` would be called with `listener(event, args...)`.


### 
`ipcRenderer.once(channel, listener)`[​](#ipcrendereroncechannel-listener "Direct link to heading")


* `channel` string
* `listener` Function
	+ `event` IpcRendererEvent
	+ `...args` any[]


Adds a one time `listener` function for the event. This `listener` is invoked only the next time a message is sent to `channel`, after which it is removed.


### 
`ipcRenderer.removeListener(channel, listener)`[​](#ipcrendererremovelistenerchannel-listener "Direct link to heading")


* `channel` string
* `listener` Function
	+ `...args` any[]


Removes the specified `listener` from the listener array for the specified `channel`.


### 
`ipcRenderer.removeAllListeners(channel)`[​](#ipcrendererremovealllistenerschannel "Direct link to heading")


* `channel` string


Removes all listeners, or those of the specified `channel`.


### 
`ipcRenderer.send(channel, ...args)`[​](#ipcrenderersendchannel-args "Direct link to heading")


* `channel` string
* `...args` any[]


Send an asynchronous message to the main process via `channel`, along with arguments. Arguments will be serialized with the [Structured Clone Algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm), just like [`window.postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage), so prototype chains will not be included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will throw an exception.



> 
> **NOTE:** Sending non-standard JavaScript types such as DOM objects or special Electron objects will throw an exception.
> 
> 
> Since the main process does not have support for DOM objects such as `ImageBitmap`, `File`, `DOMMatrix` and so on, such objects cannot be sent over Electron's IPC to the main process, as the main process would have no way to decode them. Attempting to send such objects over IPC will result in an error.
> 
> 
> 


The main process handles it by listening for `channel` with the [`ipcMain`](ipc-main) module.


If you need to transfer a [`MessagePort`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort) to the main process, use [`ipcRenderer.postMessage`](#ipcrendererpostmessagechannel-message-transfer).


If you want to receive a single response from the main process, like the result of a method call, consider using [`ipcRenderer.invoke`](#ipcrendererinvokechannel-args).


### 
`ipcRenderer.invoke(channel, ...args)`[​](#ipcrendererinvokechannel-args "Direct link to heading")


* `channel` string
* `...args` any[]


Returns `Promise<any>` - Resolves with the response from the main process.


Send a message to the main process via `channel` and expect a result asynchronously. Arguments will be serialized with the [Structured Clone Algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm), just like [`window.postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage), so prototype chains will not be included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will throw an exception.



> 
> **NOTE:** Sending non-standard JavaScript types such as DOM objects or special Electron objects will throw an exception.
> 
> 
> Since the main process does not have support for DOM objects such as `ImageBitmap`, `File`, `DOMMatrix` and so on, such objects cannot be sent over Electron's IPC to the main process, as the main process would have no way to decode them. Attempting to send such objects over IPC will result in an error.
> 
> 
> 


The main process should listen for `channel` with [`ipcMain.handle()`](ipc-main#ipcmainhandlechannel-listener).


For example:




```
// Renderer process
ipcRenderer.invoke('some-name', someArgument).then((result) => {
  // ...
})

// Main process
ipcMain.handle('some-name', async (event, someArgument) => {
  const result = await doSomeWork(someArgument)
  return result
})
```


If you need to transfer a [`MessagePort`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort) to the main process, use [`ipcRenderer.postMessage`](#ipcrendererpostmessagechannel-message-transfer).


If you do not need a response to the message, consider using [`ipcRenderer.send`](#ipcrenderersendchannel-args).


### 
`ipcRenderer.sendSync(channel, ...args)`[​](#ipcrenderersendsyncchannel-args "Direct link to heading")


* `channel` string
* `...args` any[]


Returns `any` - The value sent back by the [`ipcMain`](ipc-main) handler.


Send a message to the main process via `channel` and expect a result synchronously. Arguments will be serialized with the [Structured Clone Algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm), just like [`window.postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage), so prototype chains will not be included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will throw an exception.



> 
> **NOTE:** Sending non-standard JavaScript types such as DOM objects or special Electron objects will throw an exception.
> 
> 
> Since the main process does not have support for DOM objects such as `ImageBitmap`, `File`, `DOMMatrix` and so on, such objects cannot be sent over Electron's IPC to the main process, as the main process would have no way to decode them. Attempting to send such objects over IPC will result in an error.
> 
> 
> 


The main process handles it by listening for `channel` with [`ipcMain`](ipc-main) module, and replies by setting `event.returnValue`.



> ⚠️ **WARNING**: Sending a synchronous message will block the whole renderer process until the reply is received, so use this method only as a last resort. It's much better to use the asynchronous version, [`invoke()`](ipc-renderer#ipcrendererinvokechannel-args).
> 
> 


### 
`ipcRenderer.postMessage(channel, message, [transfer])`[​](#ipcrendererpostmessagechannel-message-transfer "Direct link to heading")


* `channel` string
* `message` any
* `transfer` MessagePort[] (optional)


Send a message to the main process, optionally transferring ownership of zero or more [`MessagePort`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort) objects.


The transferred `MessagePort` objects will be available in the main process as [`MessagePortMain`](message-port-main) objects by accessing the `ports` property of the emitted event.


For example:




```
// Renderer process
const { port1, port2 } = new MessageChannel()
ipcRenderer.postMessage('port', { message: 'hello' }, [port1])

// Main process
ipcMain.on('port', (e, msg) => {
  const [port] = e.ports
  // ...
})
```


For more information on using `MessagePort` and `MessageChannel`, see the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel).


### 
`ipcRenderer.sendTo(webContentsId, channel, ...args)`[​](#ipcrenderersendtowebcontentsid-channel-args "Direct link to heading")


* `webContentsId` number
* `channel` string
* `...args` any[]


Sends a message to a window with `webContentsId` via `channel`.


### 
`ipcRenderer.sendToHost(channel, ...args)`[​](#ipcrenderersendtohostchannel-args "Direct link to heading")


* `channel` string
* `...args` any[]


Like `ipcRenderer.send` but the event will be sent to the `<webview>` element in the host page instead of the main process.


Event object[​](#event-object "Direct link to heading")
-------------------------------------------------------


The documentation for the `event` object passed to the `callback` can be found in the [ipc-renderer-event](structures/ipc-renderer-event) structure docs.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/ipc-renderer>

FilePathWithHeaders Object
==========================


* `path` string - The path to the file to send.
* `headers` Record<string, string> (optional) - Additional headers to be sent.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/file-path-with-headers>

HIDDevice Object
================


* `deviceId` string - Unique identifier for the device.
* `name` string - Name of the device.
* `vendorId` Integer - The USB vendor ID.
* `productId` Integer - The USB product ID.
* `serialNumber` string (optional) - The USB device serial number.
* `guid` string (optional) - Unique identifier for the HID interface. A device may have multiple HID interfaces.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/hid-device>

Point Object
============


* `x` number
* `y` number


**Note:** Both `x` and `y` must be whole integers, when providing a point object as input to an Electron API we will automatically round your `x` and `y` values to the nearest whole integer.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/point>

Rectangle Object
================


* `x` number - The x coordinate of the origin of the rectangle (must be an integer).
* `y` number - The y coordinate of the origin of the rectangle (must be an integer).
* `width` number - The width of the rectangle (must be an integer).
* `height` number - The height of the rectangle (must be an integer).



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/rectangle>

ProcessMemoryInfo Object
========================


* `residentSet` Integer *Linux* *Windows* - The amount of memory currently pinned to actual physical RAM in Kilobytes.
* `private` Integer - The amount of memory not shared by other processes, such as JS heap or HTML content in Kilobytes.
* `shared` Integer - The amount of memory shared between processes, typically memory consumed by the Electron code itself in Kilobytes.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/process-memory-info>

Product Object
==============


* `productIdentifier` string - The string that identifies the product to the Apple App Store.
* `localizedDescription` string - A description of the product.
* `localizedTitle` string - The name of the product.
* `contentVersion` string - A string that identifies the version of the content.
* `contentLengths` number[] - The total size of the content, in bytes.
* `price` number - The cost of the product in the local currency.
* `formattedPrice` string - The locale formatted price of the product.
* `currencyCode` string - 3 character code presenting a product's currency based on the ISO 4217 standard.
* `introductoryPrice` [ProductDiscount](product-discount) (optional) - The object containing introductory price information for the product. available for the product.
* `discounts` [ProductDiscount](product-discount)[] - An array of discount offers
* `subscriptionGroupIdentifier` string - The identifier of the subscription group to which the subscription belongs.
* `subscriptionPeriod` [ProductSubscriptionPeriod](product-subscription-period) (optional) - The period details for products that are subscriptions.
* `isDownloadable` boolean - A boolean value that indicates whether the App Store has downloadable content for this product. `true` if at least one file has been associated with the product.
* `downloadContentVersion` string - A string that identifies the version of the content.
* `downloadContentLengths` number[] - The total size of the content, in bytes.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/product>

Multithreading
==============


With [Web Workers](https://developer.mozilla.org/en/docs/Web/API/Web_Workers_API/Using_web_workers), it is possible to run JavaScript in OS-level threads.


Multi-threaded Node.js[​](#multi-threaded-nodejs "Direct link to heading")
--------------------------------------------------------------------------


It is possible to use Node.js features in Electron's Web Workers, to do so the `nodeIntegrationInWorker` option should be set to `true` in `webPreferences`.




```
const win = new BrowserWindow({
  webPreferences: {
    nodeIntegrationInWorker: true
  }
})
```


The `nodeIntegrationInWorker` can be used independent of `nodeIntegration`, but `sandbox` must not be set to `true`.


Available APIs[​](#available-apis "Direct link to heading")
-----------------------------------------------------------


All built-in modules of Node.js are supported in Web Workers, and `asar` archives can still be read with Node.js APIs. However none of Electron's built-in modules can be used in a multi-threaded environment.


Native Node.js modules[​](#native-nodejs-modules "Direct link to heading")
--------------------------------------------------------------------------


Any native Node.js module can be loaded directly in Web Workers, but it is strongly recommended not to do so. Most existing native modules have been written assuming single-threaded environment, using them in Web Workers will lead to crashes and memory corruptions.


Note that even if a native Node.js module is thread-safe it's still not safe to load it in a Web Worker because the `process.dlopen` function is not thread safe.


The only way to load a native module safely for now, is to make sure the app loads no native modules after the Web Workers get started.




```
process.dlopen = () => {
  throw new Error('Load native module is not safe')
}
const worker = new Worker('script.js')
```



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/multithreading>

session
=======



> Manage browser sessions, cookies, cache, proxy settings, etc.
> 
> 


Process: [Main](../glossary#main-process)


The `session` module can be used to create new `Session` objects.


You can also access the `session` of existing pages by using the `session` property of [`WebContents`](web-contents), or from the `session` module.




```
const { BrowserWindow } = require('electron')

const win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('http://github.com')

const ses = win.webContents.session
console.log(ses.getUserAgent())
```


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `session` module has the following methods:


### 
`session.fromPartition(partition[, options])`[​](#sessionfrompartitionpartition-options "Direct link to heading")


* `partition` string
* `options` Object (optional)
	+ `cache` boolean - Whether to enable cache.


Returns `Session` - A session instance from `partition` string. When there is an existing `Session` with the same `partition`, it will be returned; otherwise a new `Session` instance will be created with `options`.


If `partition` starts with `persist:`, the page will use a persistent session available to all pages in the app with the same `partition`. if there is no `persist:` prefix, the page will use an in-memory session. If the `partition` is empty then default session of the app will be returned.


To create a `Session` with `options`, you have to ensure the `Session` with the `partition` has never been used before. There is no way to change the `options` of an existing `Session` object.


Properties[​](#properties "Direct link to heading")
---------------------------------------------------


The `session` module has the following properties:


### 
`session.defaultSession`[​](#sessiondefaultsession "Direct link to heading")


A `Session` object, the default session object of the app.


Class: Session[​](#class-session "Direct link to heading")
----------------------------------------------------------



> Get and set properties of a session.
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


You can create a `Session` object in the `session` module:




```
const { session } = require('electron')
const ses = session.fromPartition('persist:name')
console.log(ses.getUserAgent())
```


### Instance Events[​](#instance-events "Direct link to heading")


The following events are available on instances of `Session`:


#### Event: 'will-download'[​](#event-will-download "Direct link to heading")


Returns:


* `event` Event
* `item` [DownloadItem](download-item)
* `webContents` [WebContents](web-contents)


Emitted when Electron is about to download `item` in `webContents`.


Calling `event.preventDefault()` will cancel the download and `item` will not be available from next tick of the process.




```
const { session } = require('electron')
session.defaultSession.on('will-download', (event, item, webContents) => {
  event.preventDefault()
  require('got')(item.getURL()).then((response) => {
    require('fs').writeFileSync('/somewhere', response.body)
  })
})
```


#### Event: 'extension-loaded'[​](#event-extension-loaded "Direct link to heading")


Returns:


* `event` Event
* `extension` [Extension](structures/extension)


Emitted after an extension is loaded. This occurs whenever an extension is added to the "enabled" set of extensions. This includes:


* Extensions being loaded from `Session.loadExtension`.
* Extensions being reloaded:
	+ from a crash.
	+ if the extension requested it ([`chrome.runtime.reload()`](https://developer.chrome.com/extensions/runtime#method-reload)).


#### Event: 'extension-unloaded'[​](#event-extension-unloaded "Direct link to heading")


Returns:


* `event` Event
* `extension` [Extension](structures/extension)


Emitted after an extension is unloaded. This occurs when `Session.removeExtension` is called.


#### Event: 'extension-ready'[​](#event-extension-ready "Direct link to heading")


Returns:


* `event` Event
* `extension` [Extension](structures/extension)


Emitted after an extension is loaded and all necessary browser state is initialized to support the start of the extension's background page.


#### Event: 'preconnect'[​](#event-preconnect "Direct link to heading")


Returns:


* `event` Event
* `preconnectUrl` string - The URL being requested for preconnection by the renderer.
* `allowCredentials` boolean - True if the renderer is requesting that the connection include credentials (see the [spec](https://w3c.github.io/resource-hints/#preconnect) for more details.)


Emitted when a render process requests preconnection to a URL, generally due to a [resource hint](https://w3c.github.io/resource-hints/).


#### Event: 'spellcheck-dictionary-initialized'[​](#event-spellcheck-dictionary-initialized "Direct link to heading")


Returns:


* `event` Event
* `languageCode` string - The language code of the dictionary file


Emitted when a hunspell dictionary file has been successfully initialized. This occurs after the file has been downloaded.


#### Event: 'spellcheck-dictionary-download-begin'[​](#event-spellcheck-dictionary-download-begin "Direct link to heading")


Returns:


* `event` Event
* `languageCode` string - The language code of the dictionary file


Emitted when a hunspell dictionary file starts downloading


#### Event: 'spellcheck-dictionary-download-success'[​](#event-spellcheck-dictionary-download-success "Direct link to heading")


Returns:


* `event` Event
* `languageCode` string - The language code of the dictionary file


Emitted when a hunspell dictionary file has been successfully downloaded


#### Event: 'spellcheck-dictionary-download-failure'[​](#event-spellcheck-dictionary-download-failure "Direct link to heading")


Returns:


* `event` Event
* `languageCode` string - The language code of the dictionary file


Emitted when a hunspell dictionary file download fails. For details on the failure you should collect a netlog and inspect the download request.


#### Event: 'select-hid-device'[​](#event-select-hid-device "Direct link to heading")


Returns:


* `event` Event
* `details` Object
	+ `deviceList` [HIDDevice[]](structures/hid-device)
	+ `frame` [WebFrameMain](web-frame-main)
* `callback` Function
	+ `deviceId` string | null (optional)


Emitted when a HID device needs to be selected when a call to `navigator.hid.requestDevice` is made. `callback` should be called with `deviceId` to be selected; passing no arguments to `callback` will cancel the request. Additionally, permissioning on `navigator.hid` can be further managed by using [ses.setPermissionCheckHandler(handler)](#sessetpermissioncheckhandlerhandler) and [ses.setDevicePermissionHandler(handler)`](#sessetdevicepermissionhandlerhandler).




```
const { app, BrowserWindow } = require('electron')

let win = null

app.whenReady().then(() => {
  win = new BrowserWindow()

  win.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
    if (permission === 'hid') {
      // Add logic here to determine if permission should be given to allow HID selection
      return true
    }
    return false
  })

  // Optionally, retrieve previously persisted devices from a persistent store
  const grantedDevices = fetchGrantedDevices()

  win.webContents.session.setDevicePermissionHandler((details) => {
    if (new URL(details.origin).hostname === 'some-host' && details.deviceType === 'hid') {
      if (details.device.vendorId === 123 && details.device.productId === 345) {
        // Always allow this type of device (this allows skipping the call to `navigator.hid.requestDevice` first)
        return true
      }

      // Search through the list of devices that have previously been granted permission
      return grantedDevices.some((grantedDevice) => {
        return grantedDevice.vendorId === details.device.vendorId &&
              grantedDevice.productId === details.device.productId &&
              grantedDevice.serialNumber && grantedDevice.serialNumber === details.device.serialNumber
      })
    }
    return false
  })

  win.webContents.session.on('select-hid-device', (event, details, callback) => {
    event.preventDefault()
    const selectedDevice = details.deviceList.find((device) => {
      return device.vendorId === '9025' && device.productId === '67'
    })
    callback(selectedPort?.deviceId)
  })
})
```


#### Event: 'hid-device-added'[​](#event-hid-device-added "Direct link to heading")


Returns:


* `event` Event
* `details` Object
	+ `device` [HIDDevice[]](structures/hid-device)
	+ `frame` [WebFrameMain](web-frame-main)


Emitted after `navigator.hid.requestDevice` has been called and `select-hid-device` has fired if a new device becomes available before the callback from `select-hid-device` is called. This event is intended for use when using a UI to ask users to pick a device so that the UI can be updated with the newly added device.


#### Event: 'hid-device-removed'[​](#event-hid-device-removed "Direct link to heading")


Returns:


* `event` Event
* `details` Object
	+ `device` [HIDDevice[]](structures/hid-device)
	+ `frame` [WebFrameMain](web-frame-main)


Emitted after `navigator.hid.requestDevice` has been called and `select-hid-device` has fired if a device has been removed before the callback from `select-hid-device` is called. This event is intended for use when using a UI to ask users to pick a device so that the UI can be updated to remove the specified device.


#### Event: 'hid-device-revoked'[​](#event-hid-device-revoked "Direct link to heading")


Returns:


* `event` Event
* `details` Object
	+ `device` [HIDDevice[]](structures/hid-device)
	+ `origin` string (optional) - The origin that the device has been revoked from.


Emitted after `HIDDevice.forget()` has been called. This event can be used to help maintain persistent storage of permissions when `setDevicePermissionHandler` is used.


#### Event: 'select-serial-port'[​](#event-select-serial-port "Direct link to heading")


Returns:


* `event` Event
* `portList` [SerialPort[]](structures/serial-port)
* `webContents` [WebContents](web-contents)
* `callback` Function
	+ `portId` string


Emitted when a serial port needs to be selected when a call to `navigator.serial.requestPort` is made. `callback` should be called with `portId` to be selected, passing an empty string to `callback` will cancel the request. Additionally, permissioning on `navigator.serial` can be managed by using [ses.setPermissionCheckHandler(handler)](#sessetpermissioncheckhandlerhandler) with the `serial` permission.




```
const { app, BrowserWindow } = require('electron')

let win = null

app.whenReady().then(() => {
  win = new BrowserWindow({
    width: 800,
    height: 600
  })

  win.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
    if (permission === 'serial') {
      // Add logic here to determine if permission should be given to allow serial selection
      return true
    }
    return false
  })

  // Optionally, retrieve previously persisted devices from a persistent store
  const grantedDevices = fetchGrantedDevices()

  win.webContents.session.setDevicePermissionHandler((details) => {
    if (new URL(details.origin).hostname === 'some-host' && details.deviceType === 'serial') {
      if (details.device.vendorId === 123 && details.device.productId === 345) {
        // Always allow this type of device (this allows skipping the call to `navigator.serial.requestPort` first)
        return true
      }

      // Search through the list of devices that have previously been granted permission
      return grantedDevices.some((grantedDevice) => {
        return grantedDevice.vendorId === details.device.vendorId &&
              grantedDevice.productId === details.device.productId &&
              grantedDevice.serialNumber && grantedDevice.serialNumber === details.device.serialNumber
      })
    }
    return false
  })

  win.webContents.session.on('select-serial-port', (event, portList, webContents, callback) => {
    event.preventDefault()
    const selectedPort = portList.find((device) => {
      return device.vendorId === '9025' && device.productId === '67'
    })
    if (!selectedPort) {
      callback('')
    } else {
      callback(selectedPort.portId)
    }
  })
})
```


#### Event: 'serial-port-added'[​](#event-serial-port-added "Direct link to heading")


Returns:


* `event` Event
* `port` [SerialPort](structures/serial-port)
* `webContents` [WebContents](web-contents)


Emitted after `navigator.serial.requestPort` has been called and `select-serial-port` has fired if a new serial port becomes available before the callback from `select-serial-port` is called. This event is intended for use when using a UI to ask users to pick a port so that the UI can be updated with the newly added port.


#### Event: 'serial-port-removed'[​](#event-serial-port-removed "Direct link to heading")


Returns:


* `event` Event
* `port` [SerialPort](structures/serial-port)
* `webContents` [WebContents](web-contents)


Emitted after `navigator.serial.requestPort` has been called and `select-serial-port` has fired if a serial port has been removed before the callback from `select-serial-port` is called. This event is intended for use when using a UI to ask users to pick a port so that the UI can be updated to remove the specified port.


### Instance Methods[​](#instance-methods "Direct link to heading")


The following methods are available on instances of `Session`:


#### 
`ses.getCacheSize()`[​](#sesgetcachesize "Direct link to heading")


Returns `Promise<Integer>` - the session's current cache size, in bytes.


#### 
`ses.clearCache()`[​](#sesclearcache "Direct link to heading")


Returns `Promise<void>` - resolves when the cache clear operation is complete.


Clears the session’s HTTP cache.


#### 
`ses.clearStorageData([options])`[​](#sesclearstoragedataoptions "Direct link to heading")


* `options` Object (optional)
	+ `origin` string (optional) - Should follow `window.location.origin`’s representation `scheme://host:port`.
	+ `storages` string[] (optional) - The types of storages to clear, can contain: `appcache`, `cookies`, `filesystem`, `indexdb`, `localstorage`, `shadercache`, `websql`, `serviceworkers`, `cachestorage`. If not specified, clear all storage types.
	+ `quotas` string[] (optional) - The types of quotas to clear, can contain: `temporary`, `persistent`, `syncable`. If not specified, clear all quotas.


Returns `Promise<void>` - resolves when the storage data has been cleared.


#### 
`ses.flushStorageData()`[​](#sesflushstoragedata "Direct link to heading")


Writes any unwritten DOMStorage data to disk.


#### 
`ses.setProxy(config)`[​](#sessetproxyconfig "Direct link to heading")


* `config` Object
	+ `mode` string (optional) - The proxy mode. Should be one of `direct`, `auto_detect`, `pac_script`, `fixed_servers` or `system`. If it's unspecified, it will be automatically determined based on other specified options.
		- `direct` In direct mode all connections are created directly, without any proxy involved.
		- `auto_detect` In auto\_detect mode the proxy configuration is determined by a PAC script that can be downloaded at http://wpad/wpad.dat.
		- `pac_script` In pac\_script mode the proxy configuration is determined by a PAC script that is retrieved from the URL specified in the `pacScript`. This is the default mode if `pacScript` is specified.
		- `fixed_servers` In fixed\_servers mode the proxy configuration is specified in `proxyRules`. This is the default mode if `proxyRules` is specified.
		- `system` In system mode the proxy configuration is taken from the operating system. Note that the system mode is different from setting no proxy configuration. In the latter case, Electron falls back to the system settings only if no command-line options influence the proxy configuration.
	+ `pacScript` string (optional) - The URL associated with the PAC file.
	+ `proxyRules` string (optional) - Rules indicating which proxies to use.
	+ `proxyBypassRules` string (optional) - Rules indicating which URLs should bypass the proxy settings.


Returns `Promise<void>` - Resolves when the proxy setting process is complete.


Sets the proxy settings.


When `mode` is unspecified, `pacScript` and `proxyRules` are provided together, the `proxyRules` option is ignored and `pacScript` configuration is applied.


You may need `ses.closeAllConnections` to close currently in flight connections to prevent pooled sockets using previous proxy from being reused by future requests.


The `proxyRules` has to follow the rules below:




```
proxyRules = schemeProxies[";"<schemeProxies>]
schemeProxies = [<urlScheme>"="]<proxyURIList>
urlScheme = "http" | "https" | "ftp" | "socks"
proxyURIList = <proxyURL>[","<proxyURIList>]
proxyURL = [<proxyScheme>"://"]<proxyHost>[":"<proxyPort>]
```


For example:


* `http=foopy:80;ftp=foopy2` - Use HTTP proxy `foopy:80` for `http://` URLs, and HTTP proxy `foopy2:80` for `ftp://` URLs.
* `foopy:80` - Use HTTP proxy `foopy:80` for all URLs.
* `foopy:80,bar,direct://` - Use HTTP proxy `foopy:80` for all URLs, failing over to `bar` if `foopy:80` is unavailable, and after that using no proxy.
* `socks4://foopy` - Use SOCKS v4 proxy `foopy:1080` for all URLs.
* `http=foopy,socks5://bar.com` - Use HTTP proxy `foopy` for http URLs, and fail over to the SOCKS5 proxy `bar.com` if `foopy` is unavailable.
* `http=foopy,direct://` - Use HTTP proxy `foopy` for http URLs, and use no proxy if `foopy` is unavailable.
* `http=foopy;socks=foopy2` - Use HTTP proxy `foopy` for http URLs, and use `socks4://foopy2` for all other URLs.


The `proxyBypassRules` is a comma separated list of rules described below:


* `[ URL_SCHEME "://" ] HOSTNAME_PATTERN [ ":" <port> ]`


 Match all hostnames that match the pattern HOSTNAME\_PATTERN.


 Examples: "foobar.com", "*foobar.com", "*.foobar.com", "*foobar.com:99", "https://x.*.y.com:99"
* `"." HOSTNAME_SUFFIX_PATTERN [ ":" PORT ]`


 Match a particular domain suffix.


 Examples: ".google.com", ".com", "http://.google.com"
* `[ SCHEME "://" ] IP_LITERAL [ ":" PORT ]`


 Match URLs which are IP address literals.


 Examples: "127.0.1", "[0:0::1]", "[::1]", "http://[::1]:99"
* `IP_LITERAL "/" PREFIX_LENGTH_IN_BITS`


 Match any URL that is to an IP literal that falls between the given range. IP range is specified using CIDR notation.


 Examples: "192.168.1.1/16", "fefe:13::abc/33".
* `<local>`


 Match local addresses. The meaning of `<local>` is whether the host matches one of: "127.0.0.1", "::1", "localhost".


#### 
`ses.resolveProxy(url)`[​](#sesresolveproxyurl "Direct link to heading")


* `url` URL


Returns `Promise<string>` - Resolves with the proxy information for `url`.


#### 
`ses.forceReloadProxyConfig()`[​](#sesforcereloadproxyconfig "Direct link to heading")


Returns `Promise<void>` - Resolves when the all internal states of proxy service is reset and the latest proxy configuration is reapplied if it's already available. The pac script will be fetched from `pacScript` again if the proxy mode is `pac_script`.


#### 
`ses.setDownloadPath(path)`[​](#sessetdownloadpathpath "Direct link to heading")


* `path` string - The download location.


Sets download saving directory. By default, the download directory will be the `Downloads` under the respective app folder.


#### 
`ses.enableNetworkEmulation(options)`[​](#sesenablenetworkemulationoptions "Direct link to heading")


* `options` Object
	+ `offline` boolean (optional) - Whether to emulate network outage. Defaults to false.
	+ `latency` Double (optional) - RTT in ms. Defaults to 0 which will disable latency throttling.
	+ `downloadThroughput` Double (optional) - Download rate in Bps. Defaults to 0 which will disable download throttling.
	+ `uploadThroughput` Double (optional) - Upload rate in Bps. Defaults to 0 which will disable upload throttling.


Emulates network with the given configuration for the `session`.




```
// To emulate a GPRS connection with 50kbps throughput and 500 ms latency.
window.webContents.session.enableNetworkEmulation({
  latency: 500,
  downloadThroughput: 6400,
  uploadThroughput: 6400
})

// To emulate a network outage.
window.webContents.session.enableNetworkEmulation({ offline: true })
```


#### 
`ses.preconnect(options)`[​](#sespreconnectoptions "Direct link to heading")


* `options` Object
	+ `url` string - URL for preconnect. Only the origin is relevant for opening the socket.
	+ `numSockets` number (optional) - number of sockets to preconnect. Must be between 1 and 6. Defaults to 1.


Preconnects the given number of sockets to an origin.


#### 
`ses.closeAllConnections()`[​](#sescloseallconnections "Direct link to heading")


Returns `Promise<void>` - Resolves when all connections are closed.


**Note:** It will terminate / fail all requests currently in flight.


#### 
`ses.disableNetworkEmulation()`[​](#sesdisablenetworkemulation "Direct link to heading")


Disables any network emulation already active for the `session`. Resets to the original network configuration.


#### 
`ses.setCertificateVerifyProc(proc)`[​](#sessetcertificateverifyprocproc "Direct link to heading")


* `proc` Function | null
	+ `request` Object
		- `hostname` string
		- `certificate` [Certificate](structures/certificate)
		- `validatedCertificate` [Certificate](structures/certificate)
		- `isIssuedByKnownRoot` boolean - `true` if Chromium recognises the root CA as a standard root. If it isn't then it's probably the case that this certificate was generated by a MITM proxy whose root has been installed locally (for example, by a corporate proxy). This should not be trusted if the `verificationResult` is not `OK`.
		- `verificationResult` string - `OK` if the certificate is trusted, otherwise an error like `CERT_REVOKED`.
		- `errorCode` Integer - Error code.
	+ `callback` Function
		- `verificationResult` Integer - Value can be one of certificate error codes from [here](https://source.chromium.org/chromium/chromium/src/+/main:net/base/net_error_list.h). Apart from the certificate error codes, the following special codes can be used.
			* `0` - Indicates success and disables Certificate Transparency verification.
			* `-2` - Indicates failure.
			* `-3` - Uses the verification result from chromium.


Sets the certificate verify proc for `session`, the `proc` will be called with `proc(request, callback)` whenever a server certificate verification is requested. Calling `callback(0)` accepts the certificate, calling `callback(-2)` rejects it.


Calling `setCertificateVerifyProc(null)` will revert back to default certificate verify proc.




```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()

win.webContents.session.setCertificateVerifyProc((request, callback) => {
  const { hostname } = request
  if (hostname === 'github.com') {
    callback(0)
  } else {
    callback(-2)
  }
})
```



> **NOTE:** The result of this procedure is cached by the network service.
> 
> 


#### 
`ses.setPermissionRequestHandler(handler)`[​](#sessetpermissionrequesthandlerhandler "Direct link to heading")


* `handler` Function | null
	+ `webContents` [WebContents](web-contents) - WebContents requesting the permission. Please note that if the request comes from a subframe you should use `requestingUrl` to check the request origin.
	+ `permission` string - The type of requested permission.
		- `clipboard-read` - Request access to read from the clipboard.
		- `media` - Request access to media devices such as camera, microphone and speakers.
		- `display-capture` - Request access to capture the screen.
		- `mediaKeySystem` - Request access to DRM protected content.
		- `geolocation` - Request access to user's current location.
		- `notifications` - Request notification creation and the ability to display them in the user's system tray.
		- `midi` - Request MIDI access in the `webmidi` API.
		- `midiSysex` - Request the use of system exclusive messages in the `webmidi` API.
		- `pointerLock` - Request to directly interpret mouse movements as an input method. Click [here](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API) to know more.
		- `fullscreen` - Request for the app to enter fullscreen mode.
		- `openExternal` - Request to open links in external applications.
		- `unknown` - An unrecognized permission request
	+ `callback` Function
		- `permissionGranted` boolean - Allow or deny the permission.
	+ `details` Object - Some properties are only available on certain permission types.
		- `externalURL` string (optional) - The url of the `openExternal` request.
		- `securityOrigin` string (optional) - The security origin of the `media` request.
		- `mediaTypes` string[] (optional) - The types of media access being requested, elements can be `video` or `audio`
		- `requestingUrl` string - The last URL the requesting frame loaded
		- `isMainFrame` boolean - Whether the frame making the request is the main frame


Sets the handler which can be used to respond to permission requests for the `session`. Calling `callback(true)` will allow the permission and `callback(false)` will reject it. To clear the handler, call `setPermissionRequestHandler(null)`. Please note that you must also implement `setPermissionCheckHandler` to get complete permission handling. Most web APIs do a permission check and then make a permission request if the check is denied.




```
const { session } = require('electron')
session.fromPartition('some-partition').setPermissionRequestHandler((webContents, permission, callback) => {
  if (webContents.getURL() === 'some-host' && permission === 'notifications') {
    return callback(false) // denied.
  }

  callback(true)
})
```


#### 
`ses.setPermissionCheckHandler(handler)`[​](#sessetpermissioncheckhandlerhandler "Direct link to heading")


* `handler` Function\<boolean> | null
	+ `webContents` ([WebContents](web-contents) | null) - WebContents checking the permission. Please note that if the request comes from a subframe you should use `requestingUrl` to check the request origin. All cross origin sub frames making permission checks will pass a `null` webContents to this handler, while certain other permission checks such as `notifications` checks will always pass `null`. You should use `embeddingOrigin` and `requestingOrigin` to determine what origin the owning frame and the requesting frame are on respectively.
	+ `permission` string - Type of permission check. Valid values are `midiSysex`, `notifications`, `geolocation`, `media`,`mediaKeySystem`,`midi`, `pointerLock`, `fullscreen`, `openExternal`, `hid`, or `serial`.
	+ `requestingOrigin` string - The origin URL of the permission check
	+ `details` Object - Some properties are only available on certain permission types.
		- `embeddingOrigin` string (optional) - The origin of the frame embedding the frame that made the permission check. Only set for cross-origin sub frames making permission checks.
		- `securityOrigin` string (optional) - The security origin of the `media` check.
		- `mediaType` string (optional) - The type of media access being requested, can be `video`, `audio` or `unknown`
		- `requestingUrl` string (optional) - The last URL the requesting frame loaded. This is not provided for cross-origin sub frames making permission checks.
		- `isMainFrame` boolean - Whether the frame making the request is the main frame


Sets the handler which can be used to respond to permission checks for the `session`. Returning `true` will allow the permission and `false` will reject it. Please note that you must also implement `setPermissionRequestHandler` to get complete permission handling. Most web APIs do a permission check and then make a permission request if the check is denied. To clear the handler, call `setPermissionCheckHandler(null)`.




```
const { session } = require('electron')
const url = require('url')
session.fromPartition('some-partition').setPermissionCheckHandler((webContents, permission, requestingOrigin) => {
  if (new URL(requestingOrigin).hostname === 'some-host' && permission === 'notifications') {
    return true // granted
  }

  return false // denied
})
```


#### 
`ses.setDevicePermissionHandler(handler)`[​](#sessetdevicepermissionhandlerhandler "Direct link to heading")


* `handler` Function\<boolean> | null
	+ `details` Object
		- `deviceType` string - The type of device that permission is being requested on, can be `hid` or `serial`.
		- `origin` string - The origin URL of the device permission check.
		- `device` [HIDDevice](structures/hid-device) | [SerialPort](structures/serial-port)- the device that permission is being requested for.


Sets the handler which can be used to respond to device permission checks for the `session`. Returning `true` will allow the device to be permitted and `false` will reject it. To clear the handler, call `setDevicePermissionHandler(null)`. This handler can be used to provide default permissioning to devices without first calling for permission to devices (eg via `navigator.hid.requestDevice`). If this handler is not defined, the default device permissions as granted through device selection (eg via `navigator.hid.requestDevice`) will be used. Additionally, the default behavior of Electron is to store granted device permision in memory. If longer term storage is needed, a developer can store granted device permissions (eg when handling the `select-hid-device` event) and then read from that storage with `setDevicePermissionHandler`.




```
const { app, BrowserWindow } = require('electron')

let win = null

app.whenReady().then(() => {
  win = new BrowserWindow()

  win.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
    if (permission === 'hid') {
      // Add logic here to determine if permission should be given to allow HID selection
      return true
    } else if (permission === 'serial') {
      // Add logic here to determine if permission should be given to allow serial port selection
    }
    return false
  })

  // Optionally, retrieve previously persisted devices from a persistent store
  const grantedDevices = fetchGrantedDevices()

  win.webContents.session.setDevicePermissionHandler((details) => {
    if (new URL(details.origin).hostname === 'some-host' && details.deviceType === 'hid') {
      if (details.device.vendorId === 123 && details.device.productId === 345) {
        // Always allow this type of device (this allows skipping the call to `navigator.hid.requestDevice` first)
        return true
      }

      // Search through the list of devices that have previously been granted permission
      return grantedDevices.some((grantedDevice) => {
        return grantedDevice.vendorId === details.device.vendorId &&
              grantedDevice.productId === details.device.productId &&
              grantedDevice.serialNumber && grantedDevice.serialNumber === details.device.serialNumber
      })
    } else if (details.deviceType === 'serial') {
      if (details.device.vendorId === 123 && details.device.productId === 345) {
        // Always allow this type of device (this allows skipping the call to `navigator.hid.requestDevice` first)
        return true
      }
    }
    return false
  })

  win.webContents.session.on('select-hid-device', (event, details, callback) => {
    event.preventDefault()
    const selectedDevice = details.deviceList.find((device) => {
      return device.vendorId === '9025' && device.productId === '67'
    })
    callback(selectedPort?.deviceId)
  })
})
```


#### 
`ses.clearHostResolverCache()`[​](#sesclearhostresolvercache "Direct link to heading")


Returns `Promise<void>` - Resolves when the operation is complete.


Clears the host resolver cache.


#### 
`ses.allowNTLMCredentialsForDomains(domains)`[​](#sesallowntlmcredentialsfordomainsdomains "Direct link to heading")


* `domains` string - A comma-separated list of servers for which integrated authentication is enabled.


Dynamically sets whether to always send credentials for HTTP NTLM or Negotiate authentication.




```
const { session } = require('electron')
// consider any url ending with `example.com`, `foobar.com`, `baz`
// for integrated authentication.
session.defaultSession.allowNTLMCredentialsForDomains('*example.com, *foobar.com, *baz')

// consider all urls for integrated authentication.
session.defaultSession.allowNTLMCredentialsForDomains('*')
```


#### 
`ses.setUserAgent(userAgent[, acceptLanguages])`[​](#sessetuseragentuseragent-acceptlanguages "Direct link to heading")


* `userAgent` string
* `acceptLanguages` string (optional)


Overrides the `userAgent` and `acceptLanguages` for this session.


The `acceptLanguages` must a comma separated ordered list of language codes, for example `"en-US,fr,de,ko,zh-CN,ja"`.


This doesn't affect existing `WebContents`, and each `WebContents` can use `webContents.setUserAgent` to override the session-wide user agent.


#### 
`ses.isPersistent()`[​](#sesispersistent "Direct link to heading")


Returns `boolean` - Whether or not this session is a persistent one. The default `webContents` session of a `BrowserWindow` is persistent. When creating a session from a partition, session prefixed with `persist:` will be persistent, while others will be temporary.


#### 
`ses.getUserAgent()`[​](#sesgetuseragent "Direct link to heading")


Returns `string` - The user agent for this session.


#### 
`ses.setSSLConfig(config)`[​](#sessetsslconfigconfig "Direct link to heading")


* `config` Object
	+ `minVersion` string (optional) - Can be `tls1`, `tls1.1`, `tls1.2` or `tls1.3`. The minimum SSL version to allow when connecting to remote servers. Defaults to `tls1`.
	+ `maxVersion` string (optional) - Can be `tls1.2` or `tls1.3`. The maximum SSL version to allow when connecting to remote servers. Defaults to `tls1.3`.
	+ `disabledCipherSuites` Integer[] (optional) - List of cipher suites which should be explicitly prevented from being used in addition to those disabled by the net built-in policy. Supported literal forms: 0xAABB, where AA is `cipher_suite[0]` and BB is `cipher_suite[1]`, as defined in RFC 2246, Section 7.4.1.2. Unrecognized but parsable cipher suites in this form will not return an error. Ex: To disable TLS\_RSA\_WITH\_RC4\_128\_MD5, specify 0x0004, while to disable TLS\_ECDH\_ECDSA\_WITH\_RC4\_128\_SHA, specify 0xC002. Note that TLSv1.3 ciphers cannot be disabled using this mechanism.


Sets the SSL configuration for the session. All subsequent network requests will use the new configuration. Existing network connections (such as WebSocket connections) will not be terminated, but old sockets in the pool will not be reused for new connections.


#### 
`ses.getBlobData(identifier)`[​](#sesgetblobdataidentifier "Direct link to heading")


* `identifier` string - Valid UUID.


Returns `Promise<Buffer>` - resolves with blob data.


#### 
`ses.downloadURL(url)`[​](#sesdownloadurlurl "Direct link to heading")


* `url` string


Initiates a download of the resource at `url`. The API will generate a [DownloadItem](download-item) that can be accessed with the [will-download](#event-will-download) event.


**Note:** This does not perform any security checks that relate to a page's origin, unlike [`webContents.downloadURL`](web-contents#contentsdownloadurlurl).


#### 
`ses.createInterruptedDownload(options)`[​](#sescreateinterrupteddownloadoptions "Direct link to heading")


* `options` Object
	+ `path` string - Absolute path of the download.
	+ `urlChain` string[] - Complete URL chain for the download.
	+ `mimeType` string (optional)
	+ `offset` Integer - Start range for the download.
	+ `length` Integer - Total length of the download.
	+ `lastModified` string (optional) - Last-Modified header value.
	+ `eTag` string (optional) - ETag header value.
	+ `startTime` Double (optional) - Time when download was started in number of seconds since UNIX epoch.


Allows resuming `cancelled` or `interrupted` downloads from previous `Session`. The API will generate a [DownloadItem](download-item) that can be accessed with the [will-download](#event-will-download) event. The [DownloadItem](download-item) will not have any `WebContents` associated with it and the initial state will be `interrupted`. The download will start only when the `resume` API is called on the [DownloadItem](download-item).


#### 
`ses.clearAuthCache()`[​](#sesclearauthcache "Direct link to heading")


Returns `Promise<void>` - resolves when the session’s HTTP authentication cache has been cleared.


#### 
`ses.setPreloads(preloads)`[​](#sessetpreloadspreloads "Direct link to heading")


* `preloads` string[] - An array of absolute path to preload scripts


Adds scripts that will be executed on ALL web contents that are associated with this session just before normal `preload` scripts run.


#### 
`ses.getPreloads()`[​](#sesgetpreloads "Direct link to heading")


Returns `string[]` an array of paths to preload scripts that have been registered.


#### 
`ses.setCodeCachePath(path)`[​](#sessetcodecachepathpath "Direct link to heading")


* `path` String - Absolute path to store the v8 generated JS code cache from the renderer.


Sets the directory to store the generated JS [code cache](https://v8.dev/blog/code-caching-for-devs) for this session. The directory is not required to be created by the user before this call, the runtime will create if it does not exist otherwise will use the existing directory. If directory cannot be created, then code cache will not be used and all operations related to code cache will fail silently inside the runtime. By default, the directory will be `Code Cache` under the respective user data folder.


#### 
`ses.clearCodeCaches(options)`[​](#sesclearcodecachesoptions "Direct link to heading")


* `options` Object
	+ `urls` String[] (optional) - An array of url corresponding to the resource whose generated code cache needs to be removed. If the list is empty then all entries in the cache directory will be removed.


Returns `Promise<void>` - resolves when the code cache clear operation is complete.


#### 
`ses.setSpellCheckerEnabled(enable)`[​](#sessetspellcheckerenabledenable "Direct link to heading")


* `enable` boolean


Sets whether to enable the builtin spell checker.


#### 
`ses.isSpellCheckerEnabled()`[​](#sesisspellcheckerenabled "Direct link to heading")


Returns `boolean` - Whether the builtin spell checker is enabled.


#### 
`ses.setSpellCheckerLanguages(languages)`[​](#sessetspellcheckerlanguageslanguages "Direct link to heading")


* `languages` string[] - An array of language codes to enable the spellchecker for.


The built in spellchecker does not automatically detect what language a user is typing in. In order for the spell checker to correctly check their words you must call this API with an array of language codes. You can get the list of supported language codes with the `ses.availableSpellCheckerLanguages` property.


**Note:** On macOS the OS spellchecker is used and will detect your language automatically. This API is a no-op on macOS.


#### 
`ses.getSpellCheckerLanguages()`[​](#sesgetspellcheckerlanguages "Direct link to heading")


Returns `string[]` - An array of language codes the spellchecker is enabled for. If this list is empty the spellchecker will fallback to using `en-US`. By default on launch if this setting is an empty list Electron will try to populate this setting with the current OS locale. This setting is persisted across restarts.


**Note:** On macOS the OS spellchecker is used and has its own list of languages. This API is a no-op on macOS.


#### 
`ses.setSpellCheckerDictionaryDownloadURL(url)`[​](#sessetspellcheckerdictionarydownloadurlurl "Direct link to heading")


* `url` string - A base URL for Electron to download hunspell dictionaries from.


By default Electron will download hunspell dictionaries from the Chromium CDN. If you want to override this behavior you can use this API to point the dictionary downloader at your own hosted version of the hunspell dictionaries. We publish a `hunspell_dictionaries.zip` file with each release which contains the files you need to host here.


The file server must be **case insensitive**. If you cannot do this, you must upload each file twice: once with the case it has in the ZIP file and once with the filename as all lowercase.


If the files present in `hunspell_dictionaries.zip` are available at `https://example.com/dictionaries/language-code.bdic` then you should call this api with `ses.setSpellCheckerDictionaryDownloadURL('https://example.com/dictionaries/')`. Please note the trailing slash. The URL to the dictionaries is formed as `${url}${filename}`.


**Note:** On macOS the OS spellchecker is used and therefore we do not download any dictionary files. This API is a no-op on macOS.


#### 
`ses.listWordsInSpellCheckerDictionary()`[​](#seslistwordsinspellcheckerdictionary "Direct link to heading")


Returns `Promise<string[]>` - An array of all words in app's custom dictionary. Resolves when the full dictionary is loaded from disk.


#### 
`ses.addWordToSpellCheckerDictionary(word)`[​](#sesaddwordtospellcheckerdictionaryword "Direct link to heading")


* `word` string - The word you want to add to the dictionary


Returns `boolean` - Whether the word was successfully written to the custom dictionary. This API will not work on non-persistent (in-memory) sessions.


**Note:** On macOS and Windows 10 this word will be written to the OS custom dictionary as well


#### 
`ses.removeWordFromSpellCheckerDictionary(word)`[​](#sesremovewordfromspellcheckerdictionaryword "Direct link to heading")


* `word` string - The word you want to remove from the dictionary


Returns `boolean` - Whether the word was successfully removed from the custom dictionary. This API will not work on non-persistent (in-memory) sessions.


**Note:** On macOS and Windows 10 this word will be removed from the OS custom dictionary as well


#### 
`ses.loadExtension(path[, options])`[​](#sesloadextensionpath-options "Direct link to heading")


* `path` string - Path to a directory containing an unpacked Chrome extension
* `options` Object (optional)
	+ `allowFileAccess` boolean - Whether to allow the extension to read local files over `file://` protocol and inject content scripts into `file://` pages. This is required e.g. for loading devtools extensions on `file://` URLs. Defaults to false.


Returns `Promise<Extension>` - resolves when the extension is loaded.


This method will raise an exception if the extension could not be loaded. If there are warnings when installing the extension (e.g. if the extension requests an API that Electron does not support) then they will be logged to the console.


Note that Electron does not support the full range of Chrome extensions APIs. See [Supported Extensions APIs](extensions#supported-extensions-apis) for more details on what is supported.


Note that in previous versions of Electron, extensions that were loaded would be remembered for future runs of the application. This is no longer the case: `loadExtension` must be called on every boot of your app if you want the extension to be loaded.




```
const { app, session } = require('electron')
const path = require('path')

app.on('ready', async () => {
  await session.defaultSession.loadExtension(
    path.join(__dirname, 'react-devtools'),
    // allowFileAccess is required to load the devtools extension on file:// URLs.
    { allowFileAccess: true }
  )
  // Note that in order to use the React DevTools extension, you'll need to
  // download and unzip a copy of the extension.
})
```


This API does not support loading packed (.crx) extensions.


**Note:** This API cannot be called before the `ready` event of the `app` module is emitted.


**Note:** Loading extensions into in-memory (non-persistent) sessions is not supported and will throw an error.


#### 
`ses.removeExtension(extensionId)`[​](#sesremoveextensionextensionid "Direct link to heading")


* `extensionId` string - ID of extension to remove


Unloads an extension.


**Note:** This API cannot be called before the `ready` event of the `app` module is emitted.


#### 
`ses.getExtension(extensionId)`[​](#sesgetextensionextensionid "Direct link to heading")


* `extensionId` string - ID of extension to query


Returns `Extension` | `null` - The loaded extension with the given ID.


**Note:** This API cannot be called before the `ready` event of the `app` module is emitted.


#### 
`ses.getAllExtensions()`[​](#sesgetallextensions "Direct link to heading")


Returns `Extension[]` - A list of all loaded extensions.


**Note:** This API cannot be called before the `ready` event of the `app` module is emitted.


#### 
`ses.getStoragePath()`[​](#sesgetstoragepath "Direct link to heading")


Returns `string | null` - The absolute file system path where data for this session is persisted on disk. For in memory sessions this returns `null`.


### Instance Properties[​](#instance-properties "Direct link to heading")


The following properties are available on instances of `Session`:


#### 
`ses.availableSpellCheckerLanguages` *Readonly*[​](#sesavailablespellcheckerlanguages-readonly "Direct link to heading")


A `string[]` array which consists of all the known available spell checker languages. Providing a language code to the `setSpellCheckerLanguages` API that isn't in this array will result in an error.


#### 
`ses.spellCheckerEnabled`[​](#sesspellcheckerenabled "Direct link to heading")


A `boolean` indicating whether builtin spell checker is enabled.


#### 
`ses.storagePath` *Readonly*[​](#sesstoragepath-readonly "Direct link to heading")


A `string | null` indicating the absolute file system path where data for this session is persisted on disk. For in memory sessions this returns `null`.


#### 
`ses.cookies` *Readonly*[​](#sescookies-readonly "Direct link to heading")


A [`Cookies`](cookies) object for this session.


#### 
`ses.serviceWorkers` *Readonly*[​](#sesserviceworkers-readonly "Direct link to heading")


A [`ServiceWorkers`](service-workers) object for this session.


#### 
`ses.webRequest` *Readonly*[​](#seswebrequest-readonly "Direct link to heading")


A [`WebRequest`](web-request) object for this session.


#### 
`ses.protocol` *Readonly*[​](#sesprotocol-readonly "Direct link to heading")


A [`Protocol`](protocol) object for this session.




```
const { app, session } = require('electron')
const path = require('path')

app.whenReady().then(() => {
  const protocol = session.fromPartition('some-partition').protocol
  if (!protocol.registerFileProtocol('atom', (request, callback) => {
    const url = request.url.substr(7)
    callback({ path: path.normalize(`${__dirname}/${url}`) })
  })) {
    console.error('Failed to register protocol')
  }
})
```


#### 
`ses.netLog` *Readonly*[​](#sesnetlog-readonly "Direct link to heading")


A [`NetLog`](net-log) object for this session.




```
const { app, session } = require('electron')

app.whenReady().then(async () => {
  const netLog = session.fromPartition('some-partition').netLog
  netLog.startLogging('/path/to/net-log')
  // After some network events
  const path = await netLog.stopLogging()
  console.log('Net-logs written to', path)
})
```



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/session>

REPL
====


[Read-Eval-Print-Loop](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) (REPL) is a simple, interactive computer programming environment that takes single user inputs (i.e. single expressions), evaluates them, and returns the result to the user.


Main process[​](#main-process "Direct link to heading")
-------------------------------------------------------


Electron exposes the [Node.js `repl` module](https://nodejs.org/dist/latest/docs/api/repl.html) through the `--interactive` CLI flag. Assuming you have `electron` installed as a local project dependency, you should be able to access the REPL with the following command:




```
./node_modules/.bin/electron --interactive
```


**Note:** `electron --interactive` is not available on Windows (see [electron/electron#5776](https://github.com/electron/electron/pull/5776) for more details).


Renderer process[​](#renderer-process "Direct link to heading")
---------------------------------------------------------------


You can use the DevTools Console tab to get a REPL for any renderer process. To learn more, read [the Chrome documentation](https://developer.chrome.com/docs/devtools/console/).



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/repl>

MemoryInfo Object
=================


* `workingSetSize` Integer - The amount of memory currently pinned to actual physical RAM.
* `peakWorkingSetSize` Integer - The maximum amount of memory that has ever been pinned to actual physical RAM.
* `privateBytes` Integer (optional) *Windows* - The amount of memory not shared by other processes, such as JS heap or HTML content.


Note that all statistics are reported in Kilobytes.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/memory-info>

Breaking Changes
================


Breaking changes will be documented here, and deprecation warnings added to JS code where possible, at least [one major version](tutorial/electron-versioning#semver) before the change is made.


### Types of Breaking Changes[​](#types-of-breaking-changes "Direct link to heading")


This document uses the following convention to categorize breaking changes:


* **API Changed:** An API was changed in such a way that code that has not been updated is guaranteed to throw an exception.
* **Behavior Changed:** The behavior of Electron has changed, but not in such a way that an exception will necessarily be thrown.
* **Default Changed:** Code depending on the old default may break, not necessarily throwing an exception. The old behavior can be restored by explicitly specifying the value.
* **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
* **Removed:** An API or feature was removed, and is no longer supported by Electron.


Planned Breaking API Changes (20.0)[​](#planned-breaking-api-changes-200 "Direct link to heading")
--------------------------------------------------------------------------------------------------


### Default Changed: renderers without `nodeIntegration: true` are sandboxed by default[​](#default-changed-renderers-without-nodeintegration-true-are-sandboxed-by-default "Direct link to heading")


Previously, renderers that specified a preload script defaulted to being unsandboxed. This meant that by default, preload scripts had access to Node.js. In Electron 20, this default has changed. Beginning in Electron 20, renderers will be sandboxed by default, unless `nodeIntegration: true` or `sandbox: false` is specified.


If your preload scripts do not depend on Node, no action is needed. If your preload scripts *do* depend on Node, either refactor them to remove Node usage from the renderer, or explicitly specify `sandbox: false` for the relevant renderers.


### Removed: `skipTaskbar` on Linux[​](#removed-skiptaskbar-on-linux "Direct link to heading")


On X11, `skipTaskbar` sends a `_NET_WM_STATE_SKIP_TASKBAR` message to the X11 window manager. There is not a direct equivalent for Wayland, and the known workarounds have unacceptable tradeoffs (e.g. Window.is\_skip\_taskbar in GNOME requires unsafe mode), so Electron is unable to support this feature on Linux.


### API Changed: `session.setDevicePermissionHandler(handler)`[​](#api-changed-sessionsetdevicepermissionhandlerhandler "Direct link to heading")


The handler invoked when `session.setDevicePermissionHandler(handler)` is used has a change to its arguments. This handler no longer is passed a frame `[WebFrameMain](/docs/latest/api/web-frame-main)`, but instead is passed the `origin`, which is the origin that is checking for device permission.


Planned Breaking API Changes (19.0)[​](#planned-breaking-api-changes-190 "Direct link to heading")
--------------------------------------------------------------------------------------------------


### Removed: IA32 Linux binaries[​](#removed-ia32-linux-binaries "Direct link to heading")


This is a result of Chromium 102.0.4999.0 dropping support for IA32 Linux. This concludes the [removal of support for IA32 Linux](#removed-ia32-linux-support).


Planned Breaking API Changes (18.0)[​](#planned-breaking-api-changes-180 "Direct link to heading")
--------------------------------------------------------------------------------------------------


### Removed: `nativeWindowOpen`[​](#removed-nativewindowopen "Direct link to heading")


Prior to Electron 15, `window.open` was by default shimmed to use `BrowserWindowProxy`. This meant that `window.open('about:blank')` did not work to open synchronously scriptable child windows, among other incompatibilities. Since Electron 15, `nativeWindowOpen` has been enabled by default.


See the documentation for [window.open in Electron](api/window-open) for more details.


Planned Breaking API Changes (17.0)[​](#planned-breaking-api-changes-170 "Direct link to heading")
--------------------------------------------------------------------------------------------------


### Removed: `desktopCapturer.getSources` in the renderer[​](#removed-desktopcapturergetsources-in-the-renderer "Direct link to heading")


The `desktopCapturer.getSources` API is now only available in the main process. This has been changed in order to improve the default security of Electron apps.


If you need this functionality, it can be replaced as follows:




```
// Main process
const { ipcMain, desktopCapturer } = require('electron')

ipcMain.handle(
  'DESKTOP_CAPTURER_GET_SOURCES',
  (event, opts) => desktopCapturer.getSources(opts)
)
```




```
// Renderer process
const { ipcRenderer } = require('electron')

const desktopCapturer = {
  getSources: (opts) => ipcRenderer.invoke('DESKTOP_CAPTURER_GET_SOURCES', opts)
}
```


However, you should consider further restricting the information returned to the renderer; for instance, displaying a source selector to the user and only returning the selected source.


### Deprecated: `nativeWindowOpen`[​](#deprecated-nativewindowopen "Direct link to heading")


Prior to Electron 15, `window.open` was by default shimmed to use `BrowserWindowProxy`. This meant that `window.open('about:blank')` did not work to open synchronously scriptable child windows, among other incompatibilities. Since Electron 15, `nativeWindowOpen` has been enabled by default.


See the documentation for [window.open in Electron](api/window-open) for more details.


Planned Breaking API Changes (16.0)[​](#planned-breaking-api-changes-160 "Direct link to heading")
--------------------------------------------------------------------------------------------------


### Behavior Changed: `crashReporter` implementation switched to Crashpad on Linux[​](#behavior-changed-crashreporter-implementation-switched-to-crashpad-on-linux "Direct link to heading")


The underlying implementation of the `crashReporter` API on Linux has changed from Breakpad to Crashpad, bringing it in line with Windows and Mac. As a result of this, child processes are now automatically monitored, and calling `process.crashReporter.start` in Node child processes is no longer needed (and is not advisable, as it will start a second instance of the Crashpad reporter).


There are also some subtle changes to how annotations will be reported on Linux, including that long values will no longer be split between annotations appended with `__1`, `__2` and so on, and instead will be truncated at the (new, longer) annotation value limit.


### Deprecated: `desktopCapturer.getSources` in the renderer[​](#deprecated-desktopcapturergetsources-in-the-renderer "Direct link to heading")


Usage of the `desktopCapturer.getSources` API in the renderer has been deprecated and will be removed. This change improves the default security of Electron apps.


See [here](#removed-desktopcapturergetsources-in-the-renderer) for details on how to replace this API in your app.


Planned Breaking API Changes (15.0)[​](#planned-breaking-api-changes-150 "Direct link to heading")
--------------------------------------------------------------------------------------------------


### Default Changed: `nativeWindowOpen` defaults to `true`[​](#default-changed-nativewindowopen-defaults-to-true "Direct link to heading")


Prior to Electron 15, `window.open` was by default shimmed to use `BrowserWindowProxy`. This meant that `window.open('about:blank')` did not work to open synchronously scriptable child windows, among other incompatibilities. `nativeWindowOpen` is no longer experimental, and is now the default.


See the documentation for [window.open in Electron](api/window-open) for more details.


Planned Breaking API Changes (14.0)[​](#planned-breaking-api-changes-140 "Direct link to heading")
--------------------------------------------------------------------------------------------------


### Removed: `remote` module[​](#removed-remote-module "Direct link to heading")


The `remote` module was deprecated in Electron 12, and will be removed in Electron 14. It is replaced by the [`@electron/remote`](https://github.com/electron/remote) module.




```
// Deprecated in Electron 12:
const { BrowserWindow } = require('electron').remote
```




```
// Replace with:
const { BrowserWindow } = require('@electron/remote')

// In the main process:
require('@electron/remote/main').initialize()
```


### Removed: `app.allowRendererProcessReuse`[​](#removed-appallowrendererprocessreuse "Direct link to heading")


The `app.allowRendererProcessReuse` property will be removed as part of our plan to more closely align with Chromium's process model for security, performance and maintainability.


For more detailed information see [#18397](https://github.com/electron/electron/issues/18397).


### Removed: Browser Window Affinity[​](#removed-browser-window-affinity "Direct link to heading")


The `affinity` option when constructing a new `BrowserWindow` will be removed as part of our plan to more closely align with Chromium's process model for security, performance and maintainability.


For more detailed information see [#18397](https://github.com/electron/electron/issues/18397).


### API Changed: `window.open()`[​](#api-changed-windowopen "Direct link to heading")


The optional parameter `frameName` will no longer set the title of the window. This now follows the specification described by the [native documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/open#parameters) under the corresponding parameter `windowName`.


If you were using this parameter to set the title of a window, you can instead use [win.setTitle(title)](api/browser-window#winsettitletitle).


### Removed: `worldSafeExecuteJavaScript`[​](#removed-worldsafeexecutejavascript "Direct link to heading")


In Electron 14, `worldSafeExecuteJavaScript` will be removed. There is no alternative, please ensure your code works with this property enabled. It has been enabled by default since Electron 12.


You will be affected by this change if you use either `webFrame.executeJavaScript` or `webFrame.executeJavaScriptInIsolatedWorld`. You will need to ensure that values returned by either of those methods are supported by the [Context Bridge API](api/context-bridge#parameter--error--return-type-support) as these methods use the same value passing semantics.


### Removed: BrowserWindowConstructorOptions inheriting from parent windows[​](#removed-browserwindowconstructoroptions-inheriting-from-parent-windows "Direct link to heading")


Prior to Electron 14, windows opened with `window.open` would inherit BrowserWindow constructor options such as `transparent` and `resizable` from their parent window. Beginning with Electron 14, this behavior is removed, and windows will not inherit any BrowserWindow constructor options from their parents.


Instead, explicitly set options for the new window with `setWindowOpenHandler`:




```
webContents.setWindowOpenHandler((details) => {
  return {
    action: 'allow',
    overrideBrowserWindowOptions: {
      // ...
    }
  }
})
```


### Removed: `additionalFeatures`[​](#removed-additionalfeatures "Direct link to heading")


The deprecated `additionalFeatures` property in the `new-window` and `did-create-window` events of WebContents has been removed. Since `new-window` uses positional arguments, the argument is still present, but will always be the empty array `[]`. (Though note, the `new-window` event itself is deprecated, and is replaced by `setWindowOpenHandler`.) Bare keys in window features will now present as keys with the value `true` in the options object.




```
// Removed in Electron 14
// Triggered by window.open('...', '', 'my-key')
webContents.on('did-create-window', (window, details) => {
  if (details.additionalFeatures.includes('my-key')) {
    // ...
  }
})

// Replace with
webContents.on('did-create-window', (window, details) => {
  if (details.options['my-key']) {
    // ...
  }
})
```


Planned Breaking API Changes (13.0)[​](#planned-breaking-api-changes-130 "Direct link to heading")
--------------------------------------------------------------------------------------------------


### API Changed: `session.setPermissionCheckHandler(handler)`[​](#api-changed-sessionsetpermissioncheckhandlerhandler "Direct link to heading")


The `handler` methods first parameter was previously always a `webContents`, it can now sometimes be `null`. You should use the `requestingOrigin`, `embeddingOrigin` and `securityOrigin` properties to respond to the permission check correctly. As the `webContents` can be `null` it can no longer be relied on.




```
// Old code
session.setPermissionCheckHandler((webContents, permission) => {
  if (webContents.getURL().startsWith('https://google.com/') && permission === 'notification') {
    return true
  }
  return false
})

// Replace with
session.setPermissionCheckHandler((webContents, permission, requestingOrigin) => {
  if (new URL(requestingOrigin).hostname === 'google.com' && permission === 'notification') {
    return true
  }
  return false
})
```


### Removed: `shell.moveItemToTrash()`[​](#removed-shellmoveitemtotrash "Direct link to heading")


The deprecated synchronous `shell.moveItemToTrash()` API has been removed. Use the asynchronous `shell.trashItem()` instead.




```
// Removed in Electron 13
shell.moveItemToTrash(path)
// Replace with
shell.trashItem(path).then(/* ... */)
```


### Removed: `BrowserWindow` extension APIs[​](#removed-browserwindow-extension-apis "Direct link to heading")


The deprecated extension APIs have been removed:


* `BrowserWindow.addExtension(path)`
* `BrowserWindow.addDevToolsExtension(path)`
* `BrowserWindow.removeExtension(name)`
* `BrowserWindow.removeDevToolsExtension(name)`
* `BrowserWindow.getExtensions()`
* `BrowserWindow.getDevToolsExtensions()`


Use the session APIs instead:


* `ses.loadExtension(path)`
* `ses.removeExtension(extension_id)`
* `ses.getAllExtensions()`




```
// Removed in Electron 13
BrowserWindow.addExtension(path)
BrowserWindow.addDevToolsExtension(path)
// Replace with
session.defaultSession.loadExtension(path)
```




```
// Removed in Electron 13
BrowserWindow.removeExtension(name)
BrowserWindow.removeDevToolsExtension(name)
// Replace with
session.defaultSession.removeExtension(extension_id)
```




```
// Removed in Electron 13
BrowserWindow.getExtensions()
BrowserWindow.getDevToolsExtensions()
// Replace with
session.defaultSession.getAllExtensions()
```


### Removed: methods in `systemPreferences`[​](#removed-methods-in-systempreferences "Direct link to heading")


The following `systemPreferences` methods have been deprecated:


* `systemPreferences.isDarkMode()`
* `systemPreferences.isInvertedColorScheme()`
* `systemPreferences.isHighContrastColorScheme()`


Use the following `nativeTheme` properties instead:


* `nativeTheme.shouldUseDarkColors`
* `nativeTheme.shouldUseInvertedColorScheme`
* `nativeTheme.shouldUseHighContrastColors`




```
// Removed in Electron 13
systemPreferences.isDarkMode()
// Replace with
nativeTheme.shouldUseDarkColors

// Removed in Electron 13
systemPreferences.isInvertedColorScheme()
// Replace with
nativeTheme.shouldUseInvertedColorScheme

// Removed in Electron 13
systemPreferences.isHighContrastColorScheme()
// Replace with
nativeTheme.shouldUseHighContrastColors
```


### Deprecated: WebContents `new-window` event[​](#deprecated-webcontents-new-window-event "Direct link to heading")


The `new-window` event of WebContents has been deprecated. It is replaced by [`webContents.setWindowOpenHandler()`](api/web-contents#contentssetwindowopenhandlerhandler).




```
// Deprecated in Electron 13
webContents.on('new-window', (event) => {
  event.preventDefault()
})

// Replace with
webContents.setWindowOpenHandler((details) => {
  return { action: 'deny' }
})
```


Planned Breaking API Changes (12.0)[​](#planned-breaking-api-changes-120 "Direct link to heading")
--------------------------------------------------------------------------------------------------


### Removed: Pepper Flash support[​](#removed-pepper-flash-support "Direct link to heading")


Chromium has removed support for Flash, and so we must follow suit. See Chromium's [Flash Roadmap](https://www.chromium.org/flash-roadmap) for more details.


### Default Changed: `worldSafeExecuteJavaScript` defaults to `true`[​](#default-changed-worldsafeexecutejavascript-defaults-to-true "Direct link to heading")


In Electron 12, `worldSafeExecuteJavaScript` will be enabled by default. To restore the previous behavior, `worldSafeExecuteJavaScript: false` must be specified in WebPreferences. Please note that setting this option to `false` is **insecure**.


This option will be removed in Electron 14 so please migrate your code to support the default value.


### Default Changed: `contextIsolation` defaults to `true`[​](#default-changed-contextisolation-defaults-to-true "Direct link to heading")


In Electron 12, `contextIsolation` will be enabled by default. To restore the previous behavior, `contextIsolation: false` must be specified in WebPreferences.


We [recommend having contextIsolation enabled](tutorial/security#3-enable-context-isolation) for the security of your application.


Another implication is that `require()` cannot be used in the renderer process unless `nodeIntegration` is `true` and `contextIsolation` is `false`.


For more details see: <https://github.com/electron/electron/issues/23506>


### Removed: `crashReporter.getCrashesDirectory()`[​](#removed-crashreportergetcrashesdirectory "Direct link to heading")


The `crashReporter.getCrashesDirectory` method has been removed. Usage should be replaced by `app.getPath('crashDumps')`.




```
// Removed in Electron 12
crashReporter.getCrashesDirectory()
// Replace with
app.getPath('crashDumps')
```


### Removed: `crashReporter` methods in the renderer process[​](#removed-crashreporter-methods-in-the-renderer-process "Direct link to heading")


The following `crashReporter` methods are no longer available in the renderer process:


* `crashReporter.start`
* `crashReporter.getLastCrashReport`
* `crashReporter.getUploadedReports`
* `crashReporter.getUploadToServer`
* `crashReporter.setUploadToServer`
* `crashReporter.getCrashesDirectory`


They should be called only from the main process.


See [#23265](https://github.com/electron/electron/pull/23265) for more details.


### Default Changed: `crashReporter.start({ compress: true })`[​](#default-changed-crashreporterstart-compress-true- "Direct link to heading")


The default value of the `compress` option to `crashReporter.start` has changed from `false` to `true`. This means that crash dumps will be uploaded to the crash ingestion server with the `Content-Encoding: gzip` header, and the body will be compressed.


If your crash ingestion server does not support compressed payloads, you can turn off compression by specifying `{ compress: false }` in the crash reporter options.


### Deprecated: `remote` module[​](#deprecated-remote-module "Direct link to heading")


The `remote` module is deprecated in Electron 12, and will be removed in Electron 14. It is replaced by the [`@electron/remote`](https://github.com/electron/remote) module.




```
// Deprecated in Electron 12:
const { BrowserWindow } = require('electron').remote
```




```
// Replace with:
const { BrowserWindow } = require('@electron/remote')

// In the main process:
require('@electron/remote/main').initialize()
```


### Deprecated: `shell.moveItemToTrash()`[​](#deprecated-shellmoveitemtotrash "Direct link to heading")


The synchronous `shell.moveItemToTrash()` has been replaced by the new, asynchronous `shell.trashItem()`.




```
// Deprecated in Electron 12
shell.moveItemToTrash(path)
// Replace with
shell.trashItem(path).then(/* ... */)
```


Planned Breaking API Changes (11.0)[​](#planned-breaking-api-changes-110 "Direct link to heading")
--------------------------------------------------------------------------------------------------


### Removed: `BrowserView.{destroy, fromId, fromWebContents, getAllViews}` and `id` property of `BrowserView`[​](#removed-browserviewdestroy-fromid-fromwebcontents-getallviews-and-id-property-of-browserview "Direct link to heading")


The experimental APIs `BrowserView.{destroy, fromId, fromWebContents, getAllViews}` have now been removed. Additionally, the `id` property of `BrowserView` has also been removed.


For more detailed information, see [#23578](https://github.com/electron/electron/pull/23578).


Planned Breaking API Changes (10.0)[​](#planned-breaking-api-changes-100 "Direct link to heading")
--------------------------------------------------------------------------------------------------


### Deprecated: `companyName` argument to `crashReporter.start()`[​](#deprecated-companyname-argument-to-crashreporterstart "Direct link to heading")


The `companyName` argument to `crashReporter.start()`, which was previously required, is now optional, and further, is deprecated. To get the same behavior in a non-deprecated way, you can pass a `companyName` value in `globalExtra`.




```
// Deprecated in Electron 10
crashReporter.start({ companyName: 'Umbrella Corporation' })
// Replace with
crashReporter.start({ globalExtra: { _companyName: 'Umbrella Corporation' } })
```


### Deprecated: `crashReporter.getCrashesDirectory()`[​](#deprecated-crashreportergetcrashesdirectory "Direct link to heading")


The `crashReporter.getCrashesDirectory` method has been deprecated. Usage should be replaced by `app.getPath('crashDumps')`.




```
// Deprecated in Electron 10
crashReporter.getCrashesDirectory()
// Replace with
app.getPath('crashDumps')
```


### Deprecated: `crashReporter` methods in the renderer process[​](#deprecated-crashreporter-methods-in-the-renderer-process "Direct link to heading")


Calling the following `crashReporter` methods from the renderer process is deprecated:


* `crashReporter.start`
* `crashReporter.getLastCrashReport`
* `crashReporter.getUploadedReports`
* `crashReporter.getUploadToServer`
* `crashReporter.setUploadToServer`
* `crashReporter.getCrashesDirectory`


The only non-deprecated methods remaining in the `crashReporter` module in the renderer are `addExtraParameter`, `removeExtraParameter` and `getParameters`.


All above methods remain non-deprecated when called from the main process.


See [#23265](https://github.com/electron/electron/pull/23265) for more details.


### Deprecated: `crashReporter.start({ compress: false })`[​](#deprecated-crashreporterstart-compress-false- "Direct link to heading")


Setting `{ compress: false }` in `crashReporter.start` is deprecated. Nearly all crash ingestion servers support gzip compression. This option will be removed in a future version of Electron.


### Default Changed: `enableRemoteModule` defaults to `false`[​](#default-changed-enableremotemodule-defaults-to-false "Direct link to heading")


In Electron 9, using the remote module without explicitly enabling it via the `enableRemoteModule` WebPreferences option began emitting a warning. In Electron 10, the remote module is now disabled by default. To use the remote module, `enableRemoteModule: true` must be specified in WebPreferences:




```
const w = new BrowserWindow({
  webPreferences: {
    enableRemoteModule: true
  }
})
```


We [recommend moving away from the remote module](https://medium.com/@nornagon/electrons-remote-module-considered-harmful-70d69500f31).


### 
`protocol.unregisterProtocol`[​](#protocolunregisterprotocol "Direct link to heading")


### 
`protocol.uninterceptProtocol`[​](#protocoluninterceptprotocol "Direct link to heading")


The APIs are now synchronous and the optional callback is no longer needed.




```
// Deprecated
protocol.unregisterProtocol(scheme, () => { /* ... */ })
// Replace with
protocol.unregisterProtocol(scheme)
```


### 
`protocol.registerFileProtocol`[​](#protocolregisterfileprotocol "Direct link to heading")


### 
`protocol.registerBufferProtocol`[​](#protocolregisterbufferprotocol "Direct link to heading")


### 
`protocol.registerStringProtocol`[​](#protocolregisterstringprotocol "Direct link to heading")


### 
`protocol.registerHttpProtocol`[​](#protocolregisterhttpprotocol "Direct link to heading")


### 
`protocol.registerStreamProtocol`[​](#protocolregisterstreamprotocol "Direct link to heading")


### 
`protocol.interceptFileProtocol`[​](#protocolinterceptfileprotocol "Direct link to heading")


### 
`protocol.interceptStringProtocol`[​](#protocolinterceptstringprotocol "Direct link to heading")


### 
`protocol.interceptBufferProtocol`[​](#protocolinterceptbufferprotocol "Direct link to heading")


### 
`protocol.interceptHttpProtocol`[​](#protocolintercepthttpprotocol "Direct link to heading")


### 
`protocol.interceptStreamProtocol`[​](#protocolinterceptstreamprotocol "Direct link to heading")


The APIs are now synchronous and the optional callback is no longer needed.




```
// Deprecated
protocol.registerFileProtocol(scheme, handler, () => { /* ... */ })
// Replace with
protocol.registerFileProtocol(scheme, handler)
```


The registered or intercepted protocol does not have effect on current page until navigation happens.


### 
`protocol.isProtocolHandled`[​](#protocolisprotocolhandled "Direct link to heading")


This API is deprecated and users should use `protocol.isProtocolRegistered` and `protocol.isProtocolIntercepted` instead.




```
// Deprecated
protocol.isProtocolHandled(scheme).then(() => { /* ... */ })
// Replace with
const isRegistered = protocol.isProtocolRegistered(scheme)
const isIntercepted = protocol.isProtocolIntercepted(scheme)
```


Planned Breaking API Changes (9.0)[​](#planned-breaking-api-changes-90 "Direct link to heading")
------------------------------------------------------------------------------------------------


### Default Changed: Loading non-context-aware native modules in the renderer process is disabled by default[​](#default-changed-loading-non-context-aware-native-modules-in-the-renderer-process-is-disabled-by-default "Direct link to heading")


As of Electron 9 we do not allow loading of non-context-aware native modules in the renderer process. This is to improve security, performance and maintainability of Electron as a project.


If this impacts you, you can temporarily set `app.allowRendererProcessReuse` to `false` to revert to the old behavior. This flag will only be an option until Electron 11 so you should plan to update your native modules to be context aware.


For more detailed information see [#18397](https://github.com/electron/electron/issues/18397).


### Deprecated: `BrowserWindow` extension APIs[​](#deprecated-browserwindow-extension-apis "Direct link to heading")


The following extension APIs have been deprecated:


* `BrowserWindow.addExtension(path)`
* `BrowserWindow.addDevToolsExtension(path)`
* `BrowserWindow.removeExtension(name)`
* `BrowserWindow.removeDevToolsExtension(name)`
* `BrowserWindow.getExtensions()`
* `BrowserWindow.getDevToolsExtensions()`


Use the session APIs instead:


* `ses.loadExtension(path)`
* `ses.removeExtension(extension_id)`
* `ses.getAllExtensions()`




```
// Deprecated in Electron 9
BrowserWindow.addExtension(path)
BrowserWindow.addDevToolsExtension(path)
// Replace with
session.defaultSession.loadExtension(path)
```




```
// Deprecated in Electron 9
BrowserWindow.removeExtension(name)
BrowserWindow.removeDevToolsExtension(name)
// Replace with
session.defaultSession.removeExtension(extension_id)
```




```
// Deprecated in Electron 9
BrowserWindow.getExtensions()
BrowserWindow.getDevToolsExtensions()
// Replace with
session.defaultSession.getAllExtensions()
```


### Removed: `<webview>.getWebContents()`[​](#removed-webviewgetwebcontents "Direct link to heading")


This API, which was deprecated in Electron 8.0, is now removed.




```
// Removed in Electron 9.0
webview.getWebContents()
// Replace with
const { remote } = require('electron')
remote.webContents.fromId(webview.getWebContentsId())
```


### Removed: `webFrame.setLayoutZoomLevelLimits()`[​](#removed-webframesetlayoutzoomlevellimits "Direct link to heading")


Chromium has removed support for changing the layout zoom level limits, and it is beyond Electron's capacity to maintain it. The function was deprecated in Electron 8.x, and has been removed in Electron 9.x. The layout zoom level limits are now fixed at a minimum of 0.25 and a maximum of 5.0, as defined [here](https://chromium.googlesource.com/chromium/src/+/938b37a6d2886bf8335fc7db792f1eb46c65b2ae/third_party/blink/common/page/page_zoom.cc#11).


### Behavior Changed: Sending non-JS objects over IPC now throws an exception[​](#behavior-changed-sending-non-js-objects-over-ipc-now-throws-an-exception "Direct link to heading")


In Electron 8.0, IPC was changed to use the Structured Clone Algorithm, bringing significant performance improvements. To help ease the transition, the old IPC serialization algorithm was kept and used for some objects that aren't serializable with Structured Clone. In particular, DOM objects (e.g. `Element`, `Location` and `DOMMatrix`), Node.js objects backed by C++ classes (e.g. `process.env`, some members of `Stream`), and Electron objects backed by C++ classes (e.g. `WebContents`, `BrowserWindow` and `WebFrame`) are not serializable with Structured Clone. Whenever the old algorithm was invoked, a deprecation warning was printed.


In Electron 9.0, the old serialization algorithm has been removed, and sending such non-serializable objects will now throw an "object could not be cloned" error.


### API Changed: `shell.openItem` is now `shell.openPath`[​](#api-changed-shellopenitem-is-now-shellopenpath "Direct link to heading")


The `shell.openItem` API has been replaced with an asynchronous `shell.openPath` API. You can see the original API proposal and reasoning [here](https://github.com/electron/governance/blob/main/wg-api/spec-documents/shell-openitem.md).


Planned Breaking API Changes (8.0)[​](#planned-breaking-api-changes-80 "Direct link to heading")
------------------------------------------------------------------------------------------------


### Behavior Changed: Values sent over IPC are now serialized with Structured Clone Algorithm[​](#behavior-changed-values-sent-over-ipc-are-now-serialized-with-structured-clone-algorithm "Direct link to heading")


The algorithm used to serialize objects sent over IPC (through `ipcRenderer.send`, `ipcRenderer.sendSync`, `WebContents.send` and related methods) has been switched from a custom algorithm to V8's built-in [Structured Clone Algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm), the same algorithm used to serialize messages for `postMessage`. This brings about a 2x performance improvement for large messages, but also brings some breaking changes in behavior.


* Sending Functions, Promises, WeakMaps, WeakSets, or objects containing any such values, over IPC will now throw an exception, instead of silently converting the functions to `undefined`.




```
// Previously:
ipcRenderer.send('channel', { value: 3, someFunction: () => {} })
// => results in { value: 3 } arriving in the main process

// From Electron 8:
ipcRenderer.send('channel', { value: 3, someFunction: () => {} })
// => throws Error("() => {} could not be cloned.")
```


* `NaN`, `Infinity` and `-Infinity` will now be correctly serialized, instead of being converted to `null`.
* Objects containing cyclic references will now be correctly serialized, instead of being converted to `null`.
* `Set`, `Map`, `Error` and `RegExp` values will be correctly serialized, instead of being converted to `{}`.
* `BigInt` values will be correctly serialized, instead of being converted to `null`.
* Sparse arrays will be serialized as such, instead of being converted to dense arrays with `null`s.
* `Date` objects will be transferred as `Date` objects, instead of being converted to their ISO string representation.
* Typed Arrays (such as `Uint8Array`, `Uint16Array`, `Uint32Array` and so on) will be transferred as such, instead of being converted to Node.js `Buffer`.
* Node.js `Buffer` objects will be transferred as `Uint8Array`s. You can convert a `Uint8Array` back to a Node.js `Buffer` by wrapping the underlying `ArrayBuffer`:




```
Buffer.from(value.buffer, value.byteOffset, value.byteLength)
```


Sending any objects that aren't native JS types, such as DOM objects (e.g. `Element`, `Location`, `DOMMatrix`), Node.js objects (e.g. `process.env`, `Stream`), or Electron objects (e.g. `WebContents`, `BrowserWindow`, `WebFrame`) is deprecated. In Electron 8, these objects will be serialized as before with a DeprecationWarning message, but starting in Electron 9, sending these kinds of objects will throw a 'could not be cloned' error.


### Deprecated: `<webview>.getWebContents()`[​](#deprecated-webviewgetwebcontents "Direct link to heading")


This API is implemented using the `remote` module, which has both performance and security implications. Therefore its usage should be explicit.




```
// Deprecated
webview.getWebContents()
// Replace with
const { remote } = require('electron')
remote.webContents.fromId(webview.getWebContentsId())
```


However, it is recommended to avoid using the `remote` module altogether.




```
// main
const { ipcMain, webContents } = require('electron')

const getGuestForWebContents = (webContentsId, contents) => {
  const guest = webContents.fromId(webContentsId)
  if (!guest) {
    throw new Error(`Invalid webContentsId: ${webContentsId}`)
  }
  if (guest.hostWebContents !== contents) {
    throw new Error('Access denied to webContents')
  }
  return guest
}

ipcMain.handle('openDevTools', (event, webContentsId) => {
  const guest = getGuestForWebContents(webContentsId, event.sender)
  guest.openDevTools()
})

// renderer
const { ipcRenderer } = require('electron')

ipcRenderer.invoke('openDevTools', webview.getWebContentsId())
```


### Deprecated: `webFrame.setLayoutZoomLevelLimits()`[​](#deprecated-webframesetlayoutzoomlevellimits "Direct link to heading")


Chromium has removed support for changing the layout zoom level limits, and it is beyond Electron's capacity to maintain it. The function will emit a warning in Electron 8.x, and cease to exist in Electron 9.x. The layout zoom level limits are now fixed at a minimum of 0.25 and a maximum of 5.0, as defined [here](https://chromium.googlesource.com/chromium/src/+/938b37a6d2886bf8335fc7db792f1eb46c65b2ae/third_party/blink/common/page/page_zoom.cc#11).


### Deprecated events in `systemPreferences`[​](#deprecated-events-in-systempreferences "Direct link to heading")


The following `systemPreferences` events have been deprecated:


* `inverted-color-scheme-changed`
* `high-contrast-color-scheme-changed`


Use the new `updated` event on the `nativeTheme` module instead.




```
// Deprecated
systemPreferences.on('inverted-color-scheme-changed', () => { /* ... */ })
systemPreferences.on('high-contrast-color-scheme-changed', () => { /* ... */ })

// Replace with
nativeTheme.on('updated', () => { /* ... */ })
```


### Deprecated: methods in `systemPreferences`[​](#deprecated-methods-in-systempreferences "Direct link to heading")


The following `systemPreferences` methods have been deprecated:


* `systemPreferences.isDarkMode()`
* `systemPreferences.isInvertedColorScheme()`
* `systemPreferences.isHighContrastColorScheme()`


Use the following `nativeTheme` properties instead:


* `nativeTheme.shouldUseDarkColors`
* `nativeTheme.shouldUseInvertedColorScheme`
* `nativeTheme.shouldUseHighContrastColors`




```
// Deprecated
systemPreferences.isDarkMode()
// Replace with
nativeTheme.shouldUseDarkColors

// Deprecated
systemPreferences.isInvertedColorScheme()
// Replace with
nativeTheme.shouldUseInvertedColorScheme

// Deprecated
systemPreferences.isHighContrastColorScheme()
// Replace with
nativeTheme.shouldUseHighContrastColors
```


Planned Breaking API Changes (7.0)[​](#planned-breaking-api-changes-70 "Direct link to heading")
------------------------------------------------------------------------------------------------


### Deprecated: Atom.io Node Headers URL[​](#deprecated-atomio-node-headers-url "Direct link to heading")


This is the URL specified as `disturl` in a `.npmrc` file or as the `--dist-url` command line flag when building native Node modules. Both will be supported for the foreseeable future but it is recommended that you switch.


Deprecated: <https://atom.io/download/electron>


Replace with: <https://electronjs.org/headers>


### API Changed: `session.clearAuthCache()` no longer accepts options[​](#api-changed-sessionclearauthcache-no-longer-accepts-options "Direct link to heading")


The `session.clearAuthCache` API no longer accepts options for what to clear, and instead unconditionally clears the whole cache.




```
// Deprecated
session.clearAuthCache({ type: 'password' })
// Replace with
session.clearAuthCache()
```


### API Changed: `powerMonitor.querySystemIdleState` is now `powerMonitor.getSystemIdleState`[​](#api-changed-powermonitorquerysystemidlestate-is-now-powermonitorgetsystemidlestate "Direct link to heading")




```
// Removed in Electron 7.0
powerMonitor.querySystemIdleState(threshold, callback)
// Replace with synchronous API
const idleState = powerMonitor.getSystemIdleState(threshold)
```


### API Changed: `powerMonitor.querySystemIdleTime` is now `powerMonitor.getSystemIdleTime`[​](#api-changed-powermonitorquerysystemidletime-is-now-powermonitorgetsystemidletime "Direct link to heading")




```
// Removed in Electron 7.0
powerMonitor.querySystemIdleTime(callback)
// Replace with synchronous API
const idleTime = powerMonitor.getSystemIdleTime()
```


### API Changed: `webFrame.setIsolatedWorldInfo` replaces separate methods[​](#api-changed-webframesetisolatedworldinfo-replaces-separate-methods "Direct link to heading")




```
// Removed in Electron 7.0
webFrame.setIsolatedWorldContentSecurityPolicy(worldId, csp)
webFrame.setIsolatedWorldHumanReadableName(worldId, name)
webFrame.setIsolatedWorldSecurityOrigin(worldId, securityOrigin)
// Replace with
webFrame.setIsolatedWorldInfo(
  worldId,
  {
    securityOrigin: 'some_origin',
    name: 'human_readable_name',
    csp: 'content_security_policy'
  })
```


### Removed: `marked` property on `getBlinkMemoryInfo`[​](#removed-marked-property-on-getblinkmemoryinfo "Direct link to heading")


This property was removed in Chromium 77, and as such is no longer available.


### Behavior Changed: `webkitdirectory` attribute for `<input type="file"/>` now lists directory contents[​](#behavior-changed-webkitdirectory-attribute-for-input-typefile-now-lists-directory-contents "Direct link to heading")


The `webkitdirectory` property on HTML file inputs allows them to select folders. Previous versions of Electron had an incorrect implementation where the `event.target.files` of the input returned a `FileList` that returned one `File` corresponding to the selected folder.


As of Electron 7, that `FileList` is now list of all files contained within the folder, similarly to Chrome, Firefox, and Edge ([link to MDN docs](https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/webkitdirectory)).


As an illustration, take a folder with this structure:




```
folder
├── file1
├── file2
└── file3
```


In Electron <=6, this would return a `FileList` with a `File` object for:




```
path/to/folder
```


In Electron 7, this now returns a `FileList` with a `File` object for:




```
/path/to/folder/file3
/path/to/folder/file2
/path/to/folder/file1
```


Note that `webkitdirectory` no longer exposes the path to the selected folder. If you require the path to the selected folder rather than the folder contents, see the `dialog.showOpenDialog` API ([link](api/dialog#dialogshowopendialogbrowserwindow-options)).


### API Changed: Callback-based versions of promisified APIs[​](#api-changed-callback-based-versions-of-promisified-apis "Direct link to heading")


Electron 5 and Electron 6 introduced Promise-based versions of existing asynchronous APIs and deprecated their older, callback-based counterparts. In Electron 7, all deprecated callback-based APIs are now removed.


These functions now only return Promises:


* `app.getFileIcon()` [#15742](https://github.com/electron/electron/pull/15742)
* `app.dock.show()` [#16904](https://github.com/electron/electron/pull/16904)
* `contentTracing.getCategories()` [#16583](https://github.com/electron/electron/pull/16583)
* `contentTracing.getTraceBufferUsage()` [#16600](https://github.com/electron/electron/pull/16600)
* `contentTracing.startRecording()` [#16584](https://github.com/electron/electron/pull/16584)
* `contentTracing.stopRecording()` [#16584](https://github.com/electron/electron/pull/16584)
* `contents.executeJavaScript()` [#17312](https://github.com/electron/electron/pull/17312)
* `cookies.flushStore()` [#16464](https://github.com/electron/electron/pull/16464)
* `cookies.get()` [#16464](https://github.com/electron/electron/pull/16464)
* `cookies.remove()` [#16464](https://github.com/electron/electron/pull/16464)
* `cookies.set()` [#16464](https://github.com/electron/electron/pull/16464)
* `debugger.sendCommand()` [#16861](https://github.com/electron/electron/pull/16861)
* `dialog.showCertificateTrustDialog()` [#17181](https://github.com/electron/electron/pull/17181)
* `inAppPurchase.getProducts()` [#17355](https://github.com/electron/electron/pull/17355)
* `inAppPurchase.purchaseProduct()`[#17355](https://github.com/electron/electron/pull/17355)
* `netLog.stopLogging()` [#16862](https://github.com/electron/electron/pull/16862)
* `session.clearAuthCache()` [#17259](https://github.com/electron/electron/pull/17259)
* `session.clearCache()` [#17185](https://github.com/electron/electron/pull/17185)
* `session.clearHostResolverCache()` [#17229](https://github.com/electron/electron/pull/17229)
* `session.clearStorageData()` [#17249](https://github.com/electron/electron/pull/17249)
* `session.getBlobData()` [#17303](https://github.com/electron/electron/pull/17303)
* `session.getCacheSize()` [#17185](https://github.com/electron/electron/pull/17185)
* `session.resolveProxy()` [#17222](https://github.com/electron/electron/pull/17222)
* `session.setProxy()` [#17222](https://github.com/electron/electron/pull/17222)
* `shell.openExternal()` [#16176](https://github.com/electron/electron/pull/16176)
* `webContents.loadFile()` [#15855](https://github.com/electron/electron/pull/15855)
* `webContents.loadURL()` [#15855](https://github.com/electron/electron/pull/15855)
* `webContents.hasServiceWorker()` [#16535](https://github.com/electron/electron/pull/16535)
* `webContents.printToPDF()` [#16795](https://github.com/electron/electron/pull/16795)
* `webContents.savePage()` [#16742](https://github.com/electron/electron/pull/16742)
* `webFrame.executeJavaScript()` [#17312](https://github.com/electron/electron/pull/17312)
* `webFrame.executeJavaScriptInIsolatedWorld()` [#17312](https://github.com/electron/electron/pull/17312)
* `webviewTag.executeJavaScript()` [#17312](https://github.com/electron/electron/pull/17312)
* `win.capturePage()` [#15743](https://github.com/electron/electron/pull/15743)


These functions now have two forms, synchronous and Promise-based asynchronous:


* `dialog.showMessageBox()`/`dialog.showMessageBoxSync()` [#17298](https://github.com/electron/electron/pull/17298)
* `dialog.showOpenDialog()`/`dialog.showOpenDialogSync()` [#16973](https://github.com/electron/electron/pull/16973)
* `dialog.showSaveDialog()`/`dialog.showSaveDialogSync()` [#17054](https://github.com/electron/electron/pull/17054)


Planned Breaking API Changes (6.0)[​](#planned-breaking-api-changes-60 "Direct link to heading")
------------------------------------------------------------------------------------------------


### API Changed: `win.setMenu(null)` is now `win.removeMenu()`[​](#api-changed-winsetmenunull-is-now-winremovemenu "Direct link to heading")




```
// Deprecated
win.setMenu(null)
// Replace with
win.removeMenu()
```


### API Changed: `electron.screen` in the renderer process should be accessed via `remote`[​](#api-changed-electronscreen-in-the-renderer-process-should-be-accessed-via-remote "Direct link to heading")




```
// Deprecated
require('electron').screen
// Replace with
require('electron').remote.screen
```


### API Changed: `require()`ing node builtins in sandboxed renderers no longer implicitly loads the `remote` version[​](#api-changed-requireing-node-builtins-in-sandboxed-renderers-no-longer-implicitly-loads-the-remote-version "Direct link to heading")




```
// Deprecated
require('child_process')
// Replace with
require('electron').remote.require('child_process')

// Deprecated
require('fs')
// Replace with
require('electron').remote.require('fs')

// Deprecated
require('os')
// Replace with
require('electron').remote.require('os')

// Deprecated
require('path')
// Replace with
require('electron').remote.require('path')
```


### Deprecated: `powerMonitor.querySystemIdleState` replaced with `powerMonitor.getSystemIdleState`[​](#deprecated-powermonitorquerysystemidlestate-replaced-with-powermonitorgetsystemidlestate "Direct link to heading")




```
// Deprecated
powerMonitor.querySystemIdleState(threshold, callback)
// Replace with synchronous API
const idleState = powerMonitor.getSystemIdleState(threshold)
```


### Deprecated: `powerMonitor.querySystemIdleTime` replaced with `powerMonitor.getSystemIdleTime`[​](#deprecated-powermonitorquerysystemidletime-replaced-with-powermonitorgetsystemidletime "Direct link to heading")




```
// Deprecated
powerMonitor.querySystemIdleTime(callback)
// Replace with synchronous API
const idleTime = powerMonitor.getSystemIdleTime()
```


### Deprecated: `app.enableMixedSandbox()` is no longer needed[​](#deprecated-appenablemixedsandbox-is-no-longer-needed "Direct link to heading")




```
// Deprecated
app.enableMixedSandbox()
```


Mixed-sandbox mode is now enabled by default.


### Deprecated: `Tray.setHighlightMode`[​](#deprecated-traysethighlightmode "Direct link to heading")


Under macOS Catalina our former Tray implementation breaks. Apple's native substitute doesn't support changing the highlighting behavior.




```
// Deprecated
tray.setHighlightMode(mode)
// API will be removed in v7.0 without replacement.
```


Planned Breaking API Changes (5.0)[​](#planned-breaking-api-changes-50 "Direct link to heading")
------------------------------------------------------------------------------------------------


### Default Changed: `nodeIntegration` and `webviewTag` default to false, `contextIsolation` defaults to true[​](#default-changed-nodeintegration-and-webviewtag-default-to-false-contextisolation-defaults-to-true "Direct link to heading")


The following `webPreferences` option default values are deprecated in favor of the new defaults listed below.




| Property | Deprecated Default | New Default |
| --- | --- | --- |
| `contextIsolation` | `false` | `true` |
| `nodeIntegration` | `true` | `false` |
| `webviewTag` | `nodeIntegration` if set else `true` | `false` |


E.g. Re-enabling the webviewTag




```
const w = new BrowserWindow({
  webPreferences: {
    webviewTag: true
  }
})
```


### Behavior Changed: `nodeIntegration` in child windows opened via `nativeWindowOpen`[​](#behavior-changed-nodeintegration-in-child-windows-opened-via-nativewindowopen "Direct link to heading")


Child windows opened with the `nativeWindowOpen` option will always have Node.js integration disabled, unless `nodeIntegrationInSubFrames` is `true`.


### API Changed: Registering privileged schemes must now be done before app ready[​](#api-changed-registering-privileged-schemes-must-now-be-done-before-app-ready "Direct link to heading")


Renderer process APIs `webFrame.registerURLSchemeAsPrivileged` and `webFrame.registerURLSchemeAsBypassingCSP` as well as browser process API `protocol.registerStandardSchemes` have been removed. A new API, `protocol.registerSchemesAsPrivileged` has been added and should be used for registering custom schemes with the required privileges. Custom schemes are required to be registered before app ready.


### Deprecated: `webFrame.setIsolatedWorld*` replaced with `webFrame.setIsolatedWorldInfo`[​](#deprecated-webframesetisolatedworld-replaced-with-webframesetisolatedworldinfo "Direct link to heading")




```
// Deprecated
webFrame.setIsolatedWorldContentSecurityPolicy(worldId, csp)
webFrame.setIsolatedWorldHumanReadableName(worldId, name)
webFrame.setIsolatedWorldSecurityOrigin(worldId, securityOrigin)
// Replace with
webFrame.setIsolatedWorldInfo(
  worldId,
  {
    securityOrigin: 'some_origin',
    name: 'human_readable_name',
    csp: 'content_security_policy'
  })
```


### API Changed: `webFrame.setSpellCheckProvider` now takes an asynchronous callback[​](#api-changed-webframesetspellcheckprovider-now-takes-an-asynchronous-callback "Direct link to heading")


The `spellCheck` callback is now asynchronous, and `autoCorrectWord` parameter has been removed.




```
// Deprecated
webFrame.setSpellCheckProvider('en-US', true, {
  spellCheck: (text) => {
    return !spellchecker.isMisspelled(text)
  }
})
// Replace with
webFrame.setSpellCheckProvider('en-US', {
  spellCheck: (words, callback) => {
    callback(words.filter(text => spellchecker.isMisspelled(text)))
  }
})
```


### API Changed: `webContents.getZoomLevel` and `webContents.getZoomFactor` are now synchronous[​](#api-changed-webcontentsgetzoomlevel-and-webcontentsgetzoomfactor-are-now-synchronous "Direct link to heading")


`webContents.getZoomLevel` and `webContents.getZoomFactor` no longer take callback parameters, instead directly returning their number values.




```
// Deprecated
webContents.getZoomLevel((level) => {
  console.log(level)
})
// Replace with
const level = webContents.getZoomLevel()
console.log(level)
```




```
// Deprecated
webContents.getZoomFactor((factor) => {
  console.log(factor)
})
// Replace with
const factor = webContents.getZoomFactor()
console.log(factor)
```


Planned Breaking API Changes (4.0)[​](#planned-breaking-api-changes-40 "Direct link to heading")
------------------------------------------------------------------------------------------------


The following list includes the breaking API changes made in Electron 4.0.


### 
`app.makeSingleInstance`[​](#appmakesingleinstance "Direct link to heading")




```
// Deprecated
app.makeSingleInstance((argv, cwd) => {
  /* ... */
})
// Replace with
app.requestSingleInstanceLock()
app.on('second-instance', (event, argv, cwd) => {
  /* ... */
})
```


### 
`app.releaseSingleInstance`[​](#appreleasesingleinstance "Direct link to heading")




```
// Deprecated
app.releaseSingleInstance()
// Replace with
app.releaseSingleInstanceLock()
```


### 
`app.getGPUInfo`[​](#appgetgpuinfo "Direct link to heading")




```
app.getGPUInfo('complete')
// Now behaves the same with `basic` on macOS
app.getGPUInfo('basic')
```


### 
`win_delay_load_hook`[​](#win_delay_load_hook "Direct link to heading")


When building native modules for windows, the `win_delay_load_hook` variable in the module's `binding.gyp` must be true (which is the default). If this hook is not present, then the native module will fail to load on Windows, with an error message like `Cannot find module`. See the [native module guide](tutorial/using-native-node-modules) for more.


### Removed: IA32 Linux support[​](#removed-ia32-linux-support "Direct link to heading")


Electron 18 will no longer run on 32-bit Linux systems. See [discontinuing support for 32-bit Linux](https://www.electronjs.org/blog/linux-32bit-support) for more information.


Breaking API Changes (3.0)[​](#breaking-api-changes-30 "Direct link to heading")
--------------------------------------------------------------------------------


The following list includes the breaking API changes in Electron 3.0.


### 
`app`[​](#app "Direct link to heading")




```
// Deprecated
app.getAppMemoryInfo()
// Replace with
app.getAppMetrics()

// Deprecated
const metrics = app.getAppMetrics()
const { memory } = metrics[0] // Deprecated property
```


### 
`BrowserWindow`[​](#browserwindow "Direct link to heading")




```
// Deprecated
const optionsA = { webPreferences: { blinkFeatures: '' } }
const windowA = new BrowserWindow(optionsA)
// Replace with
const optionsB = { webPreferences: { enableBlinkFeatures: '' } }
const windowB = new BrowserWindow(optionsB)

// Deprecated
window.on('app-command', (e, cmd) => {
  if (cmd === 'media-play_pause') {
    // do something
  }
})
// Replace with
window.on('app-command', (e, cmd) => {
  if (cmd === 'media-play-pause') {
    // do something
  }
})
```


### 
`clipboard`[​](#clipboard "Direct link to heading")




```
// Deprecated
clipboard.readRtf()
// Replace with
clipboard.readRTF()

// Deprecated
clipboard.writeRtf()
// Replace with
clipboard.writeRTF()

// Deprecated
clipboard.readHtml()
// Replace with
clipboard.readHTML()

// Deprecated
clipboard.writeHtml()
// Replace with
clipboard.writeHTML()
```


### 
`crashReporter`[​](#crashreporter "Direct link to heading")




```
// Deprecated
crashReporter.start({
  companyName: 'Crashly',
  submitURL: 'https://crash.server.com',
  autoSubmit: true
})
// Replace with
crashReporter.start({
  companyName: 'Crashly',
  submitURL: 'https://crash.server.com',
  uploadToServer: true
})
```


### 
`nativeImage`[​](#nativeimage "Direct link to heading")




```
// Deprecated
nativeImage.createFromBuffer(buffer, 1.0)
// Replace with
nativeImage.createFromBuffer(buffer, {
  scaleFactor: 1.0
})
```


### 
`process`[​](#process "Direct link to heading")




```
// Deprecated
const info = process.getProcessMemoryInfo()
```


### 
`screen`[​](#screen "Direct link to heading")




```
// Deprecated
screen.getMenuBarHeight()
// Replace with
screen.getPrimaryDisplay().workArea
```


### 
`session`[​](#session "Direct link to heading")




```
// Deprecated
ses.setCertificateVerifyProc((hostname, certificate, callback) => {
  callback(true)
})
// Replace with
ses.setCertificateVerifyProc((request, callback) => {
  callback(0)
})
```


### 
`Tray`[​](#tray "Direct link to heading")




```
// Deprecated
tray.setHighlightMode(true)
// Replace with
tray.setHighlightMode('on')

// Deprecated
tray.setHighlightMode(false)
// Replace with
tray.setHighlightMode('off')
```


### 
`webContents`[​](#webcontents "Direct link to heading")




```
// Deprecated
webContents.openDevTools({ detach: true })
// Replace with
webContents.openDevTools({ mode: 'detach' })

// Removed
webContents.setSize(options)
// There is no replacement for this API
```


### 
`webFrame`[​](#webframe "Direct link to heading")




```
// Deprecated
webFrame.registerURLSchemeAsSecure('app')
// Replace with
protocol.registerStandardSchemes(['app'], { secure: true })

// Deprecated
webFrame.registerURLSchemeAsPrivileged('app', { secure: true })
// Replace with
protocol.registerStandardSchemes(['app'], { secure: true })
```


### 
`<webview>`[​](#webview "Direct link to heading")




```
// Removed
webview.setAttribute('disableguestresize', '')
// There is no replacement for this API

// Removed
webview.setAttribute('guestinstance', instanceId)
// There is no replacement for this API

// Keyboard listeners no longer work on webview tag
webview.onkeydown = () => { /* handler */ }
webview.onkeyup = () => { /* handler */ }
```


### Node Headers URL[​](#node-headers-url "Direct link to heading")


This is the URL specified as `disturl` in a `.npmrc` file or as the `--dist-url` command line flag when building native Node modules.


Deprecated: <https://atom.io/download/atom-shell>


Replace with: <https://atom.io/download/electron>


Breaking API Changes (2.0)[​](#breaking-api-changes-20 "Direct link to heading")
--------------------------------------------------------------------------------


The following list includes the breaking API changes made in Electron 2.0.


### 
`BrowserWindow`[​](#browserwindow-1 "Direct link to heading")




```
// Deprecated
const optionsA = { titleBarStyle: 'hidden-inset' }
const windowA = new BrowserWindow(optionsA)
// Replace with
const optionsB = { titleBarStyle: 'hiddenInset' }
const windowB = new BrowserWindow(optionsB)
```


### 
`menu`[​](#menu "Direct link to heading")




```
// Removed
menu.popup(browserWindow, 100, 200, 2)
// Replaced with
menu.popup(browserWindow, { x: 100, y: 200, positioningItem: 2 })
```


### 
`nativeImage`[​](#nativeimage-1 "Direct link to heading")




```
// Removed
nativeImage.toPng()
// Replaced with
nativeImage.toPNG()

// Removed
nativeImage.toJpeg()
// Replaced with
nativeImage.toJPEG()
```


### 
`process`[​](#process-1 "Direct link to heading")


* `process.versions.electron` and `process.version.chrome` will be made read-only properties for consistency with the other `process.versions` properties set by Node.


### 
`webContents`[​](#webcontents-1 "Direct link to heading")




```
// Removed
webContents.setZoomLevelLimits(1, 2)
// Replaced with
webContents.setVisualZoomLevelLimits(1, 2)
```


### 
`webFrame`[​](#webframe-1 "Direct link to heading")




```
// Removed
webFrame.setZoomLevelLimits(1, 2)
// Replaced with
webFrame.setVisualZoomLevelLimits(1, 2)
```


### 
`<webview>`[​](#webview-1 "Direct link to heading")




```
// Removed
webview.setZoomLevelLimits(1, 2)
// Replaced with
webview.setVisualZoomLevelLimits(1, 2)
```


### Duplicate ARM Assets[​](#duplicate-arm-assets "Direct link to heading")


Each Electron release includes two identical ARM builds with slightly different filenames, like `electron-v1.7.3-linux-arm.zip` and `electron-v1.7.3-linux-armv7l.zip`. The asset with the `v7l` prefix was added to clarify to users which ARM version it supports, and to disambiguate it from future armv6l and arm64 assets that may be produced.


The file *without the prefix* is still being published to avoid breaking any setups that may be consuming it. Starting at 2.0, the unprefixed file will no longer be published.


For details, see [6986](https://github.com/electron/electron/pull/6986) and [7189](https://github.com/electron/electron/pull/7189).



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/breaking-changes>

Inter-Process Communication
===========================


Inter-process communication (IPC) is a key part of building feature-rich desktop applications in Electron. Because the main and renderer processes have different responsibilities in Electron's process model, IPC is the only way to perform many common tasks, such as calling a native API from your UI or triggering changes in your web contents from native menus.


IPC channels[​](#ipc-channels "Direct link to heading")
-------------------------------------------------------


In Electron, processes communicate by passing messages through developer-defined "channels" with the [`ipcMain`](../api/ipc-main) and [`ipcRenderer`](../api/ipc-renderer) modules. These channels are **arbitrary** (you can name them anything you want) and **bidirectional** (you can use the same channel name for both modules).


In this guide, we'll be going over some fundamental IPC patterns with concrete examples that you can use as a reference for your app code.


Understanding context-isolated processes[​](#understanding-context-isolated-processes "Direct link to heading")
---------------------------------------------------------------------------------------------------------------


Before proceeding to implementation details, you should be familiar with the idea of using a [preload script](process-model#preload-scripts) to import Node.js and Electron modules in a context-isolated renderer process.


* For a full overview of Electron's process model, you can read the [process model docs](process-model).
* For a primer into exposing APIs from your preload script using the `contextBridge` module, check out the [context isolation tutorial](context-isolation).


Pattern 1: Renderer to main (one-way)[​](#pattern-1-renderer-to-main-one-way "Direct link to heading")
------------------------------------------------------------------------------------------------------


To fire a one-way IPC message from a renderer process to the main process, you can use the [`ipcRenderer.send`](../api/ipc-renderer) API to send a message that is then received by the [`ipcMain.on`](../api/ipc-main) API.


You usually use this pattern to call a main process API from your web contents. We'll demonstrate this pattern by creating a simple app that can programmatically change its window title.


For this demo, you'll need to add code to your main process, your renderer process, and a preload script. The full code is below, but we'll be explaining each file individually in the following sections.




[docs/fiddles/ipc/pattern-1 (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/ipc/pattern-1)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/ipc/pattern-1)


* main.js
* preload.js
* index.html
* renderer.js





```
const {app, BrowserWindow, ipcMain} = require('electron')
const path = require('path')

function createWindow () {
  const mainWindow = new BrowserWindow({
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  ipcMain.on('set-title', (event, title) => {
    const webContents = event.sender
    const win = BrowserWindow.fromWebContents(webContents)
    win.setTitle(title)
  })

  mainWindow.loadFile('index.html')
}

app.whenReady().then(() => {
  createWindow()
  
  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})
```




```
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
    setTitle: (title) => ipcRenderer.send('set-title', title)
})
```




```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Hello World!</title>
  </head>
  <body>
    Title: <input id="title"/>
    <button id="btn" type="button">Set</button>
    <script src="./renderer.js"></script>
  </body>
</html>
```




```
const setButton = document.getElementById('btn')
const titleInput = document.getElementById('title')
setButton.addEventListener('click', () => {
    const title = titleInput.value
    window.electronAPI.setTitle(title)
});
```





### 1. Listen for events with `ipcMain.on`[​](#1-listen-for-events-with-ipcmainon "Direct link to heading")


In the main process, set an IPC listener on the `set-title` channel with the `ipcMain.on` API:



main.js (Main Process)


```
const {app, BrowserWindow, ipcMain} = require('electron')
const path = require('path')

//...

function handleSetTitle (event, title) {
  const webContents = event.sender
  const win = BrowserWindow.fromWebContents(webContents)
  win.setTitle(title)
}

function createWindow () {
  const mainWindow = new BrowserWindow({
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })
  mainWindow.loadFile('index.html')
}

app.whenReady().then(() => {
  ipcMain.on('set-title', handleSetTitle)
  createWindow()
}
//...
```



The above `handleSetTitle` callback has two parameters: an [IpcMainEvent](../api/structures/ipc-main-event) structure and a `title` string. Whenever a message comes through the `set-title` channel, this function will find the BrowserWindow instance attached to the message sender and use the `win.setTitle` API on it.




info
Make sure you're loading the `index.html` and `preload.js` entry points for the following steps!



### 2. Expose `ipcRenderer.send` via preload[​](#2-expose-ipcrenderersend-via-preload "Direct link to heading")


To send messages to the listener created above, you can use the `ipcRenderer.send` API. By default, the renderer process has no Node.js or Electron module access. As an app developer, you need to choose which APIs to expose from your preload script using the `contextBridge` API.


In your preload script, add the following code, which will expose a global `window.electronAPI` variable to your renderer process.



preload.js (Preload Script)


```
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
    setTitle: (title) => ipcRenderer.send('set-title', title)
})
```



At this point, you'll be able to use the `window.electronAPI.setTitle()` function in the renderer process.




Security warning
We don't directly expose the whole `ipcRenderer.send` API for [security reasons](context-isolation#security-considerations). Make sure to limit the renderer's access to Electron APIs as much as possible.



### 3. Build the renderer process UI[​](#3-build-the-renderer-process-ui "Direct link to heading")


In our BrowserWindow's loaded HTML file, add a basic user interface consisting of a text input and a button:



index.html


```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Hello World!</title>
  </head>
  <body>
    Title: <input id="title"/>
    <button id="btn" type="button">Set</button>
    <script src="./renderer.js"></script>
  </body>
</html>
```



To make these elements interactive, we'll be adding a few lines of code in the imported `renderer.js` file that leverages the `window.electronAPI` functionality exposed from the preload script:



renderer.js (Renderer Process)


```
const setButton = document.getElementById('btn')
const titleInput = document.getElementById('title')
setButton.addEventListener('click', () => {
    const title = titleInput.value
    window.electronAPI.setTitle(title)
});
```



At this point, your demo should be fully functional. Try using the input field and see what happens to your BrowserWindow title!


Pattern 2: Renderer to main (two-way)[​](#pattern-2-renderer-to-main-two-way "Direct link to heading")
------------------------------------------------------------------------------------------------------


A common application for two-way IPC is calling a main process module from your renderer process code and waiting for a result. This can be done by using [`ipcRenderer.invoke`](../api/ipc-renderer#ipcrendererinvokechannel-args) paired with [`ipcMain.handle`](../api/ipc-main#ipcmainhandlechannel-listener).


In the following example, we'll be opening a native file dialog from the renderer process and returning the selected file's path.


For this demo, you'll need to add code to your main process, your renderer process, and a preload script. The full code is below, but we'll be explaining each file individually in the following sections.




[docs/fiddles/ipc/pattern-2 (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/ipc/pattern-2)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/ipc/pattern-2)


* main.js
* preload.js
* index.html
* renderer.js





```
const {app, BrowserWindow, ipcMain, dialog} = require('electron')
const path = require('path')

async function handleFileOpen() {
  const { canceled, filePaths } = await dialog.showOpenDialog()
  if (canceled) {
    return
  } else {
    return filePaths[0]
  }
}

function createWindow () {
  const mainWindow = new BrowserWindow({
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })
  mainWindow.loadFile('index.html')
}

app.whenReady().then(() => {
  ipcMain.handle('dialog:openFile', handleFileOpen)
  createWindow()
  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})
```




```
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI',{
  openFile: () => ipcRenderer.invoke('dialog:openFile')
})
```




```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Dialog</title>
  </head>
  <body>
    <button type="button" id="btn">Open a File</button>
    File path: <strong id="filePath"></strong>
    <script src='./renderer.js'></script>
  </body>
</html>
```




```
const btn = document.getElementById('btn')
const filePathElement = document.getElementById('filePath')

btn.addEventListener('click', async () => {
  const filePath = await window.electronAPI.openFile()
  filePathElement.innerText = filePath
})
```





### 1. Listen for events with `ipcMain.handle`[​](#1-listen-for-events-with-ipcmainhandle "Direct link to heading")


In the main process, we'll be creating a `handleFileOpen()` function that calls `dialog.showOpenDialog` and returns the value of the file path selected by the user. This function is used as a callback whenever an `ipcRender.invoke` message is sent through the `dialog:openFile` channel from the renderer process. The return value is then returned as a Promise to the original `invoke` call.




A word on error handling
Errors thrown through `handle` in the main process are not transparent as they are serialized and only the `message` property from the original error is provided to the renderer process. Please refer to [#24427](https://github.com/electron/electron/issues/24427) for details.




main.js (Main Process)


```
const { BrowserWindow, dialog, ipcMain } = require('electron')
const path = require('path')

//...

async function handleFileOpen() {
  const { canceled, filePaths } = await dialog.showOpenDialog()
  if (canceled) {
    return
  } else {
    return filePaths[0]
  }
}

function createWindow () {
  const mainWindow = new BrowserWindow({
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })
  mainWindow.loadFile('index.html')
}

app.whenReady(() => {
  ipcMain.handle('dialog:openFile', handleFileOpen)
  createWindow()
})
//...
```





on channel names
The `dialog:` prefix on the IPC channel name has no effect on the code. It only serves as a namespace that helps with code readability.





info
Make sure you're loading the `index.html` and `preload.js` entry points for the following steps!



### 2. Expose `ipcRenderer.invoke` via preload[​](#2-expose-ipcrendererinvoke-via-preload "Direct link to heading")


In the preload script, we expose a one-line `openFile` function that calls and returns the value of `ipcRenderer.invoke('dialog:openFile')`. We'll be using this API in the next step to call the native dialog from our renderer's user interface.



preload.js (Preload Script)


```
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
  openFile: () => ipcRenderer.invoke('dialog:openFile')
})
```





Security warning
We don't directly expose the whole `ipcRenderer.invoke` API for [security reasons](context-isolation#security-considerations). Make sure to limit the renderer's access to Electron APIs as much as possible.



### 3. Build the renderer process UI[​](#3-build-the-renderer-process-ui-1 "Direct link to heading")


Finally, let's build the HTML file that we load into our BrowserWindow.



index.html


```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Dialog</title>
  </head>
  <body>
    <button type="button" id="btn">Open a File</button>
    File path: <strong id="filePath"></strong>
    <script src='./renderer.js'></script>
  </body>
</html>
```



The UI consists of a single `#btn` button element that will be used to trigger our preload API, and a `#filePath` element that will be used to display the path of the selected file. Making these pieces work will take a few lines of code in the renderer process script:



renderer.js (Renderer Process)


```
const btn = document.getElementById('btn')
const filePathElement = document.getElementById('filePath')

btn.addEventListener('click', async () => {
  const filePath = await window.electronAPI.openFile()
  filePathElement.innerText = filePath
})
```



In the above snippet, we listen for clicks on the `#btn` button, and call our `window.electronAPI.openFile()` API to activate the native Open File dialog. We then display the selected file path in the `#filePath` element.


### Note: legacy approaches[​](#note-legacy-approaches "Direct link to heading")


The `ipcRenderer.invoke` API was added in Electron 7 as a developer-friendly way to tackle two-way IPC from the renderer process. However, there exist a couple alternative approaches to this IPC pattern.




Avoid legacy approaches if possible
We recommend using `ipcRenderer.invoke` whenever possible. The following two-way renderer-to-main patterns are documented for historical purposes.





info
For the following examples, we're calling `ipcRenderer` directly from the preload script to keep the code samples small.



#### Using `ipcRenderer.send`[​](#using-ipcrenderersend "Direct link to heading")


The `ipcRenderer.send` API that we used for single-way communication can also be leveraged to perform two-way communication. This was the recommended way for asynchronous two-way communication via IPC prior to Electron 7.



preload.js (Preload Script)


```
// You can also put expose this code to the renderer
// process with the `contextBridge` API
const { ipcRenderer } = require('electron')

ipcRenderer.on('asynchronous-reply', (_event, arg) => {
  console.log(arg) // prints "pong" in the DevTools console
})
ipcRenderer.send('asynchronous-message', 'ping')
```




main.js (Main Process)


```
ipcMain.on('asynchronous-message', (event, arg) => {
  console.log(arg) // prints "ping" in the Node console
  // works like `send`, but returning a message back
  // to the renderer that sent the original message
  event.reply('asynchronous-reply', 'pong')
})
```



There are a couple downsides to this approach:


* You need to set up a second `ipcRenderer.on` listener to handle the response in the renderer process. With `invoke`, you get the response value returned as a Promise to the original API call.
* There's no obvious way to pair the `asynchronous-reply` message to the original `asynchronous-message` one. If you have very frequent messages going back and forth through these channels, you would need to add additional app code to track each call and response individually.


#### Using `ipcRenderer.sendSync`[​](#using-ipcrenderersendsync "Direct link to heading")


The `ipcRenderer.sendSync` API sends a message to the main process and waits *synchronously* for a response.



main.js (Main Process)


```
const { ipcMain } = require('electron')
ipcMain.on('synchronous-message', (event, arg) => {
  console.log(arg) // prints "ping" in the Node console
  event.returnValue = 'pong'
})
```




preload.js (Preload Script)


```
// You can also put expose this code to the renderer
// process with the `contextBridge` API
const { ipcRenderer } = require('electron')

const result = ipcRenderer.sendSync('synchronous-message', 'ping')
console.log(result) // prints "pong" in the DevTools console
```



The structure of this code is very similar to the `invoke` model, but we recommend **avoiding this API** for performance reasons. Its synchronous nature means that it'll block the renderer process until a reply is received.


Pattern 3: Main to renderer[​](#pattern-3-main-to-renderer "Direct link to heading")
------------------------------------------------------------------------------------


When sending a message from the main process to a renderer process, you need to specify which renderer is receiving the message. Messages need to be sent to a renderer process via its [`WebContents`](../api/web-contents) instance. This WebContents instance contains a [`send`](../api/web-contents#contentssendchannel-args) method that can be used in the same way as `ipcRenderer.send`.


To demonstrate this pattern, we'll be building a number counter controlled by the native operating system menu.


For this demo, you'll need to add code to your main process, your renderer process, and a preload script. The full code is below, but we'll be explaining each file individually in the following sections.




[docs/fiddles/ipc/pattern-3 (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/ipc/pattern-3)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/ipc/pattern-3)


* main.js
* preload.js
* index.html
* renderer.js





```
const {app, BrowserWindow, Menu, ipcMain} = require('electron')
const path = require('path')

function createWindow () {
  const mainWindow = new BrowserWindow({
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  const menu = Menu.buildFromTemplate([
    {
      label: app.name,
      submenu: [
      {
        click: () => mainWindow.webContents.send('update-counter', 1),
        label: 'Increment',
      },
      {
        click: () => mainWindow.webContents.send('update-counter', -1),
        label: 'Decrement',
      }
      ]
    }

  ])

  Menu.setApplicationMenu(menu)
  mainWindow.loadFile('index.html')

  // Open the DevTools.
  mainWindow.webContents.openDevTools()
}

app.whenReady().then(() => {
  ipcMain.on('counter-value', (_event, value) => {
    console.log(value) // will print value to Node console
  })
  createWindow()
  
  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})
```




```
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
  handleCounter: (callback) => ipcRenderer.on('update-counter', callback)
})
```




```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Menu Counter</title>
  </head>
  <body>
    Current value: <strong id="counter">0</strong>
    <script src="./renderer.js"></script>
  </body>
</html>
```




```
const counter = document.getElementById('counter')

window.electronAPI.handleCounter((event, value) => {
    const oldValue = Number(counter.innerText)
    const newValue = oldValue + value
    counter.innerText = newValue
    event.sender.send('counter-value', newValue)
})
```





### 1. Send messages with the `webContents` module[​](#1-send-messages-with-the-webcontents-module "Direct link to heading")


For this demo, we'll need to first build a custom menu in the main process using Electron's `Menu` module that uses the `webContents.send` API to send an IPC message from the main process to the target renderer.



main.js (Main Process)


```
const {app, BrowserWindow, Menu, ipcMain} = require('electron')
const path = require('path')

function createWindow () {
  const mainWindow = new BrowserWindow({
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  const menu = Menu.buildFromTemplate([
    {
      label: app.name,
      submenu: [
        {
          click: () => mainWindow.webContents.send('update-counter', 1),
          label: 'Increment',
        },
        {
          click: () => mainWindow.webContents.send('update-counter', -1),
          label: 'Decrement',
        }
      ]
    }
  ])
  Menu.setApplicationMenu(menu)

  mainWindow.loadFile('index.html')
}
//...

```



For the purposes of the tutorial, it's important to note that the `click` handler sends a message (either `1` or `-1`) to the renderer process through the `update-counter` channel.




```
click: () => mainWindow.webContents.send('update-counter', -1)
```




info
Make sure you're loading the `index.html` and `preload.js` entry points for the following steps!



### 2. Expose `ipcRenderer.on` via preload[​](#2-expose-ipcrendereron-via-preload "Direct link to heading")


Like in the previous renderer-to-main example, we use the `contextBridge` and `ipcRenderer` modules in the preload script to expose IPC functionality to the renderer process:



preload.js (Preload Script)


```
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electronAPI', {
    onUpdateCounter: (callback) => ipcRenderer.on('update-counter', callback)
})
```



After loading the preload script, your renderer process should have access to the `window.electronAPI.onUpdateCounter()` listener function.




Security warning
We don't directly expose the whole `ipcRenderer.on` API for [security reasons](context-isolation#security-considerations). Make sure to limit the renderer's access to Electron APIs as much as possible.





info

In the case of this minimal example, you can call `ipcRenderer.on` directly in the preload script rather than exposing it over the context bridge.



preload.js (Preload Script)


```
const { ipcRenderer } = require('electron')

window.addEventListener('DOMContentLoaded', () => {
    const counter = document.getElementById('counter')
    ipcRenderer.on('update-counter', (_event, value) => {
        const oldValue = Number(counter.innerText)
        const newValue = oldValue + value
        counter.innerText = newValue
    })
})
```



However, this approach has limited flexibility compared to exposing your preload APIs over the context bridge, since your listener can't directly interact with your renderer code.




### 3. Build the renderer process UI[​](#3-build-the-renderer-process-ui-2 "Direct link to heading")


To tie it all together, we'll create an interface in the loaded HTML file that contains a `#counter` element that we'll use to display the values:



index.html


```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Menu Counter</title>
  </head>
  <body>
    Current value: <strong id="counter">0</strong>
    <script src="./renderer.js"></script>
  </body>
</html>
```



Finally, to make the values update in the HTML document, we'll add a few lines of DOM manipulation so that the value of the `#counter` element is updated whenever we fire an `update-counter` event.



renderer.js (Renderer Process)


```
const counter = document.getElementById('counter')

window.electronAPI.onUpdateCounter((_event, value) => {
    const oldValue = Number(counter.innerText)
    const newValue = oldValue + value
    counter.innerText = newValue
})
```



In the above code, we're passing in a callback to the `window.electronAPI.onUpdateCounter` function exposed from our preload script. The second `value` parameter corresponds to the `1` or `-1` we were passing in from the `webContents.send` call from the native menu.


### Optional: returning a reply[​](#optional-returning-a-reply "Direct link to heading")


There's no equivalent for `ipcRenderer.invoke` for main-to-renderer IPC. Instead, you can send a reply back to the main process from within the `ipcRenderer.on` callback.


We can demonstrate this with slight modifications to the code from the previous example. In the renderer process, use the `event` parameter to send a reply back to the main process through the `counter-value` channel.



renderer.js (Renderer Process)


```
const counter = document.getElementById('counter')

window.electronAPI.onUpdateCounter((event, value) => {
  const oldValue = Number(counter.innerText)
  const newValue = oldValue + value
  counter.innerText = newValue
  event.sender.send('counter-value', newValue)
})
```



In the main process, listen for `counter-value` events and handle them appropriately.



main.js (Main Process)


```
//...
ipcMain.on('counter-value', (_event, value) => {
  console.log(value) // will print value to Node console
})
//...
```



Pattern 4: Renderer to renderer[​](#pattern-4-renderer-to-renderer "Direct link to heading")
--------------------------------------------------------------------------------------------


There's no direct way to send messages between renderer processes in Electron using the `ipcMain` and `ipcRenderer` modules. To achieve this, you have two options:


* Use the main process as a message broker between renderers. This would involve sending a message from one renderer to the main process, which would forward the message to the other renderer.
* Pass a [MessagePort](message-ports) from the main process to both renderers. This will allow direct communication between renderers after the initial setup.


Object serialization[​](#object-serialization "Direct link to heading")
-----------------------------------------------------------------------


Electron's IPC implementation uses the HTML standard [Structured Clone Algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) to serialize objects passed between processes, meaning that only certain types of objects can be passed through IPC channels.


In particular, DOM objects (e.g. `Element`, `Location` and `DOMMatrix`), Node.js objects backed by C++ classes (e.g. `process.env`, some members of `Stream`), and Electron objects backed by C++ classes (e.g. `WebContents`, `BrowserWindow` and `WebFrame`) are not serializable with Structured Clone.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/ipc>

Referrer Object
===============


* `url` string - HTTP Referrer URL.
* `policy` string - Can be `default`, `unsafe-url`, `no-referrer-when-downgrade`, `no-referrer`, `origin`, `strict-origin-when-cross-origin`, `same-origin` or `strict-origin`. See the [Referrer-Policy spec](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy) for more details on the meaning of these values.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/referrer>

UploadRawData Object
====================


* `type` 'rawData' - `rawData`.
* `bytes` Buffer - Data to be uploaded.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/upload-raw-data>

webContents
===========



> Render and control web pages.
> 
> 


Process: [Main](../glossary#main-process)


`webContents` is an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter). It is responsible for rendering and controlling a web page and is a property of the [`BrowserWindow`](browser-window) object. An example of accessing the `webContents` object:




```
const { BrowserWindow } = require('electron')

const win = new BrowserWindow({ width: 800, height: 1500 })
win.loadURL('http://github.com')

const contents = win.webContents
console.log(contents)
```


Methods[​](#methods "Direct link to heading")
---------------------------------------------


These methods can be accessed from the `webContents` module:




```
const { webContents } = require('electron')
console.log(webContents)
```


### 
`webContents.getAllWebContents()`[​](#webcontentsgetallwebcontents "Direct link to heading")


Returns `WebContents[]` - An array of all `WebContents` instances. This will contain web contents for all windows, webviews, opened devtools, and devtools extension background pages.


### 
`webContents.getFocusedWebContents()`[​](#webcontentsgetfocusedwebcontents "Direct link to heading")


Returns `WebContents` | null - The web contents that is focused in this application, otherwise returns `null`.


### 
`webContents.fromId(id)`[​](#webcontentsfromidid "Direct link to heading")


* `id` Integer


Returns `WebContents` | undefined - A WebContents instance with the given ID, or `undefined` if there is no WebContents associated with the given ID.


### 
`webContents.fromDevToolsTargetId(targetId)`[​](#webcontentsfromdevtoolstargetidtargetid "Direct link to heading")


* `targetId` string - The Chrome DevTools Protocol [TargetID](https://chromedevtools.github.io/devtools-protocol/tot/Target/#type-TargetID) associated with the WebContents instance.


Returns `WebContents` | undefined - A WebContents instance with the given TargetID, or `undefined` if there is no WebContents associated with the given TargetID.


When communicating with the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/), it can be useful to lookup a WebContents instance based on its assigned TargetID.




```
async function lookupTargetId (browserWindow) {
  const wc = browserWindow.webContents
  await wc.debugger.attach('1.3')
  const { targetInfo } = await wc.debugger.sendCommand('Target.getTargetInfo')
  const { targetId } = targetInfo
  const targetWebContents = await webContents.fromDevToolsTargetId(targetId)
}
```


Class: WebContents[​](#class-webcontents "Direct link to heading")
------------------------------------------------------------------



> Render and control the contents of a BrowserWindow instance.
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


### Instance Events[​](#instance-events "Direct link to heading")


#### Event: 'did-finish-load'[​](#event-did-finish-load "Direct link to heading")


Emitted when the navigation is done, i.e. the spinner of the tab has stopped spinning, and the `onload` event was dispatched.


#### Event: 'did-fail-load'[​](#event-did-fail-load "Direct link to heading")


Returns:


* `event` Event
* `errorCode` Integer
* `errorDescription` string
* `validatedURL` string
* `isMainFrame` boolean
* `frameProcessId` Integer
* `frameRoutingId` Integer


This event is like `did-finish-load` but emitted when the load failed. The full list of error codes and their meaning is available [here](https://source.chromium.org/chromium/chromium/src/+/main:net/base/net_error_list.h).


#### Event: 'did-fail-provisional-load'[​](#event-did-fail-provisional-load "Direct link to heading")


Returns:


* `event` Event
* `errorCode` Integer
* `errorDescription` string
* `validatedURL` string
* `isMainFrame` boolean
* `frameProcessId` Integer
* `frameRoutingId` Integer


This event is like `did-fail-load` but emitted when the load was cancelled (e.g. `window.stop()` was invoked).


#### Event: 'did-frame-finish-load'[​](#event-did-frame-finish-load "Direct link to heading")


Returns:


* `event` Event
* `isMainFrame` boolean
* `frameProcessId` Integer
* `frameRoutingId` Integer


Emitted when a frame has done navigation.


#### Event: 'did-start-loading'[​](#event-did-start-loading "Direct link to heading")


Corresponds to the points in time when the spinner of the tab started spinning.


#### Event: 'did-stop-loading'[​](#event-did-stop-loading "Direct link to heading")


Corresponds to the points in time when the spinner of the tab stopped spinning.


#### Event: 'dom-ready'[​](#event-dom-ready "Direct link to heading")


Returns:


* `event` Event


Emitted when the document in the top-level frame is loaded.


#### Event: 'page-title-updated'[​](#event-page-title-updated "Direct link to heading")


Returns:


* `event` Event
* `title` string
* `explicitSet` boolean


Fired when page title is set during navigation. `explicitSet` is false when title is synthesized from file url.


#### Event: 'page-favicon-updated'[​](#event-page-favicon-updated "Direct link to heading")


Returns:


* `event` Event
* `favicons` string[] - Array of URLs.


Emitted when page receives favicon urls.


#### Event: 'new-window' *Deprecated*[​](#event-new-window-deprecated "Direct link to heading")


Returns:


* `event` NewWindowWebContentsEvent
* `url` string
* `frameName` string
* `disposition` string - Can be `default`, `foreground-tab`, `background-tab`, `new-window`, `save-to-disk` and `other`.
* `options` BrowserWindowConstructorOptions - The options which will be used for creating the new [`BrowserWindow`](browser-window).
* `additionalFeatures` string[] - The non-standard features (features not handled by Chromium or Electron) given to `window.open()`. Deprecated, and will now always be the empty array `[]`.
* `referrer` [Referrer](structures/referrer) - The referrer that will be passed to the new window. May or may not result in the `Referer` header being sent, depending on the referrer policy.
* `postBody` [PostBody](structures/post-body) (optional) - The post data that will be sent to the new window, along with the appropriate headers that will be set. If no post data is to be sent, the value will be `null`. Only defined when the window is being created by a form that set `target=_blank`.


Deprecated in favor of [`webContents.setWindowOpenHandler`](web-contents#contentssetwindowopenhandlerhandler).


Emitted when the page requests to open a new window for a `url`. It could be requested by `window.open` or an external link like `<a target='_blank'>`.


By default a new `BrowserWindow` will be created for the `url`.


Calling `event.preventDefault()` will prevent Electron from automatically creating a new [`BrowserWindow`](browser-window). If you call `event.preventDefault()` and manually create a new [`BrowserWindow`](browser-window) then you must set `event.newGuest` to reference the new [`BrowserWindow`](browser-window) instance, failing to do so may result in unexpected behavior. For example:




```
myBrowserWindow.webContents.on('new-window', (event, url, frameName, disposition, options, additionalFeatures, referrer, postBody) => {
  event.preventDefault()
  const win = new BrowserWindow({
    webContents: options.webContents, // use existing webContents if provided
    show: false
  })
  win.once('ready-to-show', () => win.show())
  if (!options.webContents) {
    const loadOptions = {
      httpReferrer: referrer
    }
    if (postBody != null) {
      const { data, contentType, boundary } = postBody
      loadOptions.postData = postBody.data
      loadOptions.extraHeaders = `content-type: ${contentType}; boundary=${boundary}`
    }

    win.loadURL(url, loadOptions) // existing webContents will be navigated automatically
  }
  event.newGuest = win
})
```


#### Event: 'did-create-window'[​](#event-did-create-window "Direct link to heading")


Returns:


* `window` BrowserWindow
* `details` Object
	+ `url` string - URL for the created window.
	+ `frameName` string - Name given to the created window in the `window.open()` call.
	+ `options` BrowserWindowConstructorOptions - The options used to create the BrowserWindow. They are merged in increasing precedence: parsed options from the `features` string from `window.open()`, security-related webPreferences inherited from the parent, and options given by [`webContents.setWindowOpenHandler`](web-contents#contentssetwindowopenhandlerhandler). Unrecognized options are not filtered out.
	+ `referrer` [Referrer](structures/referrer) - The referrer that will be passed to the new window. May or may not result in the `Referer` header being sent, depending on the referrer policy.
	+ `postBody` [PostBody](structures/post-body) (optional) - The post data that will be sent to the new window, along with the appropriate headers that will be set. If no post data is to be sent, the value will be `null`. Only defined when the window is being created by a form that set `target=_blank`.
	+ `disposition` string - Can be `default`, `foreground-tab`, `background-tab`, `new-window`, `save-to-disk` and `other`.


Emitted *after* successful creation of a window via `window.open` in the renderer. Not emitted if the creation of the window is canceled from [`webContents.setWindowOpenHandler`](web-contents#contentssetwindowopenhandlerhandler).


See [`window.open()`](window-open) for more details and how to use this in conjunction with `webContents.setWindowOpenHandler`.


#### Event: 'will-navigate'[​](#event-will-navigate "Direct link to heading")


Returns:


* `event` Event
* `url` string


Emitted when a user or the page wants to start navigation. It can happen when the `window.location` object is changed or a user clicks a link in the page.


This event will not emit when the navigation is started programmatically with APIs like `webContents.loadURL` and `webContents.back`.


It is also not emitted for in-page navigations, such as clicking anchor links or updating the `window.location.hash`. Use `did-navigate-in-page` event for this purpose.


Calling `event.preventDefault()` will prevent the navigation.


#### Event: 'did-start-navigation'[​](#event-did-start-navigation "Direct link to heading")


Returns:


* `event` Event
* `url` string
* `isInPlace` boolean
* `isMainFrame` boolean
* `frameProcessId` Integer
* `frameRoutingId` Integer


Emitted when any frame (including main) starts navigating. `isInPlace` will be `true` for in-page navigations.


#### Event: 'will-redirect'[​](#event-will-redirect "Direct link to heading")


Returns:


* `event` Event
* `url` string
* `isInPlace` boolean
* `isMainFrame` boolean
* `frameProcessId` Integer
* `frameRoutingId` Integer


Emitted when a server side redirect occurs during navigation. For example a 302 redirect.


This event will be emitted after `did-start-navigation` and always before the `did-redirect-navigation` event for the same navigation.


Calling `event.preventDefault()` will prevent the navigation (not just the redirect).


#### Event: 'did-redirect-navigation'[​](#event-did-redirect-navigation "Direct link to heading")


Returns:


* `event` Event
* `url` string
* `isInPlace` boolean
* `isMainFrame` boolean
* `frameProcessId` Integer
* `frameRoutingId` Integer


Emitted after a server side redirect occurs during navigation. For example a 302 redirect.


This event cannot be prevented, if you want to prevent redirects you should checkout out the `will-redirect` event above.


#### Event: 'did-navigate'[​](#event-did-navigate "Direct link to heading")


Returns:


* `event` Event
* `url` string
* `httpResponseCode` Integer - -1 for non HTTP navigations
* `httpStatusText` string - empty for non HTTP navigations


Emitted when a main frame navigation is done.


This event is not emitted for in-page navigations, such as clicking anchor links or updating the `window.location.hash`. Use `did-navigate-in-page` event for this purpose.


#### Event: 'did-frame-navigate'[​](#event-did-frame-navigate "Direct link to heading")


Returns:


* `event` Event
* `url` string
* `httpResponseCode` Integer - -1 for non HTTP navigations
* `httpStatusText` string - empty for non HTTP navigations,
* `isMainFrame` boolean
* `frameProcessId` Integer
* `frameRoutingId` Integer


Emitted when any frame navigation is done.


This event is not emitted for in-page navigations, such as clicking anchor links or updating the `window.location.hash`. Use `did-navigate-in-page` event for this purpose.


#### Event: 'did-navigate-in-page'[​](#event-did-navigate-in-page "Direct link to heading")


Returns:


* `event` Event
* `url` string
* `isMainFrame` boolean
* `frameProcessId` Integer
* `frameRoutingId` Integer


Emitted when an in-page navigation happened in any frame.


When in-page navigation happens, the page URL changes but does not cause navigation outside of the page. Examples of this occurring are when anchor links are clicked or when the DOM `hashchange` event is triggered.


#### Event: 'will-prevent-unload'[​](#event-will-prevent-unload "Direct link to heading")


Returns:


* `event` Event


Emitted when a `beforeunload` event handler is attempting to cancel a page unload.


Calling `event.preventDefault()` will ignore the `beforeunload` event handler and allow the page to be unloaded.




```
const { BrowserWindow, dialog } = require('electron')
const win = new BrowserWindow({ width: 800, height: 600 })
win.webContents.on('will-prevent-unload', (event) => {
  const choice = dialog.showMessageBoxSync(win, {
    type: 'question',
    buttons: ['Leave', 'Stay'],
    title: 'Do you want to leave this site?',
    message: 'Changes you made may not be saved.',
    defaultId: 0,
    cancelId: 1
  })
  const leave = (choice === 0)
  if (leave) {
    event.preventDefault()
  }
})
```


**Note:** This will be emitted for `BrowserViews` but will *not* be respected - this is because we have chosen not to tie the `BrowserView` lifecycle to its owning BrowserWindow should one exist per the [specification](https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event).


#### Event: 'crashed' *Deprecated*[​](#event-crashed-deprecated "Direct link to heading")


Returns:


* `event` Event
* `killed` boolean


Emitted when the renderer process crashes or is killed.


**Deprecated:** This event is superceded by the `render-process-gone` event which contains more information about why the render process disappeared. It isn't always because it crashed. The `killed` boolean can be replaced by checking `reason === 'killed'` when you switch to that event.


#### Event: 'render-process-gone'[​](#event-render-process-gone "Direct link to heading")


Returns:


* `event` Event
* `details` Object
	+ `reason` string - The reason the render process is gone. Possible values:
		- `clean-exit` - Process exited with an exit code of zero
		- `abnormal-exit` - Process exited with a non-zero exit code
		- `killed` - Process was sent a SIGTERM or otherwise killed externally
		- `crashed` - Process crashed
		- `oom` - Process ran out of memory
		- `launch-failed` - Process never successfully launched
		- `integrity-failure` - Windows code integrity checks failed
	+ `exitCode` Integer - The exit code of the process, unless `reason` is `launch-failed`, in which case `exitCode` will be a platform-specific launch failure error code.


Emitted when the renderer process unexpectedly disappears. This is normally because it was crashed or killed.


#### Event: 'unresponsive'[​](#event-unresponsive "Direct link to heading")


Emitted when the web page becomes unresponsive.


#### Event: 'responsive'[​](#event-responsive "Direct link to heading")


Emitted when the unresponsive web page becomes responsive again.


#### Event: 'plugin-crashed'[​](#event-plugin-crashed "Direct link to heading")


Returns:


* `event` Event
* `name` string
* `version` string


Emitted when a plugin process has crashed.


#### Event: 'destroyed'[​](#event-destroyed "Direct link to heading")


Emitted when `webContents` is destroyed.


#### Event: 'before-input-event'[​](#event-before-input-event "Direct link to heading")


Returns:


* `event` Event
* `input` Object - Input properties.
	+ `type` string - Either `keyUp` or `keyDown`.
	+ `key` string - Equivalent to [KeyboardEvent.key](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent).
	+ `code` string - Equivalent to [KeyboardEvent.code](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent).
	+ `isAutoRepeat` boolean - Equivalent to [KeyboardEvent.repeat](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent).
	+ `isComposing` boolean - Equivalent to [KeyboardEvent.isComposing](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent).
	+ `shift` boolean - Equivalent to [KeyboardEvent.shiftKey](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent).
	+ `control` boolean - Equivalent to [KeyboardEvent.controlKey](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent).
	+ `alt` boolean - Equivalent to [KeyboardEvent.altKey](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent).
	+ `meta` boolean - Equivalent to [KeyboardEvent.metaKey](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent).
	+ `location` number - Equivalent to [KeyboardEvent.location](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent).
	+ `modifiers` string[] - See [InputEvent.modifiers](structures/input-event).


Emitted before dispatching the `keydown` and `keyup` events in the page. Calling `event.preventDefault` will prevent the page `keydown`/`keyup` events and the menu shortcuts.


To only prevent the menu shortcuts, use [`setIgnoreMenuShortcuts`](#contentssetignoremenushortcutsignore):




```
const { BrowserWindow } = require('electron')

const win = new BrowserWindow({ width: 800, height: 600 })

win.webContents.on('before-input-event', (event, input) => {
  // For example, only enable application menu keyboard shortcuts when
  // Ctrl/Cmd are down.
  win.webContents.setIgnoreMenuShortcuts(!input.control && !input.meta)
})
```


#### Event: 'enter-html-full-screen'[​](#event-enter-html-full-screen "Direct link to heading")


Emitted when the window enters a full-screen state triggered by HTML API.


#### Event: 'leave-html-full-screen'[​](#event-leave-html-full-screen "Direct link to heading")


Emitted when the window leaves a full-screen state triggered by HTML API.


#### Event: 'zoom-changed'[​](#event-zoom-changed "Direct link to heading")


Returns:


* `event` Event
* `zoomDirection` string - Can be `in` or `out`.


Emitted when the user is requesting to change the zoom level using the mouse wheel.


#### Event: 'blur'[​](#event-blur "Direct link to heading")


Emitted when the `WebContents` loses focus.


#### Event: 'focus'[​](#event-focus "Direct link to heading")


Emitted when the `WebContents` gains focus.


Note that on macOS, having focus means the `WebContents` is the first responder of window, so switching focus between windows would not trigger the `focus` and `blur` events of `WebContents`, as the first responder of each window is not changed.


The `focus` and `blur` events of `WebContents` should only be used to detect focus change between different `WebContents` and `BrowserView` in the same window.


#### Event: 'devtools-opened'[​](#event-devtools-opened "Direct link to heading")


Emitted when DevTools is opened.


#### Event: 'devtools-closed'[​](#event-devtools-closed "Direct link to heading")


Emitted when DevTools is closed.


#### Event: 'devtools-focused'[​](#event-devtools-focused "Direct link to heading")


Emitted when DevTools is focused / opened.


#### Event: 'certificate-error'[​](#event-certificate-error "Direct link to heading")


Returns:


* `event` Event
* `url` string
* `error` string - The error code.
* `certificate` [Certificate](structures/certificate)
* `callback` Function
	+ `isTrusted` boolean - Indicates whether the certificate can be considered trusted.
* `isMainFrame` boolean


Emitted when failed to verify the `certificate` for `url`.


The usage is the same with [the `certificate-error` event of `app`](app#event-certificate-error).


#### Event: 'select-client-certificate'[​](#event-select-client-certificate "Direct link to heading")


Returns:


* `event` Event
* `url` URL
* `certificateList` [Certificate[]](structures/certificate)
* `callback` Function
	+ `certificate` [Certificate](structures/certificate) - Must be a certificate from the given list.


Emitted when a client certificate is requested.


The usage is the same with [the `select-client-certificate` event of `app`](app#event-select-client-certificate).


#### Event: 'login'[​](#event-login "Direct link to heading")


Returns:


* `event` Event
* `authenticationResponseDetails` Object
	+ `url` URL
* `authInfo` Object
	+ `isProxy` boolean
	+ `scheme` string
	+ `host` string
	+ `port` Integer
	+ `realm` string
* `callback` Function
	+ `username` string (optional)
	+ `password` string (optional)


Emitted when `webContents` wants to do basic auth.


The usage is the same with [the `login` event of `app`](app#event-login).


#### Event: 'found-in-page'[​](#event-found-in-page "Direct link to heading")


Returns:


* `event` Event
* `result` Object
	+ `requestId` Integer
	+ `activeMatchOrdinal` Integer - Position of the active match.
	+ `matches` Integer - Number of Matches.
	+ `selectionArea` Rectangle - Coordinates of first match region.
	+ `finalUpdate` boolean


Emitted when a result is available for [`webContents.findInPage`] request.


#### Event: 'media-started-playing'[​](#event-media-started-playing "Direct link to heading")


Emitted when media starts playing.


#### Event: 'media-paused'[​](#event-media-paused "Direct link to heading")


Emitted when media is paused or done playing.


#### Event: 'did-change-theme-color'[​](#event-did-change-theme-color "Direct link to heading")


Returns:


* `event` Event
* `color` (string | null) - Theme color is in format of '#rrggbb'. It is `null` when no theme color is set.


Emitted when a page's theme color changes. This is usually due to encountering a meta tag:




```
<meta name='theme-color' content='#ff0000'>
```


#### Event: 'update-target-url'[​](#event-update-target-url "Direct link to heading")


Returns:


* `event` Event
* `url` string


Emitted when mouse moves over a link or the keyboard moves the focus to a link.


#### Event: 'cursor-changed'[​](#event-cursor-changed "Direct link to heading")


Returns:


* `event` Event
* `type` string
* `image` [NativeImage](native-image) (optional)
* `scale` Float (optional) - scaling factor for the custom cursor.
* `size` [Size](structures/size) (optional) - the size of the `image`.
* `hotspot` [Point](structures/point) (optional) - coordinates of the custom cursor's hotspot.


Emitted when the cursor's type changes. The `type` parameter can be `default`, `crosshair`, `pointer`, `text`, `wait`, `help`, `e-resize`, `n-resize`, `ne-resize`, `nw-resize`, `s-resize`, `se-resize`, `sw-resize`, `w-resize`, `ns-resize`, `ew-resize`, `nesw-resize`, `nwse-resize`, `col-resize`, `row-resize`, `m-panning`, `e-panning`, `n-panning`, `ne-panning`, `nw-panning`, `s-panning`, `se-panning`, `sw-panning`, `w-panning`, `move`, `vertical-text`, `cell`, `context-menu`, `alias`, `progress`, `nodrop`, `copy`, `none`, `not-allowed`, `zoom-in`, `zoom-out`, `grab`, `grabbing` or `custom`.


If the `type` parameter is `custom`, the `image` parameter will hold the custom cursor image in a [`NativeImage`](native-image), and `scale`, `size` and `hotspot` will hold additional information about the custom cursor.


#### Event: 'context-menu'[​](#event-context-menu "Direct link to heading")


Returns:


* `event` Event
* `params` Object
	+ `x` Integer - x coordinate.
	+ `y` Integer - y coordinate.
	+ `frame` WebFrameMain - Frame from which the context menu was invoked.
	+ `linkURL` string - URL of the link that encloses the node the context menu was invoked on.
	+ `linkText` string - Text associated with the link. May be an empty string if the contents of the link are an image.
	+ `pageURL` string - URL of the top level page that the context menu was invoked on.
	+ `frameURL` string - URL of the subframe that the context menu was invoked on.
	+ `srcURL` string - Source URL for the element that the context menu was invoked on. Elements with source URLs are images, audio and video.
	+ `mediaType` string - Type of the node the context menu was invoked on. Can be `none`, `image`, `audio`, `video`, `canvas`, `file` or `plugin`.
	+ `hasImageContents` boolean - Whether the context menu was invoked on an image which has non-empty contents.
	+ `isEditable` boolean - Whether the context is editable.
	+ `selectionText` string - Text of the selection that the context menu was invoked on.
	+ `titleText` string - Title text of the selection that the context menu was invoked on.
	+ `altText` string - Alt text of the selection that the context menu was invoked on.
	+ `suggestedFilename` string - Suggested filename to be used when saving file through 'Save Link As' option of context menu.
	+ `selectionRect` [Rectangle](structures/rectangle) - Rect representing the coordinates in the document space of the selection.
	+ `selectionStartOffset` number - Start position of the selection text.
	+ `referrerPolicy` [Referrer](structures/referrer) - The referrer policy of the frame on which the menu is invoked.
	+ `misspelledWord` string - The misspelled word under the cursor, if any.
	+ `dictionarySuggestions` string[] - An array of suggested words to show the user to replace the `misspelledWord`. Only available if there is a misspelled word and spellchecker is enabled.
	+ `frameCharset` string - The character encoding of the frame on which the menu was invoked.
	+ `inputFieldType` string - If the context menu was invoked on an input field, the type of that field. Possible values are `none`, `plainText`, `password`, `other`.
	+ `spellcheckEnabled` boolean - If the context is editable, whether or not spellchecking is enabled.
	+ `menuSourceType` string - Input source that invoked the context menu. Can be `none`, `mouse`, `keyboard`, `touch`, `touchMenu`, `longPress`, `longTap`, `touchHandle`, `stylus`, `adjustSelection`, or `adjustSelectionReset`.
	+ `mediaFlags` Object - The flags for the media element the context menu was invoked on.
		- `inError` boolean - Whether the media element has crashed.
		- `isPaused` boolean - Whether the media element is paused.
		- `isMuted` boolean - Whether the media element is muted.
		- `hasAudio` boolean - Whether the media element has audio.
		- `isLooping` boolean - Whether the media element is looping.
		- `isControlsVisible` boolean - Whether the media element's controls are visible.
		- `canToggleControls` boolean - Whether the media element's controls are toggleable.
		- `canPrint` boolean - Whether the media element can be printed.
		- `canSave` boolean - Whether or not the media element can be downloaded.
		- `canShowPictureInPicture` boolean - Whether the media element can show picture-in-picture.
		- `isShowingPictureInPicture` boolean - Whether the media element is currently showing picture-in-picture.
		- `canRotate` boolean - Whether the media element can be rotated.
		- `canLoop` boolean - Whether the media element can be looped.
	+ `editFlags` Object - These flags indicate whether the renderer believes it is able to perform the corresponding action.
		- `canUndo` boolean - Whether the renderer believes it can undo.
		- `canRedo` boolean - Whether the renderer believes it can redo.
		- `canCut` boolean - Whether the renderer believes it can cut.
		- `canCopy` boolean - Whether the renderer believes it can copy.
		- `canPaste` boolean - Whether the renderer believes it can paste.
		- `canDelete` boolean - Whether the renderer believes it can delete.
		- `canSelectAll` boolean - Whether the renderer believes it can select all.
		- `canEditRichly` boolean - Whether the renderer believes it can edit text richly.


Emitted when there is a new context menu that needs to be handled.


#### Event: 'select-bluetooth-device'[​](#event-select-bluetooth-device "Direct link to heading")


Returns:


* `event` Event
* `devices` [BluetoothDevice[]](structures/bluetooth-device)
* `callback` Function
	+ `deviceId` string


Emitted when bluetooth device needs to be selected on call to `navigator.bluetooth.requestDevice`. To use `navigator.bluetooth` api `webBluetooth` should be enabled. If `event.preventDefault` is not called, first available device will be selected. `callback` should be called with `deviceId` to be selected, passing empty string to `callback` will cancel the request.


If no event listener is added for this event, all bluetooth requests will be cancelled.




```
const { app, BrowserWindow } = require('electron')

let win = null
app.commandLine.appendSwitch('enable-experimental-web-platform-features')

app.whenReady().then(() => {
  win = new BrowserWindow({ width: 800, height: 600 })
  win.webContents.on('select-bluetooth-device', (event, deviceList, callback) => {
    event.preventDefault()
    const result = deviceList.find((device) => {
      return device.deviceName === 'test'
    })
    if (!result) {
      callback('')
    } else {
      callback(result.deviceId)
    }
  })
})
```


#### Event: 'paint'[​](#event-paint "Direct link to heading")


Returns:


* `event` Event
* `dirtyRect` [Rectangle](structures/rectangle)
* `image` [NativeImage](native-image) - The image data of the whole frame.


Emitted when a new frame is generated. Only the dirty area is passed in the buffer.




```
const { BrowserWindow } = require('electron')

const win = new BrowserWindow({ webPreferences: { offscreen: true } })
win.webContents.on('paint', (event, dirty, image) => {
  // updateBitmap(dirty, image.getBitmap())
})
win.loadURL('http://github.com')
```


#### Event: 'devtools-reload-page'[​](#event-devtools-reload-page "Direct link to heading")


Emitted when the devtools window instructs the webContents to reload


#### Event: 'will-attach-webview'[​](#event-will-attach-webview "Direct link to heading")


Returns:


* `event` Event
* `webPreferences` WebPreferences - The web preferences that will be used by the guest page. This object can be modified to adjust the preferences for the guest page.
* `params` Record<string, string> - The other `<webview>` parameters such as the `src` URL. This object can be modified to adjust the parameters of the guest page.


Emitted when a `<webview>`'s web contents is being attached to this web contents. Calling `event.preventDefault()` will destroy the guest page.


This event can be used to configure `webPreferences` for the `webContents` of a `<webview>` before it's loaded, and provides the ability to set settings that can't be set via `<webview>` attributes.


#### Event: 'did-attach-webview'[​](#event-did-attach-webview "Direct link to heading")


Returns:


* `event` Event
* `webContents` WebContents - The guest web contents that is used by the `<webview>`.


Emitted when a `<webview>` has been attached to this web contents.


#### Event: 'console-message'[​](#event-console-message "Direct link to heading")


Returns:


* `event` Event
* `level` Integer - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
* `message` string - The actual console message
* `line` Integer - The line number of the source that triggered this console message
* `sourceId` string


Emitted when the associated window logs a console message.


#### Event: 'preload-error'[​](#event-preload-error "Direct link to heading")


Returns:


* `event` Event
* `preloadPath` string
* `error` Error


Emitted when the preload script `preloadPath` throws an unhandled exception `error`.


#### Event: 'ipc-message'[​](#event-ipc-message "Direct link to heading")


Returns:


* `event` Event
* `channel` string
* `...args` any[]


Emitted when the renderer process sends an asynchronous message via `ipcRenderer.send()`.


#### Event: 'ipc-message-sync'[​](#event-ipc-message-sync "Direct link to heading")


Returns:


* `event` Event
* `channel` string
* `...args` any[]


Emitted when the renderer process sends a synchronous message via `ipcRenderer.sendSync()`.


#### Event: 'preferred-size-changed'[​](#event-preferred-size-changed "Direct link to heading")


Returns:


* `event` Event
* `preferredSize` [Size](structures/size) - The minimum size needed to contain the layout of the document—without requiring scrolling.


Emitted when the `WebContents` preferred size has changed.


This event will only be emitted when `enablePreferredSizeMode` is set to `true` in `webPreferences`.


#### Event: 'frame-created'[​](#event-frame-created "Direct link to heading")


Returns:


* `event` Event
* `details` Object
	+ `frame` WebFrameMain


Emitted when the [mainFrame](web-contents#contentsmainframe-readonly), an `<iframe>`, or a nested `<iframe>` is loaded within the page.


### Instance Methods[​](#instance-methods "Direct link to heading")


#### 
`contents.loadURL(url[, options])`[​](#contentsloadurlurl-options "Direct link to heading")


* `url` string
* `options` Object (optional)
	+ `httpReferrer` (string | [Referrer](structures/referrer)) (optional) - An HTTP Referrer url.
	+ `userAgent` string (optional) - A user agent originating the request.
	+ `extraHeaders` string (optional) - Extra headers separated by "\n".
	+ `postData` ([UploadRawData](structures/upload-raw-data) | [UploadFile](structures/upload-file))[] (optional)
	+ `baseURLForDataURL` string (optional) - Base url (with trailing path separator) for files to be loaded by the data url. This is needed only if the specified `url` is a data url and needs to load other files.


Returns `Promise<void>` - the promise will resolve when the page has finished loading (see [`did-finish-load`](web-contents#event-did-finish-load)), and rejects if the page fails to load (see [`did-fail-load`](web-contents#event-did-fail-load)). A noop rejection handler is already attached, which avoids unhandled rejection errors.


Loads the `url` in the window. The `url` must contain the protocol prefix, e.g. the `http://` or `file://`. If the load should bypass http cache then use the `pragma` header to achieve it.




```
const { webContents } = require('electron')
const options = { extraHeaders: 'pragma: no-cache\n' }
webContents.loadURL('https://github.com', options)
```


#### 
`contents.loadFile(filePath[, options])`[​](#contentsloadfilefilepath-options "Direct link to heading")


* `filePath` string
* `options` Object (optional)
	+ `query` Record<string, string> (optional) - Passed to `url.format()`.
	+ `search` string (optional) - Passed to `url.format()`.
	+ `hash` string (optional) - Passed to `url.format()`.


Returns `Promise<void>` - the promise will resolve when the page has finished loading (see [`did-finish-load`](web-contents#event-did-finish-load)), and rejects if the page fails to load (see [`did-fail-load`](web-contents#event-did-fail-load)).


Loads the given file in the window, `filePath` should be a path to an HTML file relative to the root of your application. For instance an app structure like this:




```
| root
| - package.json
| - src
|   - main.js
|   - index.html
```


Would require code like this




```
win.loadFile('src/index.html')
```


#### 
`contents.downloadURL(url)`[​](#contentsdownloadurlurl "Direct link to heading")


* `url` string


Initiates a download of the resource at `url` without navigating. The `will-download` event of `session` will be triggered.


#### 
`contents.getURL()`[​](#contentsgeturl "Direct link to heading")


Returns `string` - The URL of the current web page.




```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('http://github.com').then(() => {
  const currentURL = win.webContents.getURL()
  console.log(currentURL)
})
```


#### 
`contents.getTitle()`[​](#contentsgettitle "Direct link to heading")


Returns `string` - The title of the current web page.


#### 
`contents.isDestroyed()`[​](#contentsisdestroyed "Direct link to heading")


Returns `boolean` - Whether the web page is destroyed.


#### 
`contents.focus()`[​](#contentsfocus "Direct link to heading")


Focuses the web page.


#### 
`contents.isFocused()`[​](#contentsisfocused "Direct link to heading")


Returns `boolean` - Whether the web page is focused.


#### 
`contents.isLoading()`[​](#contentsisloading "Direct link to heading")


Returns `boolean` - Whether web page is still loading resources.


#### 
`contents.isLoadingMainFrame()`[​](#contentsisloadingmainframe "Direct link to heading")


Returns `boolean` - Whether the main frame (and not just iframes or frames within it) is still loading.


#### 
`contents.isWaitingForResponse()`[​](#contentsiswaitingforresponse "Direct link to heading")


Returns `boolean` - Whether the web page is waiting for a first-response from the main resource of the page.


#### 
`contents.stop()`[​](#contentsstop "Direct link to heading")


Stops any pending navigation.


#### 
`contents.reload()`[​](#contentsreload "Direct link to heading")


Reloads the current web page.


#### 
`contents.reloadIgnoringCache()`[​](#contentsreloadignoringcache "Direct link to heading")


Reloads current page and ignores cache.


#### 
`contents.canGoBack()`[​](#contentscangoback "Direct link to heading")


Returns `boolean` - Whether the browser can go back to previous web page.


#### 
`contents.canGoForward()`[​](#contentscangoforward "Direct link to heading")


Returns `boolean` - Whether the browser can go forward to next web page.


#### 
`contents.canGoToOffset(offset)`[​](#contentscangotooffsetoffset "Direct link to heading")


* `offset` Integer


Returns `boolean` - Whether the web page can go to `offset`.


#### 
`contents.clearHistory()`[​](#contentsclearhistory "Direct link to heading")


Clears the navigation history.


#### 
`contents.goBack()`[​](#contentsgoback "Direct link to heading")


Makes the browser go back a web page.


#### 
`contents.goForward()`[​](#contentsgoforward "Direct link to heading")


Makes the browser go forward a web page.


#### 
`contents.goToIndex(index)`[​](#contentsgotoindexindex "Direct link to heading")


* `index` Integer


Navigates browser to the specified absolute web page index.


#### 
`contents.goToOffset(offset)`[​](#contentsgotooffsetoffset "Direct link to heading")


* `offset` Integer


Navigates to the specified offset from the "current entry".


#### 
`contents.isCrashed()`[​](#contentsiscrashed "Direct link to heading")


Returns `boolean` - Whether the renderer process has crashed.


#### 
`contents.forcefullyCrashRenderer()`[​](#contentsforcefullycrashrenderer "Direct link to heading")


Forcefully terminates the renderer process that is currently hosting this `webContents`. This will cause the `render-process-gone` event to be emitted with the `reason=killed || reason=crashed`. Please note that some webContents share renderer processes and therefore calling this method may also crash the host process for other webContents as well.


Calling `reload()` immediately after calling this method will force the reload to occur in a new process. This should be used when this process is unstable or unusable, for instance in order to recover from the `unresponsive` event.




```
contents.on('unresponsive', async () => {
  const { response } = await dialog.showMessageBox({
    message: 'App X has become unresponsive',
    title: 'Do you want to try forcefully reloading the app?',
    buttons: ['OK', 'Cancel'],
    cancelId: 1
  })
  if (response === 0) {
    contents.forcefullyCrashRenderer()
    contents.reload()
  }
})
```


#### 
`contents.setUserAgent(userAgent)`[​](#contentssetuseragentuseragent "Direct link to heading")


* `userAgent` string


Overrides the user agent for this web page.


#### 
`contents.getUserAgent()`[​](#contentsgetuseragent "Direct link to heading")


Returns `string` - The user agent for this web page.


#### 
`contents.insertCSS(css[, options])`[​](#contentsinsertcsscss-options "Direct link to heading")


* `css` string
* `options` Object (optional)
	+ `cssOrigin` string (optional) - Can be either 'user' or 'author'. Sets the [cascade origin](https://www.w3.org/TR/css3-cascade/#cascade-origin) of the inserted stylesheet. Default is 'author'.


Returns `Promise<string>` - A promise that resolves with a key for the inserted CSS that can later be used to remove the CSS via `contents.removeInsertedCSS(key)`.


Injects CSS into the current web page and returns a unique key for the inserted stylesheet.




```
contents.on('did-finish-load', () => {
  contents.insertCSS('html, body { background-color: #f00; }')
})
```


#### 
`contents.removeInsertedCSS(key)`[​](#contentsremoveinsertedcsskey "Direct link to heading")


* `key` string


Returns `Promise<void>` - Resolves if the removal was successful.


Removes the inserted CSS from the current web page. The stylesheet is identified by its key, which is returned from `contents.insertCSS(css)`.




```
contents.on('did-finish-load', async () => {
  const key = await contents.insertCSS('html, body { background-color: #f00; }')
  contents.removeInsertedCSS(key)
})
```


#### 
`contents.executeJavaScript(code[, userGesture])`[​](#contentsexecutejavascriptcode-usergesture "Direct link to heading")


* `code` string
* `userGesture` boolean (optional) - Default is `false`.


Returns `Promise<any>` - A promise that resolves with the result of the executed code or is rejected if the result of the code is a rejected promise.


Evaluates `code` in page.


In the browser window some HTML APIs like `requestFullScreen` can only be invoked by a gesture from the user. Setting `userGesture` to `true` will remove this limitation.


Code execution will be suspended until web page stop loading.




```
contents.executeJavaScript('fetch("https://jsonplaceholder.typicode.com/users/1").then(resp => resp.json())', true)
  .then((result) => {
    console.log(result) // Will be the JSON object from the fetch call
  })
```


#### 
`contents.executeJavaScriptInIsolatedWorld(worldId, scripts[, userGesture])`[​](#contentsexecutejavascriptinisolatedworldworldid-scripts-usergesture "Direct link to heading")


* `worldId` Integer - The ID of the world to run the javascript in, `0` is the default world, `999` is the world used by Electron's `contextIsolation` feature. You can provide any integer here.
* `scripts` [WebSource[]](structures/web-source)
* `userGesture` boolean (optional) - Default is `false`.


Returns `Promise<any>` - A promise that resolves with the result of the executed code or is rejected if the result of the code is a rejected promise.


Works like `executeJavaScript` but evaluates `scripts` in an isolated context.


#### 
`contents.setIgnoreMenuShortcuts(ignore)`[​](#contentssetignoremenushortcutsignore "Direct link to heading")


* `ignore` boolean


Ignore application menu shortcuts while this web contents is focused.


#### 
`contents.setWindowOpenHandler(handler)`[​](#contentssetwindowopenhandlerhandler "Direct link to heading")


* `handler` Function<{action: 'deny'} | {action: 'allow', overrideBrowserWindowOptions?: BrowserWindowConstructorOptions}>


	+ `details` Object
		- `url` string - The *resolved* version of the URL passed to `window.open()`. e.g. opening a window with `window.open('foo')` will yield something like `https://the-origin/the/current/path/foo`.
		- `frameName` string - Name of the window provided in `window.open()`
		- `features` string - Comma separated list of window features provided to `window.open()`.
		- `disposition` string - Can be `default`, `foreground-tab`, `background-tab`, `new-window`, `save-to-disk` or `other`.
		- `referrer` [Referrer](structures/referrer) - The referrer that will be passed to the new window. May or may not result in the `Referer` header being sent, depending on the referrer policy.
		- `postBody` [PostBody](structures/post-body) (optional) - The post data that will be sent to the new window, along with the appropriate headers that will be set. If no post data is to be sent, the value will be `null`. Only defined when the window is being created by a form that set `target=_blank`.Returns `{action: 'deny'} | {action: 'allow', overrideBrowserWindowOptions?: BrowserWindowConstructorOptions}` - `deny` cancels the creation of the new window. `allow` will allow the new window to be created. Specifying `overrideBrowserWindowOptions` allows customization of the created window. Returning an unrecognized value such as a null, undefined, or an object without a recognized 'action' value will result in a console error and have the same effect as returning `{action: 'deny'}`.


Called before creating a window a new window is requested by the renderer, e.g. by `window.open()`, a link with `target="_blank"`, shift+clicking on a link, or submitting a form with `<form target="_blank">`. See [`window.open()`](window-open) for more details and how to use this in conjunction with `did-create-window`.


#### 
`contents.setAudioMuted(muted)`[​](#contentssetaudiomutedmuted "Direct link to heading")


* `muted` boolean


Mute the audio on the current web page.


#### 
`contents.isAudioMuted()`[​](#contentsisaudiomuted "Direct link to heading")


Returns `boolean` - Whether this page has been muted.


#### 
`contents.isCurrentlyAudible()`[​](#contentsiscurrentlyaudible "Direct link to heading")


Returns `boolean` - Whether audio is currently playing.


#### 
`contents.setZoomFactor(factor)`[​](#contentssetzoomfactorfactor "Direct link to heading")


* `factor` Double - Zoom factor; default is 1.0.


Changes the zoom factor to the specified factor. Zoom factor is zoom percent divided by 100, so 300% = 3.0.


The factor must be greater than 0.0.


#### 
`contents.getZoomFactor()`[​](#contentsgetzoomfactor "Direct link to heading")


Returns `number` - the current zoom factor.


#### 
`contents.setZoomLevel(level)`[​](#contentssetzoomlevellevel "Direct link to heading")


* `level` number - Zoom level.


Changes the zoom level to the specified level. The original size is 0 and each increment above or below represents zooming 20% larger or smaller to default limits of 300% and 50% of original size, respectively. The formula for this is `scale := 1.2 ^ level`.



> **NOTE**: The zoom policy at the Chromium level is same-origin, meaning that the zoom level for a specific domain propagates across all instances of windows with the same domain. Differentiating the window URLs will make zoom work per-window.
> 
> 


#### 
`contents.getZoomLevel()`[​](#contentsgetzoomlevel "Direct link to heading")


Returns `number` - the current zoom level.


#### 
`contents.setVisualZoomLevelLimits(minimumLevel, maximumLevel)`[​](#contentssetvisualzoomlevellimitsminimumlevel-maximumlevel "Direct link to heading")


* `minimumLevel` number
* `maximumLevel` number


Returns `Promise<void>`


Sets the maximum and minimum pinch-to-zoom level.



> 
> **NOTE**: Visual zoom is disabled by default in Electron. To re-enable it, call:
> 
> 
> 
> 
> ```
> contents.setVisualZoomLevelLimits(1, 3)
> ```
> 
> 
> 


#### 
`contents.undo()`[​](#contentsundo "Direct link to heading")


Executes the editing command `undo` in web page.


#### 
`contents.redo()`[​](#contentsredo "Direct link to heading")


Executes the editing command `redo` in web page.


#### 
`contents.cut()`[​](#contentscut "Direct link to heading")


Executes the editing command `cut` in web page.


#### 
`contents.copy()`[​](#contentscopy "Direct link to heading")


Executes the editing command `copy` in web page.


#### 
`contents.copyImageAt(x, y)`[​](#contentscopyimageatx-y "Direct link to heading")


* `x` Integer
* `y` Integer


Copy the image at the given position to the clipboard.


#### 
`contents.paste()`[​](#contentspaste "Direct link to heading")


Executes the editing command `paste` in web page.


#### 
`contents.pasteAndMatchStyle()`[​](#contentspasteandmatchstyle "Direct link to heading")


Executes the editing command `pasteAndMatchStyle` in web page.


#### 
`contents.delete()`[​](#contentsdelete "Direct link to heading")


Executes the editing command `delete` in web page.


#### 
`contents.selectAll()`[​](#contentsselectall "Direct link to heading")


Executes the editing command `selectAll` in web page.


#### 
`contents.unselect()`[​](#contentsunselect "Direct link to heading")


Executes the editing command `unselect` in web page.


#### 
`contents.replace(text)`[​](#contentsreplacetext "Direct link to heading")


* `text` string


Executes the editing command `replace` in web page.


#### 
`contents.replaceMisspelling(text)`[​](#contentsreplacemisspellingtext "Direct link to heading")


* `text` string


Executes the editing command `replaceMisspelling` in web page.


#### 
`contents.insertText(text)`[​](#contentsinserttexttext "Direct link to heading")


* `text` string


Returns `Promise<void>`


Inserts `text` to the focused element.


#### 
`contents.findInPage(text[, options])`[​](#contentsfindinpagetext-options "Direct link to heading")


* `text` string - Content to be searched, must not be empty.
* `options` Object (optional)
	+ `forward` boolean (optional) - Whether to search forward or backward, defaults to `true`.
	+ `findNext` boolean (optional) - Whether to begin a new text finding session with this request. Should be `true` for initial requests, and `false` for follow-up requests. Defaults to `false`.
	+ `matchCase` boolean (optional) - Whether search should be case-sensitive, defaults to `false`.


Returns `Integer` - The request id used for the request.


Starts a request to find all matches for the `text` in the web page. The result of the request can be obtained by subscribing to [`found-in-page`](web-contents#event-found-in-page) event.


#### 
`contents.stopFindInPage(action)`[​](#contentsstopfindinpageaction "Direct link to heading")


* `action` string - Specifies the action to take place when ending [`webContents.findInPage`] request.
	+ `clearSelection` - Clear the selection.
	+ `keepSelection` - Translate the selection into a normal selection.
	+ `activateSelection` - Focus and click the selection node.


Stops any `findInPage` request for the `webContents` with the provided `action`.




```
const { webContents } = require('electron')
webContents.on('found-in-page', (event, result) => {
  if (result.finalUpdate) webContents.stopFindInPage('clearSelection')
})

const requestId = webContents.findInPage('api')
console.log(requestId)
```


#### 
`contents.capturePage([rect])`[​](#contentscapturepagerect "Direct link to heading")


* `rect` [Rectangle](structures/rectangle) (optional) - The area of the page to be captured.


Returns `Promise<NativeImage>` - Resolves with a [NativeImage](native-image)


Captures a snapshot of the page within `rect`. Omitting `rect` will capture the whole visible page.


#### 
`contents.isBeingCaptured()`[​](#contentsisbeingcaptured "Direct link to heading")


Returns `boolean` - Whether this page is being captured. It returns true when the capturer count is large then 0.


#### 
`contents.incrementCapturerCount([size, stayHidden, stayAwake])`[​](#contentsincrementcapturercountsize-stayhidden-stayawake "Direct link to heading")


* `size` [Size](structures/size) (optional) - The preferred size for the capturer.
* `stayHidden` boolean (optional) - Keep the page hidden instead of visible.
* `stayAwake` boolean (optional) - Keep the system awake instead of allowing it to sleep.


Increase the capturer count by one. The page is considered visible when its browser window is hidden and the capturer count is non-zero. If you would like the page to stay hidden, you should ensure that `stayHidden` is set to true.


This also affects the Page Visibility API.


#### 
`contents.decrementCapturerCount([stayHidden, stayAwake])`[​](#contentsdecrementcapturercountstayhidden-stayawake "Direct link to heading")


* `stayHidden` boolean (optional) - Keep the page in hidden state instead of visible.
* `stayAwake` boolean (optional) - Keep the system awake instead of allowing it to sleep.


Decrease the capturer count by one. The page will be set to hidden or occluded state when its browser window is hidden or occluded and the capturer count reaches zero. If you want to decrease the hidden capturer count instead you should set `stayHidden` to true.


#### 
`contents.getPrinters()` *Deprecated*[​](#contentsgetprinters-deprecated "Direct link to heading")


Get the system printer list.


Returns [PrinterInfo[]](structures/printer-info)


**Deprecated:** Should use the new [`contents.getPrintersAsync`](web-contents#contentsgetprintersasync) API.


#### 
`contents.getPrintersAsync()`[​](#contentsgetprintersasync "Direct link to heading")


Get the system printer list.


Returns `Promise<PrinterInfo[]>` - Resolves with a [PrinterInfo[]](structures/printer-info)


#### 
`contents.print([options], [callback])`[​](#contentsprintoptions-callback "Direct link to heading")


* `options` Object (optional)
	+ `silent` boolean (optional) - Don't ask user for print settings. Default is `false`.
	+ `printBackground` boolean (optional) - Prints the background color and image of the web page. Default is `false`.
	+ `deviceName` string (optional) - Set the printer device name to use. Must be the system-defined name and not the 'friendly' name, e.g 'Brother\_QL\_820NWB' and not 'Brother QL-820NWB'.
	+ `color` boolean (optional) - Set whether the printed web page will be in color or grayscale. Default is `true`.
	+ `margins` Object (optional)
		- `marginType` string (optional) - Can be `default`, `none`, `printableArea`, or `custom`. If `custom` is chosen, you will also need to specify `top`, `bottom`, `left`, and `right`.
		- `top` number (optional) - The top margin of the printed web page, in pixels.
		- `bottom` number (optional) - The bottom margin of the printed web page, in pixels.
		- `left` number (optional) - The left margin of the printed web page, in pixels.
		- `right` number (optional) - The right margin of the printed web page, in pixels.
	+ `landscape` boolean (optional) - Whether the web page should be printed in landscape mode. Default is `false`.
	+ `scaleFactor` number (optional) - The scale factor of the web page.
	+ `pagesPerSheet` number (optional) - The number of pages to print per page sheet.
	+ `collate` boolean (optional) - Whether the web page should be collated.
	+ `copies` number (optional) - The number of copies of the web page to print.
	+ `pageRanges` Object[] (optional) - The page range to print. On macOS, only one range is honored.
		- `from` number - Index of the first page to print (0-based).
		- `to` number - Index of the last page to print (inclusive) (0-based).
	+ `duplexMode` string (optional) - Set the duplex mode of the printed web page. Can be `simplex`, `shortEdge`, or `longEdge`.
	+ `dpi` Record<string, number> (optional)
		- `horizontal` number (optional) - The horizontal dpi.
		- `vertical` number (optional) - The vertical dpi.
	+ `header` string (optional) - string to be printed as page header.
	+ `footer` string (optional) - string to be printed as page footer.
	+ `pageSize` string | Size (optional) - Specify page size of the printed document. Can be `A3`, `A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height`.
* `callback` Function (optional)
	+ `success` boolean - Indicates success of the print call.
	+ `failureReason` string - Error description called back if the print fails.


When a custom `pageSize` is passed, Chromium attempts to validate platform specific minimum values for `width_microns` and `height_microns`. Width and height must both be minimum 353 microns but may be higher on some operating systems.


Prints window's web page. When `silent` is set to `true`, Electron will pick the system's default printer if `deviceName` is empty and the default settings for printing.


Use `page-break-before: always;` CSS style to force to print to a new page.


Example usage:




```
const options = {
  silent: true,
  deviceName: 'My-Printer',
  pageRanges: [{
    from: 0,
    to: 1
  }]
}
win.webContents.print(options, (success, errorType) => {
  if (!success) console.log(errorType)
})
```


#### 
`contents.printToPDF(options)`[​](#contentsprinttopdfoptions "Direct link to heading")


* `options` Object
	+ `headerFooter` Record<string, string> (optional) - the header and footer for the PDF.
		- `title` string - The title for the PDF header.
		- `url` string - the url for the PDF footer.
	+ `landscape` boolean (optional) - `true` for landscape, `false` for portrait.
	+ `marginsType` Integer (optional) - Specifies the type of margins to use. Uses 0 for default margin, 1 for no margin, and 2 for minimum margin.
	+ `scaleFactor` number (optional) - The scale factor of the web page. Can range from 0 to 100.
	+ `pageRanges` Record<string, number> (optional) - The page range to print.
		- `from` number - Index of the first page to print (0-based).
		- `to` number - Index of the last page to print (inclusive) (0-based).
	+ `pageSize` string | Size (optional) - Specify page size of the generated PDF. Can be `A3`, `A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` and `width` in microns.
	+ `printBackground` boolean (optional) - Whether to print CSS backgrounds.
	+ `printSelectionOnly` boolean (optional) - Whether to print selection only.


Returns `Promise<Buffer>` - Resolves with the generated PDF data.


Prints window's web page as PDF with Chromium's preview printing custom settings.


The `landscape` will be ignored if `@page` CSS at-rule is used in the web page.


By default, an empty `options` will be regarded as:




```
{
  marginsType: 0,
  printBackground: false,
  printSelectionOnly: false,
  landscape: false,
  pageSize: 'A4',
  scaleFactor: 100
}
```


Use `page-break-before: always;` CSS style to force to print to a new page.


An example of `webContents.printToPDF`:




```
const { BrowserWindow } = require('electron')
const fs = require('fs')
const path = require('path')
const os = require('os')

const win = new BrowserWindow({ width: 800, height: 600 })
win.loadURL('http://github.com')

win.webContents.on('did-finish-load', () => {
  // Use default printing options
  const pdfPath = path.join(os.homedir(), 'Desktop', 'temp.pdf')
  win.webContents.printToPDF({}).then(data => {
    fs.writeFile(pdfPath, data, (error) => {
      if (error) throw error
      console.log(`Wrote PDF successfully to ${pdfPath}`)
    })
  }).catch(error => {
    console.log(`Failed to write PDF to ${pdfPath}: `, error)
  })
})
```


#### 
`contents.addWorkSpace(path)`[​](#contentsaddworkspacepath "Direct link to heading")


* `path` string


Adds the specified path to DevTools workspace. Must be used after DevTools creation:




```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.webContents.on('devtools-opened', () => {
  win.webContents.addWorkSpace(__dirname)
})
```


#### 
`contents.removeWorkSpace(path)`[​](#contentsremoveworkspacepath "Direct link to heading")


* `path` string


Removes the specified path from DevTools workspace.


#### 
`contents.setDevToolsWebContents(devToolsWebContents)`[​](#contentssetdevtoolswebcontentsdevtoolswebcontents "Direct link to heading")


* `devToolsWebContents` WebContents


Uses the `devToolsWebContents` as the target `WebContents` to show devtools.


The `devToolsWebContents` must not have done any navigation, and it should not be used for other purposes after the call.


By default Electron manages the devtools by creating an internal `WebContents` with native view, which developers have very limited control of. With the `setDevToolsWebContents` method, developers can use any `WebContents` to show the devtools in it, including `BrowserWindow`, `BrowserView` and `<webview>` tag.


Note that closing the devtools does not destroy the `devToolsWebContents`, it is caller's responsibility to destroy `devToolsWebContents`.


An example of showing devtools in a `<webview>` tag:




```
<html>
<head>
  <style type="text/css">
    * { margin: 0; }
    #browser { height: 70%; }
    #devtools { height: 30%; }
  </style>
</head>
<body>
  <webview id="browser" src="https://github.com"></webview>
  <webview id="devtools" src="about:blank"></webview>
  <script>
    const { ipcRenderer } = require('electron')
    const emittedOnce = (element, eventName) => new Promise(resolve => {
      element.addEventListener(eventName, event => resolve(event), { once: true })
    })
    const browserView = document.getElementById('browser')
    const devtoolsView = document.getElementById('devtools')
    const browserReady = emittedOnce(browserView, 'dom-ready')
    const devtoolsReady = emittedOnce(devtoolsView, 'dom-ready')
    Promise.all([browserReady, devtoolsReady]).then(() => {
      const targetId = browserView.getWebContentsId()
      const devtoolsId = devtoolsView.getWebContentsId()
      ipcRenderer.send('open-devtools', targetId, devtoolsId)
    })
  </script>
</body>
</html>
```




```
// Main process
const { ipcMain, webContents } = require('electron')
ipcMain.on('open-devtools', (event, targetContentsId, devtoolsContentsId) => {
  const target = webContents.fromId(targetContentsId)
  const devtools = webContents.fromId(devtoolsContentsId)
  target.setDevToolsWebContents(devtools)
  target.openDevTools()
})
```


An example of showing devtools in a `BrowserWindow`:




```
const { app, BrowserWindow } = require('electron')

let win = null
let devtools = null

app.whenReady().then(() => {
  win = new BrowserWindow()
  devtools = new BrowserWindow()
  win.loadURL('https://github.com')
  win.webContents.setDevToolsWebContents(devtools.webContents)
  win.webContents.openDevTools({ mode: 'detach' })
})
```


#### 
`contents.openDevTools([options])`[​](#contentsopendevtoolsoptions "Direct link to heading")


* `options` Object (optional)
	+ `mode` string - Opens the devtools with specified dock state, can be `left`, `right`, `bottom`, `undocked`, `detach`. Defaults to last used dock state. In `undocked` mode it's possible to dock back. In `detach` mode it's not.
	+ `activate` boolean (optional) - Whether to bring the opened devtools window to the foreground. The default is `true`.


Opens the devtools.


When `contents` is a `<webview>` tag, the `mode` would be `detach` by default, explicitly passing an empty `mode` can force using last used dock state.


On Windows, if Windows Control Overlay is enabled, Devtools will be opened with `mode: 'detach'`.


#### 
`contents.closeDevTools()`[​](#contentsclosedevtools "Direct link to heading")


Closes the devtools.


#### 
`contents.isDevToolsOpened()`[​](#contentsisdevtoolsopened "Direct link to heading")


Returns `boolean` - Whether the devtools is opened.


#### 
`contents.isDevToolsFocused()`[​](#contentsisdevtoolsfocused "Direct link to heading")


Returns `boolean` - Whether the devtools view is focused .


#### 
`contents.toggleDevTools()`[​](#contentstoggledevtools "Direct link to heading")


Toggles the developer tools.


#### 
`contents.inspectElement(x, y)`[​](#contentsinspectelementx-y "Direct link to heading")


* `x` Integer
* `y` Integer


Starts inspecting element at position (`x`, `y`).


#### 
`contents.inspectSharedWorker()`[​](#contentsinspectsharedworker "Direct link to heading")


Opens the developer tools for the shared worker context.


#### 
`contents.inspectSharedWorkerById(workerId)`[​](#contentsinspectsharedworkerbyidworkerid "Direct link to heading")


* `workerId` string


Inspects the shared worker based on its ID.


#### 
`contents.getAllSharedWorkers()`[​](#contentsgetallsharedworkers "Direct link to heading")


Returns [SharedWorkerInfo[]](structures/shared-worker-info) - Information about all Shared Workers.


#### 
`contents.inspectServiceWorker()`[​](#contentsinspectserviceworker "Direct link to heading")


Opens the developer tools for the service worker context.


#### 
`contents.send(channel, ...args)`[​](#contentssendchannel-args "Direct link to heading")


* `channel` string
* `...args` any[]


Send an asynchronous message to the renderer process via `channel`, along with arguments. Arguments will be serialized with the [Structured Clone Algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm), just like [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage), so prototype chains will not be included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will throw an exception.



> **NOTE**: Sending non-standard JavaScript types such as DOM objects or special Electron objects will throw an exception.
> 
> 


The renderer process can handle the message by listening to `channel` with the [`ipcRenderer`](ipc-renderer) module.


An example of sending messages from the main process to the renderer process:




```
// In the main process.
const { app, BrowserWindow } = require('electron')
let win = null

app.whenReady().then(() => {
  win = new BrowserWindow({ width: 800, height: 600 })
  win.loadURL(`file://${__dirname}/index.html`)
  win.webContents.on('did-finish-load', () => {
    win.webContents.send('ping', 'whoooooooh!')
  })
})
```




```
<!-- index.html -->
<html>
<body>
  <script>
    require('electron').ipcRenderer.on('ping', (event, message) => {
      console.log(message) // Prints 'whoooooooh!'
    })
  </script>
</body>
</html>
```


#### 
`contents.sendToFrame(frameId, channel, ...args)`[​](#contentssendtoframeframeid-channel-args "Direct link to heading")


* `frameId` Integer | [number, number] - the ID of the frame to send to, or a pair of `[processId, frameId]` if the frame is in a different process to the main frame.
* `channel` string
* `...args` any[]


Send an asynchronous message to a specific frame in a renderer process via `channel`, along with arguments. Arguments will be serialized with the [Structured Clone Algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm), just like [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage), so prototype chains will not be included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will throw an exception.



> **NOTE:** Sending non-standard JavaScript types such as DOM objects or special Electron objects will throw an exception.
> 
> 


The renderer process can handle the message by listening to `channel` with the [`ipcRenderer`](ipc-renderer) module.


If you want to get the `frameId` of a given renderer context you should use the `webFrame.routingId` value. E.g.




```
// In a renderer process
console.log('My frameId is:', require('electron').webFrame.routingId)
```


You can also read `frameId` from all incoming IPC messages in the main process.




```
// In the main process
ipcMain.on('ping', (event) => {
  console.info('Message came from frameId:', event.frameId)
})
```


#### 
`contents.postMessage(channel, message, [transfer])`[​](#contentspostmessagechannel-message-transfer "Direct link to heading")


* `channel` string
* `message` any
* `transfer` MessagePortMain[] (optional)


Send a message to the renderer process, optionally transferring ownership of zero or more [`MessagePortMain`][] objects.


The transferred `MessagePortMain` objects will be available in the renderer process by accessing the `ports` property of the emitted event. When they arrive in the renderer, they will be native DOM `MessagePort` objects.


For example:




```
// Main process
const { port1, port2 } = new MessageChannelMain()
webContents.postMessage('port', { message: 'hello' }, [port1])

// Renderer process
ipcRenderer.on('port', (e, msg) => {
  const [port] = e.ports
  // ...
})
```


#### 
`contents.enableDeviceEmulation(parameters)`[​](#contentsenabledeviceemulationparameters "Direct link to heading")


* `parameters` Object
	+ `screenPosition` string - Specify the screen type to emulate (default: `desktop`):
		- `desktop` - Desktop screen type.
		- `mobile` - Mobile screen type.
	+ `screenSize` [Size](structures/size) - Set the emulated screen size (screenPosition == mobile).
	+ `viewPosition` [Point](structures/point) - Position the view on the screen (screenPosition == mobile) (default: `{ x: 0, y: 0 }`).
	+ `deviceScaleFactor` Integer - Set the device scale factor (if zero defaults to original device scale factor) (default: `0`).
	+ `viewSize` [Size](structures/size) - Set the emulated view size (empty means no override)
	+ `scale` Float - Scale of emulated view inside available space (not in fit to view mode) (default: `1`).


Enable device emulation with the given parameters.


#### 
`contents.disableDeviceEmulation()`[​](#contentsdisabledeviceemulation "Direct link to heading")


Disable device emulation enabled by `webContents.enableDeviceEmulation`.


#### 
`contents.sendInputEvent(inputEvent)`[​](#contentssendinputeventinputevent "Direct link to heading")


* `inputEvent` [MouseInputEvent](structures/mouse-input-event) | [MouseWheelInputEvent](structures/mouse-wheel-input-event) | [KeyboardInputEvent](structures/keyboard-input-event)


Sends an input `event` to the page. **Note:** The [`BrowserWindow`](browser-window) containing the contents needs to be focused for `sendInputEvent()` to work.


#### 
`contents.beginFrameSubscription([onlyDirty ,]callback)`[​](#contentsbeginframesubscriptiononlydirty-callback "Direct link to heading")


* `onlyDirty` boolean (optional) - Defaults to `false`.
* `callback` Function
	+ `image` [NativeImage](native-image)
	+ `dirtyRect` [Rectangle](structures/rectangle)


Begin subscribing for presentation events and captured frames, the `callback` will be called with `callback(image, dirtyRect)` when there is a presentation event.


The `image` is an instance of [NativeImage](native-image) that stores the captured frame.


The `dirtyRect` is an object with `x, y, width, height` properties that describes which part of the page was repainted. If `onlyDirty` is set to `true`, `image` will only contain the repainted area. `onlyDirty` defaults to `false`.


#### 
`contents.endFrameSubscription()`[​](#contentsendframesubscription "Direct link to heading")


End subscribing for frame presentation events.


#### 
`contents.startDrag(item)`[​](#contentsstartdragitem "Direct link to heading")


* `item` Object
	+ `file` string - The path to the file being dragged.
	+ `files` string[] (optional) - The paths to the files being dragged. (`files` will override `file` field)
	+ `icon` [NativeImage](native-image) | string - The image must be non-empty on macOS.


Sets the `item` as dragging item for current drag-drop operation, `file` is the absolute path of the file to be dragged, and `icon` is the image showing under the cursor when dragging.


#### 
`contents.savePage(fullPath, saveType)`[​](#contentssavepagefullpath-savetype "Direct link to heading")


* `fullPath` string - The absolute file path.
* `saveType` string - Specify the save type.
	+ `HTMLOnly` - Save only the HTML of the page.
	+ `HTMLComplete` - Save complete-html page.
	+ `MHTML` - Save complete-html page as MHTML.


Returns `Promise<void>` - resolves if the page is saved.




```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()

win.loadURL('https://github.com')

win.webContents.on('did-finish-load', async () => {
  win.webContents.savePage('/tmp/test.html', 'HTMLComplete').then(() => {
    console.log('Page was saved successfully.')
  }).catch(err => {
    console.log(err)
  })
})
```


#### 
`contents.showDefinitionForSelection()` *macOS*[​](#contentsshowdefinitionforselection-macos "Direct link to heading")


Shows pop-up dictionary that searches the selected word on the page.


#### 
`contents.isOffscreen()`[​](#contentsisoffscreen "Direct link to heading")


Returns `boolean` - Indicates whether *offscreen rendering* is enabled.


#### 
`contents.startPainting()`[​](#contentsstartpainting "Direct link to heading")


If *offscreen rendering* is enabled and not painting, start painting.


#### 
`contents.stopPainting()`[​](#contentsstoppainting "Direct link to heading")


If *offscreen rendering* is enabled and painting, stop painting.


#### 
`contents.isPainting()`[​](#contentsispainting "Direct link to heading")


Returns `boolean` - If *offscreen rendering* is enabled returns whether it is currently painting.


#### 
`contents.setFrameRate(fps)`[​](#contentssetframeratefps "Direct link to heading")


* `fps` Integer


If *offscreen rendering* is enabled sets the frame rate to the specified number. Only values between 1 and 240 are accepted.


#### 
`contents.getFrameRate()`[​](#contentsgetframerate "Direct link to heading")


Returns `Integer` - If *offscreen rendering* is enabled returns the current frame rate.


#### 
`contents.invalidate()`[​](#contentsinvalidate "Direct link to heading")


Schedules a full repaint of the window this web contents is in.


If *offscreen rendering* is enabled invalidates the frame and generates a new one through the `'paint'` event.


#### 
`contents.getWebRTCIPHandlingPolicy()`[​](#contentsgetwebrtciphandlingpolicy "Direct link to heading")


Returns `string` - Returns the WebRTC IP Handling Policy.


#### 
`contents.setWebRTCIPHandlingPolicy(policy)`[​](#contentssetwebrtciphandlingpolicypolicy "Direct link to heading")


* `policy` string - Specify the WebRTC IP Handling Policy.
	+ `default` - Exposes user's public and local IPs. This is the default behavior. When this policy is used, WebRTC has the right to enumerate all interfaces and bind them to discover public interfaces.
	+ `default_public_interface_only` - Exposes user's public IP, but does not expose user's local IP. When this policy is used, WebRTC should only use the default route used by http. This doesn't expose any local addresses.
	+ `default_public_and_private_interfaces` - Exposes user's public and local IPs. When this policy is used, WebRTC should only use the default route used by http. This also exposes the associated default private address. Default route is the route chosen by the OS on a multi-homed endpoint.
	+ `disable_non_proxied_udp` - Does not expose public or local IPs. When this policy is used, WebRTC should only use TCP to contact peers or servers unless the proxy server supports UDP.


Setting the WebRTC IP handling policy allows you to control which IPs are exposed via WebRTC. See [BrowserLeaks](https://browserleaks.com/webrtc) for more details.


#### 
`contents.getMediaSourceId(requestWebContents)`[​](#contentsgetmediasourceidrequestwebcontents "Direct link to heading")


* `requestWebContents` WebContents - Web contents that the id will be registered to.


Returns `string` - The identifier of a WebContents stream. This identifier can be used with `navigator.mediaDevices.getUserMedia` using a `chromeMediaSource` of `tab`. The identifier is restricted to the web contents that it is registered to and is only valid for 10 seconds.


#### 
`contents.getOSProcessId()`[​](#contentsgetosprocessid "Direct link to heading")


Returns `Integer` - The operating system `pid` of the associated renderer process.


#### 
`contents.getProcessId()`[​](#contentsgetprocessid "Direct link to heading")


Returns `Integer` - The Chromium internal `pid` of the associated renderer. Can be compared to the `frameProcessId` passed by frame specific navigation events (e.g. `did-frame-navigate`)


#### 
`contents.takeHeapSnapshot(filePath)`[​](#contentstakeheapsnapshotfilepath "Direct link to heading")


* `filePath` string - Path to the output file.


Returns `Promise<void>` - Indicates whether the snapshot has been created successfully.


Takes a V8 heap snapshot and saves it to `filePath`.


#### 
`contents.getBackgroundThrottling()`[​](#contentsgetbackgroundthrottling "Direct link to heading")


Returns `boolean` - whether or not this WebContents will throttle animations and timers when the page becomes backgrounded. This also affects the Page Visibility API.


#### 
`contents.setBackgroundThrottling(allowed)`[​](#contentssetbackgroundthrottlingallowed "Direct link to heading")


* `allowed` boolean


Controls whether or not this WebContents will throttle animations and timers when the page becomes backgrounded. This also affects the Page Visibility API.


#### 
`contents.getType()`[​](#contentsgettype "Direct link to heading")


Returns `string` - the type of the webContent. Can be `backgroundPage`, `window`, `browserView`, `remote`, `webview` or `offscreen`.


#### 
`contents.setImageAnimationPolicy(policy)`[​](#contentssetimageanimationpolicypolicy "Direct link to heading")


* `policy` string - Can be `animate`, `animateOnce` or `noAnimation`.


Sets the image animation policy for this webContents. The policy only affects *new* images, existing images that are currently being animated are unaffected. This is a known limitation in Chromium, you can force image animation to be recalculated with `img.src = img.src` which will result in no network traffic but will update the animation policy.


This corresponds to the [animationPolicy](https://developer.chrome.com/docs/extensions/reference/accessibilityFeatures/#property-animationPolicy) accessibility feature in Chromium.


### Instance Properties[​](#instance-properties "Direct link to heading")


#### 
`contents.audioMuted`[​](#contentsaudiomuted "Direct link to heading")


A `boolean` property that determines whether this page is muted.


#### 
`contents.userAgent`[​](#contentsuseragent "Direct link to heading")


A `string` property that determines the user agent for this web page.


#### 
`contents.zoomLevel`[​](#contentszoomlevel "Direct link to heading")


A `number` property that determines the zoom level for this web contents.


The original size is 0 and each increment above or below represents zooming 20% larger or smaller to default limits of 300% and 50% of original size, respectively. The formula for this is `scale := 1.2 ^ level`.


#### 
`contents.zoomFactor`[​](#contentszoomfactor "Direct link to heading")


A `number` property that determines the zoom factor for this web contents.


The zoom factor is the zoom percent divided by 100, so 300% = 3.0.


#### 
`contents.frameRate`[​](#contentsframerate "Direct link to heading")


An `Integer` property that sets the frame rate of the web contents to the specified number. Only values between 1 and 240 are accepted.


Only applicable if *offscreen rendering* is enabled.


#### 
`contents.id` *Readonly*[​](#contentsid-readonly "Direct link to heading")


A `Integer` representing the unique ID of this WebContents. Each ID is unique among all `WebContents` instances of the entire Electron application.


#### 
`contents.session` *Readonly*[​](#contentssession-readonly "Direct link to heading")


A [`Session`](session) used by this webContents.


#### 
`contents.hostWebContents` *Readonly*[​](#contentshostwebcontents-readonly "Direct link to heading")


A [`WebContents`](web-contents) instance that might own this `WebContents`.


#### 
`contents.devToolsWebContents` *Readonly*[​](#contentsdevtoolswebcontents-readonly "Direct link to heading")


A `WebContents | null` property that represents the of DevTools `WebContents` associated with a given `WebContents`.


**Note:** Users should never store this object because it may become `null` when the DevTools has been closed.


#### 
`contents.debugger` *Readonly*[​](#contentsdebugger-readonly "Direct link to heading")


A [`Debugger`](debugger) instance for this webContents.


#### 
`contents.backgroundThrottling`[​](#contentsbackgroundthrottling "Direct link to heading")


A `boolean` property that determines whether or not this WebContents will throttle animations and timers when the page becomes backgrounded. This also affects the Page Visibility API.


#### 
`contents.mainFrame` *Readonly*[​](#contentsmainframe-readonly "Direct link to heading")


A [`WebFrameMain`](web-frame-main) property that represents the top frame of the page's frame hierarchy.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/web-contents>

Offscreen Rendering
===================


Overview[​](#overview "Direct link to heading")
-----------------------------------------------


Offscreen rendering lets you obtain the content of a `BrowserWindow` in a bitmap, so it can be rendered anywhere, for example, on texture in a 3D scene. The offscreen rendering in Electron uses a similar approach to that of the [Chromium Embedded Framework](https://bitbucket.org/chromiumembedded/cef) project.


*Notes*:


* There are two rendering modes that can be used (see the section below) and only the dirty area is passed to the `paint` event to be more efficient.
* You can stop/continue the rendering as well as set the frame rate.
* The maximum frame rate is 240 because greater values bring only performance losses with no benefits.
* When nothing is happening on a webpage, no frames are generated.
* An offscreen window is always created as a [Frameless Window](window-customization)..


### Rendering Modes[​](#rendering-modes "Direct link to heading")


#### GPU accelerated[​](#gpu-accelerated "Direct link to heading")


GPU accelerated rendering means that the GPU is used for composition. Because of that, the frame has to be copied from the GPU which requires more resources, thus this mode is slower than the Software output device. The benefit of this mode is that WebGL and 3D CSS animations are supported.


#### Software output device[​](#software-output-device "Direct link to heading")


This mode uses a software output device for rendering in the CPU, so the frame generation is much faster. As a result, this mode is preferred over the GPU accelerated one.


To enable this mode, GPU acceleration has to be disabled by calling the [`app.disableHardwareAcceleration()`](../api/app#appdisablehardwareacceleration) API.


Example[​](#example "Direct link to heading")
---------------------------------------------




[docs/fiddles/features/offscreen-rendering (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/features/offscreen-rendering)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/features/offscreen-rendering)


* main.js




```
const { app, BrowserWindow } = require('electron')
const fs = require('fs')
const path = require('path')

app.disableHardwareAcceleration()

let win

app.whenReady().then(() => {
  win = new BrowserWindow({ webPreferences: { offscreen: true } })
  win.loadURL('https://github.com')
  win.webContents.on('paint', (event, dirty, image) => {
    fs.writeFileSync('ex.png', image.toPNG())
  })
  win.webContents.setFrameRate(60)
  console.log(`The screenshot has been successfully saved to ${path.join(process.cwd(), 'ex.png')}`)
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})
```




After launching the Electron application, navigate to your application's working folder, where you'll find the rendered image.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/offscreen-rendering>

Window Customization
====================


The `BrowserWindow` module is the foundation of your Electron application, and it exposes many APIs that can change the look and behavior of your browser windows. In this tutorial, we will be going over the various use-cases for window customization on macOS, Windows, and Linux.


Create frameless windows[​](#create-frameless-windows "Direct link to heading")
-------------------------------------------------------------------------------


A frameless window is a window that has no [chrome](https://developer.mozilla.org/en-US/docs/Glossary/Chrome). Not to be confused with the Google Chrome browser, window *chrome* refers to the parts of the window (e.g. toolbars, controls) that are not a part of the web page.


To create a frameless window, you need to set `frame` to `false` in the `BrowserWindow` constructor.



main.js


```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ frame: false })
```



Apply custom title bar styles *macOS* *Windows*[​](#apply-custom-title-bar-styles-macos-windows "Direct link to heading")
-------------------------------------------------------------------------------------------------------------------------


Title bar styles allow you to hide most of a BrowserWindow's chrome while keeping the system's native window controls intact and can be configured with the `titleBarStyle` option in the `BrowserWindow` constructor.


Applying the `hidden` title bar style results in a hidden title bar and a full-size content window.



main.js


```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ titleBarStyle: 'hidden' })
```



### Control the traffic lights *macOS*[​](#control-the-traffic-lights-macos "Direct link to heading")


On macOS, applying the `hidden` title bar style will still expose the standard window controls (“traffic lights”) in the top left.


#### Customize the look of your traffic lights *macOS*[​](#customize-the-look-of-your-traffic-lights-macos "Direct link to heading")


The `customButtonsOnHover` title bar style will hide the traffic lights until you hover over them. This is useful if you want to create custom traffic lights in your HTML but still use the native UI to control the window.




```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ titleBarStyle: 'customButtonsOnHover' })
```


#### Customize the traffic light position *macOS*[​](#customize-the-traffic-light-position-macos "Direct link to heading")


To modify the position of the traffic light window controls, there are two configuration options available.


Applying `hiddenInset` title bar style will shift the vertical inset of the traffic lights by a fixed amount.



main.js


```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ titleBarStyle: 'hiddenInset' })
```



If you need more granular control over the positioning of the traffic lights, you can pass a set of coordinates to the `trafficLightPosition` option in the `BrowserWindow` constructor.



main.js


```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
  titleBarStyle: 'hidden',
  trafficLightPosition: { x: 10, y: 10 }
})
```



#### Show and hide the traffic lights programmatically *macOS*[​](#show-and-hide-the-traffic-lights-programmatically-macos "Direct link to heading")


You can also show and hide the traffic lights programmatically from the main process. The `win.setWindowButtonVisibility` forces traffic lights to be show or hidden depending on the value of its boolean parameter.



main.js


```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
// hides the traffic lights
win.setWindowButtonVisibility(false)
```




> Note: Given the number of APIs available, there are many ways of achieving this. For instance, combining `frame: false` with `win.setWindowButtonVisibility(true)` will yield the same layout outcome as setting `titleBarStyle: 'hidden'`.
> 
> 


Window Controls Overlay *macOS* *Windows*[​](#window-controls-overlay-macos-windows "Direct link to heading")
-------------------------------------------------------------------------------------------------------------


The [Window Controls Overlay API](https://github.com/WICG/window-controls-overlay/blob/main/explainer.md) is a web standard that gives web apps the ability to customize their title bar region when installed on desktop. Electron exposes this API through the `BrowserWindow` constructor option `titleBarOverlay`.


This option only works whenever a custom `titlebarStyle` is applied on macOS or Windows. When `titleBarOverlay` is enabled, the window controls become exposed in their default position, and DOM elements cannot use the area underneath this region.


The `titleBarOverlay` option accepts two different value formats.


Specifying `true` on either platform will result in an overlay region with default system colors:



main.js


```
// on macOS or Windows
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
  titleBarStyle: 'hidden',
  titleBarOverlay: true
})
```



On Windows, you can also specify additional parameters. The color of the overlay and its symbols can be specified by setting `titleBarOverlay` to an object and using the `color` and `symbolColor` properties respectively. The height of the overlay can also be specified with the `height` property.


If a color option is not specified, the color will default to its system color for the window control buttons. Similarly, if the height option is not specified it will default to the default height:



main.js


```
// on Windows
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({
  titleBarStyle: 'hidden',
  titleBarOverlay: {
    color: '#2f3241',
    symbolColor: '#74b1be',
    height: 60
  }
})
```




> Note: Once your title bar overlay is enabled from the main process, you can access the overlay's color and dimension values from a renderer using a set of readonly [JavaScript APIs](https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#javascript-apis) and [CSS Environment Variables](https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#css-environment-variables).
> 
> 


### Limitations[​](#limitations "Direct link to heading")


* Transparent colors are currently not supported. Progress updates for this feature can be found in PR [#33567](https://github.com/electron/electron/issues/33567).


Create transparent windows[​](#create-transparent-windows "Direct link to heading")
-----------------------------------------------------------------------------------


By setting the `transparent` option to `true`, you can make a fully transparent window.



main.js


```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow({ transparent: true })
```



### Limitations[​](#limitations-1 "Direct link to heading")


* You cannot click through the transparent area. See [#1335](https://github.com/electron/electron/issues/1335) for details.
* Transparent windows are not resizable. Setting `resizable` to `true` may make a transparent window stop working on some platforms.
* The CSS [`blur()`](https://developer.mozilla.org/en-US/docs/Web/CSS/filter-function/blur()) filter only applies to the window's web contents, so there is no way to apply blur effect to the content below the window (i.e. other applications open on the user's system).
* The window will not be transparent when DevTools is opened.
* On *Windows*:
	+ Transparent windows will not work when DWM is disabled.
	+ Transparent windows can not be maximized using the Windows system menu or by double clicking the title bar. The reasoning behind this can be seen on PR [#28207](https://github.com/electron/electron/pull/28207).
* On *macOS*:
	+ The native window shadow will not be shown on a transparent window.


Create click-through windows[​](#create-click-through-windows "Direct link to heading")
---------------------------------------------------------------------------------------


To create a click-through window, i.e. making the window ignore all mouse events, you can call the [win.setIgnoreMouseEvents(ignore)](../api/browser-window#winsetignoremouseeventsignore-options) API:



main.js


```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.setIgnoreMouseEvents(true)
```



### Forward mouse events *macOS* *Windows*[​](#forward-mouse-events-macos-windows "Direct link to heading")


Ignoring mouse messages makes the web contents oblivious to mouse movement, meaning that mouse movement events will not be emitted. On Windows and macOS, an optional parameter can be used to forward mouse move messages to the web page, allowing events such as `mouseleave` to be emitted:



main.js


```
const { BrowserWindow, ipcMain } = require('electron')
const path = require('path')

const win = new BrowserWindow({
  webPreferences: {
    preload: path.join(__dirname, 'preload.js')
  }
})

ipcMain.on('set-ignore-mouse-events', (event, ...args) => {
  const win = BrowserWindow.fromWebContents(event.sender)
  win.setIgnoreMouseEvents(...args)
})
```




preload.js


```
window.addEventListener('DOMContentLoaded', () => {
  const el = document.getElementById('clickThroughElement')
  el.addEventListener('mouseenter', () => {
    ipcRenderer.send('set-ignore-mouse-events', true, { forward: true })
  })
  el.addEventListener('mouseleave', () => {
    ipcRenderer.send('set-ignore-mouse-events', false)
  })
})
```



This makes the web page click-through when over the `#clickThroughElement` element, and returns to normal outside it.


Set custom draggable region[​](#set-custom-draggable-region "Direct link to heading")
-------------------------------------------------------------------------------------


By default, the frameless window is non-draggable. Apps need to specify `-webkit-app-region: drag` in CSS to tell Electron which regions are draggable (like the OS's standard titlebar), and apps can also use `-webkit-app-region: no-drag` to exclude the non-draggable area from the draggable region. Note that only rectangular shapes are currently supported.


To make the whole window draggable, you can add `-webkit-app-region: drag` as `body`'s style:



styles.css


```
body {
  -webkit-app-region: drag;
}
```



And note that if you have made the whole window draggable, you must also mark buttons as non-draggable, otherwise it would be impossible for users to click on them:



styles.css


```
button {
  -webkit-app-region: no-drag;
}
```



If you're only setting a custom titlebar as draggable, you also need to make all buttons in titlebar non-draggable.


### Tip: disable text selection[​](#tip-disable-text-selection "Direct link to heading")


When creating a draggable region, the dragging behavior may conflict with text selection. For example, when you drag the titlebar, you may accidentally select its text contents. To prevent this, you need to disable text selection within a draggable area like this:




```
.titlebar {
  -webkit-user-select: none;
  -webkit-app-region: drag;
}
```


### Tip: disable context menus[​](#tip-disable-context-menus "Direct link to heading")


On some platforms, the draggable area will be treated as a non-client frame, so when you right click on it, a system menu will pop up. To make the context menu behave correctly on all platforms, you should never use a custom context menu on draggable areas.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/window-customization>

Application Packaging
=====================

To distribute your app with Electron, you need to package and rebrand it. To do this, you can either use specialized tooling or manual approaches.


With tooling[​](#with-tooling "Direct link to heading")
-------------------------------------------------------


There are a couple tools out there that exist to package and distribute your Electron app. We recommend using [Electron Forge](https://www.electronforge.io). You can check out its documentation directly, or refer to the [Packaging and Distribution](tutorial-packaging) part of the Electron tutorial.


Manual packaging[​](#manual-packaging "Direct link to heading")
---------------------------------------------------------------


If you prefer the manual approach, there are 2 ways to distribute your application:


* With prebuilt binaries
* With an app source code archive


### With prebuilt binaries[​](#with-prebuilt-binaries "Direct link to heading")


To distribute your app manually, you need to download Electron's [prebuilt binaries](https://github.com/electron/electron/releases). Next, the folder containing your app should be named `app` and placed in Electron's resources directory as shown in the following examples.




note
The location of Electron's prebuilt binaries is indicated with `electron/` in the examples below.




macOS


```
electron/Electron.app/Contents/Resources/app/
├── package.json
├── main.js
└── index.html
```




Windows and Linux


```
electron/resources/app
├── package.json
├── main.js
└── index.html
```



Then execute `Electron.app` on macOS, `electron` on Linux, or `electron.exe` on Windows, and Electron will start as your app. The `electron` directory will then be your distribution to deliver to users.


### With an app source code archive (asar)[​](#with-an-app-source-code-archive-asar "Direct link to heading")


Instead of shipping your app by copying all of its source files, you can package your app into an [asar](https://github.com/electron/asar) archive to improve the performance of reading files on platforms like Windows, if you are not already using a bundler such as Parcel or Webpack.


To use an `asar` archive to replace the `app` folder, you need to rename the archive to `app.asar`, and put it under Electron's resources directory like below, and Electron will then try to read the archive and start from it.



macOS


```
electron/Electron.app/Contents/Resources/
└── app.asar
```




Windows


```
electron/resources/
└── app.asar
```



You can find more details on how to use `asar` in the [`electron/asar` repository](https://github.com/electron/asar).


### Rebranding with downloaded binaries[​](#rebranding-with-downloaded-binaries "Direct link to heading")


After bundling your app into Electron, you will want to rebrand Electron before distributing it to users.


* **Windows:** You can rename `electron.exe` to any name you like, and edit its icon and other information with tools like [rcedit](https://github.com/electron/rcedit).
* **Linux:** You can rename the `electron` executable to any name you like.
* **macOS:** You can rename `Electron.app` to any name you want, and you also have to rename the `CFBundleDisplayName`, `CFBundleIdentifier` and `CFBundleName` fields in the following files:


	+ `Electron.app/Contents/Info.plist`
	+ `Electron.app/Contents/Frameworks/Electron Helper.app/Contents/Info.plist`You can also rename the helper app to avoid showing `Electron Helper` in the Activity Monitor, but make sure you have renamed the helper app's executable file's name.


The structure of a renamed app would be like:




```
MyApp.app/Contents
├── Info.plist
├── MacOS/
│   └── MyApp
└── Frameworks/
    └── MyApp Helper.app
        ├── Info.plist
        └── MacOS/
            └── MyApp Helper
```




note

it is also possible to rebrand Electron by changing the product name and building it from source. To do this you need to set the build argument corresponding to the product name (`electron_product_name = "YourProductName"`) in the `args.gn` file and rebuild.


Keep in mind this is not recommended as setting up the environment to compile from source is not trivial and takes significant time.





 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/application-distribution>

Class: ClientRequest
====================

Class: ClientRequest[​](#class-clientrequest "Direct link to heading")
----------------------------------------------------------------------



> Make HTTP/HTTPS requests.
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


`ClientRequest` implements the [Writable Stream](https://nodejs.org/api/stream.html#stream_writable_streams) interface and is therefore an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter).


### 
`new ClientRequest(options)`[​](#new-clientrequestoptions "Direct link to heading")


* `options` (Object | string) - If `options` is a string, it is interpreted as the request URL. If it is an object, it is expected to fully specify an HTTP request via the following properties:
	+ `method` string (optional) - The HTTP request method. Defaults to the GET method.
	+ `url` string (optional) - The request URL. Must be provided in the absolute form with the protocol scheme specified as http or https.
	+ `session` Session (optional) - The [`Session`](session) instance with which the request is associated.
	+ `partition` string (optional) - The name of the [`partition`](session) with which the request is associated. Defaults to the empty string. The `session` option supersedes `partition`. Thus if a `session` is explicitly specified, `partition` is ignored.
	+ `credentials` string (optional) - Can be `include` or `omit`. Whether to send [credentials](https://fetch.spec.whatwg.org/#credentials) with this request. If set to `include`, credentials from the session associated with the request will be used. If set to `omit`, credentials will not be sent with the request (and the `'login'` event will not be triggered in the event of a 401). This matches the behavior of the [fetch](https://fetch.spec.whatwg.org/#concept-request-credentials-mode) option of the same name. If this option is not specified, authentication data from the session will be sent, and cookies will not be sent (unless `useSessionCookies` is set).
	+ `useSessionCookies` boolean (optional) - Whether to send cookies with this request from the provided session. If `credentials` is specified, this option has no effect. Default is `false`.
	+ `protocol` string (optional) - Can be `http:` or `https:`. The protocol scheme in the form 'scheme:'. Defaults to 'http:'.
	+ `host` string (optional) - The server host provided as a concatenation of the hostname and the port number 'hostname:port'.
	+ `hostname` string (optional) - The server host name.
	+ `port` Integer (optional) - The server's listening port number.
	+ `path` string (optional) - The path part of the request URL.
	+ `redirect` string (optional) - Can be `follow`, `error` or `manual`. The redirect mode for this request. When mode is `error`, any redirection will be aborted. When mode is `manual` the redirection will be cancelled unless [`request.followRedirect`](#requestfollowredirect) is invoked synchronously during the [`redirect`](#event-redirect) event. Defaults to `follow`.
	+ `origin` string (optional) - The origin URL of the request.


`options` properties such as `protocol`, `host`, `hostname`, `port` and `path` strictly follow the Node.js model as described in the [URL](https://nodejs.org/api/url.html) module.


For instance, we could have created the same request to 'github.com' as follows:




```
const request = net.request({
  method: 'GET',
  protocol: 'https:',
  hostname: 'github.com',
  port: 443,
  path: '/'
})
```


### Instance Events[​](#instance-events "Direct link to heading")


#### Event: 'response'[​](#event-response "Direct link to heading")


Returns:


* `response` [IncomingMessage](incoming-message) - An object representing the HTTP response message.


#### Event: 'login'[​](#event-login "Direct link to heading")


Returns:


* `authInfo` Object
	+ `isProxy` boolean
	+ `scheme` string
	+ `host` string
	+ `port` Integer
	+ `realm` string
* `callback` Function
	+ `username` string (optional)
	+ `password` string (optional)


Emitted when an authenticating proxy is asking for user credentials.


The `callback` function is expected to be called back with user credentials:


* `username` string
* `password` string




```
request.on('login', (authInfo, callback) => {
  callback('username', 'password')
})
```


Providing empty credentials will cancel the request and report an authentication error on the response object:




```
request.on('response', (response) => {
  console.log(`STATUS: ${response.statusCode}`);
  response.on('error', (error) => {
    console.log(`ERROR: ${JSON.stringify(error)}`)
  })
})
request.on('login', (authInfo, callback) => {
  callback()
})
```


#### Event: 'finish'[​](#event-finish "Direct link to heading")


Emitted just after the last chunk of the `request`'s data has been written into the `request` object.


#### Event: 'abort'[​](#event-abort "Direct link to heading")


Emitted when the `request` is aborted. The `abort` event will not be fired if the `request` is already closed.


#### Event: 'error'[​](#event-error "Direct link to heading")


Returns:


* `error` Error - an error object providing some information about the failure.


Emitted when the `net` module fails to issue a network request. Typically when the `request` object emits an `error` event, a `close` event will subsequently follow and no response object will be provided.


#### Event: 'close'[​](#event-close "Direct link to heading")


Emitted as the last event in the HTTP request-response transaction. The `close` event indicates that no more events will be emitted on either the `request` or `response` objects.


#### Event: 'redirect'[​](#event-redirect "Direct link to heading")


Returns:


* `statusCode` Integer
* `method` string
* `redirectUrl` string
* `responseHeaders` Record<string, string[]>


Emitted when the server returns a redirect response (e.g. 301 Moved Permanently). Calling [`request.followRedirect`](#requestfollowredirect) will continue with the redirection. If this event is handled, [`request.followRedirect`](#requestfollowredirect) must be called **synchronously**, otherwise the request will be cancelled.


### Instance Properties[​](#instance-properties "Direct link to heading")


#### 
`request.chunkedEncoding`[​](#requestchunkedencoding "Direct link to heading")


A `boolean` specifying whether the request will use HTTP chunked transfer encoding or not. Defaults to false. The property is readable and writable, however it can be set only before the first write operation as the HTTP headers are not yet put on the wire. Trying to set the `chunkedEncoding` property after the first write will throw an error.


Using chunked encoding is strongly recommended if you need to send a large request body as data will be streamed in small chunks instead of being internally buffered inside Electron process memory.


### Instance Methods[​](#instance-methods "Direct link to heading")


#### 
`request.setHeader(name, value)`[​](#requestsetheadername-value "Direct link to heading")


* `name` string - An extra HTTP header name.
* `value` string - An extra HTTP header value.


Adds an extra HTTP header. The header name will be issued as-is without lowercasing. It can be called only before first write. Calling this method after the first write will throw an error. If the passed value is not a `string`, its `toString()` method will be called to obtain the final value.


Certain headers are restricted from being set by apps. These headers are listed below. More information on restricted headers can be found in [Chromium's header utils](https://source.chromium.org/chromium/chromium/src/+/main:services/network/public/cpp/header_util.cc;drc=1562cab3f1eda927938f8f4a5a91991fefde66d3;bpv=1;bpt=1;l=22).


* `Content-Length`
* `Host`
* `Trailer` or `Te`
* `Upgrade`
* `Cookie2`
* `Keep-Alive`
* `Transfer-Encoding`


Additionally, setting the `Connection` header to the value `upgrade` is also disallowed.


#### 
`request.getHeader(name)`[​](#requestgetheadername "Direct link to heading")


* `name` string - Specify an extra header name.


Returns `string` - The value of a previously set extra header name.


#### 
`request.removeHeader(name)`[​](#requestremoveheadername "Direct link to heading")


* `name` string - Specify an extra header name.


Removes a previously set extra header name. This method can be called only before first write. Trying to call it after the first write will throw an error.


#### 
`request.write(chunk[, encoding][, callback])`[​](#requestwritechunk-encoding-callback "Direct link to heading")


* `chunk` (string | Buffer) - A chunk of the request body's data. If it is a string, it is converted into a Buffer using the specified encoding.
* `encoding` string (optional) - Used to convert string chunks into Buffer objects. Defaults to 'utf-8'.
* `callback` Function (optional) - Called after the write operation ends.


`callback` is essentially a dummy function introduced in the purpose of keeping similarity with the Node.js API. It is called asynchronously in the next tick after `chunk` content have been delivered to the Chromium networking layer. Contrary to the Node.js implementation, it is not guaranteed that `chunk` content have been flushed on the wire before `callback` is called.


Adds a chunk of data to the request body. The first write operation may cause the request headers to be issued on the wire. After the first write operation, it is not allowed to add or remove a custom header.


#### 
`request.end([chunk][, encoding][, callback])`[​](#requestendchunk-encoding-callback "Direct link to heading")


* `chunk` (string | Buffer) (optional)
* `encoding` string (optional)
* `callback` Function (optional)


Sends the last chunk of the request data. Subsequent write or end operations will not be allowed. The `finish` event is emitted just after the end operation.


#### 
`request.abort()`[​](#requestabort "Direct link to heading")


Cancels an ongoing HTTP transaction. If the request has already emitted the `close` event, the abort operation will have no effect. Otherwise an ongoing event will emit `abort` and `close` events. Additionally, if there is an ongoing response object,it will emit the `aborted` event.


#### 
`request.followRedirect()`[​](#requestfollowredirect "Direct link to heading")


Continues any pending redirection. Can only be called during a `'redirect'` event.


#### 
`request.getUploadProgress()`[​](#requestgetuploadprogress "Direct link to heading")


Returns `Object`:


* `active` boolean - Whether the request is currently active. If this is false no other properties will be set
* `started` boolean - Whether the upload has started. If this is false both `current` and `total` will be set to 0.
* `current` Integer - The number of bytes that have been uploaded so far
* `total` Integer - The number of bytes that will be uploaded this request


You can use this method in conjunction with `POST` requests to get the progress of a file upload or other data transfer.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/client-request>

Class: Debugger
===============

Class: Debugger[​](#class-debugger "Direct link to heading")
------------------------------------------------------------



> An alternate transport for Chrome's remote debugging protocol.
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


Chrome Developer Tools has a [special binding](https://chromedevtools.github.io/devtools-protocol/) available at JavaScript runtime that allows interacting with pages and instrumenting them.




```
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()

try {
  win.webContents.debugger.attach('1.1')
} catch (err) {
  console.log('Debugger attach failed : ', err)
}

win.webContents.debugger.on('detach', (event, reason) => {
  console.log('Debugger detached due to : ', reason)
})

win.webContents.debugger.on('message', (event, method, params) => {
  if (method === 'Network.requestWillBeSent') {
    if (params.request.url === 'https://www.github.com') {
      win.webContents.debugger.detach()
    }
  }
})

win.webContents.debugger.sendCommand('Network.enable')
```


### Instance Events[​](#instance-events "Direct link to heading")


#### Event: 'detach'[​](#event-detach "Direct link to heading")


Returns:


* `event` Event
* `reason` string - Reason for detaching debugger.


Emitted when the debugging session is terminated. This happens either when `webContents` is closed or devtools is invoked for the attached `webContents`.


#### Event: 'message'[​](#event-message "Direct link to heading")


Returns:


* `event` Event
* `method` string - Method name.
* `params` any - Event parameters defined by the 'parameters' attribute in the remote debugging protocol.
* `sessionId` string - Unique identifier of attached debugging session, will match the value sent from `debugger.sendCommand`.


Emitted whenever the debugging target issues an instrumentation event.


### Instance Methods[​](#instance-methods "Direct link to heading")


#### 
`debugger.attach([protocolVersion])`[​](#debuggerattachprotocolversion "Direct link to heading")


* `protocolVersion` string (optional) - Requested debugging protocol version.


Attaches the debugger to the `webContents`.


#### 
`debugger.isAttached()`[​](#debuggerisattached "Direct link to heading")


Returns `boolean` - Whether a debugger is attached to the `webContents`.


#### 
`debugger.detach()`[​](#debuggerdetach "Direct link to heading")


Detaches the debugger from the `webContents`.


#### 
`debugger.sendCommand(method[, commandParams, sessionId])`[​](#debuggersendcommandmethod-commandparams-sessionid "Direct link to heading")


* `method` string - Method name, should be one of the methods defined by the [remote debugging protocol](https://chromedevtools.github.io/devtools-protocol/).
* `commandParams` any (optional) - JSON object with request parameters.
* `sessionId` string (optional) - send command to the target with associated debugging session id. The initial value can be obtained by sending [Target.attachToTarget](https://chromedevtools.github.io/devtools-protocol/tot/Target/#method-attachToTarget) message.


Returns `Promise<any>` - A promise that resolves with the response defined by the 'returns' attribute of the command description in the remote debugging protocol or is rejected indicating the failure of the command.


Send given command to the debugging target.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/debugger>

nativeTheme
===========



> Read and respond to changes in Chromium's native color theme.
> 
> 


Process: [Main](../glossary#main-process)


Events[​](#events "Direct link to heading")
-------------------------------------------


The `nativeTheme` module emits the following events:


### Event: 'updated'[​](#event-updated "Direct link to heading")


Emitted when something in the underlying NativeTheme has changed. This normally means that either the value of `shouldUseDarkColors`, `shouldUseHighContrastColors` or `shouldUseInvertedColorScheme` has changed. You will have to check them to determine which one has changed.


Properties[​](#properties "Direct link to heading")
---------------------------------------------------


The `nativeTheme` module has the following properties:


### 
`nativeTheme.shouldUseDarkColors` *Readonly*[​](#nativethemeshouldusedarkcolors-readonly "Direct link to heading")


A `boolean` for if the OS / Chromium currently has a dark mode enabled or is being instructed to show a dark-style UI. If you want to modify this value you should use `themeSource` below.


### 
`nativeTheme.themeSource`[​](#nativethemethemesource "Direct link to heading")


A `string` property that can be `system`, `light` or `dark`. It is used to override and supersede the value that Chromium has chosen to use internally.


Setting this property to `system` will remove the override and everything will be reset to the OS default. By default `themeSource` is `system`.


Settings this property to `dark` will have the following effects:


* `nativeTheme.shouldUseDarkColors` will be `true` when accessed
* Any UI Electron renders on Linux and Windows including context menus, devtools, etc. will use the dark UI.
* Any UI the OS renders on macOS including menus, window frames, etc. will use the dark UI.
* The [`prefers-color-scheme`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) CSS query will match `dark` mode.
* The `updated` event will be emitted


Settings this property to `light` will have the following effects:


* `nativeTheme.shouldUseDarkColors` will be `false` when accessed
* Any UI Electron renders on Linux and Windows including context menus, devtools, etc. will use the light UI.
* Any UI the OS renders on macOS including menus, window frames, etc. will use the light UI.
* The [`prefers-color-scheme`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) CSS query will match `light` mode.
* The `updated` event will be emitted


The usage of this property should align with a classic "dark mode" state machine in your application where the user has three options.


* `Follow OS` --> `themeSource = 'system'`
* `Dark Mode` --> `themeSource = 'dark'`
* `Light Mode` --> `themeSource = 'light'`


Your application should then always use `shouldUseDarkColors` to determine what CSS to apply.


### 
`nativeTheme.shouldUseHighContrastColors` *macOS* *Windows* *Readonly*[​](#nativethemeshouldusehighcontrastcolors-macos-windows-readonly "Direct link to heading")


A `boolean` for if the OS / Chromium currently has high-contrast mode enabled or is being instructed to show a high-contrast UI.


### 
`nativeTheme.shouldUseInvertedColorScheme` *macOS* *Windows* *Readonly*[​](#nativethemeshoulduseinvertedcolorscheme-macos-windows-readonly "Direct link to heading")


A `boolean` for if the OS / Chromium currently has an inverted color scheme or is being instructed to use an inverted color scheme.


### 
`nativeTheme.inForcedColorsMode` *Windows* *Readonly*[​](#nativethemeinforcedcolorsmode-windows-readonly "Direct link to heading")


A `boolean` indicating whether Chromium is in forced colors mode, controlled by system accessibility settings. Currently, Windows high contrast is the only system setting that triggers forced colors mode.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/native-theme>

Class: MenuItem
===============

Class: MenuItem[​](#class-menuitem "Direct link to heading")
------------------------------------------------------------



> Add items to native application menus and context menus.
> 
> 


Process: [Main](../glossary#main-process)


See [`Menu`](menu) for examples.


### 
`new MenuItem(options)`[​](#new-menuitemoptions "Direct link to heading")


* `options` Object
	+ `click` Function (optional) - Will be called with `click(menuItem, browserWindow, event)` when the menu item is clicked.
		- `menuItem` MenuItem
		- `browserWindow` [BrowserWindow](browser-window) | undefined - This will not be defined if no window is open.
		- `event` [KeyboardEvent](structures/keyboard-event)
	+ `role` string (optional) - Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteAndMatchStyle`, `delete`, `selectAll`, `reload`, `forceReload`, `toggleDevTools`, `resetZoom`, `zoomIn`, `zoomOut`, `toggleSpellChecker`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideOthers`, `unhide`, `quit`, 'showSubstitutions', 'toggleSmartQuotes', 'toggleSmartDashes', 'toggleTextReplacement', `startSpeaking`, `stopSpeaking`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu`, `shareMenu`, `recentDocuments`, `toggleTabBar`, `selectNextTab`, `selectPreviousTab`, `mergeAllWindows`, `clearRecentDocuments`, `moveTabToNewWindow` or `windowMenu` - Define the action of the menu item, when specified the `click` property will be ignored. See [roles](#roles).
	+ `type` string (optional) - Can be `normal`, `separator`, `submenu`, `checkbox` or `radio`.
	+ `label` string (optional)
	+ `sublabel` string (optional)
	+ `toolTip` string (optional) *macOS* - Hover text for this menu item.
	+ `accelerator` [Accelerator](accelerator) (optional)
	+ `icon` ([NativeImage](native-image) | string) (optional)
	+ `enabled` boolean (optional) - If false, the menu item will be greyed out and unclickable.
	+ `acceleratorWorksWhenHidden` boolean (optional) *macOS* - default is `true`, and when `false` will prevent the accelerator from triggering the item if the item is not visible`.
	+ `visible` boolean (optional) - If false, the menu item will be entirely hidden.
	+ `checked` boolean (optional) - Should only be specified for `checkbox` or `radio` type menu items.
	+ `registerAccelerator` boolean (optional) *Linux* *Windows* - If false, the accelerator won't be registered with the system, but it will still be displayed. Defaults to true.
	+ `sharingItem` SharingItem (optional) *macOS* - The item to share when the `role` is `shareMenu`.
	+ `submenu` (MenuItemConstructorOptions[] | [Menu](menu)) (optional) - Should be specified for `submenu` type menu items. If `submenu` is specified, the `type: 'submenu'` can be omitted. If the value is not a [`Menu`](menu) then it will be automatically converted to one using `Menu.buildFromTemplate`.
	+ `id` string (optional) - Unique within a single menu. If defined then it can be used as a reference to this item by the position attribute.
	+ `before` string[] (optional) - Inserts this item before the item with the specified label. If the referenced item doesn't exist the item will be inserted at the end of the menu. Also implies that the menu item in question should be placed in the same “group” as the item.
	+ `after` string[] (optional) - Inserts this item after the item with the specified label. If the referenced item doesn't exist the item will be inserted at the end of the menu.
	+ `beforeGroupContaining` string[] (optional) - Provides a means for a single context menu to declare the placement of their containing group before the containing group of the item with the specified label.
	+ `afterGroupContaining` string[] (optional) - Provides a means for a single context menu to declare the placement of their containing group after the containing group of the item with the specified label.


**Note:** `acceleratorWorksWhenHidden` is specified as being macOS-only because accelerators always work when items are hidden on Windows and Linux. The option is exposed to users to give them the option to turn it off, as this is possible in native macOS development. This property is only usable on macOS High Sierra 10.13 or newer.


### Roles[​](#roles "Direct link to heading")


Roles allow menu items to have predefined behaviors.


It is best to specify `role` for any menu item that matches a standard role, rather than trying to manually implement the behavior in a `click` function. The built-in `role` behavior will give the best native experience.


The `label` and `accelerator` values are optional when using a `role` and will default to appropriate values for each platform.


Every menu item must have either a `role`, `label`, or in the case of a separator a `type`.


The `role` property can have following values:


* `undo`
* `about` - Trigger a native about panel (custom message box on Window, which does not provide its own).
* `redo`
* `cut`
* `copy`
* `paste`
* `pasteAndMatchStyle`
* `selectAll`
* `delete`
* `minimize` - Minimize current window.
* `close` - Close current window.
* `quit` - Quit the application.
* `reload` - Reload the current window.
* `forceReload` - Reload the current window ignoring the cache.
* `toggleDevTools` - Toggle developer tools in the current window.
* `togglefullscreen` - Toggle full screen mode on the current window.
* `resetZoom` - Reset the focused page's zoom level to the original size.
* `zoomIn` - Zoom in the focused page by 10%.
* `zoomOut` - Zoom out the focused page by 10%.
* `toggleSpellChecker` - Enable/disable builtin spell checker.
* `fileMenu` - Whole default "File" menu (Close / Quit)
* `editMenu` - Whole default "Edit" menu (Undo, Copy, etc.).
* `viewMenu` - Whole default "View" menu (Reload, Toggle Developer Tools, etc.)
* `windowMenu` - Whole default "Window" menu (Minimize, Zoom, etc.).


The following additional roles are available on *macOS*:


* `appMenu` - Whole default "App" menu (About, Services, etc.)
* `hide` - Map to the `hide` action.
* `hideOthers` - Map to the `hideOtherApplications` action.
* `unhide` - Map to the `unhideAllApplications` action.
* `showSubstitutions` - Map to the `orderFrontSubstitutionsPanel` action.
* `toggleSmartQuotes` - Map to the `toggleAutomaticQuoteSubstitution` action.
* `toggleSmartDashes` - Map to the `toggleAutomaticDashSubstitution` action.
* `toggleTextReplacement` - Map to the `toggleAutomaticTextReplacement` action.
* `startSpeaking` - Map to the `startSpeaking` action.
* `stopSpeaking` - Map to the `stopSpeaking` action.
* `front` - Map to the `arrangeInFront` action.
* `zoom` - Map to the `performZoom` action.
* `toggleTabBar` - Map to the `toggleTabBar` action.
* `selectNextTab` - Map to the `selectNextTab` action.
* `selectPreviousTab` - Map to the `selectPreviousTab` action.
* `mergeAllWindows` - Map to the `mergeAllWindows` action.
* `moveTabToNewWindow` - Map to the `moveTabToNewWindow` action.
* `window` - The submenu is a "Window" menu.
* `help` - The submenu is a "Help" menu.
* `services` - The submenu is a ["Services"](https://developer.apple.com/documentation/appkit/nsapplication/1428608-servicesmenu?language=objc) menu. This is only intended for use in the Application Menu and is *not* the same as the "Services" submenu used in context menus in macOS apps, which is not implemented in Electron.
* `recentDocuments` - The submenu is an "Open Recent" menu.
* `clearRecentDocuments` - Map to the `clearRecentDocuments` action.
* `shareMenu` - The submenu is [share menu](https://developer.apple.com/design/human-interface-guidelines/macos/extensions/share-extensions/). The `sharingItem` property must also be set to indicate the item to share.


When specifying a `role` on macOS, `label` and `accelerator` are the only options that will affect the menu item. All other options will be ignored. Lowercase `role`, e.g. `toggledevtools`, is still supported.


**Note:** The `enabled` and `visibility` properties are not available for top-level menu items in the tray on macOS.


### Instance Properties[​](#instance-properties "Direct link to heading")


The following properties are available on instances of `MenuItem`:


#### 
`menuItem.id`[​](#menuitemid "Direct link to heading")


A `string` indicating the item's unique id, this property can be dynamically changed.


#### 
`menuItem.label`[​](#menuitemlabel "Direct link to heading")


A `string` indicating the item's visible label.


#### 
`menuItem.click`[​](#menuitemclick "Direct link to heading")


A `Function` that is fired when the MenuItem receives a click event. It can be called with `menuItem.click(event, focusedWindow, focusedWebContents)`.


* `event` [KeyboardEvent](structures/keyboard-event)
* `focusedWindow` [BrowserWindow](browser-window)
* `focusedWebContents` [WebContents](web-contents)


#### 
`menuItem.submenu`[​](#menuitemsubmenu "Direct link to heading")


A `Menu` (optional) containing the menu item's submenu, if present.


#### 
`menuItem.type`[​](#menuitemtype "Direct link to heading")


A `string` indicating the type of the item. Can be `normal`, `separator`, `submenu`, `checkbox` or `radio`.


#### 
`menuItem.role`[​](#menuitemrole "Direct link to heading")


A `string` (optional) indicating the item's role, if set. Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteAndMatchStyle`, `delete`, `selectAll`, `reload`, `forceReload`, `toggleDevTools`, `resetZoom`, `zoomIn`, `zoomOut`, `toggleSpellChecker`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideOthers`, `unhide`, `quit`, `startSpeaking`, `stopSpeaking`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu`, `shareMenu`, `recentDocuments`, `toggleTabBar`, `selectNextTab`, `selectPreviousTab`, `mergeAllWindows`, `clearRecentDocuments`, `moveTabToNewWindow` or `windowMenu`


#### 
`menuItem.accelerator`[​](#menuitemaccelerator "Direct link to heading")


An `Accelerator` (optional) indicating the item's accelerator, if set.


#### 
`menuItem.userAccelerator` *Readonly* *macOS*[​](#menuitemuseraccelerator-readonly-macos "Direct link to heading")


An `Accelerator | null` indicating the item's [user-assigned accelerator](https://developer.apple.com/documentation/appkit/nsmenuitem/1514850-userkeyequivalent?language=objc) for the menu item.


**Note:** This property is only initialized after the `MenuItem` has been added to a `Menu`. Either via `Menu.buildFromTemplate` or via `Menu.append()/insert()`. Accessing before initialization will just return `null`.


#### 
`menuItem.icon`[​](#menuitemicon "Direct link to heading")


A `NativeImage | string` (optional) indicating the item's icon, if set.


#### 
`menuItem.sublabel`[​](#menuitemsublabel "Direct link to heading")


A `string` indicating the item's sublabel.


#### 
`menuItem.toolTip` *macOS*[​](#menuitemtooltip-macos "Direct link to heading")


A `string` indicating the item's hover text.


#### 
`menuItem.enabled`[​](#menuitemenabled "Direct link to heading")


A `boolean` indicating whether the item is enabled, this property can be dynamically changed.


#### 
`menuItem.visible`[​](#menuitemvisible "Direct link to heading")


A `boolean` indicating whether the item is visible, this property can be dynamically changed.


#### 
`menuItem.checked`[​](#menuitemchecked "Direct link to heading")


A `boolean` indicating whether the item is checked, this property can be dynamically changed.


A `checkbox` menu item will toggle the `checked` property on and off when selected.


A `radio` menu item will turn on its `checked` property when clicked, and will turn off that property for all adjacent items in the same menu.


You can add a `click` function for additional behavior.


#### 
`menuItem.registerAccelerator`[​](#menuitemregisteraccelerator "Direct link to heading")


A `boolean` indicating if the accelerator should be registered with the system or just displayed.


This property can be dynamically changed.


#### 
`menuItem.sharingItem` *macOS*[​](#menuitemsharingitem-macos "Direct link to heading")


A `SharingItem` indicating the item to share when the `role` is `shareMenu`.


This property can be dynamically changed.


#### 
`menuItem.commandId`[​](#menuitemcommandid "Direct link to heading")


A `number` indicating an item's sequential unique id.


#### 
`menuItem.menu`[​](#menuitemmenu "Direct link to heading")


A `Menu` that the item is a part of.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/menu-item>

ipcMain
=======



> Communicate asynchronously from the main process to renderer processes.
> 
> 


Process: [Main](../glossary#main-process)


The `ipcMain` module is an [Event Emitter](https://nodejs.org/api/events.html#events_class_eventemitter). When used in the main process, it handles asynchronous and synchronous messages sent from a renderer process (web page). Messages sent from a renderer will be emitted to this module.


For usage examples, check out the [IPC tutorial](../tutorial/ipc).


Sending messages[​](#sending-messages "Direct link to heading")
---------------------------------------------------------------


It is also possible to send messages from the main process to the renderer process, see [webContents.send](web-contents#contentssendchannel-args) for more information.


* When sending a message, the event name is the `channel`.
* To reply to a synchronous message, you need to set `event.returnValue`.
* To send an asynchronous message back to the sender, you can use `event.reply(...)`. This helper method will automatically handle messages coming from frames that aren't the main frame (e.g. iframes) whereas `event.sender.send(...)` will always send to the main frame.


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `ipcMain` module has the following method to listen for events:


### 
`ipcMain.on(channel, listener)`[​](#ipcmainonchannel-listener "Direct link to heading")


* `channel` string
* `listener` Function
	+ `event` [IpcMainEvent](structures/ipc-main-event)
	+ `...args` any[]


Listens to `channel`, when a new message arrives `listener` would be called with `listener(event, args...)`.


### 
`ipcMain.once(channel, listener)`[​](#ipcmainoncechannel-listener "Direct link to heading")


* `channel` string
* `listener` Function
	+ `event` [IpcMainEvent](structures/ipc-main-event)
	+ `...args` any[]


Adds a one time `listener` function for the event. This `listener` is invoked only the next time a message is sent to `channel`, after which it is removed.


### 
`ipcMain.removeListener(channel, listener)`[​](#ipcmainremovelistenerchannel-listener "Direct link to heading")


* `channel` string
* `listener` Function
	+ `...args` any[]


Removes the specified `listener` from the listener array for the specified `channel`.


### 
`ipcMain.removeAllListeners([channel])`[​](#ipcmainremovealllistenerschannel "Direct link to heading")


* `channel` string (optional)


Removes listeners of the specified `channel`.


### 
`ipcMain.handle(channel, listener)`[​](#ipcmainhandlechannel-listener "Direct link to heading")


* `channel` string
* `listener` Function<Promise\<void> | any>
	+ `event` [IpcMainInvokeEvent](structures/ipc-main-invoke-event)
	+ `...args` any[]


Adds a handler for an `invoke`able IPC. This handler will be called whenever a renderer calls `ipcRenderer.invoke(channel, ...args)`.


If `listener` returns a Promise, the eventual result of the promise will be returned as a reply to the remote caller. Otherwise, the return value of the listener will be used as the value of the reply.



Main Process


```
ipcMain.handle('my-invokable-ipc', async (event, ...args) => {
  const result = await somePromise(...args)
  return result
})
```




Renderer Process


```
async () => {
  const result = await ipcRenderer.invoke('my-invokable-ipc', arg1, arg2)
  // ...
}
```



The `event` that is passed as the first argument to the handler is the same as that passed to a regular event listener. It includes information about which WebContents is the source of the invoke request.


Errors thrown through `handle` in the main process are not transparent as they are serialized and only the `message` property from the original error is provided to the renderer process. Please refer to [#24427](https://github.com/electron/electron/issues/24427) for details.


### 
`ipcMain.handleOnce(channel, listener)`[​](#ipcmainhandleoncechannel-listener "Direct link to heading")


* `channel` string
* `listener` Function<Promise\<void> | any>
	+ `event` IpcMainInvokeEvent
	+ `...args` any[]


Handles a single `invoke`able IPC message, then removes the listener. See `ipcMain.handle(channel, listener)`.


### 
`ipcMain.removeHandler(channel)`[​](#ipcmainremovehandlerchannel "Direct link to heading")


* `channel` string


Removes any handler for `channel`, if present.


IpcMainEvent object[​](#ipcmainevent-object "Direct link to heading")
---------------------------------------------------------------------


The documentation for the `event` object passed to the `callback` can be found in the [`ipc-main-event`](structures/ipc-main-event) structure docs.


IpcMainInvokeEvent object[​](#ipcmaininvokeevent-object "Direct link to heading")
---------------------------------------------------------------------------------


The documentation for the `event` object passed to `handle` callbacks can be found in the [`ipc-main-invoke-event`](structures/ipc-main-invoke-event) structure docs.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/ipc-main>

Class: DownloadItem
===================

Class: DownloadItem[​](#class-downloaditem "Direct link to heading")
--------------------------------------------------------------------



> Control file downloads from remote sources.
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


`DownloadItem` is an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter) that represents a download item in Electron. It is used in `will-download` event of `Session` class, and allows users to control the download item.




```
// In the main process.
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.webContents.session.on('will-download', (event, item, webContents) => {
  // Set the save path, making Electron not to prompt a save dialog.
  item.setSavePath('/tmp/save.pdf')

  item.on('updated', (event, state) => {
    if (state === 'interrupted') {
      console.log('Download is interrupted but can be resumed')
    } else if (state === 'progressing') {
      if (item.isPaused()) {
        console.log('Download is paused')
      } else {
        console.log(`Received bytes: ${item.getReceivedBytes()}`)
      }
    }
  })
  item.once('done', (event, state) => {
    if (state === 'completed') {
      console.log('Download successfully')
    } else {
      console.log(`Download failed: ${state}`)
    }
  })
})
```


### Instance Events[​](#instance-events "Direct link to heading")


#### Event: 'updated'[​](#event-updated "Direct link to heading")


Returns:


* `event` Event
* `state` string - Can be `progressing` or `interrupted`.


Emitted when the download has been updated and is not done.


The `state` can be one of following:


* `progressing` - The download is in-progress.
* `interrupted` - The download has interrupted and can be resumed.


#### Event: 'done'[​](#event-done "Direct link to heading")


Returns:


* `event` Event
* `state` string - Can be `completed`, `cancelled` or `interrupted`.


Emitted when the download is in a terminal state. This includes a completed download, a cancelled download (via `downloadItem.cancel()`), and interrupted download that can't be resumed.


The `state` can be one of following:


* `completed` - The download completed successfully.
* `cancelled` - The download has been cancelled.
* `interrupted` - The download has interrupted and can not resume.


### Instance Methods[​](#instance-methods "Direct link to heading")


The `downloadItem` object has the following methods:


#### 
`downloadItem.setSavePath(path)`[​](#downloaditemsetsavepathpath "Direct link to heading")


* `path` string - Set the save file path of the download item.


The API is only available in session's `will-download` callback function. If `path` doesn't exist, Electron will try to make the directory recursively. If user doesn't set the save path via the API, Electron will use the original routine to determine the save path; this usually prompts a save dialog.


#### 
`downloadItem.getSavePath()`[​](#downloaditemgetsavepath "Direct link to heading")


Returns `string` - The save path of the download item. This will be either the path set via `downloadItem.setSavePath(path)` or the path selected from the shown save dialog.


#### 
`downloadItem.setSaveDialogOptions(options)`[​](#downloaditemsetsavedialogoptionsoptions "Direct link to heading")


* `options` SaveDialogOptions - Set the save file dialog options. This object has the same properties as the `options` parameter of [`dialog.showSaveDialog()`](dialog).


This API allows the user to set custom options for the save dialog that opens for the download item by default. The API is only available in session's `will-download` callback function.


#### 
`downloadItem.getSaveDialogOptions()`[​](#downloaditemgetsavedialogoptions "Direct link to heading")


Returns `SaveDialogOptions` - Returns the object previously set by `downloadItem.setSaveDialogOptions(options)`.


#### 
`downloadItem.pause()`[​](#downloaditempause "Direct link to heading")


Pauses the download.


#### 
`downloadItem.isPaused()`[​](#downloaditemispaused "Direct link to heading")


Returns `boolean` - Whether the download is paused.


#### 
`downloadItem.resume()`[​](#downloaditemresume "Direct link to heading")


Resumes the download that has been paused.


**Note:** To enable resumable downloads the server you are downloading from must support range requests and provide both `Last-Modified` and `ETag` header values. Otherwise `resume()` will dismiss previously received bytes and restart the download from the beginning.


#### 
`downloadItem.canResume()`[​](#downloaditemcanresume "Direct link to heading")


Returns `boolean` - Whether the download can resume.


#### 
`downloadItem.cancel()`[​](#downloaditemcancel "Direct link to heading")


Cancels the download operation.


#### 
`downloadItem.getURL()`[​](#downloaditemgeturl "Direct link to heading")


Returns `string` - The origin URL where the item is downloaded from.


#### 
`downloadItem.getMimeType()`[​](#downloaditemgetmimetype "Direct link to heading")


Returns `string` - The files mime type.


#### 
`downloadItem.hasUserGesture()`[​](#downloaditemhasusergesture "Direct link to heading")


Returns `boolean` - Whether the download has user gesture.


#### 
`downloadItem.getFilename()`[​](#downloaditemgetfilename "Direct link to heading")


Returns `string` - The file name of the download item.


**Note:** The file name is not always the same as the actual one saved in local disk. If user changes the file name in a prompted download saving dialog, the actual name of saved file will be different.


#### 
`downloadItem.getTotalBytes()`[​](#downloaditemgettotalbytes "Direct link to heading")


Returns `Integer` - The total size in bytes of the download item.


If the size is unknown, it returns 0.


#### 
`downloadItem.getReceivedBytes()`[​](#downloaditemgetreceivedbytes "Direct link to heading")


Returns `Integer` - The received bytes of the download item.


#### 
`downloadItem.getContentDisposition()`[​](#downloaditemgetcontentdisposition "Direct link to heading")


Returns `string` - The Content-Disposition field from the response header.


#### 
`downloadItem.getState()`[​](#downloaditemgetstate "Direct link to heading")


Returns `string` - The current state. Can be `progressing`, `completed`, `cancelled` or `interrupted`.


**Note:** The following methods are useful specifically to resume a `cancelled` item when session is restarted.


#### 
`downloadItem.getURLChain()`[​](#downloaditemgeturlchain "Direct link to heading")


Returns `string[]` - The complete URL chain of the item including any redirects.


#### 
`downloadItem.getLastModifiedTime()`[​](#downloaditemgetlastmodifiedtime "Direct link to heading")


Returns `string` - Last-Modified header value.


#### 
`downloadItem.getETag()`[​](#downloaditemgetetag "Direct link to heading")


Returns `string` - ETag header value.


#### 
`downloadItem.getStartTime()`[​](#downloaditemgetstarttime "Direct link to heading")


Returns `Double` - Number of seconds since the UNIX epoch when the download was started.


### Instance Properties[​](#instance-properties "Direct link to heading")


#### 
`downloadItem.savePath`[​](#downloaditemsavepath "Direct link to heading")


A `string` property that determines the save file path of the download item.


The property is only available in session's `will-download` callback function. If user doesn't set the save path via the property, Electron will use the original routine to determine the save path; this usually prompts a save dialog.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/download-item>

process
=======



> Extensions to process object.
> 
> 


Process: [Main](../glossary#main-process), [Renderer](../glossary#renderer-process)


Electron's `process` object is extended from the [Node.js `process` object](https://nodejs.org/api/process.html). It adds the following events, properties, and methods:


Sandbox[​](#sandbox "Direct link to heading")
---------------------------------------------


In sandboxed renderers the `process` object contains only a subset of the APIs:


* `crash()`
* `hang()`
* `getCreationTime()`
* `getHeapStatistics()`
* `getBlinkMemoryInfo()`
* `getProcessMemoryInfo()`
* `getSystemMemoryInfo()`
* `getSystemVersion()`
* `getCPUUsage()`
* `getIOCounters()`
* `uptime()`
* `argv`
* `execPath`
* `env`
* `pid`
* `arch`
* `platform`
* `sandboxed`
* `contextIsolated`
* `type`
* `version`
* `versions`
* `mas`
* `windowsStore`
* `contextId`


Events[​](#events "Direct link to heading")
-------------------------------------------


### Event: 'loaded'[​](#event-loaded "Direct link to heading")


Emitted when Electron has loaded its internal initialization script and is beginning to load the web page or the main script.


Properties[​](#properties "Direct link to heading")
---------------------------------------------------


### 
`process.defaultApp` *Readonly*[​](#processdefaultapp-readonly "Direct link to heading")


A `boolean`. When app is started by being passed as parameter to the default app, this property is `true` in the main process, otherwise it is `undefined`.


### 
`process.isMainFrame` *Readonly*[​](#processismainframe-readonly "Direct link to heading")


A `boolean`, `true` when the current renderer context is the "main" renderer frame. If you want the ID of the current frame you should use `webFrame.routingId`.


### 
`process.mas` *Readonly*[​](#processmas-readonly "Direct link to heading")


A `boolean`. For Mac App Store build, this property is `true`, for other builds it is `undefined`.


### 
`process.noAsar`[​](#processnoasar "Direct link to heading")


A `boolean` that controls ASAR support inside your application. Setting this to `true` will disable the support for `asar` archives in Node's built-in modules.


### 
`process.noDeprecation`[​](#processnodeprecation "Direct link to heading")


A `boolean` that controls whether or not deprecation warnings are printed to `stderr`. Setting this to `true` will silence deprecation warnings. This property is used instead of the `--no-deprecation` command line flag.


### 
`process.resourcesPath` *Readonly*[​](#processresourcespath-readonly "Direct link to heading")


A `string` representing the path to the resources directory.


### 
`process.sandboxed` *Readonly*[​](#processsandboxed-readonly "Direct link to heading")


A `boolean`. When the renderer process is sandboxed, this property is `true`, otherwise it is `undefined`.


### 
`process.contextIsolated` *Readonly*[​](#processcontextisolated-readonly "Direct link to heading")


A `boolean` that indicates whether the current renderer context has `contextIsolation` enabled. It is `undefined` in the main process.


### 
`process.throwDeprecation`[​](#processthrowdeprecation "Direct link to heading")


A `boolean` that controls whether or not deprecation warnings will be thrown as exceptions. Setting this to `true` will throw errors for deprecations. This property is used instead of the `--throw-deprecation` command line flag.


### 
`process.traceDeprecation`[​](#processtracedeprecation "Direct link to heading")


A `boolean` that controls whether or not deprecations printed to `stderr` include their stack trace. Setting this to `true` will print stack traces for deprecations. This property is instead of the `--trace-deprecation` command line flag.


### 
`process.traceProcessWarnings`[​](#processtraceprocesswarnings "Direct link to heading")


A `boolean` that controls whether or not process warnings printed to `stderr` include their stack trace. Setting this to `true` will print stack traces for process warnings (including deprecations). This property is instead of the `--trace-warnings` command line flag.


### 
`process.type` *Readonly*[​](#processtype-readonly "Direct link to heading")


A `string` representing the current process's type, can be:


* `browser` - The main process
* `renderer` - A renderer process
* `worker` - In a web worker


### 
`process.versions.chrome` *Readonly*[​](#processversionschrome-readonly "Direct link to heading")


A `string` representing Chrome's version string.


### 
`process.versions.electron` *Readonly*[​](#processversionselectron-readonly "Direct link to heading")


A `string` representing Electron's version string.


### 
`process.windowsStore` *Readonly*[​](#processwindowsstore-readonly "Direct link to heading")


A `boolean`. If the app is running as a Windows Store app (appx), this property is `true`, for otherwise it is `undefined`.


### 
`process.contextId` *Readonly*[​](#processcontextid-readonly "Direct link to heading")


A `string` (optional) representing a globally unique ID of the current JavaScript context. Each frame has its own JavaScript context. When contextIsolation is enabled, the isolated world also has a separate JavaScript context. This property is only available in the renderer process.


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `process` object has the following methods:


### 
`process.crash()`[​](#processcrash "Direct link to heading")


Causes the main thread of the current process crash.


### 
`process.getCreationTime()`[​](#processgetcreationtime "Direct link to heading")


Returns `number | null` - The number of milliseconds since epoch, or `null` if the information is unavailable


Indicates the creation time of the application. The time is represented as number of milliseconds since epoch. It returns null if it is unable to get the process creation time.


### 
`process.getCPUUsage()`[​](#processgetcpuusage "Direct link to heading")


Returns [CPUUsage](structures/cpu-usage)


### 
`process.getIOCounters()` *Windows* *Linux*[​](#processgetiocounters-windows-linux "Direct link to heading")


Returns [IOCounters](structures/io-counters)


### 
`process.getHeapStatistics()`[​](#processgetheapstatistics "Direct link to heading")


Returns `Object`:


* `totalHeapSize` Integer
* `totalHeapSizeExecutable` Integer
* `totalPhysicalSize` Integer
* `totalAvailableSize` Integer
* `usedHeapSize` Integer
* `heapSizeLimit` Integer
* `mallocedMemory` Integer
* `peakMallocedMemory` Integer
* `doesZapGarbage` boolean


Returns an object with V8 heap statistics. Note that all statistics are reported in Kilobytes.


### 
`process.getBlinkMemoryInfo()`[​](#processgetblinkmemoryinfo "Direct link to heading")


Returns `Object`:


* `allocated` Integer - Size of all allocated objects in Kilobytes.
* `total` Integer - Total allocated space in Kilobytes.


Returns an object with Blink memory information. It can be useful for debugging rendering / DOM related memory issues. Note that all values are reported in Kilobytes.


### 
`process.getProcessMemoryInfo()`[​](#processgetprocessmemoryinfo "Direct link to heading")


Returns `Promise<ProcessMemoryInfo>` - Resolves with a [ProcessMemoryInfo](structures/process-memory-info)


Returns an object giving memory usage statistics about the current process. Note that all statistics are reported in Kilobytes. This api should be called after app ready.


Chromium does not provide `residentSet` value for macOS. This is because macOS performs in-memory compression of pages that haven't been recently used. As a result the resident set size value is not what one would expect. `private` memory is more representative of the actual pre-compression memory usage of the process on macOS.


### 
`process.getSystemMemoryInfo()`[​](#processgetsystemmemoryinfo "Direct link to heading")


Returns `Object`:


* `total` Integer - The total amount of physical memory in Kilobytes available to the system.
* `free` Integer - The total amount of memory not being used by applications or disk cache.
* `swapTotal` Integer *Windows* *Linux* - The total amount of swap memory in Kilobytes available to the system.
* `swapFree` Integer *Windows* *Linux* - The free amount of swap memory in Kilobytes available to the system.


Returns an object giving memory usage statistics about the entire system. Note that all statistics are reported in Kilobytes.


### 
`process.getSystemVersion()`[​](#processgetsystemversion "Direct link to heading")


Returns `string` - The version of the host operating system.


Example:




```
const version = process.getSystemVersion()
console.log(version)
// On macOS -> '10.13.6'
// On Windows -> '10.0.17763'
// On Linux -> '4.15.0-45-generic'
```


**Note:** It returns the actual operating system version instead of kernel version on macOS unlike `os.release()`.


### 
`process.takeHeapSnapshot(filePath)`[​](#processtakeheapsnapshotfilepath "Direct link to heading")


* `filePath` string - Path to the output file.


Returns `boolean` - Indicates whether the snapshot has been created successfully.


Takes a V8 heap snapshot and saves it to `filePath`.


### 
`process.hang()`[​](#processhang "Direct link to heading")


Causes the main thread of the current process hang.


### 
`process.setFdLimit(maxDescriptors)` *macOS* *Linux*[​](#processsetfdlimitmaxdescriptors-macos-linux "Direct link to heading")


* `maxDescriptors` Integer


Sets the file descriptor soft limit to `maxDescriptors` or the OS hard limit, whichever is lower for the current process.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/process>

NotificationAction Object
=========================


* `type` string - The type of action, can be `button`.
* `text` string (optional) - The label for the given action.


Platform / Action Support[​](#platform--action-support "Direct link to heading")
--------------------------------------------------------------------------------




| Action Type | Platform Support | Usage of `text` | Default `text` | Limitations |
| --- | --- | --- | --- | --- |
| `button` | macOS | Used as the label for the button | "Show" (or a localized string by system default if first of such `button`, otherwise empty) | Only the first one is used. If multiple are provided, those beyond the first will be listed as additional actions (displayed when mouse active over the action button). Any such action also is incompatible with `hasReply` and will be ignored if `hasReply` is `true`. |


### Button support on macOS[​](#button-support-on-macos "Direct link to heading")


In order for extra notification buttons to work on macOS your app must meet the following criteria.


* App is signed
* App has it's `NSUserNotificationAlertStyle` set to `alert` in the `Info.plist`.


If either of these requirements are not met the button won't appear.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/notification-action>

CertificatePrincipal Object
===========================


* `commonName` string - Common Name.
* `organizations` string[] - Organization names.
* `organizationUnits` string[] - Organization Unit names.
* `locality` string - Locality.
* `state` string - State or province.
* `country` string - Country or region.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/certificate-principal>

UploadFile Object
=================


* `type` 'file' - `file`.
* `filePath` string - Path of file to be uploaded.
* `offset` Integer - Defaults to `0`.
* `length` Integer - Number of bytes to read from `offset`. Defaults to `0`.
* `modificationTime` Double - Last Modification time in number of seconds since the UNIX epoch.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/upload-file>

Updating Applications
=====================

There are several ways to provide automatic updates to your Electron application. The easiest and officially supported one is taking advantage of the built-in [Squirrel](https://github.com/Squirrel) framework and Electron's [autoUpdater](../api/auto-updater) module.


Using update.electronjs.org[​](#using-updateelectronjsorg "Direct link to heading")
-----------------------------------------------------------------------------------


The Electron team maintains [update.electronjs.org](https://github.com/electron/update.electronjs.org), a free and open-source webservice that Electron apps can use to self-update. The service is designed for Electron apps that meet the following criteria:


* App runs on macOS or Windows
* App has a public GitHub repository
* Builds are published to [GitHub Releases](https://help.github.com/articles/creating-releases/)
* Builds are [code-signed](code-signing)


The easiest way to use this service is by installing [update-electron-app](https://github.com/electron/update-electron-app), a Node.js module preconfigured for use with update.electronjs.org.


Install the module using your Node.js package manager of choice:



* npm
* Yarn





```
npm install update-electron-app
```




```
yarn add update-electron-app
```




Then, invoke the updater from your app's main process file:



main.js


```
require('update-electron-app')()
```



By default, this module will check for updates at app startup, then every ten minutes. When an update is found, it will automatically be downloaded in the background. When the download completes, a dialog is displayed allowing the user to restart the app.


If you need to customize your configuration, you can [pass options to update-electron-app](https://github.com/electron/update-electron-app) or [use the update service directly](https://github.com/electron/update.electronjs.org).


Using other update services[​](#using-other-update-services "Direct link to heading")
-------------------------------------------------------------------------------------


If you're developing a private Electron application, or if you're not publishing releases to GitHub Releases, it may be necessary to run your own update server.


### Step 1: Deploying an update server[​](#step-1-deploying-an-update-server "Direct link to heading")


Depending on your needs, you can choose from one of these:


* [Hazel](https://github.com/vercel/hazel) – Update server for private or open-source apps which can be deployed for free on [Vercel](https://vercel.com). It pulls from [GitHub Releases](https://help.github.com/articles/creating-releases/) and leverages the power of GitHub's CDN.
* [Nuts](https://github.com/GitbookIO/nuts) – Also uses [GitHub Releases](https://help.github.com/articles/creating-releases/), but caches app updates on disk and supports private repositories.
* [electron-release-server](https://github.com/ArekSredzki/electron-release-server) – Provides a dashboard for handling releases and does not require releases to originate on GitHub.
* [Nucleus](https://github.com/atlassian/nucleus) – A complete update server for Electron apps maintained by Atlassian. Supports multiple applications and channels; uses a static file store to minify server cost.


Once you've deployed your update server, you can instrument your app code to receive and apply the updates with Electron's [autoUpdater] module.


### Step 2: Receiving updates in your app[​](#step-2-receiving-updates-in-your-app "Direct link to heading")


First, import the required modules in your main process code. The following code might vary for different server software, but it works like described when using [Hazel](https://github.com/vercel/hazel).




Check your execution environment!
Please ensure that the code below will only be executed in your packaged app, and not in development. You can use the [app.isPackaged](../api/app#appispackaged-readonly) API to check the environment.




main.js


```
const { app, autoUpdater, dialog } = require('electron')
```



Next, construct the URL of the update server feed and tell [autoUpdater](../api/auto-updater) about it:



main.js


```
const server = 'https://your-deployment-url.com'
const url = `${server}/update/${process.platform}/${app.getVersion()}`

autoUpdater.setFeedURL({ url })
```



As the final step, check for updates. The example below will check every minute:



main.js


```
setInterval(() => {
  autoUpdater.checkForUpdates()
}, 60000)
```



Once your application is [packaged](application-distribution), it will receive an update for each new [GitHub Release](https://help.github.com/articles/creating-releases/) that you publish.


### Step 3: Notifying users when updates are available[​](#step-3-notifying-users-when-updates-are-available "Direct link to heading")


Now that you've configured the basic update mechanism for your application, you need to ensure that the user will get notified when there's an update. This can be achieved using the [autoUpdater API events](../api/auto-updater#events):



main.js


```
autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
  const dialogOpts = {
    type: 'info',
    buttons: ['Restart', 'Later'],
    title: 'Application Update',
    message: process.platform === 'win32' ? releaseNotes : releaseName,
    detail:
      'A new version has been downloaded. Restart the application to apply the updates.',
  }

  dialog.showMessageBox(dialogOpts).then((returnValue) => {
    if (returnValue.response === 0) autoUpdater.quitAndInstall()
  })
})
```



Also make sure that errors are [being handled](../api/auto-updater#event-error). Here's an example for logging them to `stderr`:



main.js


```
autoUpdater.on('error', (message) => {
  console.error('There was a problem updating the application')
  console.error(message)
})
```





Handling updates manually
Because the requests made by autoUpdate aren't under your direct control, you may find situations that are difficult to handle (such as if the update server is behind authentication). The `url` field supports the `file://` protocol, which means that with some effort, you can sidestep the server-communication aspect of the process by loading your update from a local directory. [Here's an example of how this could work](https://github.com/electron/electron/issues/5020#issuecomment-477636990).




 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/updates>

Class: Cookies
==============

Class: Cookies[​](#class-cookies "Direct link to heading")
----------------------------------------------------------



> Query and modify a session's cookies.
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


Instances of the `Cookies` class are accessed by using `cookies` property of a `Session`.


For example:




```
const { session } = require('electron')

// Query all cookies.
session.defaultSession.cookies.get({})
  .then((cookies) => {
    console.log(cookies)
  }).catch((error) => {
    console.log(error)
  })

// Query all cookies associated with a specific url.
session.defaultSession.cookies.get({ url: 'http://www.github.com' })
  .then((cookies) => {
    console.log(cookies)
  }).catch((error) => {
    console.log(error)
  })

// Set a cookie with the given cookie data;
// may overwrite equivalent cookies if they exist.
const cookie = { url: 'http://www.github.com', name: 'dummy_name', value: 'dummy' }
session.defaultSession.cookies.set(cookie)
  .then(() => {
    // success
  }, (error) => {
    console.error(error)
  })
```


### Instance Events[​](#instance-events "Direct link to heading")


The following events are available on instances of `Cookies`:


#### Event: 'changed'[​](#event-changed "Direct link to heading")


Returns:


* `event` Event
* `cookie` [Cookie](structures/cookie) - The cookie that was changed.
* `cause` string - The cause of the change with one of the following values:
	+ `explicit` - The cookie was changed directly by a consumer's action.
	+ `overwrite` - The cookie was automatically removed due to an insert operation that overwrote it.
	+ `expired` - The cookie was automatically removed as it expired.
	+ `evicted` - The cookie was automatically evicted during garbage collection.
	+ `expired-overwrite` - The cookie was overwritten with an already-expired expiration date.
* `removed` boolean - `true` if the cookie was removed, `false` otherwise.


Emitted when a cookie is changed because it was added, edited, removed, or expired.


### Instance Methods[​](#instance-methods "Direct link to heading")


The following methods are available on instances of `Cookies`:


#### 
`cookies.get(filter)`[​](#cookiesgetfilter "Direct link to heading")


* `filter` Object
	+ `url` string (optional) - Retrieves cookies which are associated with `url`. Empty implies retrieving cookies of all URLs.
	+ `name` string (optional) - Filters cookies by name.
	+ `domain` string (optional) - Retrieves cookies whose domains match or are subdomains of `domains`.
	+ `path` string (optional) - Retrieves cookies whose path matches `path`.
	+ `secure` boolean (optional) - Filters cookies by their Secure property.
	+ `session` boolean (optional) - Filters out session or persistent cookies.


Returns `Promise<Cookie[]>` - A promise which resolves an array of cookie objects.


Sends a request to get all cookies matching `filter`, and resolves a promise with the response.


#### 
`cookies.set(details)`[​](#cookiessetdetails "Direct link to heading")


* `details` Object
	+ `url` string - The URL to associate the cookie with. The promise will be rejected if the URL is invalid.
	+ `name` string (optional) - The name of the cookie. Empty by default if omitted.
	+ `value` string (optional) - The value of the cookie. Empty by default if omitted.
	+ `domain` string (optional) - The domain of the cookie; this will be normalized with a preceding dot so that it's also valid for subdomains. Empty by default if omitted.
	+ `path` string (optional) - The path of the cookie. Empty by default if omitted.
	+ `secure` boolean (optional) - Whether the cookie should be marked as Secure. Defaults to false unless [Same Site=None](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite#samesitenone_requires_secure) attribute is used.
	+ `httpOnly` boolean (optional) - Whether the cookie should be marked as HTTP only. Defaults to false.
	+ `expirationDate` Double (optional) - The expiration date of the cookie as the number of seconds since the UNIX epoch. If omitted then the cookie becomes a session cookie and will not be retained between sessions.
	+ `sameSite` string (optional) - The [Same Site](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_cookies) policy to apply to this cookie. Can be `unspecified`, `no_restriction`, `lax` or `strict`. Default is `lax`.


Returns `Promise<void>` - A promise which resolves when the cookie has been set


Sets a cookie with `details`.


#### 
`cookies.remove(url, name)`[​](#cookiesremoveurl-name "Direct link to heading")


* `url` string - The URL associated with the cookie.
* `name` string - The name of cookie to remove.


Returns `Promise<void>` - A promise which resolves when the cookie has been removed


Removes the cookies matching `url` and `name`


#### 
`cookies.flushStore()`[​](#cookiesflushstore "Direct link to heading")


Returns `Promise<void>` - A promise which resolves when the cookie store has been flushed


Writes any unwritten cookies data to disk.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/cookies>

clipboard
=========



> Perform copy and paste operations on the system clipboard.
> 
> 


Process: [Main](../glossary#main-process), [Renderer](../glossary#renderer-process)


On Linux, there is also a `selection` clipboard. To manipulate it you need to pass `selection` to each method:




```
const { clipboard } = require('electron')

clipboard.writeText('Example string', 'selection')
console.log(clipboard.readText('selection'))
```


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `clipboard` module has the following methods:


**Note:** Experimental APIs are marked as such and could be removed in future.


### 
`clipboard.readText([type])`[​](#clipboardreadtexttype "Direct link to heading")


* `type` string (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux.


Returns `string` - The content in the clipboard as plain text.




```
const { clipboard } = require('electron')

clipboard.writeText('hello i am a bit of text!')

const text = clipboard.readText()
console.log(text)
// hello i am a bit of text!'
```


### 
`clipboard.writeText(text[, type])`[​](#clipboardwritetexttext-type "Direct link to heading")


* `text` string
* `type` string (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux.


Writes the `text` into the clipboard as plain text.




```
const { clipboard } = require('electron')

const text = 'hello i am a bit of text!'
clipboard.writeText(text)
```


### 
`clipboard.readHTML([type])`[​](#clipboardreadhtmltype "Direct link to heading")


* `type` string (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux.


Returns `string` - The content in the clipboard as markup.




```
const { clipboard } = require('electron')

clipboard.writeHTML('<b>Hi</b>')
const html = clipboard.readHTML()

console.log(html)
// <meta charset='utf-8'><b>Hi</b>
```


### 
`clipboard.writeHTML(markup[, type])`[​](#clipboardwritehtmlmarkup-type "Direct link to heading")


* `markup` string
* `type` string (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux.


Writes `markup` to the clipboard.




```
const { clipboard } = require('electron')

clipboard.writeHTML('<b>Hi</b>')
```


### 
`clipboard.readImage([type])`[​](#clipboardreadimagetype "Direct link to heading")


* `type` string (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux.


Returns [`NativeImage`](native-image) - The image content in the clipboard.


### 
`clipboard.writeImage(image[, type])`[​](#clipboardwriteimageimage-type "Direct link to heading")


* `image` [NativeImage](native-image)
* `type` string (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux.


Writes `image` to the clipboard.


### 
`clipboard.readRTF([type])`[​](#clipboardreadrtftype "Direct link to heading")


* `type` string (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux.


Returns `string` - The content in the clipboard as RTF.




```
const { clipboard } = require('electron')

clipboard.writeRTF('{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\nThis is some {\\b bold} text.\\par\n}')

const rtf = clipboard.readRTF()
console.log(rtf)
// {\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\nThis is some {\\b bold} text.\\par\n}
```


### 
`clipboard.writeRTF(text[, type])`[​](#clipboardwritertftext-type "Direct link to heading")


* `text` string
* `type` string (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux.


Writes the `text` into the clipboard in RTF.




```
const { clipboard } = require('electron')

const rtf = '{\\rtf1\\ansi{\\fonttbl\\f0\\fswiss Helvetica;}\\f0\\pard\nThis is some {\\b bold} text.\\par\n}'
clipboard.writeRTF(rtf)
```


### 
`clipboard.readBookmark()` *macOS* *Windows*[​](#clipboardreadbookmark-macos-windows "Direct link to heading")


Returns `Object`:


* `title` string
* `url` string


Returns an Object containing `title` and `url` keys representing the bookmark in the clipboard. The `title` and `url` values will be empty strings when the bookmark is unavailable. The `title` value will always be empty on Windows.


### 
`clipboard.writeBookmark(title, url[, type])` *macOS* *Windows*[​](#clipboardwritebookmarktitle-url-type-macos-windows "Direct link to heading")


* `title` string - Unused on Windows
* `url` string
* `type` string (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux.


Writes the `title` (macOS only) and `url` into the clipboard as a bookmark.


**Note:** Most apps on Windows don't support pasting bookmarks into them so you can use `clipboard.write` to write both a bookmark and fallback text to the clipboard.




```
const { clipboard } = require('electron')

clipboard.writeBookmark({
  text: 'https://electronjs.org',
  bookmark: 'Electron Homepage'
})
```


### 
`clipboard.readFindText()` *macOS*[​](#clipboardreadfindtext-macos "Direct link to heading")


Returns `string` - The text on the find pasteboard, which is the pasteboard that holds information about the current state of the active application’s find panel.


This method uses synchronous IPC when called from the renderer process. The cached value is reread from the find pasteboard whenever the application is activated.


### 
`clipboard.writeFindText(text)` *macOS*[​](#clipboardwritefindtexttext-macos "Direct link to heading")


* `text` string


Writes the `text` into the find pasteboard (the pasteboard that holds information about the current state of the active application’s find panel) as plain text. This method uses synchronous IPC when called from the renderer process.


### 
`clipboard.clear([type])`[​](#clipboardcleartype "Direct link to heading")


* `type` string (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux.


Clears the clipboard content.


### 
`clipboard.availableFormats([type])`[​](#clipboardavailableformatstype "Direct link to heading")


* `type` string (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux.


Returns `string[]` - An array of supported formats for the clipboard `type`.




```
const { clipboard } = require('electron')

const formats = clipboard.availableFormats()
console.log(formats)
// [ 'text/plain', 'text/html' ]
```


### 
`clipboard.has(format[, type])` *Experimental*[​](#clipboardhasformat-type-experimental "Direct link to heading")


* `format` string
* `type` string (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux.


Returns `boolean` - Whether the clipboard supports the specified `format`.




```
const { clipboard } = require('electron')

const hasFormat = clipboard.has('public/utf8-plain-text')
console.log(hasFormat)
// 'true' or 'false'
```


### 
`clipboard.read(format)` *Experimental*[​](#clipboardreadformat-experimental "Direct link to heading")


* `format` string


Returns `string` - Reads `format` type from the clipboard.


`format` should contain valid ASCII characters and have `/` separator. `a/c`, `a/bc` are valid formats while `/abc`, `abc/`, `a/`, `/a`, `a` are not valid.


### 
`clipboard.readBuffer(format)` *Experimental*[​](#clipboardreadbufferformat-experimental "Direct link to heading")


* `format` string


Returns `Buffer` - Reads `format` type from the clipboard.




```
const { clipboard } = require('electron')

const buffer = Buffer.from('this is binary', 'utf8')
clipboard.writeBuffer('public/utf8-plain-text', buffer)

const ret = clipboard.readBuffer('public/utf8-plain-text')

console.log(buffer.equals(out))
// true
```


### 
`clipboard.writeBuffer(format, buffer[, type])` *Experimental*[​](#clipboardwritebufferformat-buffer-type-experimental "Direct link to heading")


* `format` string
* `buffer` Buffer
* `type` string (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux.


Writes the `buffer` into the clipboard as `format`.




```
const { clipboard } = require('electron')

const buffer = Buffer.from('writeBuffer', 'utf8')
clipboard.writeBuffer('public/utf8-plain-text', buffer)
```


### 
`clipboard.write(data[, type])`[​](#clipboardwritedata-type "Direct link to heading")


* `data` Object
	+ `text` string (optional)
	+ `html` string (optional)
	+ `image` [NativeImage](native-image) (optional)
	+ `rtf` string (optional)
	+ `bookmark` string (optional) - The title of the URL at `text`.
* `type` string (optional) - Can be `selection` or `clipboard`; default is 'clipboard'. `selection` is only available on Linux.


Writes `data` to the clipboard.




```
const { clipboard } = require('electron')

clipboard.write({
  text: 'test',
  html: '<b>Hi</b>',
  rtf: '{\\rtf1\\utf8 text}',
  bookmark: 'a title'
})

console.log(clipboard.readText())
// 'test'

console.log(clipboard.readHTML())
// <meta charset='utf-8'><b>Hi</b>

console.log(clipboard.readRTF())
// '{\\rtf1\\utf8 text}'

console.log(clipboard.readBookmark())
// { title: 'a title', url: 'test' }
```



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/clipboard>

MessageChannelMain
==================


`MessageChannelMain` is the main-process-side equivalent of the DOM [`MessageChannel`](https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel) object. Its singular function is to create a pair of connected [`MessagePortMain`](message-port-main) objects.


See the [Channel Messaging API](https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API) documentation for more information on using channel messaging.


Class: MessageChannelMain[​](#class-messagechannelmain "Direct link to heading")
--------------------------------------------------------------------------------



> Channel interface for channel messaging in the main process.
> 
> 


Process: [Main](../glossary#main-process)


Example:




```
// Main process
const { MessageChannelMain } = require('electron')
const { port1, port2 } = new MessageChannelMain()
w.webContents.postMessage('port', null, [port2])
port1.postMessage({ some: 'message' })

// Renderer process
const { ipcRenderer } = require('electron')
ipcRenderer.on('port', (e) => {
  // e.ports is a list of ports sent along with this message
  e.ports[0].on('message', (messageEvent) => {
    console.log(messageEvent.data)
  })
})
```


### Instance Properties[​](#instance-properties "Direct link to heading")


#### 
`channel.port1`[​](#channelport1 "Direct link to heading")


A [`MessagePortMain`](message-port-main) property.


#### 
`channel.port2`[​](#channelport2 "Direct link to heading")


A [`MessagePortMain`](message-port-main) property.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/message-channel-main>

BluetoothDevice Object
======================


* `deviceName` string
* `deviceId` string



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/bluetooth-device>

IpcRendererEvent Object extends `Event`
=======================================


* `sender` IpcRenderer - The `IpcRenderer` instance that emitted the event originally
* `senderId` Integer - The `webContents.id` that sent the message, you can call `event.sender.sendTo(event.senderId, ...)` to reply to the message, see [ipcRenderer.sendTo](../ipc-renderer#ipcrenderersendtowebcontentsid-channel-args) for more information. This only applies to messages sent from a different renderer. Messages sent directly from the main process set `event.senderId` to `0`.
* `ports` MessagePort[] - A list of MessagePorts that were transferred with this message



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/ipc-renderer-event>

MessagePorts in Electron
========================


[`MessagePort`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort)s are a web feature that allow passing messages between different contexts. It's like `window.postMessage`, but on different channels. The goal of this document is to describe how Electron extends the Channel Messaging model, and to give some examples of how you might use MessagePorts in your app.


Here is a very brief example of what a MessagePort is and how it works:



renderer.js (Renderer Process)


```
// MessagePorts are created in pairs. A connected pair of message ports is
// called a channel.
const channel = new MessageChannel()

// The only difference between port1 and port2 is in how you use them. Messages
// sent to port1 will be received by port2 and vice-versa.
const port1 = channel.port1
const port2 = channel.port2

// It's OK to send a message on the channel before the other end has registered
// a listener. Messages will be queued until a listener is registered.
port2.postMessage({ answer: 42 })

// Here we send the other end of the channel, port1, to the main process. It's
// also possible to send MessagePorts to other frames, or to Web Workers, etc.
ipcRenderer.postMessage('port', null, [port1])
```




main.js (Main Process)


```
// In the main process, we receive the port.
ipcMain.on('port', (event) => {
  // When we receive a MessagePort in the main process, it becomes a
  // MessagePortMain.
  const port = event.ports[0]

  // MessagePortMain uses the Node.js-style events API, rather than the
  // web-style events API. So .on('message', ...) instead of .onmessage = ...
  port.on('message', (event) => {
    // data is { answer: 42 }
    const data = event.data
  })

  // MessagePortMain queues messages until the .start() method has been called.
  port.start()
})
```



The [Channel Messaging API](https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API) documentation is a great way to learn more about how MessagePorts work.


MessagePorts in the main process[​](#messageports-in-the-main-process "Direct link to heading")
-----------------------------------------------------------------------------------------------


In the renderer, the `MessagePort` class behaves exactly as it does on the web. The main process is not a web page, though—it has no Blink integration—and so it does not have the `MessagePort` or `MessageChannel` classes. In order to handle and interact with MessagePorts in the main process, Electron adds two new classes: [`MessagePortMain`](../api/message-port-main) and [`MessageChannelMain`](../api/message-channel-main). These behave similarly to the analogous classes in the renderer.


`MessagePort` objects can be created in either the renderer or the main process, and passed back and forth using the [`ipcRenderer.postMessage`](../api/ipc-renderer#ipcrendererpostmessagechannel-message-transfer) and [`WebContents.postMessage`](../api/web-contents#contentspostmessagechannel-message-transfer) methods. Note that the usual IPC methods like `send` and `invoke` cannot be used to transfer `MessagePort`s, only the `postMessage` methods can transfer `MessagePort`s.


By passing `MessagePort`s via the main process, you can connect two pages that might not otherwise be able to communicate (e.g. due to same-origin restrictions).


Extension: `close` event[​](#extension-close-event "Direct link to heading")
----------------------------------------------------------------------------


Electron adds one feature to `MessagePort` that isn't present on the web, in order to make MessagePorts more useful. That is the `close` event, which is emitted when the other end of the channel is closed. Ports can also be implicitly closed by being garbage-collected.


In the renderer, you can listen for the `close` event either by assigning to `port.onclose` or by calling `port.addEventListener('close', ...)`. In the main process, you can listen for the `close` event by calling `port.on('close',
...)`.


Example use cases[​](#example-use-cases "Direct link to heading")
-----------------------------------------------------------------


### Setting up a MessageChannel between two renderers[​](#setting-up-a-messagechannel-between-two-renderers "Direct link to heading")


In this example, the main process sets up a MessageChannel, then sends each port to a different renderer. This allows renderers to send messages to each other without needing to use the main process as an in-between.



main.js (Main Process)


```
const { BrowserWindow, app, MessageChannelMain } = require('electron')

app.whenReady().then(async () => {
  // create the windows.
  const mainWindow = new BrowserWindow({
    show: false,
    webPreferences: {
      contextIsolation: false,
      preload: 'preloadMain.js'
    }
  })

  const secondaryWindow = BrowserWindow({
    show: false,
    webPreferences: {
      contextIsolation: false,
      preload: 'preloadSecondary.js'
    }
  })

  // set up the channel.
  const { port1, port2 } = new MessageChannelMain()

  // once the webContents are ready, send a port to each webContents with postMessage.
  mainWindow.once('ready-to-show', () => {
    mainWindow.webContents.postMessage('port', null, [port1])
  })

  secondaryWindow.once('ready-to-show', () => {
    secondaryWindow.webContents.postMessage('port', null, [port2])
  })
})
```



Then, in your preload scripts you receive the port through IPC and set up the listeners.



preloadMain.js and preloadSecondary.js (Preload scripts)


```
const { ipcRenderer } = require('electron')

ipcRenderer.on('port', e => {
  // port received, make it globally available.
  window.electronMessagePort = e.ports[0]

  window.electronMessagePort.onmessage = messageEvent => {
    // handle message
  }
})
```



In this example messagePort is bound to the `window` object directly. It is better to use `contextIsolation` and set up specific contextBridge calls for each of your expected messages, but for the simplicity of this example we don't. You can find an example of context isolation further down this page at [Communicating directly between the main process and the main world of a context-isolated page](#communicating-directly-between-the-main-process-and-the-main-world-of-a-context-isolated-page)


That means window.messagePort is globally available and you can call `postMessage` on it from anywhere in your app to send a message to the other renderer.



renderer.js (Renderer Process)


```
// elsewhere in your code to send a message to the other renderers message handler
window.electronMessagePort.postmessage('ping')
```



### Worker process[​](#worker-process "Direct link to heading")


In this example, your app has a worker process implemented as a hidden window. You want the app page to be able to communicate directly with the worker process, without the performance overhead of relaying via the main process.



main.js (Main Process)


```
const { BrowserWindow, app, ipcMain, MessageChannelMain } = require('electron')

app.whenReady().then(async () => {
  // The worker process is a hidden BrowserWindow, so that it will have access
  // to a full Blink context (including e.g. <canvas>, audio, fetch(), etc.)
  const worker = new BrowserWindow({
    show: false,
    webPreferences: { nodeIntegration: true }
  })
  await worker.loadFile('worker.html')

  // The main window will send work to the worker process and receive results
  // over a MessagePort.
  const mainWindow = new BrowserWindow({
    webPreferences: { nodeIntegration: true }
  })
  mainWindow.loadFile('app.html')

  // We can't use ipcMain.handle() here, because the reply needs to transfer a
  // MessagePort.
  ipcMain.on('request-worker-channel', (event) => {
    // For security reasons, let's make sure only the frames we expect can
    // access the worker.
    if (event.senderFrame === mainWindow.webContents.mainFrame) {
      // Create a new channel ...
      const { port1, port2 } = new MessageChannelMain()
      // ... send one end to the worker ...
      worker.webContents.postMessage('new-client', null, [port1])
      // ... and the other end to the main window.
      event.senderFrame.postMessage('provide-worker-channel', null, [port2])
      // Now the main window and the worker can communicate with each other
      // without going through the main process!
    }
  })
})
```




worker.html


```
<script>
const { ipcRenderer } = require('electron')

const doWork = (input) => {
  // Something cpu-intensive.
  return input * 2
}

// We might get multiple clients, for instance if there are multiple windows,
// or if the main window reloads.
ipcRenderer.on('new-client', (event) => {
  const [ port ] = event.ports
  port.onmessage = (event) => {
    // The event data can be any serializable object (and the event could even
    // carry other MessagePorts with it!)
    const result = doWork(event.data)
    port.postMessage(result)
  }
})
</script>
```




app.html


```
<script>
const { ipcRenderer } = require('electron')

// We request that the main process sends us a channel we can use to
// communicate with the worker.
ipcRenderer.send('request-worker-channel')

ipcRenderer.once('provide-worker-channel', (event) => {
  // Once we receive the reply, we can take the port...
  const [ port ] = event.ports
  // ... register a handler to receive results ...
  port.onmessage = (event) => {
    console.log('received result:', event.data)
  }
  // ... and start sending it work!
  port.postMessage(21)
})
</script>
```



### Reply streams[​](#reply-streams "Direct link to heading")


Electron's built-in IPC methods only support two modes: fire-and-forget (e.g. `send`), or request-response (e.g. `invoke`). Using MessageChannels, you can implement a "response stream", where a single request responds with a stream of data.



renderer.js (Renderer Process)


```
const makeStreamingRequest = (element, callback) => {
  // MessageChannels are lightweight--it's cheap to create a new one for each
  // request.
  const { port1, port2 } = new MessageChannel()

  // We send one end of the port to the main process ...
  ipcRenderer.postMessage(
    'give-me-a-stream',
    { element, count: 10 },
    [port2]
  )

  // ... and we hang on to the other end. The main process will send messages
  // to its end of the port, and close it when it's finished.
  port1.onmessage = (event) => {
    callback(event.data)
  }
  port1.onclose = () => {
    console.log('stream ended')
  }
}

makeStreamingRequest(42, (data) => {
  console.log('got response data:', event.data)
})
// We will see "got response data: 42" 10 times.
```




main.js (Main Process)


```
ipcMain.on('give-me-a-stream', (event, msg) => {
  // The renderer has sent us a MessagePort that it wants us to send our
  // response over.
  const [replyPort] = event.ports

  // Here we send the messages synchronously, but we could just as easily store
  // the port somewhere and send messages asynchronously.
  for (let i = 0; i < msg.count; i++) {
    replyPort.postMessage(msg.element)
  }

  // We close the port when we're done to indicate to the other end that we
  // won't be sending any more messages. This isn't strictly necessary--if we
  // didn't explicitly close the port, it would eventually be garbage
  // collected, which would also trigger the 'close' event in the renderer.
  replyPort.close()
})
```



### Communicating directly between the main process and the main world of a context-isolated page[​](#communicating-directly-between-the-main-process-and-the-main-world-of-a-context-isolated-page "Direct link to heading")


When [context isolation](context-isolation) is enabled, IPC messages from the main process to the renderer are delivered to the isolated world, rather than to the main world. Sometimes you want to deliver messages to the main world directly, without having to step through the isolated world.



main.js (Main Process)


```
const { BrowserWindow, app, MessageChannelMain } = require('electron')
const path = require('path')

app.whenReady().then(async () => {
  // Create a BrowserWindow with contextIsolation enabled.
  const bw = new BrowserWindow({
    webPreferences: {
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js')
    }
  })
  bw.loadURL('index.html')

  // We'll be sending one end of this channel to the main world of the
  // context-isolated page.
  const { port1, port2 } = new MessageChannelMain()

  // It's OK to send a message on the channel before the other end has
  // registered a listener. Messages will be queued until a listener is
  // registered.
  port2.postMessage({ test: 21 })

  // We can also receive messages from the main world of the renderer.
  port2.on('message', (event) => {
    console.log('from renderer main world:', event.data)
  })
  port2.start()

  // The preload script will receive this IPC message and transfer the port
  // over to the main world.
  bw.webContents.postMessage('main-world-port', null, [port1])
})
```




preload.js (Preload Script)


```
const { ipcRenderer } = require('electron')

// We need to wait until the main world is ready to receive the message before
// sending the port. We create this promise in the preload so it's guaranteed
// to register the onload listener before the load event is fired.
const windowLoaded = new Promise(resolve => {
  window.onload = resolve
})

ipcRenderer.on('main-world-port', async (event) => {
  await windowLoaded
  // We use regular window.postMessage to transfer the port from the isolated
  // world to the main world.
  window.postMessage('main-world-port', '*', event.ports)
})
```




index.html


```
<script>
window.onmessage = (event) => {
  // event.source === window means the message is coming from the preload
  // script, as opposed to from an <iframe> or other source.
  if (event.source === window && event.data === 'main-world-port') {
    const [ port ] = event.ports
    // Once we have the port, we can communicate directly with the main
    // process.
    port.onmessage = (event) => {
      console.log('from main process:', event.data)
      port.postMessage(event.data * 2)
    }
  }
}
</script>
```




 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/message-ports>

Device Access
=============


Like Chromium based browsers, Electron provides access to device hardware through web APIs. For the most part these APIs work like they do in a browser, but there are some differences that need to be taken into account. The primary difference between Electron and browsers is what happens when device access is requested. In a browser, users are presented with a popup where they can grant access to an individual device. In Electron APIs are provided which can be used by a developer to either automatically pick a device or prompt users to pick a device via a developer created interface.


Web Bluetooth API[​](#web-bluetooth-api "Direct link to heading")
-----------------------------------------------------------------


The [Web Bluetooth API](https://web.dev/bluetooth/) can be used to communicate with bluetooth devices. In order to use this API in Electron, developers will need to handle the [`select-bluetooth-device` event on the webContents](../api/web-contents#event-select-bluetooth-device) associated with the device request.


### Example[​](#example "Direct link to heading")


This example demonstrates an Electron application that automatically selects the first available bluetooth device when the `Test Bluetooth` button is clicked.




[docs/fiddles/features/web-bluetooth (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/features/web-bluetooth)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/features/web-bluetooth)


* main.js
* index.html
* renderer.js





```
const {app, BrowserWindow} = require('electron')
const path = require('path')

function createWindow () {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600
  })

  mainWindow.webContents.on('select-bluetooth-device', (event, deviceList, callback) => {
    event.preventDefault()
    if (deviceList && deviceList.length > 0) {
      callback(deviceList[0].deviceId)
    } 
  })

  mainWindow.loadFile('index.html')
}

app.whenReady().then(() => {
  createWindow()
  
  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})
```




```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Web Bluetooth API</title>
  </head>
  <body>
    <h1>Web Bluetooth API</h1>

    <button id="clickme">Test Bluetooth</button>

    <p>Currently selected bluetooth device: <strong id="device-name""></strong></p>

    <script src="./renderer.js"></script>
  </body>
</html>
```




```
async function testIt() {
  const device = await navigator.bluetooth.requestDevice({
    acceptAllDevices: true
  })
  document.getElementById('device-name').innerHTML = device.name || `ID: ${device.id}`
}

document.getElementById('clickme').addEventListener('click',testIt)
```





WebHID API[​](#webhid-api "Direct link to heading")
---------------------------------------------------


The [WebHID API](https://web.dev/hid/) can be used to access HID devices such as keyboards and gamepads. Electron provides several APIs for working with the WebHID API:


* The [`select-hid-device` event on the Session](../api/session#event-select-hid-device) can be used to select a HID device when a call to `navigator.hid.requestDevice` is made. Additionally the [`hid-device-added`](../api/session#event-hid-device-added) and [`hid-device-removed`](../api/session#event-hid-device-removed) events on the Session can be used to handle devices being plugged in or unplugged when handling the `select-hid-device` event. **Note:** These events only fire until the callback from `select-hid-device` is called. They are not intended to be used as a generic hid device listener.
* [`ses.setDevicePermissionHandler(handler)`](../api/session#sessetdevicepermissionhandlerhandler) can be used to provide default permissioning to devices without first calling for permission to devices via `navigator.hid.requestDevice`. Additionally, the default behavior of Electron is to store granted device permision through the lifetime of the corresponding WebContents. If longer term storage is needed, a developer can store granted device permissions (eg when handling the `select-hid-device` event) and then read from that storage with `setDevicePermissionHandler`.
* [`ses.setPermissionCheckHandler(handler)`](../api/session#sessetpermissioncheckhandlerhandler) can be used to disable HID access for specific origins.


### Blocklist[​](#blocklist "Direct link to heading")


By default Electron employs the same [blocklist](https://github.com/WICG/webhid/blob/main/blocklist.txt) used by Chromium. If you wish to override this behavior, you can do so by setting the `disable-hid-blocklist` flag:




```
app.commandLine.appendSwitch('disable-hid-blocklist')
```


### Example[​](#example-1 "Direct link to heading")


This example demonstrates an Electron application that automatically selects HID devices through [`ses.setDevicePermissionHandler(handler)`](../api/session#sessetdevicepermissionhandlerhandler) and through [`select-hid-device` event on the Session](../api/session#event-select-hid-device) when the `Test WebHID` button is clicked.




[docs/fiddles/features/web-hid (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/features/web-hid)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/features/web-hid)


* main.js
* index.html
* renderer.js





```
const {app, BrowserWindow} = require('electron')
const path = require('path')

function createWindow () {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600
  })
  
  mainWindow.webContents.session.on('select-hid-device', (event, details, callback) => {
    //Add events to handle devices being added or removed before the callback on
    //`select-hid-device` is called.
    mainWindow.webContents.session.on('hid-device-added', (event, device) => {    
      console.log('hid-device-added FIRED WITH', device)
      //Optionally update details.deviceList
    })
  
    mainWindow.webContents.session.on('hid-device-removed', (event, device) => {    
      console.log('hid-device-removed FIRED WITH', device)
      //Optionally update details.deviceList
    })

    event.preventDefault()
    if (details.deviceList && details.deviceList.length > 0) {
      callback(details.deviceList[0].deviceId)
    }
  })

  mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
    if (permission === 'hid' && details.securityOrigin === 'file:///') {
      return true
    }
  })

  mainWindow.webContents.session.setDevicePermissionHandler((details) => {
    if (details.deviceType === 'hid' && details.origin === 'file://') {
      return true
    }
  })
  
  mainWindow.loadFile('index.html')
}

app.whenReady().then(() => {
  createWindow()
  
  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})
```




```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>WebHID API</title>
  </head>
  <body>
    <h1>WebHID API</h1>

    <button id="clickme">Test WebHID</button>

    <h3>HID devices automatically granted access via <i>setDevicePermissionHandler</i></h3>
    <div id="granted-devices"></div>
    
    <h3>HID devices automatically granted access via <i>select-hid-device</i></h3>
    <div id="granted-devices2"></div>

    <script src="./renderer.js"></script>
  </body>
</html>
```




```
async function testIt() {
  const grantedDevices = await navigator.hid.getDevices()
  let grantedDeviceList = ''
  grantedDevices.forEach(device => {
    grantedDeviceList += `<hr>${device.productName}</hr>`
  })
  document.getElementById('granted-devices').innerHTML = grantedDeviceList
  const grantedDevices2 = await navigator.hid.requestDevice({
    filters: []
  })

  grantedDeviceList = ''
   grantedDevices2.forEach(device => {
    grantedDeviceList += `<hr>${device.productName}</hr>`
  })
  document.getElementById('granted-devices2').innerHTML = grantedDeviceList
}

document.getElementById('clickme').addEventListener('click',testIt)
```





Web Serial API[​](#web-serial-api "Direct link to heading")
-----------------------------------------------------------


The [Web Serial API](https://web.dev/serial/) can be used to access serial devices that are connected via serial port, USB, or Bluetooth. In order to use this API in Electron, developers will need to handle the [`select-serial-port` event on the Session](../api/session#event-select-serial-port) associated with the serial port request.


There are several additional APIs for working with the Web Serial API:


* The [`serial-port-added`](../api/session#event-serial-port-added) and [`serial-port-removed`](../api/session#event-serial-port-removed) events on the Session can be used to handle devices being plugged in or unplugged when handling the `select-serial-port` event. **Note:** These events only fire until the callback from `select-serial-port` is called. They are not intended to be used as a generic serial port listener.
* [`ses.setDevicePermissionHandler(handler)`](../api/session#sessetdevicepermissionhandlerhandler) can be used to provide default permissioning to devices without first calling for permission to devices via `navigator.serial.requestPort`. Additionally, the default behavior of Electron is to store granted device permision through the lifetime of the corresponding WebContents. If longer term storage is needed, a developer can store granted device permissions (eg when handling the `select-serial-port` event) and then read from that storage with `setDevicePermissionHandler`.
* [`ses.setPermissionCheckHandler(handler)`](../api/session#sessetpermissioncheckhandlerhandler) can be used to disable serial access for specific origins.


### Example[​](#example-2 "Direct link to heading")


This example demonstrates an Electron application that automatically selects serial devices through [`ses.setDevicePermissionHandler(handler)`](../api/session#sessetdevicepermissionhandlerhandler) as well as demonstrating selecting the first available Arduino Uno serial device (if connected) through [`select-serial-port` event on the Session](../api/session#event-select-serial-port) when the `Test Web Serial` button is clicked.




[docs/fiddles/features/web-serial (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/features/web-serial)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/features/web-serial)


* main.js
* index.html
* renderer.js





```
const {app, BrowserWindow} = require('electron')
const path = require('path')

function createWindow () {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600
  })
  
  mainWindow.webContents.session.on('select-serial-port', (event, portList, webContents, callback) => {

    //Add listeners to handle ports being added or removed before the callback for `select-serial-port`
    //is called.
    mainWindow.webContents.session.on('serial-port-added', (event, port) => {
      console.log('serial-port-added FIRED WITH', port)
      //Optionally update portList to add the new port
    })
  
    mainWindow.webContents.session.on('serial-port-removed', (event, port) => {
      console.log('serial-port-removed FIRED WITH', port)
      //Optionally update portList to remove the port
    })

    event.preventDefault()
    if (portList && portList.length > 0) {
      callback(portList[0].portId)
    } else {
      callback('') //Could not find any matching devices
    }
  })

  mainWindow.webContents.session.setPermissionCheckHandler((webContents, permission, requestingOrigin, details) => {
    if (permission === 'serial' && details.securityOrigin === 'file:///') {
      return true
    }
  })

  mainWindow.webContents.session.setDevicePermissionHandler((details) => {
    if (details.deviceType === 'serial' && details.origin === 'file://') {
      return true
    }
  })
  
  mainWindow.loadFile('index.html')

  mainWindow.webContents.openDevTools()
}

app.whenReady().then(() => {
  createWindow()
  
  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})
```




```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Web Serial API</title>
  <body>
    <h1>Web Serial API</h1>

    <button id="clickme">Test Web Serial API</button>

    <p>Matching Arduino Uno device: <strong id="device-name""></strong></p>

    <script src="./renderer.js"></script>
  </body>
</html>
```




```
async function testIt() {
  const filters = [
    { usbVendorId: 0x2341, usbProductId: 0x0043 },
    { usbVendorId: 0x2341, usbProductId: 0x0001 }
  ];
  try {
    const port = await navigator.serial.requestPort({filters});
    const portInfo = port.getInfo();
    document.getElementById('device-name').innerHTML = `vendorId: ${portInfo.usbVendorId} | productId: ${portInfo.usbProductId} `
  } catch (ex) {
    if (ex.name === 'NotFoundError') {
      document.getElementById('device-name').innerHTML = 'Device NOT found'
    } else {
      document.getElementById('device-name').innerHTML = ex
    }
  }
}

document.getElementById('clickme').addEventListener('click',testIt)
```






 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/devices>

Windows Store Guide
===================


With Windows 10, the good old win32 executable got a new sibling: The Universal Windows Platform. The new `.appx` format does not only enable a number of new powerful APIs like Cortana or Push Notifications, but through the Windows Store, also simplifies installation and updating.


Microsoft [developed a tool that compiles Electron apps as `.appx` packages](https://github.com/catalystcode/electron-windows-store), enabling developers to use some of the goodies found in the new application model. This guide explains how to use it - and what the capabilities and limitations of an Electron AppX package are.


Background and Requirements[​](#background-and-requirements "Direct link to heading")
-------------------------------------------------------------------------------------


Windows 10 "Anniversary Update" is able to run win32 `.exe` binaries by launching them together with a virtualized filesystem and registry. Both are created during compilation by running app and installer inside a Windows Container, allowing Windows to identify exactly which modifications to the operating system are done during installation. Pairing the executable with a virtual filesystem and a virtual registry allows Windows to enable one-click installation and uninstallation.


In addition, the exe is launched inside the appx model - meaning that it can use many of the APIs available to the Universal Windows Platform. To gain even more capabilities, an Electron app can pair up with an invisible UWP background task launched together with the `exe` - sort of launched as a sidekick to run tasks in the background, receive push notifications, or to communicate with other UWP applications.


To compile any existing Electron app, ensure that you have the following requirements:


* Windows 10 with Anniversary Update (released August 2nd, 2016)
* The Windows 10 SDK, [downloadable here](https://developer.microsoft.com/en-us/windows/downloads/windows-10-sdk)
* At least Node 4 (to check, run `node -v`)


Then, go and install the `electron-windows-store` CLI:




```
npm install -g electron-windows-store
```


Step 1: Package Your Electron Application[​](#step-1-package-your-electron-application "Direct link to heading")
----------------------------------------------------------------------------------------------------------------


Package the application using [electron-packager](https://github.com/electron/electron-packager) (or a similar tool). Make sure to remove `node_modules` that you don't need in your final application, since any module you don't actually need will increase your application's size.


The output should look roughly like this:




```
├── Ghost.exe
├── LICENSE
├── content_resources_200_percent.pak
├── content_shell.pak
├── d3dcompiler_47.dll
├── ffmpeg.dll
├── icudtl.dat
├── libEGL.dll
├── libGLESv2.dll
├── locales
│   ├── am.pak
│   ├── ar.pak
│   ├── [...]
├── node.dll
├── resources
│   └── app.asar
├── v8_context_snapshot.bin
├── squirrel.exe
└── ui_resources_200_percent.pak
```


Step 2: Running electron-windows-store[​](#step-2-running-electron-windows-store "Direct link to heading")
----------------------------------------------------------------------------------------------------------


From an elevated PowerShell (run it "as Administrator"), run `electron-windows-store` with the required parameters, passing both the input and output directories, the app's name and version, and confirmation that `node_modules` should be flattened.




```
electron-windows-store `
    --input-directory C:\myelectronapp `
    --output-directory C:\output\myelectronapp `
    --package-version 1.0.0.0 `
    --package-name myelectronapp
```


Once executed, the tool goes to work: It accepts your Electron app as an input, flattening the `node_modules`. Then, it archives your application as `app.zip`. Using an installer and a Windows Container, the tool creates an "expanded" AppX package - including the Windows Application Manifest (`AppXManifest.xml`) as well as the virtual file system and the virtual registry inside your output folder.


Once the expanded AppX files are created, the tool uses the Windows App Packager (`MakeAppx.exe`) to create a single-file AppX package from those files on disk. Finally, the tool can be used to create a trusted certificate on your computer to sign the new AppX package. With the signed AppX package, the CLI can also automatically install the package on your machine.


Step 3: Using the AppX Package[​](#step-3-using-the-appx-package "Direct link to heading")
------------------------------------------------------------------------------------------


In order to run your package, your users will need Windows 10 with the so-called "Anniversary Update" - details on how to update Windows can be found [here](https://blogs.windows.com/windowsexperience/2016/08/02/how-to-get-the-windows-10-anniversary-update).


In opposition to traditional UWP apps, packaged apps currently need to undergo a manual verification process, for which you can apply [here](https://developer.microsoft.com/en-us/windows/projects/campaigns/desktop-bridge). In the meantime, all users will be able to install your package by double-clicking it, so a submission to the store might not be necessary if you're looking for an easier installation method. In managed environments (usually enterprises), the `Add-AppxPackage` [PowerShell Cmdlet can be used to install it in an automated fashion](https://technet.microsoft.com/en-us/library/hh856048.aspx).


Another important limitation is that the compiled AppX package still contains a win32 executable - and will therefore not run on Xbox, HoloLens, or Phones.


Optional: Add UWP Features using a BackgroundTask[​](#optional-add-uwp-features-using-a-backgroundtask "Direct link to heading")
--------------------------------------------------------------------------------------------------------------------------------


You can pair your Electron app up with an invisible UWP background task that gets to make full use of Windows 10 features - like push notifications, Cortana integration, or live tiles.


To check out how an Electron app that uses a background task to send toast notifications and live tiles, [check out the Microsoft-provided sample](https://github.com/felixrieseberg/electron-uwp-background).


Optional: Convert using Container Virtualization[​](#optional-convert-using-container-virtualization "Direct link to heading")
------------------------------------------------------------------------------------------------------------------------------


To generate the AppX package, the `electron-windows-store` CLI uses a template that should work for most Electron apps. However, if you are using a custom installer, or should you experience any trouble with the generated package, you can attempt to create a package using compilation with a Windows Container - in that mode, the CLI will install and run your application in blank Windows Container to determine what modifications your application is exactly doing to the operating system.


Before running the CLI for the first time, you will have to setup the "Windows Desktop App Converter". This will take a few minutes, but don't worry - you only have to do this once. Download and Desktop App Converter from [here](https://docs.microsoft.com/en-us/windows/uwp/porting/desktop-to-uwp-run-desktop-app-converter). You will receive two files: `DesktopAppConverter.zip` and `BaseImage-14316.wim`.


1. Unzip `DesktopAppConverter.zip`. From an elevated PowerShell (opened with "run as Administrator", ensure that your systems execution policy allows us to run everything we intend to run by calling `Set-ExecutionPolicy bypass`.
2. Then, run the installation of the Desktop App Converter, passing in the location of the Windows base Image (downloaded as `BaseImage-14316.wim`), by calling `.\DesktopAppConverter.ps1 -Setup -BaseImage .\BaseImage-14316.wim`.
3. If running the above command prompts you for a reboot, please restart your machine and run the above command again after a successful restart.


Once installation succeeded, you can move on to compiling your Electron app.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/windows-store-guide>

WebRequestFilter Object
=======================


* `urls` string[] - Array of URL patterns that will be used to filter out the requests that do not match the URL patterns.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/web-request-filter>

UploadData Object
=================


* `bytes` Buffer - Content being sent.
* `file` string (optional) - Path of file being uploaded.
* `blobUUID` string (optional) - UUID of blob data. Use [ses.getBlobData](../session#sesgetblobdataidentifier) method to retrieve the data.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/upload-data>

KeyboardEvent Object
====================


* `ctrlKey` boolean (optional) - whether the Control key was used in an accelerator to trigger the Event
* `metaKey` boolean (optional) - whether a meta key was used in an accelerator to trigger the Event
* `shiftKey` boolean (optional) - whether a Shift key was used in an accelerator to trigger the Event
* `altKey` boolean (optional) - whether an Alt key was used in an accelerator to trigger the Event
* `triggeredByAccelerator` boolean (optional) - whether an accelerator was used to trigger the event as opposed to another user gesture like mouse click



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/keyboard-event>

FileFilter Object
=================


* `name` string
* `extensions` string[]



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/file-filter>

crashReporter
=============



> Submit crash reports to a remote server.
> 
> 


Process: [Main](../glossary#main-process), [Renderer](../glossary#renderer-process)


The following is an example of setting up Electron to automatically submit crash reports to a remote server:




```
const { crashReporter } = require('electron')

crashReporter.start({ submitURL: 'https://your-domain.com/url-to-submit' })
```


For setting up a server to accept and process crash reports, you can use following projects:


* [socorro](https://github.com/mozilla/socorro)
* [mini-breakpad-server](https://github.com/electron/mini-breakpad-server)



> **Note:** Electron uses Crashpad, not Breakpad, to collect and upload crashes, but for the time being, the [upload protocol is the same](https://chromium.googlesource.com/crashpad/crashpad/+/HEAD/doc/overview_design.md#Upload-to-collection-server).
> 
> 


Or use a 3rd party hosted solution:


* [Backtrace](https://backtrace.io/electron/)
* [Sentry](https://docs.sentry.io/clients/electron)
* [BugSplat](https://www.bugsplat.com/docs/platforms/electron)
* [Bugsnag](https://docs.bugsnag.com/platforms/electron/)


Crash reports are stored temporarily before being uploaded in a directory underneath the app's user data directory, called 'Crashpad'. You can override this directory by calling `app.setPath('crashDumps', '/path/to/crashes')` before starting the crash reporter.


Electron uses [crashpad](https://chromium.googlesource.com/crashpad/crashpad/+/refs/heads/main/README.md) to monitor and report crashes.


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `crashReporter` module has the following methods:


### 
`crashReporter.start(options)`[​](#crashreporterstartoptions "Direct link to heading")


* `options` Object
	+ `submitURL` string (optional) - URL that crash reports will be sent to as POST. Required unless `uploadToServer` is `false`.
	+ `productName` string (optional) - Defaults to `app.name`.
	+ `companyName` string (optional) *Deprecated* - Deprecated alias for `{ globalExtra: { _companyName: ... } }`.
	+ `uploadToServer` boolean (optional) - Whether crash reports should be sent to the server. If false, crash reports will be collected and stored in the crashes directory, but not uploaded. Default is `true`.
	+ `ignoreSystemCrashHandler` boolean (optional) - If true, crashes generated in the main process will not be forwarded to the system crash handler. Default is `false`.
	+ `rateLimit` boolean (optional) *macOS* *Windows* - If true, limit the number of crashes uploaded to 1/hour. Default is `false`.
	+ `compress` boolean (optional) - If true, crash reports will be compressed and uploaded with `Content-Encoding: gzip`. Default is `true`.
	+ `extra` Record<string, string> (optional) - Extra string key/value annotations that will be sent along with crash reports that are generated in the main process. Only string values are supported. Crashes generated in child processes will not contain these extra parameters to crash reports generated from child processes, call [`addExtraParameter`](#crashreporteraddextraparameterkey-value) from the child process.
	+ `globalExtra` Record<string, string> (optional) - Extra string key/value annotations that will be sent along with any crash reports generated in any process. These annotations cannot be changed once the crash reporter has been started. If a key is present in both the global extra parameters and the process-specific extra parameters, then the global one will take precedence. By default, `productName` and the app version are included, as well as the Electron version.


This method must be called before using any other `crashReporter` APIs. Once initialized this way, the crashpad handler collects crashes from all subsequently created processes. The crash reporter cannot be disabled once started.


This method should be called as early as possible in app startup, preferably before `app.on('ready')`. If the crash reporter is not initialized at the time a renderer process is created, then that renderer process will not be monitored by the crash reporter.


**Note:** You can test out the crash reporter by generating a crash using `process.crash()`.


**Note:** If you need to send additional/updated `extra` parameters after your first call `start` you can call `addExtraParameter`.


**Note:** Parameters passed in `extra`, `globalExtra` or set with `addExtraParameter` have limits on the length of the keys and values. Key names must be at most 39 bytes long, and values must be no longer than 127 bytes. Keys with names longer than the maximum will be silently ignored. Key values longer than the maximum length will be truncated.


**Note:** This method is only available in the main process.


### 
`crashReporter.getLastCrashReport()`[​](#crashreportergetlastcrashreport "Direct link to heading")


Returns [CrashReport](structures/crash-report) - The date and ID of the last crash report. Only crash reports that have been uploaded will be returned; even if a crash report is present on disk it will not be returned until it is uploaded. In the case that there are no uploaded reports, `null` is returned.


**Note:** This method is only available in the main process.


### 
`crashReporter.getUploadedReports()`[​](#crashreportergetuploadedreports "Direct link to heading")


Returns [CrashReport[]](structures/crash-report):


Returns all uploaded crash reports. Each report contains the date and uploaded ID.


**Note:** This method is only available in the main process.


### 
`crashReporter.getUploadToServer()`[​](#crashreportergetuploadtoserver "Direct link to heading")


Returns `boolean` - Whether reports should be submitted to the server. Set through the `start` method or `setUploadToServer`.


**Note:** This method is only available in the main process.


### 
`crashReporter.setUploadToServer(uploadToServer)`[​](#crashreportersetuploadtoserveruploadtoserver "Direct link to heading")


* `uploadToServer` boolean - Whether reports should be submitted to the server.


This would normally be controlled by user preferences. This has no effect if called before `start` is called.


**Note:** This method is only available in the main process.


### 
`crashReporter.addExtraParameter(key, value)`[​](#crashreporteraddextraparameterkey-value "Direct link to heading")


* `key` string - Parameter key, must be no longer than 39 bytes.
* `value` string - Parameter value, must be no longer than 127 bytes.


Set an extra parameter to be sent with the crash report. The values specified here will be sent in addition to any values set via the `extra` option when `start` was called.


Parameters added in this fashion (or via the `extra` parameter to `crashReporter.start`) are specific to the calling process. Adding extra parameters in the main process will not cause those parameters to be sent along with crashes from renderer or other child processes. Similarly, adding extra parameters in a renderer process will not result in those parameters being sent with crashes that occur in other renderer processes or in the main process.


**Note:** Parameters have limits on the length of the keys and values. Key names must be no longer than 39 bytes, and values must be no longer than 20320 bytes. Keys with names longer than the maximum will be silently ignored. Key values longer than the maximum length will be truncated.


### 
`crashReporter.removeExtraParameter(key)`[​](#crashreporterremoveextraparameterkey "Direct link to heading")


* `key` string - Parameter key, must be no longer than 39 bytes.


Remove an extra parameter from the current set of parameters. Future crashes will not include this parameter.


### 
`crashReporter.getParameters()`[​](#crashreportergetparameters "Direct link to heading")


Returns `Record<string, string>` - The current 'extra' parameters of the crash reporter.


In Node child processes[​](#in-node-child-processes "Direct link to heading")
-----------------------------------------------------------------------------


Since `require('electron')` is not available in Node child processes, the following APIs are available on the `process` object in Node child processes.


#### 
`process.crashReporter.start(options)`[​](#processcrashreporterstartoptions "Direct link to heading")


See [`crashReporter.start()`](#crashreporterstartoptions).


Note that if the crash reporter is started in the main process, it will automatically monitor child processes, so it should not be started in the child process. Only use this method if the main process does not initialize the crash reporter.


#### 
`process.crashReporter.getParameters()`[​](#processcrashreportergetparameters "Direct link to heading")


See [`crashReporter.getParameters()`](#crashreportergetparameters).


#### 
`process.crashReporter.addExtraParameter(key, value)`[​](#processcrashreporteraddextraparameterkey-value "Direct link to heading")


See [`crashReporter.addExtraParameter(key, value)`](#crashreporteraddextraparameterkey-value).


#### 
`process.crashReporter.removeExtraParameter(key)`[​](#processcrashreporterremoveextraparameterkey "Direct link to heading")


See [`crashReporter.removeExtraParameter(key)`](#crashreporterremoveextraparameterkey).


Crash Report Payload[​](#crash-report-payload "Direct link to heading")
-----------------------------------------------------------------------


The crash reporter will send the following data to the `submitURL` as a `multipart/form-data` `POST`:


* `ver` string - The version of Electron.
* `platform` string - e.g. 'win32'.
* `process_type` string - e.g. 'renderer'.
* `guid` string - e.g. '5e1286fc-da97-479e-918b-6bfb0c3d1c72'.
* `_version` string - The version in `package.json`.
* `_productName` string - The product name in the `crashReporter` `options` object.
* `prod` string - Name of the underlying product. In this case Electron.
* `_companyName` string - The company name in the `crashReporter` `options` object.
* `upload_file_minidump` File - The crash report in the format of `minidump`.
* All level one properties of the `extra` object in the `crashReporter``options` object.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/crash-reporter>

ShareMenu
=========


The `ShareMenu` class creates [Share Menu](https://developer.apple.com/design/human-interface-guidelines/macos/extensions/share-extensions/) on macOS, which can be used to share information from the current context to apps, social media accounts, and other services.


For including the share menu as a submenu of other menus, please use the `shareMenu` role of [`MenuItem`](menu-item).


Class: ShareMenu[​](#class-sharemenu "Direct link to heading")
--------------------------------------------------------------



> Create share menu on macOS.
> 
> 


Process: [Main](../glossary#main-process)


### 
`new ShareMenu(sharingItem)`[​](#new-sharemenusharingitem "Direct link to heading")


* `sharingItem` SharingItem - The item to share.


Creates a new share menu.


### Instance Methods[​](#instance-methods "Direct link to heading")


The `shareMenu` object has the following instance methods:


#### 
`shareMenu.popup([options])`[​](#sharemenupopupoptions "Direct link to heading")


* `options` PopupOptions (optional)
	+ `browserWindow` [BrowserWindow](browser-window) (optional) - Default is the focused window.
	+ `x` number (optional) - Default is the current mouse cursor position. Must be declared if `y` is declared.
	+ `y` number (optional) - Default is the current mouse cursor position. Must be declared if `x` is declared.
	+ `positioningItem` number (optional) *macOS* - The index of the menu item to be positioned under the mouse cursor at the specified coordinates. Default is -1.
	+ `callback` Function (optional) - Called when menu is closed.


Pops up this menu as a context menu in the [`BrowserWindow`](browser-window).


#### 
`shareMenu.closePopup([browserWindow])`[​](#sharemenuclosepopupbrowserwindow "Direct link to heading")


* `browserWindow` [BrowserWindow](browser-window) (optional) - Default is the focused window.


Closes the context menu in the `browserWindow`.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/share-menu>

Chromium Development
====================



> A collection of resources for learning about Chromium and tracking its development.
> 
> 


See also [V8 Development](v8-development)


Contributing to Chromium[​](#contributing-to-chromium "Direct link to heading")
-------------------------------------------------------------------------------


* [Checking Out and Building](https://chromium.googlesource.com/chromium/src/+/main/docs/#checking-out-and-building)


	+ [Windows](https://chromium.googlesource.com/chromium/src/+/main/docs/windows_build_instructions.md)
	+ [macOS](https://chromium.googlesource.com/chromium/src/+/main/docs/mac_build_instructions.md)
	+ [Linux](https://chromium.googlesource.com/chromium/src/+/main/docs/linux/build_instructions.md)
* [Contributing](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/contributing.md) - This document outlines the process of getting a code change merged to the Chromium source tree.


	+ Assumes a working Chromium checkout and build.


Resources for Chromium Development[​](#resources-for-chromium-development "Direct link to heading")
---------------------------------------------------------------------------------------------------


### Code Resources[​](#code-resources "Direct link to heading")


* [Code Search](https://cs.chromium.org/) - Indexed and searchable source code for Chromium and associated projects.
* [Source Code](https://cs.chromium.org/chromium/src/) - The source code for Chromium itself.
* [Chromium Review](https://chromium-review.googlesource.com) - The searchable code host which facilitates code reviews for Chromium and related projects.


### Informational Resources[​](#informational-resources "Direct link to heading")


* [Chromium Dash](https://chromiumdash.appspot.com/home) - Chromium Dash ties together multiple data sources in order to present a consolidated view of what's going on in Chromium and Chrome, plus related projects like V8, WebRTC & Skia.
	+ [Schedule](https://chromiumdash.appspot.com/schedule) - Review upcoming Chromium release schedule.
	+ [Branches](https://chromiumdash.appspot.com/branches) - Look up which branch corresponds to which milestone.
	+ [Releases](https://chromiumdash.appspot.com/releases) - See what version of Chromium is shipping to each release channel and look up changes between each version.
	+ [Commits](https://chromiumdash.appspot.com/commits) - See and search for commits to the Chromium source tree by commit SHA or committer username.
* [Discussion Groups](https://www.chromium.org/developers/discussion-groups) - Subscribe to the following groups to get project updates and discuss the Chromium projects, and to get help in developing for Chromium-based browsers.
* [Chromium Slack](https://www.chromium.org/developers/slack) - a virtual meeting place where Chromium ecosystem developers can foster community and coordinate work.


Social Links[​](#social-links "Direct link to heading")
-------------------------------------------------------


* [Blog](https://blog.chromium.org) - News and developments from Chromium.
* [@ChromiumDev](https://twitter.com/ChromiumDev) - Twitter account containing news & guidance for developers from the Google Chrome Developer Relations team.
* [@googlechrome](https://twitter.com/googlechrome) - Official Twitter account for the Google Chrome browser.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/chromium-development>

globalShortcut
==============



> Detect keyboard events when the application does not have keyboard focus.
> 
> 


Process: [Main](../glossary#main-process)


The `globalShortcut` module can register/unregister a global keyboard shortcut with the operating system so that you can customize the operations for various shortcuts.


**Note:** The shortcut is global; it will work even if the app does not have the keyboard focus. This module cannot be used before the `ready` event of the app module is emitted.




```
const { app, globalShortcut } = require('electron')

app.whenReady().then(() => {
  // Register a 'CommandOrControl+X' shortcut listener.
  const ret = globalShortcut.register('CommandOrControl+X', () => {
    console.log('CommandOrControl+X is pressed')
  })

  if (!ret) {
    console.log('registration failed')
  }

  // Check whether a shortcut is registered.
  console.log(globalShortcut.isRegistered('CommandOrControl+X'))
})

app.on('will-quit', () => {
  // Unregister a shortcut.
  globalShortcut.unregister('CommandOrControl+X')

  // Unregister all shortcuts.
  globalShortcut.unregisterAll()
})
```


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `globalShortcut` module has the following methods:


### 
`globalShortcut.register(accelerator, callback)`[​](#globalshortcutregisteraccelerator-callback "Direct link to heading")


* `accelerator` [Accelerator](accelerator)
* `callback` Function


Returns `boolean` - Whether or not the shortcut was registered successfully.


Registers a global shortcut of `accelerator`. The `callback` is called when the registered shortcut is pressed by the user.


When the accelerator is already taken by other applications, this call will silently fail. This behavior is intended by operating systems, since they don't want applications to fight for global shortcuts.


The following accelerators will not be registered successfully on macOS 10.14 Mojave unless the app has been authorized as a [trusted accessibility client](https://developer.apple.com/library/archive/documentation/Accessibility/Conceptual/AccessibilityMacOSX/OSXAXTestingApps.html):


* "Media Play/Pause"
* "Media Next Track"
* "Media Previous Track"
* "Media Stop"


### 
`globalShortcut.registerAll(accelerators, callback)`[​](#globalshortcutregisterallaccelerators-callback "Direct link to heading")


* `accelerators` string[] - an array of [Accelerator](accelerator)s.
* `callback` Function


Registers a global shortcut of all `accelerator` items in `accelerators`. The `callback` is called when any of the registered shortcuts are pressed by the user.


When a given accelerator is already taken by other applications, this call will silently fail. This behavior is intended by operating systems, since they don't want applications to fight for global shortcuts.


The following accelerators will not be registered successfully on macOS 10.14 Mojave unless the app has been authorized as a [trusted accessibility client](https://developer.apple.com/library/archive/documentation/Accessibility/Conceptual/AccessibilityMacOSX/OSXAXTestingApps.html):


* "Media Play/Pause"
* "Media Next Track"
* "Media Previous Track"
* "Media Stop"


### 
`globalShortcut.isRegistered(accelerator)`[​](#globalshortcutisregisteredaccelerator "Direct link to heading")


* `accelerator` [Accelerator](accelerator)


Returns `boolean` - Whether this application has registered `accelerator`.


When the accelerator is already taken by other applications, this call will still return `false`. This behavior is intended by operating systems, since they don't want applications to fight for global shortcuts.


### 
`globalShortcut.unregister(accelerator)`[​](#globalshortcutunregisteraccelerator "Direct link to heading")


* `accelerator` [Accelerator](accelerator)


Unregisters the global shortcut of `accelerator`.


### 
`globalShortcut.unregisterAll()`[​](#globalshortcutunregisterall "Direct link to heading")


Unregisters all of the global shortcuts.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/global-shortcut>

ShortcutDetails Object
======================


* `target` string - The target to launch from this shortcut.
* `cwd` string (optional) - The working directory. Default is empty.
* `args` string (optional) - The arguments to be applied to `target` when launching from this shortcut. Default is empty.
* `description` string (optional) - The description of the shortcut. Default is empty.
* `icon` string (optional) - The path to the icon, can be a DLL or EXE. `icon` and `iconIndex` have to be set together. Default is empty, which uses the target's icon.
* `iconIndex` number (optional) - The resource ID of icon when `icon` is a DLL or EXE. Default is 0.
* `appUserModelId` string (optional) - The Application User Model ID. Default is empty.
* `toastActivatorClsid` string (optional) - The Application Toast Activator CLSID. Needed for participating in Action Center.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/shortcut-details>

TraceCategoriesAndOptions Object
================================


* `categoryFilter` string - A filter to control what category groups should be traced. A filter can have an optional '-' prefix to exclude category groups that contain a matching category. Having both included and excluded category patterns in the same list is not supported. Examples: `test_MyTest*`, `test_MyTest*,test_OtherStuff`, `-excluded_category1,-excluded_category2`.
* `traceOptions` string - Controls what kind of tracing is enabled, it is a comma-delimited sequence of the following strings: `record-until-full`, `record-continuously`, `trace-to-console`, `enable-sampling`, `enable-systrace`, e.g. `'record-until-full,enable-sampling'`. The first 3 options are trace recording modes and hence mutually exclusive. If more than one trace recording modes appear in the `traceOptions` string, the last one takes precedence. If none of the trace recording modes are specified, recording mode is `record-until-full`. The trace option will first be reset to the default option (`record_mode` set to `record-until-full`, `enable_sampling` and `enable_systrace` set to `false`) before options parsed from `traceOptions` are applied on it.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/trace-categories-and-options>

Debugging the Main Process
==========================


The DevTools in an Electron browser window can only debug JavaScript that's executed in that window (i.e. the web pages). To debug JavaScript that's executed in the main process you will need to use an external debugger and launch Electron with the `--inspect` or `--inspect-brk` switch.


Command Line Switches[​](#command-line-switches "Direct link to heading")
-------------------------------------------------------------------------


Use one of the following command line switches to enable debugging of the main process:


### 
`--inspect=[port]`[​](#--inspectport "Direct link to heading")


Electron will listen for V8 inspector protocol messages on the specified `port`, an external debugger will need to connect on this port. The default `port` is `5858`.




```
electron --inspect=5858 your/app
```


### 
`--inspect-brk=[port]`[​](#--inspect-brkport "Direct link to heading")


Like `--inspect` but pauses execution on the first line of JavaScript.


External Debuggers[​](#external-debuggers "Direct link to heading")
-------------------------------------------------------------------


You will need to use a debugger that supports the V8 inspector protocol.


* Connect Chrome by visiting `chrome://inspect` and selecting to inspect the launched Electron app present there.
* [Debugging in VSCode](debugging-vscode)



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/debugging-main-process>

desktopCapturer
===============



> Access information about media sources that can be used to capture audio and video from the desktop using the [`navigator.mediaDevices.getUserMedia`](https://developer.mozilla.org/en/docs/Web/API/MediaDevices/getUserMedia) API.
> 
> 


Process: [Main](../glossary#main-process)


The following example shows how to capture video from a desktop window whose title is `Electron`:




```
// In the main process.
const { desktopCapturer } = require('electron')

desktopCapturer.getSources({ types: ['window', 'screen'] }).then(async sources => {
  for (const source of sources) {
    if (source.name === 'Electron') {
      mainWindow.webContents.send('SET_SOURCE', source.id)
      return
    }
  }
})
```




```
// In the preload script.
const { ipcRenderer } = require('electron')

ipcRenderer.on('SET_SOURCE', async (event, sourceId) => {
  try {
    const stream = await navigator.mediaDevices.getUserMedia({
      audio: false,
      video: {
        mandatory: {
          chromeMediaSource: 'desktop',
          chromeMediaSourceId: sourceId,
          minWidth: 1280,
          maxWidth: 1280,
          minHeight: 720,
          maxHeight: 720
        }
      }
    })
    handleStream(stream)
  } catch (e) {
    handleError(e)
  }
})

function handleStream (stream) {
  const video = document.querySelector('video')
  video.srcObject = stream
  video.onloadedmetadata = (e) => video.play()
}

function handleError (e) {
  console.log(e)
}
```


To capture video from a source provided by `desktopCapturer` the constraints passed to [`navigator.mediaDevices.getUserMedia`](https://developer.mozilla.org/en/docs/Web/API/MediaDevices/getUserMedia) must include `chromeMediaSource: 'desktop'`, and `audio: false`.


To capture both audio and video from the entire desktop the constraints passed to [`navigator.mediaDevices.getUserMedia`](https://developer.mozilla.org/en/docs/Web/API/MediaDevices/getUserMedia) must include `chromeMediaSource: 'desktop'`, for both `audio` and `video`, but should not include a `chromeMediaSourceId` constraint.




```
const constraints = {
  audio: {
    mandatory: {
      chromeMediaSource: 'desktop'
    }
  },
  video: {
    mandatory: {
      chromeMediaSource: 'desktop'
    }
  }
}
```


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `desktopCapturer` module has the following methods:


### 
`desktopCapturer.getSources(options)`[​](#desktopcapturergetsourcesoptions "Direct link to heading")


* `options` Object
	+ `types` string[] - An array of strings that lists the types of desktop sources to be captured, available types are `screen` and `window`.
	+ `thumbnailSize` [Size](structures/size) (optional) - The size that the media source thumbnail should be scaled to. Default is `150` x `150`. Set width or height to 0 when you do not need the thumbnails. This will save the processing time required for capturing the content of each window and screen.
	+ `fetchWindowIcons` boolean (optional) - Set to true to enable fetching window icons. The default value is false. When false the appIcon property of the sources return null. Same if a source has the type screen.


Returns `Promise<DesktopCapturerSource[]>` - Resolves with an array of [DesktopCapturerSource](structures/desktop-capturer-source) objects, each `DesktopCapturerSource` represents a screen or an individual window that can be captured.


**Note** Capturing the screen contents requires user consent on macOS 10.15 Catalina or higher, which can detected by [`systemPreferences.getMediaAccessStatus`](system-preferences#systempreferencesgetmediaaccessstatusmediatype-windows-macos).


Caveats[​](#caveats "Direct link to heading")
---------------------------------------------


`navigator.mediaDevices.getUserMedia` does not work on macOS for audio capture due to a fundamental limitation whereby apps that want to access the system's audio require a [signed kernel extension](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/KernelExtensions/KernelExtensions.html). Chromium, and by extension Electron, does not provide this.


It is possible to circumvent this limitation by capturing system audio with another macOS app like Soundflower and passing it through a virtual audio input device. This virtual device can then be queried with `navigator.mediaDevices.getUserMedia`.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/desktop-capturer>

Environment Variables
=====================



> Control application configuration and behavior without changing code.
> 
> 


Certain Electron behaviors are controlled by environment variables because they are initialized earlier than the command line flags and the app's code.


POSIX shell example:




```
$ export ELECTRON_ENABLE_LOGGING=true
$ electron
```


Windows console example:




```
> set ELECTRON_ENABLE_LOGGING=true
> electron
```


Production Variables[​](#production-variables "Direct link to heading")
-----------------------------------------------------------------------


The following environment variables are intended primarily for use at runtime in packaged Electron applications.


### 
`NODE_OPTIONS`[​](#node_options "Direct link to heading")


Electron includes support for a subset of Node's [`NODE_OPTIONS`](https://nodejs.org/api/cli.html#cli_node_options_options). The majority are supported with the exception of those which conflict with Chromium's use of BoringSSL.


Example:




```
export NODE_OPTIONS="--no-warnings --max-old-space-size=2048"
```


Unsupported options are:




```
--use-bundled-ca
--force-fips
--enable-fips
--openssl-config
--use-openssl-ca
```


`NODE_OPTIONS` are explicitly disallowed in packaged apps, except for the following:




```
--max-http-header-size
--http-parser
```


### 
`GOOGLE_API_KEY`[​](#google_api_key "Direct link to heading")


Geolocation support in Electron requires the use of Google Cloud Platform's geolocation webservice. To enable this feature, acquire a [Google API key](https://developers.google.com/maps/documentation/geolocation/get-api-key) and place the following code in your main process file, before opening any browser windows that will make geolocation requests:




```
process.env.GOOGLE_API_KEY = 'YOUR_KEY_HERE'
```


By default, a newly generated Google API key may not be allowed to make geolocation requests. To enable the geolocation webservice for your project, enable it through the [API library](https://console.cloud.google.com/apis/library).


N.B. You will need to add a [Billing Account](https://cloud.google.com/billing/docs/how-to/payment-methods#add_a_payment_method) to the project associated to the API key for the geolocation webservice to work.


### 
`ELECTRON_NO_ASAR`[​](#electron_no_asar "Direct link to heading")


Disables ASAR support. This variable is only supported in forked child processes and spawned child processes that set `ELECTRON_RUN_AS_NODE`.


### 
`ELECTRON_RUN_AS_NODE`[​](#electron_run_as_node "Direct link to heading")


Starts the process as a normal Node.js process.


In this mode, you will be able to pass [cli options](https://nodejs.org/api/cli.html) to Node.js as you would when running the normal Node.js executable, with the exception of the following flags:


* "--openssl-config"
* "--use-bundled-ca"
* "--use-openssl-ca",
* "--force-fips"
* "--enable-fips"


These flags are disabled owing to the fact that Electron uses BoringSSL instead of OpenSSL when building Node.js' `crypto` module, and so will not work as designed.


### 
`ELECTRON_NO_ATTACH_CONSOLE` *Windows*[​](#electron_no_attach_console-windows "Direct link to heading")


Don't attach to the current console session.


### 
`ELECTRON_FORCE_WINDOW_MENU_BAR` *Linux*[​](#electron_force_window_menu_bar-linux "Direct link to heading")


Don't use the global menu bar on Linux.


### 
`ELECTRON_TRASH` *Linux*[​](#electron_trash-linux "Direct link to heading")


Set the trash implementation on Linux. Default is `gio`.


Options:


* `gvfs-trash`
* `trash-cli`
* `kioclient5`
* `kioclient`


Development Variables[​](#development-variables "Direct link to heading")
-------------------------------------------------------------------------


The following environment variables are intended primarily for development and debugging purposes.


### 
`ELECTRON_ENABLE_LOGGING`[​](#electron_enable_logging "Direct link to heading")


Prints Chromium's internal logging to the console.


Setting this variable is the same as passing `--enable-logging` on the command line. For more info, see `--enable-logging` in [command-line switches](command-line-switches#--enable-loggingfile).


### 
`ELECTRON_LOG_FILE`[​](#electron_log_file "Direct link to heading")


Sets the file destination for Chromium's internal logging.


Setting this variable is the same as passing `--log-file` on the command line. For more info, see `--log-file` in [command-line switches](command-line-switches#--log-filepath).


### 
`ELECTRON_DEBUG_DRAG_REGIONS`[​](#electron_debug_drag_regions "Direct link to heading")


Adds coloration to draggable regions on [`BrowserView`](browser-view)s on macOS - draggable regions will be colored green and non-draggable regions will be colored red to aid debugging.


### 
`ELECTRON_DEBUG_NOTIFICATIONS`[​](#electron_debug_notifications "Direct link to heading")


Adds extra logs to [`Notification`](notification) lifecycles on macOS to aid in debugging. Extra logging will be displayed when new Notifications are created or activated. They will also be displayed when common a tions are taken: a notification is shown, dismissed, its button is clicked, or it is replied to.


Sample output:




```
Notification created (com.github.Electron:notification:EAF7B87C-A113-43D7-8E76-F88EC9D73D44)
Notification displayed (com.github.Electron:notification:EAF7B87C-A113-43D7-8E76-F88EC9D73D44)
Notification activated (com.github.Electron:notification:EAF7B87C-A113-43D7-8E76-F88EC9D73D44)
Notification replied to (com.github.Electron:notification:EAF7B87C-A113-43D7-8E76-F88EC9D73D44)
```


### 
`ELECTRON_LOG_ASAR_READS`[​](#electron_log_asar_reads "Direct link to heading")


When Electron reads from an ASAR file, log the read offset and file path to the system `tmpdir`. The resulting file can be provided to the ASAR module to optimize file ordering.


### 
`ELECTRON_ENABLE_STACK_DUMPING`[​](#electron_enable_stack_dumping "Direct link to heading")


Prints the stack trace to the console when Electron crashes.


This environment variable will not work if the `crashReporter` is started.


### 
`ELECTRON_DEFAULT_ERROR_MODE` *Windows*[​](#electron_default_error_mode-windows "Direct link to heading")


Shows the Windows's crash dialog when Electron crashes.


This environment variable will not work if the `crashReporter` is started.


### 
`ELECTRON_OVERRIDE_DIST_PATH`[​](#electron_override_dist_path "Direct link to heading")


When running from the `electron` package, this variable tells the `electron` command to use the specified build of Electron instead of the one downloaded by `npm install`. Usage:




```
export ELECTRON_OVERRIDE_DIST_PATH=/Users/username/projects/electron/out/Testing
```


Set By Electron[​](#set-by-electron "Direct link to heading")
-------------------------------------------------------------


Electron sets some variables in your environment at runtime.


### 
`ORIGINAL_XDG_CURRENT_DESKTOP`[​](#original_xdg_current_desktop "Direct link to heading")


This variable is set to the value of `XDG_CURRENT_DESKTOP` that your application originally launched with. Electron sometimes modifies the value of `XDG_CURRENT_DESKTOP` to affect other logic within Chromium so if you want access to the *original* value you should look up this environment variable instead.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/environment-variables>

Testing on Headless CI Systems (Travis CI, Jenkins)
===================================================


Being based on Chromium, Electron requires a display driver to function. If Chromium can't find a display driver, Electron will fail to launch - and therefore not executing any of your tests, regardless of how you are running them. Testing Electron-based apps on Travis, CircleCI, Jenkins or similar Systems requires therefore a little bit of configuration. In essence, we need to use a virtual display driver.


Configuring the Virtual Display Server[​](#configuring-the-virtual-display-server "Direct link to heading")
-----------------------------------------------------------------------------------------------------------


First, install [Xvfb](https://en.wikipedia.org/wiki/Xvfb). It's a virtual framebuffer, implementing the X11 display server protocol - it performs all graphical operations in memory without showing any screen output, which is exactly what we need.


Then, create a virtual Xvfb screen and export an environment variable called DISPLAY that points to it. Chromium in Electron will automatically look for `$DISPLAY`, so no further configuration of your app is required. This step can be automated with Anaïs Betts' [xvfb-maybe](https://github.com/anaisbetts/xvfb-maybe): Prepend your test commands with `xvfb-maybe` and the little tool will automatically configure Xvfb, if required by the current system. On Windows or macOS, it will do nothing.




```
## On Windows or macOS, this invokes electron-mocha
## On Linux, if we are in a headless environment, this will be equivalent
## to xvfb-run electron-mocha ./test/*.js
xvfb-maybe electron-mocha ./test/*.js
```


### Travis CI[​](#travis-ci "Direct link to heading")


On Travis, your `.travis.yml` should look roughly like this:




```
addons:
  apt:
    packages:
      - xvfb

install:
  - export DISPLAY=':99.0'
  - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 &
```


### Jenkins[​](#jenkins "Direct link to heading")


For Jenkins, a [Xvfb plugin is available](https://wiki.jenkins-ci.org/display/JENKINS/Xvfb+Plugin).


### CircleCI[​](#circleci "Direct link to heading")


CircleCI is awesome and has Xvfb and `$DISPLAY` already set up, so no further configuration is required.


### AppVeyor[​](#appveyor "Direct link to heading")


AppVeyor runs on Windows, supporting Selenium, Chromium, Electron and similar tools out of the box - no configuration is required.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/testing-on-headless-ci>

MouseWheelInputEvent Object extends `MouseInputEvent`
=====================================================


* `type` string - The type of the event, can be `mouseWheel`.
* `deltaX` Integer (optional)
* `deltaY` Integer (optional)
* `wheelTicksX` Integer (optional)
* `wheelTicksY` Integer (optional)
* `accelerationRatioX` Integer (optional)
* `accelerationRatioY` Integer (optional)
* `hasPreciseScrollingDeltas` boolean (optional)
* `canScroll` boolean (optional)



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/mouse-wheel-input-event>

`File` Object
==============



> Use the HTML5 `File` API to work natively with files on the filesystem.
> 
> 


The DOM's File interface provides abstraction around native files in order to let users work on native files directly with the HTML5 file API. Electron has added a `path` attribute to the `File` interface which exposes the file's real path on filesystem.


Example of getting a real path from a dragged-onto-the-app file:




```
<div id="holder">
  Drag your file here
</div>

<script>
  document.addEventListener('drop', (e) => {
    e.preventDefault();
    e.stopPropagation();

    for (const f of e.dataTransfer.files) {
      console.log('File(s) you dragged here: ', f.path)
    }
  });
  document.addEventListener('dragover', (e) => {
    e.preventDefault();
    e.stopPropagation();
  });
</script>
```



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/file-object>

Opening windows from the renderer
=================================


There are several ways to control how windows are created from trusted or untrusted content within a renderer. Windows can be created from the renderer in two ways:


* clicking on links or submitting forms adorned with `target=_blank`
* JavaScript calling `window.open()`


For same-origin content, the new window is created within the same process, enabling the parent to access the child window directly. This can be very useful for app sub-windows that act as preference panels, or similar, as the parent can render to the sub-window directly, as if it were a `div` in the parent. This is the same behavior as in the browser.


Electron pairs this native Chrome `Window` with a BrowserWindow under the hood. You can take advantage of all the customization available when creating a BrowserWindow in the main process by using `webContents.setWindowOpenHandler()` for renderer-created windows.


BrowserWindow constructor options are set by, in increasing precedence order: parsed options from the `features` string from `window.open()`, security-related webPreferences inherited from the parent, and options given by [`webContents.setWindowOpenHandler`](web-contents#contentssetwindowopenhandlerhandler). Note that `webContents.setWindowOpenHandler` has final say and full privilege because it is invoked in the main process.


### 
`window.open(url[, frameName][, features])`[​](#windowopenurl-framename-features "Direct link to heading")


* `url` string
* `frameName` string (optional)
* `features` string (optional)


Returns [`Window`](https://developer.mozilla.org/en-US/docs/Web/API/Window) | null


`features` is a comma-separated key-value list, following the standard format of the browser. Electron will parse `BrowserWindowConstructorOptions` out of this list where possible, for convenience. For full control and better ergonomics, consider using `webContents.setWindowOpenHandler` to customize the BrowserWindow creation.


A subset of `WebPreferences` can be set directly, unnested, from the features string: `zoomFactor`, `nodeIntegration`, `preload`, `javascript`, `contextIsolation`, and `webviewTag`.


For example:




```
window.open('https://github.com', '_blank', 'top=500,left=200,frame=false,nodeIntegration=no')
```


**Notes:**


* Node integration will always be disabled in the opened `window` if it is disabled on the parent window.
* Context isolation will always be enabled in the opened `window` if it is enabled on the parent window.
* JavaScript will always be disabled in the opened `window` if it is disabled on the parent window.
* Non-standard features (that are not handled by Chromium or Electron) given in `features` will be passed to any registered `webContents`'s `did-create-window` event handler in the `options` argument.
* `frameName` follows the specification of `windowName` located in the [native documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/open#parameters).
* When opening `about:blank`, the child window's `WebPreferences` will be copied from the parent window, and there is no way to override it because Chromium skips browser side navigation in this case.


To customize or cancel the creation of the window, you can optionally set an override handler with `webContents.setWindowOpenHandler()` from the main process. Returning `{ action: 'deny' }` cancels the window. Returning `{
action: 'allow', overrideBrowserWindowOptions: { ... } }` will allow opening the window and setting the `BrowserWindowConstructorOptions` to be used when creating the window. Note that this is more powerful than passing options through the feature string, as the renderer has more limited privileges in deciding security preferences than the main process.


In addition to passing in `action` and `overrideBrowserWindowOptions`, `outlivesOpener` can be passed like: `{ action: 'allow', outlivesOpener: true,
overrideBrowserWindowOptions: { ... } }`. If set to `true`, the newly created window will not close when the opener window closes. The default value is `false`.


### Native `Window` example[​](#native-window-example "Direct link to heading")




```
// main.js
const mainWindow = new BrowserWindow()

// In this example, only windows with the `about:blank` url will be created.
// All other urls will be blocked.
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
  if (url === 'about:blank') {
    return {
      action: 'allow',
      overrideBrowserWindowOptions: {
        frame: false,
        fullscreenable: false,
        backgroundColor: 'black',
        webPreferences: {
          preload: 'my-child-window-preload-script.js'
        }
      }
    }
  }
  return { action: 'deny' }
})
```




```
// renderer process (mainWindow)
const childWindow = window.open('', 'modal')
childWindow.document.write('<h1>Hello</h1>')
```



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/window-open>

Cookie Object
=============


* `name` string - The name of the cookie.
* `value` string - The value of the cookie.
* `domain` string (optional) - The domain of the cookie; this will be normalized with a preceding dot so that it's also valid for subdomains.
* `hostOnly` boolean (optional) - Whether the cookie is a host-only cookie; this will only be `true` if no domain was passed.
* `path` string (optional) - The path of the cookie.
* `secure` boolean (optional) - Whether the cookie is marked as secure.
* `httpOnly` boolean (optional) - Whether the cookie is marked as HTTP only.
* `session` boolean (optional) - Whether the cookie is a session cookie or a persistent cookie with an expiration date.
* `expirationDate` Double (optional) - The expiration date of the cookie as the number of seconds since the UNIX epoch. Not provided for session cookies.
* `sameSite` string - The [Same Site](https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#SameSite_cookies) policy applied to this cookie. Can be `unspecified`, `no_restriction`, `lax` or `strict`.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/cookie>

CrashReport Object
==================


* `date` Date
* `id` string



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/crash-report>

Build Instructions (Linux)
==========================


Follow the guidelines below for building **Electron itself** on Linux, for the purposes of creating custom Electron binaries. For bundling and distributing your app code with the prebuilt Electron binaries, see the [application distribution](../tutorial/application-distribution) guide.


Prerequisites[​](#prerequisites "Direct link to heading")
---------------------------------------------------------


* At least 25GB disk space and 8GB RAM.
* Python >= 3.7.
* Node.js. There are various ways to install Node. You can download source code from [nodejs.org](https://nodejs.org) and compile it. Doing so permits installing Node on your own home directory as a standard user. Or try repositories such as [NodeSource](https://nodesource.com/blog/nodejs-v012-iojs-and-the-nodesource-linux-repositories).
* [clang](https://clang.llvm.org/get_started.html) 3.4 or later.
* Development headers of GTK 3 and libnotify.


On Ubuntu >= 20.04, install the following libraries:




```
$ sudo apt-get install build-essential clang libdbus-1-dev libgtk-3-dev \
                       libnotify-dev libasound2-dev libcap-dev \
                       libcups2-dev libxtst-dev \
                       libxss1 libnss3-dev gcc-multilib g++-multilib curl \
                       gperf bison python3-dbusmock openjdk-8-jre
```


On Ubuntu < 20.04, install the following libraries:




```
$ sudo apt-get install build-essential clang libdbus-1-dev libgtk-3-dev \
                       libnotify-dev libgnome-keyring-dev \
                       libasound2-dev libcap-dev libcups2-dev libxtst-dev \
                       libxss1 libnss3-dev gcc-multilib g++-multilib curl \
                       gperf bison python-dbusmock openjdk-8-jre
```


On RHEL / CentOS, install the following libraries:




```
$ sudo yum install clang dbus-devel gtk3-devel libnotify-devel \
                   libgnome-keyring-devel xorg-x11-server-utils libcap-devel \
                   cups-devel libXtst-devel alsa-lib-devel libXrandr-devel \
                   nss-devel python-dbusmock openjdk-8-jre
```


On Fedora, install the following libraries:




```
$ sudo dnf install clang dbus-devel gtk3-devel libnotify-devel \
                   libgnome-keyring-devel xorg-x11-server-utils libcap-devel \
                   cups-devel libXtst-devel alsa-lib-devel libXrandr-devel \
                   nss-devel python-dbusmock openjdk-8-jre
```


On Arch Linux / Manjaro, install the following libraries:




```
$ sudo pacman -Syu base-devel clang libdbus gtk2 libnotify \
                   libgnome-keyring alsa-lib libcap libcups libxtst \
                   libxss nss gcc-multilib curl gperf bison \
                   python2 python-dbusmock jdk8-openjdk
```


Other distributions may offer similar packages for installation via package managers such as pacman. Or one can compile from source code.


### Cross compilation[​](#cross-compilation "Direct link to heading")


If you want to build for an `arm` target you should also install the following dependencies:




```
$ sudo apt-get install libc6-dev-armhf-cross linux-libc-dev-armhf-cross \
                       g++-arm-linux-gnueabihf
```


Similarly for `arm64`, install the following:




```
$ sudo apt-get install libc6-dev-arm64-cross linux-libc-dev-arm64-cross \
                       g++-aarch64-linux-gnu
```


And to cross-compile for `arm` or targets, you should pass the `target_cpu` parameter to `gn gen`:




```
$ gn gen out/Testing --args='import(...) target_cpu="arm"'
```


Building[​](#building "Direct link to heading")
-----------------------------------------------


See [Build Instructions: GN](build-instructions-gn)


Troubleshooting[​](#troubleshooting "Direct link to heading")
-------------------------------------------------------------


### Error While Loading Shared Libraries: libtinfo.so.5[​](#error-while-loading-shared-libraries-libtinfoso5 "Direct link to heading")


Prebuilt `clang` will try to link to `libtinfo.so.5`. Depending on the host architecture, symlink to appropriate `libncurses`:




```
$ sudo ln -s /usr/lib/libncurses.so.5 /usr/lib/libtinfo.so.5
```


Advanced topics[​](#advanced-topics "Direct link to heading")
-------------------------------------------------------------


The default building configuration is targeted for major desktop Linux distributions. To build for a specific distribution or device, the following information may help you.


### Using system `clang` instead of downloaded `clang` binaries[​](#using-system-clang-instead-of-downloaded-clang-binaries "Direct link to heading")


By default Electron is built with prebuilt [`clang`](https://clang.llvm.org/get_started.html) binaries provided by the Chromium project. If for some reason you want to build with the `clang` installed in your system, you can specify the `clang_base_path` argument in the GN args.


For example if you installed `clang` under `/usr/local/bin/clang`:




```
$ gn gen out/Testing --args='import("//electron/build/args/testing.gn") clang_base_path = "/usr/local/bin"'
```


### Using compilers other than `clang`[​](#using-compilers-other-than-clang "Direct link to heading")


Building Electron with compilers other than `clang` is not supported.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/build-instructions-linux>

Build Instructions (Windows)
============================


Follow the guidelines below for building **Electron itself** on Windows, for the purposes of creating custom Electron binaries. For bundling and distributing your app code with the prebuilt Electron binaries, see the [application distribution](../tutorial/application-distribution) guide.


Prerequisites[​](#prerequisites "Direct link to heading")
---------------------------------------------------------


* Windows 10 / Server 2012 R2 or higher
* Visual Studio 2017 15.7.2 or higher - [download VS 2019 Community Edition for free](https://www.visualstudio.com/vs/)
	+ See [the Chromium build documentation](https://chromium.googlesource.com/chromium/src/+/main/docs/windows_build_instructions.md#visual-studio) for more details on which Visual Studio components are required.
	+ If your Visual Studio is installed in a directory other than the default, you'll need to set a few environment variables to point the toolchains to your installation path.
		- `vs2019_install = DRIVE:\path\to\Microsoft Visual Studio\2019\Community`, replacing `2019` and `Community` with your installed versions and replacing `DRIVE:` with the drive that Visual Studio is on. Often, this will be `C:`.
		- `WINDOWSSDKDIR = DRIVE:\path\to\Windows Kits\10`, replacing `DRIVE:` with the drive that Windows Kits is on. Often, this will be `C:`.
* [Node.js](https://nodejs.org/download/)
* [Git](https://git-scm.com)
* Debugging Tools for Windows of Windows SDK 10.0.15063.468 if you plan on creating a full distribution since `symstore.exe` is used for creating a symbol store from `.pdb` files.
	+ Different versions of the SDK can be installed side by side. To install the SDK, open Visual Studio Installer, select `Modify` → `Individual Components`, scroll down and select the appropriate Windows SDK to install. Another option would be to look at the [Windows SDK and emulator archive](https://developer.microsoft.com/en-us/windows/downloads/sdk-archive) and download the standalone version of the SDK respectively.
	+ The SDK Debugging Tools must also be installed. If the Windows 10 SDK was installed via the Visual Studio installer, then they can be installed by going to: `Control Panel` → `Programs` → `Programs and Features` → Select the "Windows Software Development Kit" → `Change` → `Change` → Check "Debugging Tools For Windows" → `Change`. Or, you can download the standalone SDK installer and use it to install the Debugging Tools.


If you don't currently have a Windows installation, [dev.microsoftedge.com](https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/) has timebombed versions of Windows that you can use to build Electron.


Building Electron is done entirely with command-line scripts and cannot be done with Visual Studio. You can develop Electron with any editor but support for building with Visual Studio will come in the future.


**Note:** Even though Visual Studio is not used for building, it's still **required** because we need the build toolchains it provides.


Exclude source tree from Windows Security[​](#exclude-source-tree-from-windows-security "Direct link to heading")
-----------------------------------------------------------------------------------------------------------------


Windows Security doesn't like one of the files in the Chromium source code (see <https://crbug.com/441184>), so it will constantly delete it, causing `gclient sync` issues. You can exclude the source tree from being monitored by Windows Security by [following these instructions](https://support.microsoft.com/en-us/windows/add-an-exclusion-to-windows-security-811816c0-4dfd-af4a-47e4-c301afe13b26).


Building[​](#building "Direct link to heading")
-----------------------------------------------


See [Build Instructions: GN](build-instructions-gn)


32bit Build[​](#32bit-build "Direct link to heading")
-----------------------------------------------------


To build for the 32bit target, you need to pass `target_cpu = "x86"` as a GN arg. You can build the 32bit target alongside the 64bit target by using a different output directory for GN, e.g. `out/Release-x86`, with different arguments.




```
$ gn gen out/Release-x86 --args="import(\"//electron/build/args/release.gn\") target_cpu=\"x86\""
```


The other building steps are exactly the same.


Visual Studio project[​](#visual-studio-project "Direct link to heading")
-------------------------------------------------------------------------


To generate a Visual Studio project, you can pass the `--ide=vs2017` parameter to `gn gen`:




```
$ gn gen out/Testing --ide=vs2017
```


Troubleshooting[​](#troubleshooting "Direct link to heading")
-------------------------------------------------------------


### Command xxxx not found[​](#command-xxxx-not-found "Direct link to heading")


If you encountered an error like `Command xxxx not found`, you may try to use the `VS2015 Command Prompt` console to execute the build scripts.


### Fatal internal compiler error: C1001[​](#fatal-internal-compiler-error-c1001 "Direct link to heading")


Make sure you have the latest Visual Studio update installed.


### LNK1181: cannot open input file 'kernel32.lib'[​](#lnk1181-cannot-open-input-file-kernel32lib "Direct link to heading")


Try reinstalling 32bit Node.js.


### Error: ENOENT, stat 'C:\Users\USERNAME\AppData\Roaming\npm'[​](#error-enoent-stat-cusersusernameappdataroamingnpm "Direct link to heading")


Creating that directory [should fix the problem](https://stackoverflow.com/a/25095327/102704):




```
$ mkdir ~\AppData\Roaming\npm
```


### node-gyp is not recognized as an internal or external command[​](#node-gyp-is-not-recognized-as-an-internal-or-external-command "Direct link to heading")


You may get this error if you are using Git Bash for building, you should use PowerShell or VS2015 Command Prompt instead.


### cannot create directory at '...': Filename too long[​](#cannot-create-directory-at--filename-too-long "Direct link to heading")


node.js has some [extremely long pathnames](https://github.com/electron/node/tree/electron/deps/npm/node_modules/libnpx/node_modules/yargs/node_modules/read-pkg-up/node_modules/read-pkg/node_modules/load-json-file/node_modules/parse-json/node_modules/error-ex/node_modules/is-arrayish), and by default git on windows doesn't handle long pathnames correctly (even though windows supports them). This should fix it:




```
$ git config --system core.longpaths true
```


### error: use of undeclared identifier 'DefaultDelegateCheckMode'[​](#error-use-of-undeclared-identifier-defaultdelegatecheckmode "Direct link to heading")


This can happen during build, when Debugging Tools for Windows has been installed with Windows Driver Kit. Uninstall Windows Driver Kit and install Debugging Tools with steps described above.


### ImportError: No module named win32file[​](#importerror-no-module-named-win32file "Direct link to heading")


Make sure you have installed `pywin32` with `pip install pywin32`.


### Build Scripts Hang Until Keypress[​](#build-scripts-hang-until-keypress "Direct link to heading")


This bug is a "feature" of Windows' command prompt. It happens when clicking inside the prompt window with `QuickEdit` enabled and is intended to allow selecting and copying output text easily. Since each accidental click will pause the build process, you might want to disable this feature in the command prompt properties.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/build-instructions-windows>

MessagePortMain
===============


`MessagePortMain` is the main-process-side equivalent of the DOM [`MessagePort`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort) object. It behaves similarly to the DOM version, with the exception that it uses the Node.js `EventEmitter` event system, instead of the DOM `EventTarget` system. This means you should use `port.on('message', ...)` to listen for events, instead of `port.onmessage = ...` or `port.addEventListener('message', ...)`


See the [Channel Messaging API](https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API) documentation for more information on using channel messaging.


`MessagePortMain` is an [EventEmitter][event-emitter].


Class: MessagePortMain[​](#class-messageportmain "Direct link to heading")
--------------------------------------------------------------------------



> Port interface for channel messaging in the main process.
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


### Instance Methods[​](#instance-methods "Direct link to heading")


#### 
`port.postMessage(message, [transfer])`[​](#portpostmessagemessage-transfer "Direct link to heading")


* `message` any
* `transfer` MessagePortMain[] (optional)


Sends a message from the port, and optionally, transfers ownership of objects to other browsing contexts.


#### 
`port.start()`[​](#portstart "Direct link to heading")


Starts the sending of messages queued on the port. Messages will be queued until this method is called.


#### 
`port.close()`[​](#portclose "Direct link to heading")


Disconnects the port, so it is no longer active.


### Instance Events[​](#instance-events "Direct link to heading")


#### Event: 'message'[​](#event-message "Direct link to heading")


Returns:


* `messageEvent` Object
	+ `data` any
	+ `ports` MessagePortMain[]


Emitted when a MessagePortMain object receives a message.


#### Event: 'close'[​](#event-close "Direct link to heading")


Emitted when the remote end of a MessagePortMain object becomes disconnected.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/message-port-main>

Testing
=======


We aim to keep the code coverage of Electron high. We ask that all pull request not only pass all existing tests, but ideally also add new tests to cover changed code and new scenarios. Ensuring that we capture as many code paths and use cases of Electron as possible ensures that we all ship apps with fewer bugs.


This repository comes with linting rules for both JavaScript and C++ – as well as unit and integration tests. To learn more about Electron's coding style, please see the <coding-style> document.


Linting[​](#linting "Direct link to heading")
---------------------------------------------


To ensure that your changes are in compliance with the Electron coding style, run `npm run lint`, which will run a variety of linting checks against your changes depending on which areas of the code they touch.


Many of these checks are included as precommit hooks, so it's likely you error would be caught at commit time.


Unit Tests[​](#unit-tests "Direct link to heading")
---------------------------------------------------


If you are not using [build-tools](https://github.com/electron/build-tools), ensure that the name you have configured for your local build of Electron is one of `Testing`, `Release`, `Default`, or you have set `process.env.ELECTRON_OUT_DIR`. Without these set, Electron will fail to perform some pre-testing steps.


To run all unit tests, run `npm run test`. The unit tests are an Electron app (surprise!) that can be found in the `spec` folder. Note that it has its own `package.json` and that its dependencies are therefore not defined in the top-level `package.json`.


To run only tests in a specific process, run `npm run test --runners=PROCESS` where `PROCESS` is one of `main` or `remote`.


To run only specific tests matching a pattern, run `npm run test --
-g=PATTERN`, replacing the `PATTERN` with a regex that matches the tests you would like to run. As an example: If you want to run only IPC tests, you would run `npm run test -- -g ipc`.


Node.js Smoke Tests[​](#nodejs-smoke-tests "Direct link to heading")
--------------------------------------------------------------------


If you've made changes that might affect the way Node.js is embedded into Electron, we have a test runner that runs all of the tests from Node.js, using Electron's custom fork of Node.js.


To run all of the Node.js tests:




```
$ node script/node-spec-runner.js
```


To run a single Node.js test:




```
$ node script/node-spec-runner.js parallel/test-crypto-keygen
```


where the argument passed to the runner is the path to the test in the Node.js source tree.


### Testing on Windows 10 devices[​](#testing-on-windows-10-devices "Direct link to heading")


#### Extra steps to run the unit test:[​](#extra-steps-to-run-the-unit-test "Direct link to heading")


1. Visual Studio 2019 must be installed.
2. Node headers have to be compiled for your configuration.




```
ninja -C out\Testing third_party\electron_node:headers
```
3. The electron.lib has to be copied as node.lib.




```
cd out\Testing
mkdir gen\node_headers\Release
copy electron.lib gen\node_headers\Release\node.lib
```


#### Missing fonts[​](#missing-fonts "Direct link to heading")


[Some Windows 10 devices](https://docs.microsoft.com/en-us/typography/fonts/windows_10_font_list) do not ship with the Meiryo font installed, which may cause a font fallback test to fail. To install Meiryo:


1. Push the Windows key and search for *Manage optional features*.
2. Click *Add a feature*.
3. Select *Japanese Supplemental Fonts* and click *Install*.


#### Pixel measurements[​](#pixel-measurements "Direct link to heading")


Some tests which rely on precise pixel measurements may not work correctly on devices with Hi-DPI screen settings due to floating point precision errors. To run these tests correctly, make sure the device is set to 100% scaling.


To configure display scaling:


1. Push the Windows key and search for *Display settings*.
2. Under *Scale and layout*, make sure that the device is set to 100%.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/testing>

Tray
====


Overview[​](#overview "Direct link to heading")
-----------------------------------------------


This guide will take you through the process of creating a [Tray](https://www.electronjs.org/docs/api/tray) icon with its own context menu to the system's notification area.


On MacOS and Ubuntu, the Tray will be located on the top right corner of your screen, adjacent to your battery and wifi icons. On Windows, the Tray will usually be located in the bottom right corner.


Example[​](#example "Direct link to heading")
---------------------------------------------


### main.js[​](#mainjs "Direct link to heading")


First we must import `app`, `Tray`, `Menu`, `nativeImage` from `electron`.




```
const { app, Tray, Menu, nativeImage } = require('electron')
```


Next we will create our Tray. To do this, we will use a [`NativeImage`](https://www.electronjs.org/docs/api/native-image) icon, which can be created through any one of these [methods](https://www.electronjs.org/docs/api/native-image#methods). Note that we wrap our Tray creation code within an [`app.whenReady`](https://www.electronjs.org/docs/api/app#appwhenready) as we will need to wait for our electron app to finish initializing.



main.js


```
let tray

app.whenReady().then(() => {
  const icon = nativeImage.createFromPath('path/to/asset.png')
  tray = new Tray(icon)

  // note: your contextMenu, Tooltip and Title code will go here!
})
```



Great! Now we can start attaching a context menu to our Tray, like so:




```
const contextMenu = Menu.buildFromTemplate([
  { label: 'Item1', type: 'radio' },
  { label: 'Item2', type: 'radio' },
  { label: 'Item3', type: 'radio', checked: true },
  { label: 'Item4', type: 'radio' }
])

tray.setContextMenu(contextMenu)
```


The code above will create 4 separate radio-type items in the context menu. To read more about constructing native menus, click [here](https://www.electronjs.org/docs/api/menu#menubuildfromtemplatetemplate).


Finally, let's give our tray a tooltip and a title.




```
tray.setToolTip('This is my application')
tray.setTitle('This is my title')
```


Conclusion[​](#conclusion "Direct link to heading")
---------------------------------------------------


After you start your electron app, you should see the Tray residing in either the top or bottom right of your screen, depending on your operating system.




[docs/fiddles/native-ui/tray (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/native-ui/tray)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/native-ui/tray)


* .keep
* main.js
* index.html





```
const { app, Tray, Menu, nativeImage } = require('electron')

let tray

app.whenReady().then(() => {
  const icon = nativeImage.createFromDataURL('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAkCAYAAADhAJiYAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAVlpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6dGlmZj0iaHR0cDovL25zLmFkb2JlLmNvbS90aWZmLzEuMC8iPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KTMInWQAACsZJREFUWAmtWFlsXFcZ/u82++Jt7IyT2Em6ZFHTpAtWIzspEgjEUhA8VNAiIYEQUvuABBIUwUMkQIVKPCIoEiABLShISEBbhFJwIGRpIKRpbNeJ7bh2HHvssR3PPnPnLnzfmRlju6EQqUc+c++c8y/fv54z1uQOh+/7Glh0TD59TE/TND7lnfa4/64OKsM071QoeZpA/y9WWvk/B4XCC06TUC+Xyw8HTXNQ1+Ww6PpOrMebewXxvBueJ6/XHOdMJBL5J9Y97m2R0SS/wweE6JxkGx5dilWr1S/7dXsEa2o4+LyFmcFcaL5zbX3Y9gh5hpeWYpSB9XV5/H678V89BGYDXnHJlCsWn4gHrGc1K9CXxferOdvPOOKUfF8cH7nUyCtklQZXih/VNNlmirk3GdBSoIcRswW7/vVkLPYi5W2Uze8bh7J+4wLfh4dViFx5/nmrUi7/MhGNvrCkBfpeWqnW/7BUdadqntQ8zwr6vhUV34xpYnDynWvcmwQNaclDXsqgLMqkocPDw7fNx7d5qIX+/PmJxKGD6VdDkeh7ztyqOFfrokGCEWiiZ1mp0uITnuKAosaT7+pNxMYTyefutcQfbA+b1XLpH5fnF97/yD335Fu6mqTqsclDINBVmI4fDxw80KPAvJSt1MZtMcLiGxYUu83p4UkgnJZlqcl3LAj3WnTkIS9lUBYNPJjueVWgg7qocyOgliFqjZsg8gq5tRdiieQTf1gq15Y8CUbRZtyWOzZwc8lEqS3PTCtgqd13ieO68BQ2uNl64tXAewktrFuX2mPdkWAxn3sxnmx7sqUTJGqso8MGS9tbXFz8DMH8bblUX3T9QARVi8RV8qljfcJy0zRlaf6mzHEuzEtmekqCoZB4rqp0OmudHtUnlEWZlE0d1EWd1N3EozourcO65pw4eTIZQTW9VazJtbqvw9XwKVFQMsKDBuNhtp4uvGGFI+IDgKnpMjYyIis3ZsQMBIR7pONsIaMsyqRs6ohY1rPUSd3EQFDqo+kdZ3Fh4aupbdu+99uFQr2A1CBs4uEAjZjIFUMHi4dVxMXzCdCXQj4vBrwVCofl0ulTcv/DAxJJJBUPc8mpoyI2JDw7bFyT+ifTcSubyXytJ51+roWBxwG9Q73WWjZ7eSUU3//nXM0NI+x0PBGrTSgsLS9JFuFxHFrvSqIrJV279gi6tjiVspTza3JjZhY+0CQZj0mlWJSeHTslCro6eFqymCcVVN77kkGjs1p4sy2VOoSlOrFwT+XR+PjkgGaZ+ycKVbRTYUdVrmaImCvzk1dlFCEJdHRJ284+ie/ol0h7p7jFvExcvCCXzp2Rqem3pAMAiqWS6JGYhFI9Mjo6KjevXVUyKEuFHrKpY6JQ8TXT3D8+OTkAHBw6o6LCFo9ag3o4JtlCyTHEt5AxKvS6YUi5kJeZG3Py0NAxlLcJ9xti+K7Mjo/JfGZRuvv6Ze+9+yWEhDZAvzg3JyhX2d6/S7q6e+TimdOS7ElLKBZDwqvmj6rztayr1fVI1IoXi4PAcYZY1tPEEO1wEVlXgRFBDcmIXTqJsS+XyhKLJ5A/OpIVXXptWUYv/UvaenfIocEhMQ2EzHHErlXFCgQl3paU1eVl6QAY8sQTCSmVihKJx1V/ogvgIYF/pACdcMBhqONoHhF88/2d+bojyA6cRvje2IdFjoSjUSnBS8hgyS9lZOzKFdmPxO3o6gQIGzwuDn1dVSCtCKPy1pZXlATXqUsVYMLRmKo87vP4Y1ioqwCdCegmMYx3W/VPn8RrSDwwIMMbcEjkYo29JZVOy+ybI7K4eksODx1VSqvligpReSVLgySM/FI5h2q062jNyL3s7FtoAyGJIlx1225UmwJF6aJRJ3XzHXO9bWvsJa3jQFlBJkz6iuXdu32HzM7MyP0PPNgAU6ko4Qzp6b+flr8MD9OYJg9CwtzL5+T65ITs2bsP3mGxN/ZbBcOn0sk20gAkLQ+huXpFi8vkoY9AoyDjxTR1mbo6Ltt275HpN0dlNxQE40mVM8Ajjxx9VAGhAvQR1akZFCq799ADysMuQqOxh2FNmamEaz51ItGLfFD9+oUJoZkLowHoFA2mljUacqOMflKuVmHpfmnfvlMuvXZeStmMBIMhcWEdjgFJtrUjXI0KchAuAg0ilxLJNoRVBxhIBm0TjjKAuqjTqTs3CQZ6QUUMGFW7eiWMUg6w+yo8YMW7DqtqlZLkUDV2ISfd29KyDwk9MjYmMyOXxQIIKuShqo4VGFNBEgeDQYqVam5N5tEePFQgURIUBCsd1EWd1XrtDUUMLARD9bKaK5ytQ2Gb75g8WMiEP6VkfnZGevv6UF1vSBW5E0PFDAweFRvlfun8WVmamhDNrkmweQ0pwaPt6M4m8mgKTTFXqcrV0ZH1FKBg6qAu6qTuJiCV1Cp2Q0NDr9Uq5Ym+oMEDlSewsoRwrVBEaij7AJ4s7zrOpumxEdm15y6558GHJVe1Zezy6zJx6aJkpq5JFB4z6zVZmBiX1VWUP0IY4CFMYcpQdZ3xqIs6oftCE5DHKwd0q/tzOV8svdDb3nk8VnG9qmgQC0ZURz8Ur91alXgSByZ6ES9kZZTr/PR16UOCh+7dq0CWyyXJ4xqCQ0nKt9YQSlPue2gAeYZzD7yNLk0wmqAreb2WYSxAJ8Dget64wxtEBlDaqVOn/K5dB67t6+t5MhoMJuc8w8UPKiQ9CQR9JK5czhZAQxPt7TKF3OiAIisUViAD2Lg5d0P2HDgoKeRaW0enyqVwBJcO5fFG5dqa7h406qaeX8384uTZL5w9+UqxhYHFp0YLIYA9ddfu3T+4UJF6Rg+YAc9D0+RoIGP1ULhpWspr10evyK7+ftWTrk9PS/++A9KZSm26cih2mMOErem6n/ZsZwA2TM/MPHXs2LEftnSTbh0Q36mIIbx44cLvOnu3f+xUwbWLmoHTCUlF6g2jBQo/GnFrnGNqSHdvr+rIKGMW1KahwEBdzHft98aNwMr8zd8/NDDwccihc0hLi3GubRjY0Bm6H19fPvnZI4c/fHd7PJ2peXYZ+WQ26JufZELjQ6lbAQtnWre0d3apY8TFIdtAo+Qri6mupsB49lBMC+QXF0YefObZT8j0eKWlswVjEyCCOXHihPGb575VCvVuf3lvetsH9rXF0rla3cnhpoIGjgsUPhR3I4TMKYJQV1Z6WO02aEjHa5mNe3OPW3OPRHVrbXFh9Ocvv/KR1372owx1Pf3005uc35Ddgtd8rsf06IdS5777zZ+mUqmPzjm6TPpmvayZOq4LyATeCzkanmiy4qEuC/yXiO8CSMRzvLs1x9phepLNZl868sy3Pyen/5hd1/EfRvWmuvSWNeaRS/RkPDI4+NjE1NSXEoXlpaNB1zqo20abi59/vu/UfM2pie7WUDVq8l3wTwnskeZ+zTbIQ17KoCzKpGzq2KqX32/roRbh8ePHdUzl0s9/5Rv9n/7go19MxCKfCkZiu3V06wrO5gocxL7Dgd/IEobEMH6rejg+auXidL5Y/vWv/vTX53/y/e/MkGajTH7fOt4RUJOY1df4RdtY6ICFRzqTySOhUOA+3Ai3o31H1ZbnlXBruFmt2iMrudy5xx9//BzWV7nXDBGN2xpjbt/5oGUEdhtO3iD47xZOvm8a5CHvpsV38wsUaMwBWsz3rbK5xr0mzdv2t9Jv/f5vhsF4J+Q63IUAAAAASUVORK5CYII=')
  tray = new Tray(icon)

  const contextMenu = Menu.buildFromTemplate([
    { label: 'Item1', type: 'radio' },
    { label: 'Item2', type: 'radio' },
    { label: 'Item3', type: 'radio', checked: true },
    { label: 'Item4', type: 'radio' }
  ])

  tray.setToolTip('This is my application.')
  tray.setContextMenu(contextMenu)
})
```




```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Tray</title>
  </head>
  <body>
    <div>
      <h1>Tray</h1>
      <h3>
        The <code>tray</code> module allows you to create an icon in the
        operating system's notification area.
      </h3>
      <p>This icon can also have a context menu attached.</p>

      <p>
        Open the
        <a href="https://electronjs.org/docs/api/tray">
          full API documentation
        </a>
        in your browser.
      </p>
    </div>
      <div>
          <div>
            <h2>ProTip</h2>
            <strong>Tray support in Linux.</strong>
            <p>
              On Linux distributions that only have app indicator support, users
              will need to install <code>libappindicator1</code> to make the
              tray icon work. See the
              <a href="https://electronjs.org/docs/api/tray">
                full API documentation
              </a>
              for more details about using Tray on Linux.
            </p>
          </div>
        </div>
      </div>
    </div>

    <script>
      // You can also require other files to run in this process
      require("./renderer.js");
    </script>
  </body>
</html>

```






 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/tray>

InputEvent Object
=================


* `modifiers` string[] (optional) - An array of modifiers of the event, can be `shift`, `control`, `ctrl`, `alt`, `meta`, `command`, `cmd`, `isKeypad`, `isAutoRepeat`, `leftButtonDown`, `middleButtonDown`, `rightButtonDown`, `capsLock`, `numLock`, `left`, `right`.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/input-event>

PostBody Object
===============


* `data` ([UploadRawData](upload-raw-data) | [UploadFile](upload-file))[] - The post data to be sent to the new window.
* `contentType` string - The `content-type` header used for the data. One of `application/x-www-form-urlencoded` or `multipart/form-data`. Corresponds to the `enctype` attribute of the submitted HTML form.
* `boundary` string (optional) - The boundary used to separate multiple parts of the message. Only valid when `contentType` is `multipart/form-data`.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/post-body>

ProtocolResponseUploadData Object
=================================


* `contentType` string - MIME type of the content.
* `data` string | Buffer - Content to be sent.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/protocol-response-upload-data>

Taskbar Customization
=====================


Overview[​](#overview "Direct link to heading")
-----------------------------------------------


Electron has APIs to configure the app's icon in the Windows taskbar. This API supports both Windows-only features like [creation of a `JumpList`](#jumplist), [custom thumbnails and toolbars](#thumbnail-toolbars), [icon overlays](#icon-overlays-in-taskbar), and the so-called ["Flash Frame" effect](#flash-frame), and cross-platform features like [recent documents](recent-documents) and [application progress](progress-bar).


JumpList[​](#jumplist "Direct link to heading")
-----------------------------------------------


Windows allows apps to define a custom context menu that shows up when users right-click the app's icon in the taskbar. That context menu is called `JumpList`. You specify custom actions in the `Tasks` category of JumpList, as quoted from [MSDN](https://docs.microsoft.com/en-us/windows/win32/shell/taskbar-extensions#tasks):



> 
> Applications define tasks based on both the program's features and the key things a user is expected to do with them. Tasks should be context-free, in that the application does not need to be running for them to work. They should also be the statistically most common actions that a normal user would perform in an application, such as compose an email message or open the calendar in a mail program, create a new document in a word processor, launch an application in a certain mode, or launch one of its subcommands. An application should not clutter the menu with advanced features that standard users won't need or one-time actions such as registration. Do not use tasks for promotional items such as upgrades or special offers.
> 
> 
> It is strongly recommended that the task list be static. It should remain the same regardless of the state or status of the application. While it is possible to vary the list dynamically, you should consider that this could confuse the user who does not expect that portion of the destination list to change.
> 
> 
> 


![Taskbar JumpList]



> NOTE: The screenshot above is an example of general tasks for Microsoft Edge
> 
> 


Unlike the dock menu in macOS which is a real menu, user tasks in Windows work like application shortcuts. For example, when a user clicks a task, the program will be executed with specified arguments.


To set user tasks for your application, you can use [app.setUserTasks](../api/app#appsetusertaskstasks-windows) API.


#### Examples[​](#examples "Direct link to heading")


##### Set user tasks[​](#set-user-tasks "Direct link to heading")


Starting with a working application from the [Quick Start Guide](quick-start), update the `main.js` file with the following lines:




```
const { app } = require('electron')

app.setUserTasks([
  {
    program: process.execPath,
    arguments: '--new-window',
    iconPath: process.execPath,
    iconIndex: 0,
    title: 'New Window',
    description: 'Create a new window'
  }
])
```


##### Clear tasks list[​](#clear-tasks-list "Direct link to heading")


To clear your tasks list, you need to call `app.setUserTasks` with an empty array in the `main.js` file.




```
const { app } = require('electron')

app.setUserTasks([])
```



> NOTE: The user tasks will still be displayed even after closing your application, so the icon and program path specified for a task should exist until your application is uninstalled.
> 
> 


### Thumbnail Toolbars[​](#thumbnail-toolbars "Direct link to heading")


On Windows, you can add a thumbnail toolbar with specified buttons to a taskbar layout of an application window. It provides users with a way to access a particular window's command without restoring or activating the window.


As quoted from [MSDN](https://docs.microsoft.com/en-us/windows/win32/shell/taskbar-extensions#thumbnail-toolbars):



> 
> This toolbar is the familiar standard toolbar common control. It has a maximum of seven buttons. Each button's ID, image, tooltip, and state are defined in a structure, which is then passed to the taskbar. The application can show, enable, disable, or hide buttons from the thumbnail toolbar as required by its current state.
> 
> 
> For example, Windows Media Player might offer standard media transport controls such as play, pause, mute, and stop.
> 
> 
> 


![Thumbnail toolbar]



> NOTE: The screenshot above is an example of thumbnail toolbar of Windows Media Player
> 
> 


To set thumbnail toolbar in your application, you need to use [BrowserWindow.setThumbarButtons](../api/browser-window#winsetthumbarbuttonsbuttons-windows)


#### Examples[​](#examples-1 "Direct link to heading")


##### Set thumbnail toolbar[​](#set-thumbnail-toolbar "Direct link to heading")


Starting with a working application from the [Quick Start Guide](quick-start), update the `main.js` file with the following lines:




```
const { BrowserWindow } = require('electron')
const path = require('path')

const win = new BrowserWindow()

win.setThumbarButtons([
  {
    tooltip: 'button1',
    icon: path.join(__dirname, 'button1.png'),
    click () { console.log('button1 clicked') }
  }, {
    tooltip: 'button2',
    icon: path.join(__dirname, 'button2.png'),
    flags: ['enabled', 'dismissonclick'],
    click () { console.log('button2 clicked.') }
  }
])
```


##### Clear thumbnail toolbar[​](#clear-thumbnail-toolbar "Direct link to heading")


To clear thumbnail toolbar buttons, you need to call `BrowserWindow.setThumbarButtons` with an empty array in the `main.js` file.




```
const { BrowserWindow } = require('electron')

const win = new BrowserWindow()
win.setThumbarButtons([])
```


### Icon Overlays in Taskbar[​](#icon-overlays-in-taskbar "Direct link to heading")


On Windows, a taskbar button can use a small overlay to display application status.


As quoted from [MSDN](https://docs.microsoft.com/en-us/windows/win32/shell/taskbar-extensions#icon-overlays):



> Icon overlays serve as a contextual notification of status, and are intended to negate the need for a separate notification area status icon to communicate that information to the user. For instance, the new mail status in Microsoft Outlook, currently shown in the notification area, can now be indicated through an overlay on the taskbar button. Again, you must decide during your development cycle which method is best for your application. Overlay icons are intended to supply important, long-standing status or notifications such as network status, messenger status, or new mail. The user should not be presented with constantly changing overlays or animations.
> 
> 


![Overlay on taskbar button]



> NOTE: The screenshot above is an example of overlay on a taskbar button
> 
> 


To set the overlay icon for a window, you need to use the [BrowserWindow.setOverlayIcon](../api/browser-window#winsetoverlayiconoverlay-description-windows) API.


#### Example[​](#example "Direct link to heading")


Starting with a working application from the [Quick Start Guide](quick-start), update the `main.js` file with the following lines:




```
const { BrowserWindow } = require('electron')

const win = new BrowserWindow()

win.setOverlayIcon('path/to/overlay.png', 'Description for overlay')
```


### Flash Frame[​](#flash-frame "Direct link to heading")


On Windows, you can highlight the taskbar button to get the user's attention. This is similar to bouncing the dock icon in macOS.


As quoted from [MSDN](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-flashwindow#remarks):



> Typically, a window is flashed to inform the user that the window requires attention but that it does not currently have the keyboard focus.
> 
> 


To flash the BrowserWindow taskbar button, you need to use the [BrowserWindow.flashFrame](../api/browser-window#winflashframeflag) API.


#### Example[​](#example-1 "Direct link to heading")


Starting with a working application from the [Quick Start Guide](quick-start), update the `main.js` file with the following lines:




```
const { BrowserWindow } = require('electron')

const win = new BrowserWindow()

win.once('focus', () => win.flashFrame(false))
win.flashFrame(true)
```



> NOTE: Don't forget to call `win.flashFrame(false)` to turn off the flash. In the above example, it is called when the window comes into focus, but you might use a timeout or some other event to disable it.
> 
> 



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/windows-taskbar>

Class: TouchBarSpacer
=====================

Class: TouchBarSpacer[​](#class-touchbarspacer "Direct link to heading")
------------------------------------------------------------------------



> Create a spacer between two items in the touch bar for native macOS applications
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


### 
`new TouchBarSpacer(options)`[​](#new-touchbarspaceroptions "Direct link to heading")


* `options` Object
	+ `size` string (optional) - Size of spacer, possible values are:
		- `small` - Small space between items. Maps to `NSTouchBarItemIdentifierFixedSpaceSmall`. This is the default.
		- `large` - Large space between items. Maps to `NSTouchBarItemIdentifierFixedSpaceLarge`.
		- `flexible` - Take up all available space. Maps to `NSTouchBarItemIdentifierFlexibleSpace`.


### Instance Properties[​](#instance-properties "Direct link to heading")


The following properties are available on instances of `TouchBarSpacer`:


#### 
`touchBarSpacer.size`[​](#touchbarspacersize "Direct link to heading")


A `string` representing the size of the spacer. Can be `small`, `large` or `flexible`.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/touch-bar-spacer>

Chrome Extension Support
========================


Electron supports a subset of the [Chrome Extensions API](https://developer.chrome.com/extensions/api_index), primarily to support DevTools extensions and Chromium-internal extensions, but it also happens to support some other extension capabilities.



> **Note:** Electron does not support arbitrary Chrome extensions from the store, and it is a **non-goal** of the Electron project to be perfectly compatible with Chrome's implementation of Extensions.
> 
> 


Loading extensions[​](#loading-extensions "Direct link to heading")
-------------------------------------------------------------------


Electron only supports loading unpacked extensions (i.e., `.crx` files do not work). Extensions are installed per-`session`. To load an extension, call [`ses.loadExtension`](session#sesloadextensionpath-options):




```
const { session } = require('electron')

session.loadExtension('path/to/unpacked/extension').then(({ id }) => {
  // ...
})
```


Loaded extensions will not be automatically remembered across exits; if you do not call `loadExtension` when the app runs, the extension will not be loaded.


Note that loading extensions is only supported in persistent sessions. Attempting to load an extension into an in-memory session will throw an error.


See the [`session`](session) documentation for more information about loading, unloading, and querying active extensions.


Supported Extensions APIs[​](#supported-extensions-apis "Direct link to heading")
---------------------------------------------------------------------------------


We support the following extensions APIs, with some caveats. Other APIs may additionally be supported, but support for any APIs not listed here is provisional and may be removed.


### 
`chrome.devtools.inspectedWindow`[​](#chromedevtoolsinspectedwindow "Direct link to heading")


All features of this API are supported.


### 
`chrome.devtools.network`[​](#chromedevtoolsnetwork "Direct link to heading")


All features of this API are supported.


### 
`chrome.devtools.panels`[​](#chromedevtoolspanels "Direct link to heading")


All features of this API are supported.


### 
`chrome.extension`[​](#chromeextension "Direct link to heading")


The following properties of `chrome.extension` are supported:


* `chrome.extension.lastError`


The following methods of `chrome.extension` are supported:


* `chrome.extension.getURL`
* `chrome.extension.getBackgroundPage`


### 
`chrome.runtime`[​](#chromeruntime "Direct link to heading")


The following properties of `chrome.runtime` are supported:


* `chrome.runtime.lastError`
* `chrome.runtime.id`


The following methods of `chrome.runtime` are supported:


* `chrome.runtime.getBackgroundPage`
* `chrome.runtime.getManifest`
* `chrome.runtime.getPlatformInfo`
* `chrome.runtime.getURL`
* `chrome.runtime.connect`
* `chrome.runtime.sendMessage`
* `chrome.runtime.reload`


The following events of `chrome.runtime` are supported:


* `chrome.runtime.onStartup`
* `chrome.runtime.onInstalled`
* `chrome.runtime.onSuspend`
* `chrome.runtime.onSuspendCanceled`
* `chrome.runtime.onConnect`
* `chrome.runtime.onMessage`


### 
`chrome.storage`[​](#chromestorage "Direct link to heading")


Only `chrome.storage.local` is supported; `chrome.storage.sync` and `chrome.storage.managed` are not.


### 
`chrome.tabs`[​](#chrometabs "Direct link to heading")


The following methods of `chrome.tabs` are supported:


* `chrome.tabs.sendMessage`
* `chrome.tabs.reload`
* `chrome.tabs.executeScript`
* `chrome.tabs.update` (partial support)
	+ supported properties: `url`, `muted`.



> **Note:** In Chrome, passing `-1` as a tab ID signifies the "currently active tab". Since Electron has no such concept, passing `-1` as a tab ID is not supported and will raise an error.
> 
> 


### 
`chrome.management`[​](#chromemanagement "Direct link to heading")


The following methods of `chrome.management` are supported:


* `chrome.management.getAll`
* `chrome.management.get`
* `chrome.management.getSelf`
* `chrome.management.getPermissionWarningsById`
* `chrome.management.getPermissionWarningsByManifest`
* `chrome.management.onEnabled`
* `chrome.management.onDisabled`


### 
`chrome.webRequest`[​](#chromewebrequest "Direct link to heading")


All features of this API are supported.



> **NOTE:** Electron's [`webRequest`](web-request) module takes precedence over `chrome.webRequest` if there are conflicting handlers.
> 
> 



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/extensions>

MouseInputEvent Object extends `InputEvent`
===========================================


* `type` string - The type of the event, can be `mouseDown`, `mouseUp`, `mouseEnter`, `mouseLeave`, `contextMenu`, `mouseWheel` or `mouseMove`.
* `x` Integer
* `y` Integer
* `button` string (optional) - The button pressed, can be `left`, `middle`, `right`.
* `globalX` Integer (optional)
* `globalY` Integer (optional)
* `movementX` Integer (optional)
* `movementY` Integer (optional)
* `clickCount` Integer (optional)



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/mouse-input-event>

Build Instructions (macOS)
==========================


Follow the guidelines below for building **Electron itself** on macOS, for the purposes of creating custom Electron binaries. For bundling and distributing your app code with the prebuilt Electron binaries, see the [application distribution](../tutorial/application-distribution) guide.


Prerequisites[​](#prerequisites "Direct link to heading")
---------------------------------------------------------


* macOS >= 11.6.0
* [Xcode](https://developer.apple.com/technologies/tools/). The exact version needed depends on what branch you are building, but the latest version of Xcode is generally a good bet for building `main`.
* [node.js](https://nodejs.org) (external)
* Python >= 3.7


Building Electron[​](#building-electron "Direct link to heading")
-----------------------------------------------------------------


See [Build Instructions: GN](build-instructions-gn).



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/build-instructions-macos>

ProductSubscriptionPeriod Object
================================


* `numberOfUnits` number - The number of units per subscription period.
* `unit` string - The increment of time that a subscription period is specified in. Can be `day`, `week`, `month`, `year`.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/product-subscription-period>

ProtocolRequest Object
======================


* `url` string
* `referrer` string
* `method` string
* `uploadData` [UploadData[]](upload-data) (optional)
* `headers` Record<string, string>



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/protocol-request>

SerialPort Object
=================


* `portId` string - Unique identifier for the port.
* `portName` string - Name of the port.
* `displayName` string - A string suitable for display to the user for describing this device.
* `vendorId` string - Optional USB vendor ID.
* `productId` string - Optional USB product ID.
* `serialNumber` string - The USB device serial number.
* `usbDriverName` string (optional) - Represents a single serial port on macOS can be enumerated by multiple drivers.
* `deviceInstanceId` string (optional) - A stable identifier on Windows that can be used for device permissions.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/serial-port>

Class: ServiceWorkers
=====================

Class: ServiceWorkers[​](#class-serviceworkers "Direct link to heading")
------------------------------------------------------------------------



> Query and receive events from a sessions active service workers.
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


Instances of the `ServiceWorkers` class are accessed by using `serviceWorkers` property of a `Session`.


For example:




```
const { session } = require('electron')

// Get all service workers.
console.log(session.defaultSession.serviceWorkers.getAllRunning())

// Handle logs and get service worker info
session.defaultSession.serviceWorkers.on('console-message', (event, messageDetails) => {
  console.log(
    'Got service worker message',
    messageDetails,
    'from',
    session.defaultSession.serviceWorkers.getFromVersionID(messageDetails.versionId)
  )
})
```


### Instance Events[​](#instance-events "Direct link to heading")


The following events are available on instances of `ServiceWorkers`:


#### Event: 'console-message'[​](#event-console-message "Direct link to heading")


Returns:


* `event` Event
* `messageDetails` Object - Information about the console message
	+ `message` string - The actual console message
	+ `versionId` number - The version ID of the service worker that sent the log message
	+ `source` string - The type of source for this message. Can be `javascript`, `xml`, `network`, `console-api`, `storage`, `rendering`, `security`, `deprecation`, `worker`, `violation`, `intervention`, `recommendation` or `other`.
	+ `level` number - The log level, from 0 to 3. In order it matches `verbose`, `info`, `warning` and `error`.
	+ `sourceUrl` string - The URL the message came from
	+ `lineNumber` number - The line number of the source that triggered this console message


Emitted when a service worker logs something to the console.


#### Event: 'registration-completed'[​](#event-registration-completed "Direct link to heading")


Returns:


* `event` Event
* `details` Object - Information about the registered service worker
	+ `scope` string - The base URL that a service worker is registered for


Emitted when a service worker has been registered. Can occur after a call to [`navigator.serviceWorker.register('/sw.js')`](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register) successfully resolves or when a Chrome extension is loaded.


### Instance Methods[​](#instance-methods "Direct link to heading")


The following methods are available on instances of `ServiceWorkers`:


#### 
`serviceWorkers.getAllRunning()`[​](#serviceworkersgetallrunning "Direct link to heading")


Returns `Record<number, ServiceWorkerInfo>` - A [ServiceWorkerInfo](structures/service-worker-info) object where the keys are the service worker version ID and the values are the information about that service worker.


#### 
`serviceWorkers.getFromVersionID(versionId)`[​](#serviceworkersgetfromversionidversionid "Direct link to heading")


* `versionId` number


Returns [ServiceWorkerInfo](structures/service-worker-info) - Information about this service worker


If the service worker does not exist or is not running this method will throw an exception.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/service-workers>

netLog
======



> Logging network events for a session.
> 
> 


Process: [Main](../glossary#main-process)




```
const { netLog } = require('electron')

app.whenReady().then(async () => {
  await netLog.startLogging('/path/to/net-log')
  // After some network events
  const path = await netLog.stopLogging()
  console.log('Net-logs written to', path)
})
```


See [`--log-net-log`](command-line-switches#--log-net-logpath) to log network events throughout the app's lifecycle.


**Note:** All methods unless specified can only be used after the `ready` event of the `app` module gets emitted.


Methods[​](#methods "Direct link to heading")
---------------------------------------------


### 
`netLog.startLogging(path[, options])`[​](#netlogstartloggingpath-options "Direct link to heading")


* `path` string - File path to record network logs.
* `options` Object (optional)
	+ `captureMode` string (optional) - What kinds of data should be captured. By default, only metadata about requests will be captured. Setting this to `includeSensitive` will include cookies and authentication data. Setting it to `everything` will include all bytes transferred on sockets. Can be `default`, `includeSensitive` or `everything`.
	+ `maxFileSize` number (optional) - When the log grows beyond this size, logging will automatically stop. Defaults to unlimited.


Returns `Promise<void>` - resolves when the net log has begun recording.


Starts recording network events to `path`.


### 
`netLog.stopLogging()`[​](#netlogstoplogging "Direct link to heading")


Returns `Promise<void>` - resolves when the net log has been flushed to disk.


Stops recording network events. If not called, net logging will automatically end when app quits.


Properties[​](#properties "Direct link to heading")
---------------------------------------------------


### 
`netLog.currentlyLogging` *Readonly*[​](#netlogcurrentlylogging-readonly "Direct link to heading")


A `boolean` property that indicates whether network logs are currently being recorded.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/net-log>

systemPreferences
=================



> Get system preferences.
> 
> 


Process: [Main](../glossary#main-process)




```
const { systemPreferences } = require('electron')
console.log(systemPreferences.isDarkMode())
```


Events[​](#events "Direct link to heading")
-------------------------------------------


The `systemPreferences` object emits the following events:


### Event: 'accent-color-changed' *Windows*[​](#event-accent-color-changed-windows "Direct link to heading")


Returns:


* `event` Event
* `newColor` string - The new RGBA color the user assigned to be their system accent color.


### Event: 'color-changed' *Windows*[​](#event-color-changed-windows "Direct link to heading")


Returns:


* `event` Event


### Event: 'inverted-color-scheme-changed' *Windows* *Deprecated*[​](#event-inverted-color-scheme-changed-windows-deprecated "Direct link to heading")


Returns:


* `event` Event
* `invertedColorScheme` boolean - `true` if an inverted color scheme (a high contrast color scheme with light text and dark backgrounds) is being used, `false` otherwise.


**Deprecated:** Should use the new [`updated`](native-theme#event-updated) event on the `nativeTheme` module.


### Event: 'high-contrast-color-scheme-changed' *Windows* *Deprecated*[​](#event-high-contrast-color-scheme-changed-windows-deprecated "Direct link to heading")


Returns:


* `event` Event
* `highContrastColorScheme` boolean - `true` if a high contrast theme is being used, `false` otherwise.


**Deprecated:** Should use the new [`updated`](native-theme#event-updated) event on the `nativeTheme` module.


Methods[​](#methods "Direct link to heading")
---------------------------------------------


### 
`systemPreferences.isDarkMode()` *macOS* *Windows* *Deprecated*[​](#systempreferencesisdarkmode-macos-windows-deprecated "Direct link to heading")


Returns `boolean` - Whether the system is in Dark Mode.


**Deprecated:** Should use the new [`nativeTheme.shouldUseDarkColors`](native-theme#nativethemeshouldusedarkcolors-readonly) API.


### 
`systemPreferences.isSwipeTrackingFromScrollEventsEnabled()` *macOS*[​](#systempreferencesisswipetrackingfromscrolleventsenabled-macos "Direct link to heading")


Returns `boolean` - Whether the Swipe between pages setting is on.


### 
`systemPreferences.postNotification(event, userInfo[, deliverImmediately])` *macOS*[​](#systempreferencespostnotificationevent-userinfo-deliverimmediately-macos "Direct link to heading")


* `event` string
* `userInfo` Record<string, any>
* `deliverImmediately` boolean (optional) - `true` to post notifications immediately even when the subscribing app is inactive.


Posts `event` as native notifications of macOS. The `userInfo` is an Object that contains the user information dictionary sent along with the notification.


### 
`systemPreferences.postLocalNotification(event, userInfo)` *macOS*[​](#systempreferencespostlocalnotificationevent-userinfo-macos "Direct link to heading")


* `event` string
* `userInfo` Record<string, any>


Posts `event` as native notifications of macOS. The `userInfo` is an Object that contains the user information dictionary sent along with the notification.


### 
`systemPreferences.postWorkspaceNotification(event, userInfo)` *macOS*[​](#systempreferencespostworkspacenotificationevent-userinfo-macos "Direct link to heading")


* `event` string
* `userInfo` Record<string, any>


Posts `event` as native notifications of macOS. The `userInfo` is an Object that contains the user information dictionary sent along with the notification.


### 
`systemPreferences.subscribeNotification(event, callback)` *macOS*[​](#systempreferencessubscribenotificationevent-callback-macos "Direct link to heading")


* `event` string | null
* `callback` Function
	+ `event` string
	+ `userInfo` Record<string, unknown>
	+ `object` string


Returns `number` - The ID of this subscription


Subscribes to native notifications of macOS, `callback` will be called with `callback(event, userInfo)` when the corresponding `event` happens. The `userInfo` is an Object that contains the user information dictionary sent along with the notification. The `object` is the sender of the notification, and only supports `NSString` values for now.


The `id` of the subscriber is returned, which can be used to unsubscribe the `event`.


Under the hood this API subscribes to `NSDistributedNotificationCenter`, example values of `event` are:


* `AppleInterfaceThemeChangedNotification`
* `AppleAquaColorVariantChanged`
* `AppleColorPreferencesChangedNotification`
* `AppleShowScrollBarsSettingChanged`


If `event` is null, the `NSDistributedNotificationCenter` doesn’t use it as criteria for delivery to the observer. See [docs](https://developer.apple.com/documentation/foundation/nsnotificationcenter/1411723-addobserverforname?language=objc) for more information.


### 
`systemPreferences.subscribeLocalNotification(event, callback)` *macOS*[​](#systempreferencessubscribelocalnotificationevent-callback-macos "Direct link to heading")


* `event` string | null
* `callback` Function
	+ `event` string
	+ `userInfo` Record<string, unknown>
	+ `object` string


Returns `number` - The ID of this subscription


Same as `subscribeNotification`, but uses `NSNotificationCenter` for local defaults. This is necessary for events such as `NSUserDefaultsDidChangeNotification`.


If `event` is null, the `NSNotificationCenter` doesn’t use it as criteria for delivery to the observer. See [docs](https://developer.apple.com/documentation/foundation/nsnotificationcenter/1411723-addobserverforname?language=objc) for more information.


### 
`systemPreferences.subscribeWorkspaceNotification(event, callback)` *macOS*[​](#systempreferencessubscribeworkspacenotificationevent-callback-macos "Direct link to heading")


* `event` string | null
* `callback` Function
	+ `event` string
	+ `userInfo` Record<string, unknown>
	+ `object` string


Returns `number` - The ID of this subscription


Same as `subscribeNotification`, but uses `NSWorkspace.sharedWorkspace.notificationCenter`. This is necessary for events such as `NSWorkspaceDidActivateApplicationNotification`.


If `event` is null, the `NSWorkspaceNotificationCenter` doesn’t use it as criteria for delivery to the observer. See [docs](https://developer.apple.com/documentation/foundation/nsnotificationcenter/1411723-addobserverforname?language=objc) for more information.


### 
`systemPreferences.unsubscribeNotification(id)` *macOS*[​](#systempreferencesunsubscribenotificationid-macos "Direct link to heading")


* `id` Integer


Removes the subscriber with `id`.


### 
`systemPreferences.unsubscribeLocalNotification(id)` *macOS*[​](#systempreferencesunsubscribelocalnotificationid-macos "Direct link to heading")


* `id` Integer


Same as `unsubscribeNotification`, but removes the subscriber from `NSNotificationCenter`.


### 
`systemPreferences.unsubscribeWorkspaceNotification(id)` *macOS*[​](#systempreferencesunsubscribeworkspacenotificationid-macos "Direct link to heading")


* `id` Integer


Same as `unsubscribeNotification`, but removes the subscriber from `NSWorkspace.sharedWorkspace.notificationCenter`.


### 
`systemPreferences.registerDefaults(defaults)` *macOS*[​](#systempreferencesregisterdefaultsdefaults-macos "Direct link to heading")


* `defaults` Record<string, string | boolean | number> - a dictionary of (`key: value`) user defaults


Add the specified defaults to your application's `NSUserDefaults`.


### 
`systemPreferences.getUserDefault<Type extends keyof UserDefaultTypes>(key, type)` *macOS*[​](#systempreferencesgetuserdefaulttype-extends-keyof-userdefaulttypeskey-type-macos "Direct link to heading")


* `key` string
* `type` Type - Can be `string`, `boolean`, `integer`, `float`, `double`, `url`, `array` or `dictionary`.


Returns [UserDefaultTypes[Type]](structures/user-default-types) - The value of `key` in `NSUserDefaults`.


Some popular `key` and `type`s are:


* `AppleInterfaceStyle`: `string`
* `AppleAquaColorVariant`: `integer`
* `AppleHighlightColor`: `string`
* `AppleShowScrollBars`: `string`
* `NSNavRecentPlaces`: `array`
* `NSPreferredWebServices`: `dictionary`
* `NSUserDictionaryReplacementItems`: `array`


### 
`systemPreferences.setUserDefault<Type extends keyof UserDefaultTypes>(key, type, value)` *macOS*[​](#systempreferencessetuserdefaulttype-extends-keyof-userdefaulttypeskey-type-value-macos "Direct link to heading")


* `key` string
* `type` Type - Can be `string`, `boolean`, `integer`, `float`, `double`, `url`, `array` or `dictionary`.
* `value` UserDefaultTypes[Type]


Set the value of `key` in `NSUserDefaults`.


Note that `type` should match actual type of `value`. An exception is thrown if they don't.


Some popular `key` and `type`s are:


* `ApplePressAndHoldEnabled`: `boolean`


### 
`systemPreferences.removeUserDefault(key)` *macOS*[​](#systempreferencesremoveuserdefaultkey-macos "Direct link to heading")


* `key` string


Removes the `key` in `NSUserDefaults`. This can be used to restore the default or global value of a `key` previously set with `setUserDefault`.


### 
`systemPreferences.isAeroGlassEnabled()` *Windows*[​](#systempreferencesisaeroglassenabled-windows "Direct link to heading")


Returns `boolean` - `true` if [DWM composition](https://msdn.microsoft.com/en-us/library/windows/desktop/aa969540.aspx) (Aero Glass) is enabled, and `false` otherwise.


An example of using it to determine if you should create a transparent window or not (transparent windows won't work correctly when DWM composition is disabled):




```
const { BrowserWindow, systemPreferences } = require('electron')
const browserOptions = { width: 1000, height: 800 }

// Make the window transparent only if the platform supports it.
if (process.platform !== 'win32' || systemPreferences.isAeroGlassEnabled()) {
  browserOptions.transparent = true
  browserOptions.frame = false
}

// Create the window.
const win = new BrowserWindow(browserOptions)

// Navigate.
if (browserOptions.transparent) {
  win.loadURL(`file://${__dirname}/index.html`)
} else {
  // No transparency, so we load a fallback that uses basic styles.
  win.loadURL(`file://${__dirname}/fallback.html`)
}
```


### 
`systemPreferences.getAccentColor()` *Windows* *macOS*[​](#systempreferencesgetaccentcolor-windows-macos "Direct link to heading")


Returns `string` - The users current system wide accent color preference in RGBA hexadecimal form.




```
const color = systemPreferences.getAccentColor() // `"aabbccdd"`
const red = color.substr(0, 2) // "aa"
const green = color.substr(2, 2) // "bb"
const blue = color.substr(4, 2) // "cc"
const alpha = color.substr(6, 2) // "dd"
```


This API is only available on macOS 10.14 Mojave or newer.


### 
`systemPreferences.getColor(color)` *Windows* *macOS*[​](#systempreferencesgetcolorcolor-windows-macos "Direct link to heading")


* `color` string - One of the following values:
	+ On **Windows**:
		- `3d-dark-shadow` - Dark shadow for three-dimensional display elements.
		- `3d-face` - Face color for three-dimensional display elements and for dialog box backgrounds.
		- `3d-highlight` - Highlight color for three-dimensional display elements.
		- `3d-light` - Light color for three-dimensional display elements.
		- `3d-shadow` - Shadow color for three-dimensional display elements.
		- `active-border` - Active window border.
		- `active-caption` - Active window title bar. Specifies the left side color in the color gradient of an active window's title bar if the gradient effect is enabled.
		- `active-caption-gradient` - Right side color in the color gradient of an active window's title bar.
		- `app-workspace` - Background color of multiple document interface (MDI) applications.
		- `button-text` - Text on push buttons.
		- `caption-text` - Text in caption, size box, and scroll bar arrow box.
		- `desktop` - Desktop background color.
		- `disabled-text` - Grayed (disabled) text.
		- `highlight` - Item(s) selected in a control.
		- `highlight-text` - Text of item(s) selected in a control.
		- `hotlight` - Color for a hyperlink or hot-tracked item.
		- `inactive-border` - Inactive window border.
		- `inactive-caption` - Inactive window caption. Specifies the left side color in the color gradient of an inactive window's title bar if the gradient effect is enabled.
		- `inactive-caption-gradient` - Right side color in the color gradient of an inactive window's title bar.
		- `inactive-caption-text` - Color of text in an inactive caption.
		- `info-background` - Background color for tooltip controls.
		- `info-text` - Text color for tooltip controls.
		- `menu` - Menu background.
		- `menu-highlight` - The color used to highlight menu items when the menu appears as a flat menu.
		- `menubar` - The background color for the menu bar when menus appear as flat menus.
		- `menu-text` - Text in menus.
		- `scrollbar` - Scroll bar gray area.
		- `window` - Window background.
		- `window-frame` - Window frame.
		- `window-text` - Text in windows.
	+ On **macOS**
		- `alternate-selected-control-text` - The text on a selected surface in a list or table. *deprecated*
		- `control-background` - The background of a large interface element, such as a browser or table.
		- `control` - The surface of a control.
		- `control-text` -The text of a control that isn’t disabled.
		- `disabled-control-text` - The text of a control that’s disabled.
		- `find-highlight` - The color of a find indicator.
		- `grid` - The gridlines of an interface element such as a table.
		- `header-text` - The text of a header cell in a table.
		- `highlight` - The virtual light source onscreen.
		- `keyboard-focus-indicator` - The ring that appears around the currently focused control when using the keyboard for interface navigation.
		- `label` - The text of a label containing primary content.
		- `link` - A link to other content.
		- `placeholder-text` - A placeholder string in a control or text view.
		- `quaternary-label` - The text of a label of lesser importance than a tertiary label such as watermark text.
		- `scrubber-textured-background` - The background of a scrubber in the Touch Bar.
		- `secondary-label` - The text of a label of lesser importance than a normal label such as a label used to represent a subheading or additional information.
		- `selected-content-background` - The background for selected content in a key window or view.
		- `selected-control` - The surface of a selected control.
		- `selected-control-text` - The text of a selected control.
		- `selected-menu-item-text` - The text of a selected menu.
		- `selected-text-background` - The background of selected text.
		- `selected-text` - Selected text.
		- `separator` - A separator between different sections of content.
		- `shadow` - The virtual shadow cast by a raised object onscreen.
		- `tertiary-label` - The text of a label of lesser importance than a secondary label such as a label used to represent disabled text.
		- `text-background` - Text background.
		- `text` - The text in a document.
		- `under-page-background` - The background behind a document's content.
		- `unemphasized-selected-content-background` - The selected content in a non-key window or view.
		- `unemphasized-selected-text-background` - A background for selected text in a non-key window or view.
		- `unemphasized-selected-text` - Selected text in a non-key window or view.
		- `window-background` - The background of a window.
		- `window-frame-text` - The text in the window's titlebar area.


Returns `string` - The system color setting in RGB hexadecimal form (`#ABCDEF`). See the [Windows docs](https://msdn.microsoft.com/en-us/library/windows/desktop/ms724371(v=vs.85).aspx) and the [macOS docs](https://developer.apple.com/design/human-interface-guidelines/macos/visual-design/color#dynamic-system-colors) for more details.


The following colors are only available on macOS 10.14: `find-highlight`, `selected-content-background`, `separator`, `unemphasized-selected-content-background`, `unemphasized-selected-text-background`, and `unemphasized-selected-text`.


### 
`systemPreferences.getSystemColor(color)` *macOS*[​](#systempreferencesgetsystemcolorcolor-macos "Direct link to heading")


* `color` string - One of the following values:
	+ `blue`
	+ `brown`
	+ `gray`
	+ `green`
	+ `orange`
	+ `pink`
	+ `purple`
	+ `red`
	+ `yellow`


Returns `string` - The standard system color formatted as `#RRGGBBAA`.


Returns one of several standard system colors that automatically adapt to vibrancy and changes in accessibility settings like 'Increase contrast' and 'Reduce transparency'. See [Apple Documentation](https://developer.apple.com/design/human-interface-guidelines/macos/visual-design/color#system-colors) for more details.


### 
`systemPreferences.isInvertedColorScheme()` *Windows* *Deprecated*[​](#systempreferencesisinvertedcolorscheme-windows-deprecated "Direct link to heading")


Returns `boolean` - `true` if an inverted color scheme (a high contrast color scheme with light text and dark backgrounds) is active, `false` otherwise.


**Deprecated:** Should use the new [`nativeTheme.shouldUseInvertedColorScheme`](native-theme#nativethemeshoulduseinvertedcolorscheme-macos-windows-readonly) API.


### 
`systemPreferences.isHighContrastColorScheme()` *macOS* *Windows* *Deprecated*[​](#systempreferencesishighcontrastcolorscheme-macos-windows-deprecated "Direct link to heading")


Returns `boolean` - `true` if a high contrast theme is active, `false` otherwise.


**Deprecated:** Should use the new [`nativeTheme.shouldUseHighContrastColors`](native-theme#nativethemeshouldusehighcontrastcolors-macos-windows-readonly) API.


### 
`systemPreferences.getEffectiveAppearance()` *macOS*[​](#systempreferencesgeteffectiveappearance-macos "Direct link to heading")


Returns `string` - Can be `dark`, `light` or `unknown`.


Gets the macOS appearance setting that is currently applied to your application, maps to [NSApplication.effectiveAppearance](https://developer.apple.com/documentation/appkit/nsapplication/2967171-effectiveappearance?language=objc)


### 
`systemPreferences.getAppLevelAppearance()` *macOS* *Deprecated*[​](#systempreferencesgetapplevelappearance-macos-deprecated "Direct link to heading")


Returns `string` | `null` - Can be `dark`, `light` or `unknown`.


Gets the macOS appearance setting that you have declared you want for your application, maps to [NSApplication.appearance](https://developer.apple.com/documentation/appkit/nsapplication/2967170-appearance?language=objc). You can use the `setAppLevelAppearance` API to set this value.


### 
`systemPreferences.setAppLevelAppearance(appearance)` *macOS* *Deprecated*[​](#systempreferencessetapplevelappearanceappearance-macos-deprecated "Direct link to heading")


* `appearance` string | null - Can be `dark` or `light`


Sets the appearance setting for your application, this should override the system default and override the value of `getEffectiveAppearance`.


### 
`systemPreferences.canPromptTouchID()` *macOS*[​](#systempreferencescanprompttouchid-macos "Direct link to heading")


Returns `boolean` - whether or not this device has the ability to use Touch ID.


**NOTE:** This API will return `false` on macOS systems older than Sierra 10.12.2.


### 
`systemPreferences.promptTouchID(reason)` *macOS*[​](#systempreferencesprompttouchidreason-macos "Direct link to heading")


* `reason` string - The reason you are asking for Touch ID authentication


Returns `Promise<void>` - resolves if the user has successfully authenticated with Touch ID.




```
const { systemPreferences } = require('electron')

systemPreferences.promptTouchID('To get consent for a Security-Gated Thing').then(success => {
  console.log('You have successfully authenticated with Touch ID!')
}).catch(err => {
  console.log(err)
})
```


This API itself will not protect your user data; rather, it is a mechanism to allow you to do so. Native apps will need to set [Access Control Constants](https://developer.apple.com/documentation/security/secaccesscontrolcreateflags?language=objc) like [`kSecAccessControlUserPresence`](https://developer.apple.com/documentation/security/secaccesscontrolcreateflags/ksecaccesscontroluserpresence?language=objc) on their keychain entry so that reading it would auto-prompt for Touch ID biometric consent. This could be done with [`node-keytar`](https://github.com/atom/node-keytar), such that one would store an encryption key with `node-keytar` and only fetch it if `promptTouchID()` resolves.


**NOTE:** This API will return a rejected Promise on macOS systems older than Sierra 10.12.2.


### 
`systemPreferences.isTrustedAccessibilityClient(prompt)` *macOS*[​](#systempreferencesistrustedaccessibilityclientprompt-macos "Direct link to heading")


* `prompt` boolean - whether or not the user will be informed via prompt if the current process is untrusted.


Returns `boolean` - `true` if the current process is a trusted accessibility client and `false` if it is not.


### 
`systemPreferences.getMediaAccessStatus(mediaType)` *Windows* *macOS*[​](#systempreferencesgetmediaaccessstatusmediatype-windows-macos "Direct link to heading")


* `mediaType` string - Can be `microphone`, `camera` or `screen`.


Returns `string` - Can be `not-determined`, `granted`, `denied`, `restricted` or `unknown`.


This user consent was not required on macOS 10.13 High Sierra or lower so this method will always return `granted`. macOS 10.14 Mojave or higher requires consent for `microphone` and `camera` access. macOS 10.15 Catalina or higher requires consent for `screen` access.


Windows 10 has a global setting controlling `microphone` and `camera` access for all win32 applications. It will always return `granted` for `screen` and for all media types on older versions of Windows.


### 
`systemPreferences.askForMediaAccess(mediaType)` *macOS*[​](#systempreferencesaskformediaaccessmediatype-macos "Direct link to heading")


* `mediaType` string - the type of media being requested; can be `microphone`, `camera`.


Returns `Promise<boolean>` - A promise that resolves with `true` if consent was granted and `false` if it was denied. If an invalid `mediaType` is passed, the promise will be rejected. If an access request was denied and later is changed through the System Preferences pane, a restart of the app will be required for the new permissions to take effect. If access has already been requested and denied, it *must* be changed through the preference pane; an alert will not pop up and the promise will resolve with the existing access status.


**Important:** In order to properly leverage this API, you [must set](https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_macos?language=objc) the `NSMicrophoneUsageDescription` and `NSCameraUsageDescription` strings in your app's `Info.plist` file. The values for these keys will be used to populate the permission dialogs so that the user will be properly informed as to the purpose of the permission request. See [Electron Application Distribution](../tutorial/application-distribution#macos) for more information about how to set these in the context of Electron.


This user consent was not required until macOS 10.14 Mojave, so this method will always return `true` if your system is running 10.13 High Sierra or lower.


### 
`systemPreferences.getAnimationSettings()`[​](#systempreferencesgetanimationsettings "Direct link to heading")


Returns `Object`:


* `shouldRenderRichAnimation` boolean - Returns true if rich animations should be rendered. Looks at session type (e.g. remote desktop) and accessibility settings to give guidance for heavy animations.
* `scrollAnimationsEnabledBySystem` boolean - Determines on a per-platform basis whether scroll animations (e.g. produced by home/end key) should be enabled.
* `prefersReducedMotion` boolean - Determines whether the user desires reduced motion based on platform APIs.


Returns an object with system animation settings.


Properties[​](#properties "Direct link to heading")
---------------------------------------------------


### 
`systemPreferences.appLevelAppearance` *macOS*[​](#systempreferencesapplevelappearance-macos "Direct link to heading")


A `string` property that can be `dark`, `light` or `unknown`. It determines the macOS appearance setting for your application. This maps to values in: [NSApplication.appearance](https://developer.apple.com/documentation/appkit/nsapplication/2967170-appearance?language=objc). Setting this will override the system default as well as the value of `getEffectiveAppearance`.


Possible values that can be set are `dark` and `light`, and possible return values are `dark`, `light`, and `unknown`.


This property is only available on macOS 10.14 Mojave or newer.


### 
`systemPreferences.effectiveAppearance` *macOS* *Readonly*[​](#systempreferenceseffectiveappearance-macos-readonly "Direct link to heading")


A `string` property that can be `dark`, `light` or `unknown`.


Returns the macOS appearance setting that is currently applied to your application, maps to [NSApplication.effectiveAppearance](https://developer.apple.com/documentation/appkit/nsapplication/2967171-effectiveappearance?language=objc)



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/system-preferences>

KeyboardInputEvent Object extends `InputEvent`
==============================================


* `type` string - The type of the event, can be `keyDown`, `keyUp` or `char`.
* `keyCode` string - The character that will be sent as the keyboard event. Should only use the valid key codes in [Accelerator](../accelerator).



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/keyboard-input-event>

Extension Object
================


* `id` string
* `manifest` any - Copy of the [extension's manifest data](https://developer.chrome.com/extensions/manifest).
* `name` string
* `path` string - The extension's file path.
* `version` string
* `url` string - The extension's `chrome-extension://` URL.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/extension>

PrinterInfo Object
==================


* `name` string - the name of the printer as understood by the OS.
* `displayName` string - the name of the printer as shown in Print Preview.
* `description` string - a longer description of the printer's type.
* `status` number - the current status of the printer.
* `isDefault` boolean - whether or not a given printer is set as the default printer on the OS.
* `options` Object - an object containing a variable number of platform-specific printer information.


The number represented by `status` means different things on different platforms: on Windows its potential values can be found [here](https://docs.microsoft.com/en-us/windows/win32/printdocs/printer-info-2), and on Linux and macOS they can be found [here](https://www.cups.org/doc/cupspm.html).


Example[​](#example "Direct link to heading")
---------------------------------------------


Below is an example of some of the additional options that may be set which may be different on each platform.




```
{
  name: 'Austin_4th_Floor_Printer___C02XK13BJHD4',
  displayName: 'Austin 4th Floor Printer @ C02XK13BJHD4',
  description: 'TOSHIBA ColorMFP',
  status: 3,
  isDefault: false,
  options: {
    copies: '1',
    'device-uri': 'dnssd://Austin%204th%20Floor%20Printer%20%40%20C02XK13BJHD4._ipps._tcp.local./?uuid=71687f1e-1147-3274-6674-22de61b110bd',
    finishings: '3',
    'job-cancel-after': '10800',
    'job-hold-until': 'no-hold',
    'job-priority': '50',
    'job-sheets': 'none,none',
    'marker-change-time': '0',
    'number-up': '1',
    'printer-commands': 'ReportLevels,PrintSelfTestPage,com.toshiba.ColourProfiles.update,com.toshiba.EFiling.update,com.toshiba.EFiling.checkPassword',
    'printer-info': 'Austin 4th Floor Printer @ C02XK13BJHD4',
    'printer-is-accepting-jobs': 'true',
    'printer-is-shared': 'false',
    'printer-is-temporary': 'false',
    'printer-location': '',
    'printer-make-and-model': 'TOSHIBA ColorMFP',
    'printer-state': '3',
    'printer-state-change-time': '1573472937',
    'printer-state-reasons': 'offline-report,com.toshiba.snmp.failed',
    'printer-type': '10531038',
    'printer-uri-supported': 'ipp://localhost/printers/Austin_4th_Floor_Printer___C02XK13BJHD4',
    system_driverinfo: 'T'
  }
}
```



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/printer-info>

ProductDiscount Object
======================


* `identifier` string - A string used to uniquely identify a discount offer for a product.
* `type` number - The type of discount offer.
* `price` number - The discount price of the product in the local currency.
* `priceLocale` string - The locale used to format the discount price of the product.
* `paymentMode` string - The payment mode for this product discount. Can be `payAsYouGo`, `payUpFront`, or `freeTrial`.
* `numberOfPeriods` number - An integer that indicates the number of periods the product discount is available.
* `subscriptionPeriod` [ProductSubscriptionPeriod](product-subscription-period) (optional) - An object that defines the period for the product discount.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/product-discount>

webFrameMain
============



> Control web pages and iframes.
> 
> 


Process: [Main](../glossary#main-process)


The `webFrameMain` module can be used to lookup frames across existing [`WebContents`](web-contents) instances. Navigation events are the common use case.




```
const { BrowserWindow, webFrameMain } = require('electron')

const win = new BrowserWindow({ width: 800, height: 1500 })
win.loadURL('https://twitter.com')

win.webContents.on(
  'did-frame-navigate',
  (event, url, httpResponseCode, httpStatusText, isMainFrame, frameProcessId, frameRoutingId) => {
    const frame = webFrameMain.fromId(frameProcessId, frameRoutingId)
    if (frame) {
      const code = 'document.body.innerHTML = document.body.innerHTML.replaceAll("heck", "h*ck")'
      frame.executeJavaScript(code)
    }
  }
)
```


You can also access frames of existing pages by using the `mainFrame` property of [`WebContents`](web-contents).




```
const { BrowserWindow } = require('electron')

async function main () {
  const win = new BrowserWindow({ width: 800, height: 600 })
  await win.loadURL('https://reddit.com')

  const youtubeEmbeds = win.webContents.mainFrame.frames.filter((frame) => {
    try {
      const url = new URL(frame.url)
      return url.host === 'www.youtube.com'
    } catch {
      return false
    }
  })

  console.log(youtubeEmbeds)
}

main()
```


Methods[​](#methods "Direct link to heading")
---------------------------------------------


These methods can be accessed from the `webFrameMain` module:


### 
`webFrameMain.fromId(processId, routingId)`[​](#webframemainfromidprocessid-routingid "Direct link to heading")


* `processId` Integer - An `Integer` representing the internal ID of the process which owns the frame.
* `routingId` Integer - An `Integer` representing the unique frame ID in the current renderer process. Routing IDs can be retrieved from `WebFrameMain` instances (`frame.routingId`) and are also passed by frame specific `WebContents` navigation events (e.g. `did-frame-navigate`).


Returns `WebFrameMain | undefined` - A frame with the given process and routing IDs, or `undefined` if there is no WebFrameMain associated with the given IDs.


Class: WebFrameMain[​](#class-webframemain "Direct link to heading")
--------------------------------------------------------------------


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


### Instance Events[​](#instance-events "Direct link to heading")


#### Event: 'dom-ready'[​](#event-dom-ready "Direct link to heading")


Emitted when the document is loaded.


### Instance Methods[​](#instance-methods "Direct link to heading")


#### 
`frame.executeJavaScript(code[, userGesture])`[​](#frameexecutejavascriptcode-usergesture "Direct link to heading")


* `code` string
* `userGesture` boolean (optional) - Default is `false`.


Returns `Promise<unknown>` - A promise that resolves with the result of the executed code or is rejected if execution throws or results in a rejected promise.


Evaluates `code` in page.


In the browser window some HTML APIs like `requestFullScreen` can only be invoked by a gesture from the user. Setting `userGesture` to `true` will remove this limitation.


#### 
`frame.reload()`[​](#framereload "Direct link to heading")


Returns `boolean` - Whether the reload was initiated successfully. Only results in `false` when the frame has no history.


#### 
`frame.send(channel, ...args)`[​](#framesendchannel-args "Direct link to heading")


* `channel` string
* `...args` any[]


Send an asynchronous message to the renderer process via `channel`, along with arguments. Arguments will be serialized with the [Structured Clone Algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm), just like [`postMessage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage), so prototype chains will not be included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will throw an exception.


The renderer process can handle the message by listening to `channel` with the [`ipcRenderer`](ipc-renderer) module.


#### 
`frame.postMessage(channel, message, [transfer])`[​](#framepostmessagechannel-message-transfer "Direct link to heading")


* `channel` string
* `message` any
* `transfer` MessagePortMain[] (optional)


Send a message to the renderer process, optionally transferring ownership of zero or more [`MessagePortMain`][] objects.


The transferred `MessagePortMain` objects will be available in the renderer process by accessing the `ports` property of the emitted event. When they arrive in the renderer, they will be native DOM `MessagePort` objects.


For example:




```
// Main process
const { port1, port2 } = new MessageChannelMain()
webContents.mainFrame.postMessage('port', { message: 'hello' }, [port1])

// Renderer process
ipcRenderer.on('port', (e, msg) => {
  const [port] = e.ports
  // ...
})
```


### Instance Properties[​](#instance-properties "Direct link to heading")


#### 
`frame.url` *Readonly*[​](#frameurl-readonly "Direct link to heading")


A `string` representing the current URL of the frame.


#### 
`frame.top` *Readonly*[​](#frametop-readonly "Direct link to heading")


A `WebFrameMain | null` representing top frame in the frame hierarchy to which `frame` belongs.


#### 
`frame.parent` *Readonly*[​](#frameparent-readonly "Direct link to heading")


A `WebFrameMain | null` representing parent frame of `frame`, the property would be `null` if `frame` is the top frame in the frame hierarchy.


#### 
`frame.frames` *Readonly*[​](#frameframes-readonly "Direct link to heading")


A `WebFrameMain[]` collection containing the direct descendents of `frame`.


#### 
`frame.framesInSubtree` *Readonly*[​](#frameframesinsubtree-readonly "Direct link to heading")


A `WebFrameMain[]` collection containing every frame in the subtree of `frame`, including itself. This can be useful when traversing through all frames.


#### 
`frame.frameTreeNodeId` *Readonly*[​](#frameframetreenodeid-readonly "Direct link to heading")


An `Integer` representing the id of the frame's internal FrameTreeNode instance. This id is browser-global and uniquely identifies a frame that hosts content. The identifier is fixed at the creation of the frame and stays constant for the lifetime of the frame. When the frame is removed, the id is not used again.


#### 
`frame.name` *Readonly*[​](#framename-readonly "Direct link to heading")


A `string` representing the frame name.


#### 
`frame.osProcessId` *Readonly*[​](#frameosprocessid-readonly "Direct link to heading")


An `Integer` representing the operating system `pid` of the process which owns this frame.


#### 
`frame.processId` *Readonly*[​](#frameprocessid-readonly "Direct link to heading")


An `Integer` representing the Chromium internal `pid` of the process which owns this frame. This is not the same as the OS process ID; to read that use `frame.osProcessId`.


#### 
`frame.routingId` *Readonly*[​](#frameroutingid-readonly "Direct link to heading")


An `Integer` representing the unique frame id in the current renderer process. Distinct `WebFrameMain` instances that refer to the same underlying frame will have the same `routingId`.


#### 
`frame.visibilityState` *Readonly*[​](#framevisibilitystate-readonly "Direct link to heading")


A `string` representing the [visibility state](https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilityState) of the frame.


See also how the [Page Visibility API](browser-window#page-visibility) is affected by other Electron APIs.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/web-frame-main>

screen
======



> Retrieve information about screen size, displays, cursor position, etc.
> 
> 


Process: [Main](../glossary#main-process)


This module cannot be used until the `ready` event of the `app` module is emitted.


`screen` is an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter).


**Note:** In the renderer / DevTools, `window.screen` is a reserved DOM property, so writing `let { screen } = require('electron')` will not work.


An example of creating a window that fills the whole screen:




[docs/fiddles/screen/fit-screen (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/screen/fit-screen)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/screen/fit-screen)


* main.js




```
// Retrieve information about screen size, displays, cursor position, etc.
//
// For more info, see:
// https://electronjs.org/docs/api/screen

const { app, BrowserWindow } = require('electron')

let mainWindow = null

app.whenReady().then(() => {
  // We cannot require the screen module until the app is ready.
  const { screen } = require('electron')

  // Create a window that fills the screen's available work area.
  const primaryDisplay = screen.getPrimaryDisplay()
  const { width, height } = primaryDisplay.workAreaSize

  mainWindow = new BrowserWindow({ width, height })
  mainWindow.loadURL('https://electronjs.org')
})
```




Another example of creating a window in the external display:




```
const { app, BrowserWindow, screen } = require('electron')

let win

app.whenReady().then(() => {
  const displays = screen.getAllDisplays()
  const externalDisplay = displays.find((display) => {
    return display.bounds.x !== 0 || display.bounds.y !== 0
  })

  if (externalDisplay) {
    win = new BrowserWindow({
      x: externalDisplay.bounds.x + 50,
      y: externalDisplay.bounds.y + 50
    })
    win.loadURL('https://github.com')
  }
})
```


Events[​](#events "Direct link to heading")
-------------------------------------------


The `screen` module emits the following events:


### Event: 'display-added'[​](#event-display-added "Direct link to heading")


Returns:


* `event` Event
* `newDisplay` [Display](structures/display)


Emitted when `newDisplay` has been added.


### Event: 'display-removed'[​](#event-display-removed "Direct link to heading")


Returns:


* `event` Event
* `oldDisplay` [Display](structures/display)


Emitted when `oldDisplay` has been removed.


### Event: 'display-metrics-changed'[​](#event-display-metrics-changed "Direct link to heading")


Returns:


* `event` Event
* `display` [Display](structures/display)
* `changedMetrics` string[]


Emitted when one or more metrics change in a `display`. The `changedMetrics` is an array of strings that describe the changes. Possible changes are `bounds`, `workArea`, `scaleFactor` and `rotation`.


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `screen` module has the following methods:


### 
`screen.getCursorScreenPoint()`[​](#screengetcursorscreenpoint "Direct link to heading")


Returns [Point](structures/point)


The current absolute position of the mouse pointer.


**Note:** The return value is a DIP point, not a screen physical point.


### 
`screen.getPrimaryDisplay()`[​](#screengetprimarydisplay "Direct link to heading")


Returns [Display](structures/display) - The primary display.


### 
`screen.getAllDisplays()`[​](#screengetalldisplays "Direct link to heading")


Returns [Display[]](structures/display) - An array of displays that are currently available.


### 
`screen.getDisplayNearestPoint(point)`[​](#screengetdisplaynearestpointpoint "Direct link to heading")


* `point` [Point](structures/point)


Returns [Display](structures/display) - The display nearest the specified point.


### 
`screen.getDisplayMatching(rect)`[​](#screengetdisplaymatchingrect "Direct link to heading")


* `rect` [Rectangle](structures/rectangle)


Returns [Display](structures/display) - The display that most closely intersects the provided bounds.


### 
`screen.screenToDipPoint(point)` *Windows*[​](#screenscreentodippointpoint-windows "Direct link to heading")


* `point` [Point](structures/point)


Returns [Point](structures/point)


Converts a screen physical point to a screen DIP point. The DPI scale is performed relative to the display containing the physical point.


### 
`screen.dipToScreenPoint(point)` *Windows*[​](#screendiptoscreenpointpoint-windows "Direct link to heading")


* `point` [Point](structures/point)


Returns [Point](structures/point)


Converts a screen DIP point to a screen physical point. The DPI scale is performed relative to the display containing the DIP point.


### 
`screen.screenToDipRect(window, rect)` *Windows*[​](#screenscreentodiprectwindow-rect-windows "Direct link to heading")


* `window` [BrowserWindow](browser-window) | null
* `rect` [Rectangle](structures/rectangle)


Returns [Rectangle](structures/rectangle)


Converts a screen physical rect to a screen DIP rect. The DPI scale is performed relative to the display nearest to `window`. If `window` is null, scaling will be performed to the display nearest to `rect`.


### 
`screen.dipToScreenRect(window, rect)` *Windows*[​](#screendiptoscreenrectwindow-rect-windows "Direct link to heading")


* `window` [BrowserWindow](browser-window) | null
* `rect` [Rectangle](structures/rectangle)


Returns [Rectangle](structures/rectangle)


Converts a screen DIP rect to a screen physical rect. The DPI scale is performed relative to the display nearest to `window`. If `window` is null, scaling will be performed to the display nearest to `rect`.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/screen>

Dock
====


Electron has APIs to configure the app's icon in the macOS Dock. A macOS-only API exists to create a custom dock menu, but Electron also uses the app dock icon as the entry point for cross-platform features like [recent documents](recent-documents) and [application progress](progress-bar).


The custom dock is commonly used to add shortcuts to tasks the user wouldn't want to open the whole app window for.


**Dock menu of Terminal.app:**


![Dock Menu]


To set your custom dock menu, you need to use the [`app.dock.setMenu`](../api/dock#docksetmenumenu-macos) API, which is only available on macOS.




[docs/fiddles/features/macos-dock-menu (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/features/macos-dock-menu)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/features/macos-dock-menu)


* main.js
* index.html





```
const { app, BrowserWindow, Menu } = require('electron')

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
  })

  win.loadFile('index.html')
}

const dockMenu = Menu.buildFromTemplate([
  {
    label: 'New Window',
    click () { console.log('New Window') }
  }, {
    label: 'New Window with Settings',
    submenu: [
      { label: 'Basic' },
      { label: 'Pro' }
    ]
  },
  { label: 'New Command...' }
])

app.whenReady().then(() => {
  if (process.platform === 'darwin') {
    app.dock.setMenu(dockMenu)
  }
}).then(createWindow)

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})
```




```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
    <h1>Hello World!</h1>
    <p>Right click the dock icon to see the custom menu options.</p>
</body>
</html>
```





After launching the Electron application, right click the application icon. You should see the custom menu you just defined:


![macOS dock menu]



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/macos-dock>

protocol
========



> Register a custom protocol and intercept existing protocol requests.
> 
> 


Process: [Main](../glossary#main-process)


An example of implementing a protocol that has the same effect as the `file://` protocol:




```
const { app, protocol } = require('electron')
const path = require('path')

app.whenReady().then(() => {
  protocol.registerFileProtocol('atom', (request, callback) => {
    const url = request.url.substr(7)
    callback({ path: path.normalize(`${__dirname}/${url}`) })
  })
})
```


**Note:** All methods unless specified can only be used after the `ready` event of the `app` module gets emitted.


Using `protocol` with a custom `partition` or `session`[​](#using-protocol-with-a-custom-partition-or-session "Direct link to heading")
---------------------------------------------------------------------------------------------------------------------------------------


A protocol is registered to a specific Electron [`session`](session) object. If you don't specify a session, then your `protocol` will be applied to the default session that Electron uses. However, if you define a `partition` or `session` on your `browserWindow`'s `webPreferences`, then that window will use a different session and your custom protocol will not work if you just use `electron.protocol.XXX`.


To have your custom protocol work in combination with a custom session, you need to register it to that session explicitly.




```
const { session, app, protocol } = require('electron')
const path = require('path')

app.whenReady().then(() => {
  const partition = 'persist:example'
  const ses = session.fromPartition(partition)

  ses.protocol.registerFileProtocol('atom', (request, callback) => {
    const url = request.url.substr(7)
    callback({ path: path.normalize(`${__dirname}/${url}`) })
  })

  mainWindow = new BrowserWindow({ webPreferences: { partition } })
})
```


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `protocol` module has the following methods:


### 
`protocol.registerSchemesAsPrivileged(customSchemes)`[​](#protocolregisterschemesasprivilegedcustomschemes "Direct link to heading")


* `customSchemes` [CustomScheme[]](structures/custom-scheme)


**Note:** This method can only be used before the `ready` event of the `app` module gets emitted and can be called only once.


Registers the `scheme` as standard, secure, bypasses content security policy for resources, allows registering ServiceWorker, supports fetch API, and streaming video/audio. Specify a privilege with the value of `true` to enable the capability.


An example of registering a privileged scheme, that bypasses Content Security Policy:




```
const { protocol } = require('electron')
protocol.registerSchemesAsPrivileged([
  { scheme: 'foo', privileges: { bypassCSP: true } }
])
```


A standard scheme adheres to what RFC 3986 calls [generic URI syntax](https://tools.ietf.org/html/rfc3986#section-3). For example `http` and `https` are standard schemes, while `file` is not.


Registering a scheme as standard allows relative and absolute resources to be resolved correctly when served. Otherwise the scheme will behave like the `file` protocol, but without the ability to resolve relative URLs.


For example when you load following page with custom protocol without registering it as standard scheme, the image will not be loaded because non-standard schemes can not recognize relative URLs:




```
<body>
  <img src='test.png'>
</body>
```


Registering a scheme as standard will allow access to files through the [FileSystem API](https://developer.mozilla.org/en-US/docs/Web/API/LocalFileSystem). Otherwise the renderer will throw a security error for the scheme.


By default web storage apis (localStorage, sessionStorage, webSQL, indexedDB, cookies) are disabled for non standard schemes. So in general if you want to register a custom protocol to replace the `http` protocol, you have to register it as a standard scheme.


Protocols that use streams (http and stream protocols) should set `stream: true`. The `<video>` and `<audio>` HTML elements expect protocols to buffer their responses by default. The `stream` flag configures those elements to correctly expect streaming responses.


### 
`protocol.registerFileProtocol(scheme, handler)`[​](#protocolregisterfileprotocolscheme-handler "Direct link to heading")


* `scheme` string
* `handler` Function
	+ `request` [ProtocolRequest](structures/protocol-request)
	+ `callback` Function
		- `response` (string | [ProtocolResponse](structures/protocol-response))


Returns `boolean` - Whether the protocol was successfully registered


Registers a protocol of `scheme` that will send a file as the response. The `handler` will be called with `request` and `callback` where `request` is an incoming request for the `scheme`.


To handle the `request`, the `callback` should be called with either the file's path or an object that has a `path` property, e.g. `callback(filePath)` or `callback({ path: filePath })`. The `filePath` must be an absolute path.


By default the `scheme` is treated like `http:`, which is parsed differently from protocols that follow the "generic URI syntax" like `file:`.


### 
`protocol.registerBufferProtocol(scheme, handler)`[​](#protocolregisterbufferprotocolscheme-handler "Direct link to heading")


* `scheme` string
* `handler` Function
	+ `request` [ProtocolRequest](structures/protocol-request)
	+ `callback` Function
		- `response` (Buffer | [ProtocolResponse](structures/protocol-response))


Returns `boolean` - Whether the protocol was successfully registered


Registers a protocol of `scheme` that will send a `Buffer` as a response.


The usage is the same with `registerFileProtocol`, except that the `callback` should be called with either a `Buffer` object or an object that has the `data` property.


Example:




```
protocol.registerBufferProtocol('atom', (request, callback) => {
  callback({ mimeType: 'text/html', data: Buffer.from('<h5>Response</h5>') })
})
```


### 
`protocol.registerStringProtocol(scheme, handler)`[​](#protocolregisterstringprotocolscheme-handler "Direct link to heading")


* `scheme` string
* `handler` Function
	+ `request` [ProtocolRequest](structures/protocol-request)
	+ `callback` Function
		- `response` (string | [ProtocolResponse](structures/protocol-response))


Returns `boolean` - Whether the protocol was successfully registered


Registers a protocol of `scheme` that will send a `string` as a response.


The usage is the same with `registerFileProtocol`, except that the `callback` should be called with either a `string` or an object that has the `data` property.


### 
`protocol.registerHttpProtocol(scheme, handler)`[​](#protocolregisterhttpprotocolscheme-handler "Direct link to heading")


* `scheme` string
* `handler` Function
	+ `request` [ProtocolRequest](structures/protocol-request)
	+ `callback` Function
		- `response` ProtocolResponse


Returns `boolean` - Whether the protocol was successfully registered


Registers a protocol of `scheme` that will send an HTTP request as a response.


The usage is the same with `registerFileProtocol`, except that the `callback` should be called with an object that has the `url` property.


### 
`protocol.registerStreamProtocol(scheme, handler)`[​](#protocolregisterstreamprotocolscheme-handler "Direct link to heading")


* `scheme` string
* `handler` Function
	+ `request` [ProtocolRequest](structures/protocol-request)
	+ `callback` Function
		- `response` (ReadableStream | [ProtocolResponse](structures/protocol-response))


Returns `boolean` - Whether the protocol was successfully registered


Registers a protocol of `scheme` that will send a stream as a response.


The usage is the same with `registerFileProtocol`, except that the `callback` should be called with either a [`ReadableStream`](https://nodejs.org/api/stream.html#stream_class_stream_readable) object or an object that has the `data` property.


Example:




```
const { protocol } = require('electron')
const { PassThrough } = require('stream')

function createStream (text) {
  const rv = new PassThrough() // PassThrough is also a Readable stream
  rv.push(text)
  rv.push(null)
  return rv
}

protocol.registerStreamProtocol('atom', (request, callback) => {
  callback({
    statusCode: 200,
    headers: {
      'content-type': 'text/html'
    },
    data: createStream('<h5>Response</h5>')
  })
})
```


It is possible to pass any object that implements the readable stream API (emits `data`/`end`/`error` events). For example, here's how a file could be returned:




```
protocol.registerStreamProtocol('atom', (request, callback) => {
  callback(fs.createReadStream('index.html'))
})
```


### 
`protocol.unregisterProtocol(scheme)`[​](#protocolunregisterprotocolscheme "Direct link to heading")


* `scheme` string


Returns `boolean` - Whether the protocol was successfully unregistered


Unregisters the custom protocol of `scheme`.


### 
`protocol.isProtocolRegistered(scheme)`[​](#protocolisprotocolregisteredscheme "Direct link to heading")


* `scheme` string


Returns `boolean` - Whether `scheme` is already registered.


### 
`protocol.interceptFileProtocol(scheme, handler)`[​](#protocolinterceptfileprotocolscheme-handler "Direct link to heading")


* `scheme` string
* `handler` Function
	+ `request` [ProtocolRequest](structures/protocol-request)
	+ `callback` Function
		- `response` (string | [ProtocolResponse](structures/protocol-response))


Returns `boolean` - Whether the protocol was successfully intercepted


Intercepts `scheme` protocol and uses `handler` as the protocol's new handler which sends a file as a response.


### 
`protocol.interceptStringProtocol(scheme, handler)`[​](#protocolinterceptstringprotocolscheme-handler "Direct link to heading")


* `scheme` string
* `handler` Function
	+ `request` [ProtocolRequest](structures/protocol-request)
	+ `callback` Function
		- `response` (string | [ProtocolResponse](structures/protocol-response))


Returns `boolean` - Whether the protocol was successfully intercepted


Intercepts `scheme` protocol and uses `handler` as the protocol's new handler which sends a `string` as a response.


### 
`protocol.interceptBufferProtocol(scheme, handler)`[​](#protocolinterceptbufferprotocolscheme-handler "Direct link to heading")


* `scheme` string
* `handler` Function
	+ `request` [ProtocolRequest](structures/protocol-request)
	+ `callback` Function
		- `response` (Buffer | [ProtocolResponse](structures/protocol-response))


Returns `boolean` - Whether the protocol was successfully intercepted


Intercepts `scheme` protocol and uses `handler` as the protocol's new handler which sends a `Buffer` as a response.


### 
`protocol.interceptHttpProtocol(scheme, handler)`[​](#protocolintercepthttpprotocolscheme-handler "Direct link to heading")


* `scheme` string
* `handler` Function
	+ `request` [ProtocolRequest](structures/protocol-request)
	+ `callback` Function
		- `response` [ProtocolResponse](structures/protocol-response)


Returns `boolean` - Whether the protocol was successfully intercepted


Intercepts `scheme` protocol and uses `handler` as the protocol's new handler which sends a new HTTP request as a response.


### 
`protocol.interceptStreamProtocol(scheme, handler)`[​](#protocolinterceptstreamprotocolscheme-handler "Direct link to heading")


* `scheme` string
* `handler` Function
	+ `request` [ProtocolRequest](structures/protocol-request)
	+ `callback` Function
		- `response` (ReadableStream | [ProtocolResponse](structures/protocol-response))


Returns `boolean` - Whether the protocol was successfully intercepted


Same as `protocol.registerStreamProtocol`, except that it replaces an existing protocol handler.


### 
`protocol.uninterceptProtocol(scheme)`[​](#protocoluninterceptprotocolscheme "Direct link to heading")


* `scheme` string


Returns `boolean` - Whether the protocol was successfully unintercepted


Remove the interceptor installed for `scheme` and restore its original handler.


### 
`protocol.isProtocolIntercepted(scheme)`[​](#protocolisprotocolinterceptedscheme "Direct link to heading")


* `scheme` string


Returns `boolean` - Whether `scheme` is already intercepted.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/protocol>

Native File Drag & Drop
=======================


Overview[​](#overview "Direct link to heading")
-----------------------------------------------


Certain kinds of applications that manipulate files might want to support the operating system's native file drag & drop feature. Dragging files into web content is common and supported by many websites. Electron additionally supports dragging files and content out from web content into the operating system's world.


To implement this feature in your app, you need to call the [`webContents.startDrag(item)`](../api/web-contents#contentsstartdragitem) API in response to the `ondragstart` event.


Example[​](#example "Direct link to heading")
---------------------------------------------


An example demonstrating how you can create a file on the fly to be dragged out of the window.


### Preload.js[​](#preloadjs "Direct link to heading")


In `preload.js` use the [`contextBridge`](../api/context-bridge) to inject a method `window.electron.startDrag(...)` that will send an IPC message to the main process.




```
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electron', {
  startDrag: (fileName) => {
    ipcRenderer.send('ondragstart', path.join(process.cwd(), fileName))
  }
})
```


### Index.html[​](#indexhtml "Direct link to heading")


Add a draggable element to `index.html`, and reference your renderer script:




```
<div style="border:2px solid black;border-radius:3px;padding:5px;display:inline-block" draggable="true" id="drag">Drag me</div>
<script src="renderer.js"></script>
```


### Renderer.js[​](#rendererjs "Direct link to heading")


In `renderer.js` set up the renderer process to handle drag events by calling the method you added via the [`contextBridge`](../api/context-bridge) above.




```
document.getElementById('drag').ondragstart = (event) => {
  event.preventDefault()
  window.electron.startDrag('drag-and-drop.md')
}
```


### Main.js[​](#mainjs "Direct link to heading")


In the Main process (`main.js` file), expand the received event with a path to the file that is being dragged and an icon:




[docs/fiddles/features/drag-and-drop (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/features/drag-and-drop)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/features/drag-and-drop)


* main.js
* preload.js
* index.html
* renderer.js





```
const { app, BrowserWindow, ipcMain, nativeImage, NativeImage } = require('electron')
const path = require('path')
const fs = require('fs')
const https = require('https')

function createWindow() {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  win.loadFile('index.html')
}

const iconName = path.join(__dirname, 'iconForDragAndDrop.png');
const icon = fs.createWriteStream(iconName);

// Create a new file to copy - you can also copy existing files.
fs.writeFileSync(path.join(__dirname, 'drag-and-drop-1.md'), '# First file to test drag and drop')
fs.writeFileSync(path.join(__dirname, 'drag-and-drop-2.md'), '# Second file to test drag and drop')

https.get('https://img.icons8.com/ios/452/drag-and-drop.png', (response) => {
  response.pipe(icon);
});

app.whenReady().then(createWindow)

ipcMain.on('ondragstart', (event, filePath) => {
  event.sender.startDrag({
    file: path.join(__dirname, filePath),
    icon: iconName,
  })
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})
```




```
const { contextBridge, ipcRenderer } = require('electron')

contextBridge.exposeInMainWorld('electron', {
  startDrag: (fileName) => {
    ipcRenderer.send('ondragstart', fileName)
  }
})
```




```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
    <h1>Hello World!</h1>
    <p>Drag the boxes below to somewhere in your OS (Finder/Explorer, Desktop, etc.) to copy an example markdown file.</p>
    <div style="border:2px solid black;border-radius:3px;padding:5px;display:inline-block" draggable="true" id="drag1">Drag me - File 1</div>
    <div style="border:2px solid black;border-radius:3px;padding:5px;display:inline-block" draggable="true" id="drag2">Drag me - File 2</div>
    <script src="renderer.js"></script>
</body>
</html>
```




```
document.getElementById('drag1').ondragstart = (event) => {
  event.preventDefault()
  window.electron.startDrag('drag-and-drop-1.md')
}

document.getElementById('drag2').ondragstart = (event) => {
  event.preventDefault()
  window.electron.startDrag('drag-and-drop-2.md')
}
```





After launching the Electron application, try dragging and dropping the item from the BrowserWindow onto your desktop. In this guide, the item is a Markdown file located in the root of the project:


![Drag and drop](https://www.electronjs.org/assets/images/drag-and-drop-67d61d654b54bcc6bd497a1d1608dc29.gif)



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/native-file-drag-drop>

Debugging in VSCode
===================


This guide goes over how to set up VSCode debugging for both your own Electron project as well as the native Electron codebase.


Debugging your Electron app[​](#debugging-your-electron-app "Direct link to heading")
-------------------------------------------------------------------------------------


### Main process[​](#main-process "Direct link to heading")


#### 1. Open an Electron project in VSCode.[​](#1-open-an-electron-project-in-vscode "Direct link to heading")




```
$ git clone git@github.com:electron/electron-quick-start.git
$ code electron-quick-start
```


#### 2. Add a file `.vscode/launch.json` with the following configuration:[​](#2-add-a-file-vscodelaunchjson-with-the-following-configuration "Direct link to heading")




```
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Debug Main Process",
      "type": "node",
      "request": "launch",
      "cwd": "${workspaceFolder}",
      "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
      "windows": {
        "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron.cmd"
      },
      "args" : ["."],
      "outputCapture": "std"
    }
  ]
}
```


#### 3. Debugging[​](#3-debugging "Direct link to heading")


Set some breakpoints in `main.js`, and start debugging in the [Debug View](https://code.visualstudio.com/docs/editor/debugging). You should be able to hit the breakpoints.


Here is a pre-configured project that you can download and directly debug in VSCode: <https://github.com/octref/vscode-electron-debug/tree/master/electron-quick-start>


Debugging the Electron codebase[​](#debugging-the-electron-codebase "Direct link to heading")
---------------------------------------------------------------------------------------------


If you want to build Electron from source and modify the native Electron codebase, this section will help you in testing your modifications.


For those unsure where to acquire this code or how to build it, [Electron's Build Tools](https://github.com/electron/build-tools) automates and explains most of this process. If you wish to manually set up the environment, you can instead use these [build instructions](../development/build-instructions-gn).


### Windows (C++)[​](#windows-c "Direct link to heading")


#### 1. Open an Electron project in VSCode.[​](#1-open-an-electron-project-in-vscode-1 "Direct link to heading")




```
$ git clone git@github.com:electron/electron-quick-start.git
$ code electron-quick-start
```


#### 2. Add a file `.vscode/launch.json` with the following configuration:[​](#2-add-a-file-vscodelaunchjson-with-the-following-configuration-1 "Direct link to heading")




```
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "(Windows) Launch",
      "type": "cppvsdbg",
      "request": "launch",
      "program": "${workspaceFolder}\\out\\your-executable-location\\electron.exe",
      "args": ["your-electron-project-path"],
      "stopAtEntry": false,
      "cwd": "${workspaceFolder}",
      "environment": [
          {"name": "ELECTRON_ENABLE_LOGGING", "value": "true"},
          {"name": "ELECTRON_ENABLE_STACK_DUMPING", "value": "true"},
          {"name": "ELECTRON_RUN_AS_NODE", "value": ""},
      ],
      "externalConsole": false,
      "sourceFileMap": {
          "o:\\": "${workspaceFolder}",
      },
    },
  ]
}
```


**Configuration Notes**


* `cppvsdbg` requires the [built-in C/C++ extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools) be enabled.
* `${workspaceFolder}` is the full path to Chromium's `src` directory.
* `your-executable-location` will be one of the following depending on a few items:
	+ `Testing`: If you are using the default settings of [Electron's Build-Tools](https://github.com/electron/build-tools) or the default instructions when [building from source](../development/build-instructions-gn#building).
	+ `Release`: If you built a Release build rather than a Testing build.
	+ `your-directory-name`: If you modified this during your build process from the default, this will be whatever you specified.
* The `args` array string `"your-electron-project-path"` should be the absolute path to either the directory or `main.js` file of the Electron project you are using for testing. In this example, it should be your path to `electron-quick-start`.


#### 3. Debugging[​](#3-debugging-1 "Direct link to heading")


Set some breakpoints in the .cc files of your choosing in the native Electron C++ code, and start debugging in the [Debug View](https://code.visualstudio.com/docs/editor/debugging).



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/debugging-vscode>

MemoryUsageDetails Object
=========================


* `count` number
* `size` number
* `liveSize` number



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/memory-usage-details>

Native Node Modules
===================


Native Node.js modules are supported by Electron, but since Electron has a different [application binary interface (ABI)](https://en.wikipedia.org/wiki/Application_binary_interface) from a given Node.js binary (due to differences such as using Chromium's BoringSSL instead of OpenSSL), the native modules you use will need to be recompiled for Electron. Otherwise, you will get the following class of error when you try to run your app:




```
Error: The module '/path/to/native/module.node'
was compiled against a different Node.js version using
NODE_MODULE_VERSION $XYZ. This version of Node.js requires
NODE_MODULE_VERSION $ABC. Please try re-compiling or re-installing
the module (for instance, using `npm rebuild` or `npm install`).
```


How to install native modules[​](#how-to-install-native-modules "Direct link to heading")
-----------------------------------------------------------------------------------------


There are several different ways to install native modules:


### Installing modules and rebuilding for Electron[​](#installing-modules-and-rebuilding-for-electron "Direct link to heading")


You can install modules like other Node projects, and then rebuild the modules for Electron with the [`electron-rebuild`](https://github.com/electron/electron-rebuild) package. This module can automatically determine the version of Electron and handle the manual steps of downloading headers and rebuilding native modules for your app. If you are using [Electron Forge](https://electronforge.io/), this tool is used automatically in both development mode and when making distributables.


For example, to install the standalone `electron-rebuild` tool and then rebuild modules with it via the command line:




```
npm install --save-dev electron-rebuild

# Every time you run "npm install", run this:
./node_modules/.bin/electron-rebuild

# If you have trouble on Windows, try:
.\node_modules\.bin\electron-rebuild.cmd
```


For more information on usage and integration with other tools such as [Electron Packager](https://github.com/electron/electron-packager), consult the project's README.


### Using `npm`[​](#using-npm "Direct link to heading")


By setting a few environment variables, you can use `npm` to install modules directly.


For example, to install all dependencies for Electron:




```
# Electron's version.
export npm_config_target=1.2.3
# The architecture of Electron, see https://electronjs.org/docs/tutorial/support#supported-platforms
# for supported architectures.
export npm_config_arch=x64
export npm_config_target_arch=x64
# Download headers for Electron.
export npm_config_disturl=https://electronjs.org/headers
# Tell node-pre-gyp that we are building for Electron.
export npm_config_runtime=electron
# Tell node-pre-gyp to build module from source code.
export npm_config_build_from_source=true
# Install all dependencies, and store cache to ~/.electron-gyp.
HOME=~/.electron-gyp npm install
```


### Manually building for Electron[​](#manually-building-for-electron "Direct link to heading")


If you are a developer developing a native module and want to test it against Electron, you might want to rebuild the module for Electron manually. You can use `node-gyp` directly to build for Electron:




```
cd /path-to-module/
HOME=~/.electron-gyp node-gyp rebuild --target=1.2.3 --arch=x64 --dist-url=https://electronjs.org/headers
```


* `HOME=~/.electron-gyp` changes where to find development headers.
* `--target=1.2.3` is the version of Electron.
* `--dist-url=...` specifies where to download the headers.
* `--arch=x64` says the module is built for a 64-bit system.


### Manually building for a custom build of Electron[​](#manually-building-for-a-custom-build-of-electron "Direct link to heading")


To compile native Node modules against a custom build of Electron that doesn't match a public release, instruct `npm` to use the version of Node you have bundled with your custom build.




```
npm rebuild --nodedir=/path/to/src/out/Default/gen/node_headers
```


Troubleshooting[​](#troubleshooting "Direct link to heading")
-------------------------------------------------------------


If you installed a native module and found it was not working, you need to check the following things:


* When in doubt, run `electron-rebuild` first.
* Make sure the native module is compatible with the target platform and architecture for your Electron app.
* Make sure `win_delay_load_hook` is not set to `false` in the module's `binding.gyp`.
* After you upgrade Electron, you usually need to rebuild the modules.


### A note about `win_delay_load_hook`[​](#a-note-about-win_delay_load_hook "Direct link to heading")


On Windows, by default, `node-gyp` links native modules against `node.dll`. However, in Electron 4.x and higher, the symbols needed by native modules are exported by `electron.exe`, and there is no `node.dll`. In order to load native modules on Windows, `node-gyp` installs a [delay-load hook](https://msdn.microsoft.com/en-us/library/z9h1h6ty.aspx) that triggers when the native module is loaded, and redirects the `node.dll` reference to use the loading executable instead of looking for `node.dll` in the library search path (which would turn up nothing). As such, on Electron 4.x and higher, `'win_delay_load_hook': 'true'` is required to load native modules.


If you get an error like `Module did not self-register`, or `The specified
procedure could not be found`, it may mean that the module you're trying to use did not correctly include the delay-load hook. If the module is built with node-gyp, ensure that the `win_delay_load_hook` variable is set to `true` in the `binding.gyp` file, and isn't getting overridden anywhere. If the module is built with another system, you'll need to ensure that you build with a delay-load hook installed in the main `.node` file. Your `link.exe` invocation should look like this:




```
 link.exe /OUT:"foo.node" "...\node.lib" delayimp.lib /DELAYLOAD:node.exe /DLL
     "my_addon.obj" "win_delay_load_hook.obj"
```


In particular, it's important that:


* you link against `node.lib` from *Electron* and not Node. If you link against the wrong `node.lib` you will get load-time errors when you require the module in Electron.
* you include the flag `/DELAYLOAD:node.exe`. If the `node.exe` link is not delayed, then the delay-load hook won't get a chance to fire and the node symbols won't be correctly resolved.
* `win_delay_load_hook.obj` is linked directly into the final DLL. If the hook is set up in a dependent DLL, it won't fire at the right time.


See [`node-gyp`](https://github.com/nodejs/node-gyp/blob/e2401e1395bef1d3c8acec268b42dc5fb71c4a38/src/win_delay_load_hook.cc) for an example delay-load hook if you're implementing your own.


Modules that rely on `prebuild`[​](#modules-that-rely-on-prebuild "Direct link to heading")
-------------------------------------------------------------------------------------------


[`prebuild`](https://github.com/prebuild/prebuild) provides a way to publish native Node modules with prebuilt binaries for multiple versions of Node and Electron.


If the `prebuild`-powered module provide binaries for the usage in Electron, make sure to omit `--build-from-source` and the `npm_config_build_from_source` environment variable in order to take full advantage of the prebuilt binaries.


Modules that rely on `node-pre-gyp`[​](#modules-that-rely-on-node-pre-gyp "Direct link to heading")
---------------------------------------------------------------------------------------------------


The [`node-pre-gyp` tool](https://github.com/mapbox/node-pre-gyp) provides a way to deploy native Node modules with prebuilt binaries, and many popular modules are using it.


Sometimes those modules work fine under Electron, but when there are no Electron-specific binaries available, you'll need to build from source. Because of this, it is recommended to use `electron-rebuild` for these modules.


If you are following the `npm` way of installing modules, you'll need to pass `--build-from-source` to `npm`, or set the `npm_config_build_from_source` environment variable.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/using-native-node-modules>

Accessibility
=============


Accessibility concerns in Electron applications are similar to those of websites because they're both ultimately HTML.


Manually enabling accessibility features[​](#manually-enabling-accessibility-features "Direct link to heading")
---------------------------------------------------------------------------------------------------------------


Electron applications will automatically enable accessibility features in the presence of assistive technology (e.g. [JAWS](https://www.freedomscientific.com/products/software/jaws/) on Windows or [VoiceOver](https://help.apple.com/voiceover/mac/10.15/) on macOS). See Chrome's [accessibility documentation](https://www.chromium.org/developers/design-documents/accessibility#TOC-How-Chrome-detects-the-presence-of-Assistive-Technology) for more details.


You can also manually toggle these features either within your Electron application or by setting flags in third-party native software.


### Using Electron's API[​](#using-electrons-api "Direct link to heading")


By using the [`app.setAccessibilitySupportEnabled(enabled)`](../api/app#appsetaccessibilitysupportenabledenabled-macos-windows) API, you can manually expose Chrome's accessibility tree to users in the application preferences. Note that the user's system assistive utilities have priority over this setting and will override it.


### Within third-party software[​](#within-third-party-software "Direct link to heading")


#### macOS[​](#macos "Direct link to heading")


On macOS, third-party assistive technology can toggle accessibility features inside Electron applications by setting the `AXManualAccessibility` attribute programmatically:




```
CFStringRef kAXManualAccessibility = CFSTR("AXManualAccessibility");

+ (void)enableAccessibility:(BOOL)enable inElectronApplication:(NSRunningApplication *)app
{
    AXUIElementRef appRef = AXUIElementCreateApplication(app.processIdentifier);
    if (appRef == nil)
        return;

    CFBooleanRef value = enable ? kCFBooleanTrue : kCFBooleanFalse;
    AXUIElementSetAttributeValue(appRef, kAXManualAccessibility, value);
    CFRelease(appRef);
}
```



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/accessibility>

Distribution Overview
=====================

Once your app is ready for production, there are a couple steps you need to take before you can deliver it to your users.


Packaging[​](#packaging "Direct link to heading")
-------------------------------------------------


To distribute your app with Electron, you need to package all your resources and assets into an executable and rebrand it. To do this, you can either use specialized tooling or do it manually. See the [Application Packaging](application-distribution) tutorial for more information.


Code signing[​](#code-signing "Direct link to heading")
-------------------------------------------------------


Code signing is a security technology that you use to certify that an app was created by you. You should sign your application so it does not trigger the security checks of your user's operating system.


To get started with each operating system's code signing process, please read the [Code Signing](code-signing) docs.


Publishing[​](#publishing "Direct link to heading")
---------------------------------------------------


Once your app is packaged and signed, you can freely distribute your app directly to users by uploading your installers online.


To reach more users, you can also choose to upload your app to each operating system's digital distribution platform (i.e. app store). These require another build step aside from your direct download app. For more information, check out each individual app store guide:


* [Mac App Store](mac-app-store-submission-guide)
* [Windows Store](windows-store-guide)
* [Snapcraft (Linux)](snapcraft)


Updating[​](#updating "Direct link to heading")
-----------------------------------------------


Electron's auto-updater allows you to deliver application updates to users without forcing them to manually download new versions of your application. Check out the [Updating Applications](updates) guide for details on implementing automatic updates with Electron.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/distribution-overview>

Accelerator
===========



> Define keyboard shortcuts.
> 
> 


Accelerators are strings that can contain multiple modifiers and a single key code, combined by the `+` character, and are used to define keyboard shortcuts throughout your application.


Examples:


* `CommandOrControl+A`
* `CommandOrControl+Shift+Z`


Shortcuts are registered with the [`globalShortcut`](global-shortcut) module using the [`register`](global-shortcut#globalshortcutregisteraccelerator-callback) method, i.e.




```
const { app, globalShortcut } = require('electron')

app.whenReady().then(() => {
  // Register a 'CommandOrControl+Y' shortcut listener.
  globalShortcut.register('CommandOrControl+Y', () => {
    // Do stuff when Y and either Command/Control is pressed.
  })
})
```


Platform notice[​](#platform-notice "Direct link to heading")
-------------------------------------------------------------


On Linux and Windows, the `Command` key does not have any effect so use `CommandOrControl` which represents `Command` on macOS and `Control` on Linux and Windows to define some accelerators.


Use `Alt` instead of `Option`. The `Option` key only exists on macOS, whereas the `Alt` key is available on all platforms.


The `Super` (or `Meta`) key is mapped to the `Windows` key on Windows and Linux and `Cmd` on macOS.


Available modifiers[​](#available-modifiers "Direct link to heading")
---------------------------------------------------------------------


* `Command` (or `Cmd` for short)
* `Control` (or `Ctrl` for short)
* `CommandOrControl` (or `CmdOrCtrl` for short)
* `Alt`
* `Option`
* `AltGr`
* `Shift`
* `Super`
* `Meta`


Available key codes[​](#available-key-codes "Direct link to heading")
---------------------------------------------------------------------


* `0` to `9`
* `A` to `Z`
* `F1` to `F24`
* Punctuation like `~`, `!`, `@`, `#`, `$`, etc.
* `Plus`
* `Space`
* `Tab`
* `Capslock`
* `Numlock`
* `Scrolllock`
* `Backspace`
* `Delete`
* `Insert`
* `Return` (or `Enter` as alias)
* `Up`, `Down`, `Left` and `Right`
* `Home` and `End`
* `PageUp` and `PageDown`
* `Escape` (or `Esc` for short)
* `VolumeUp`, `VolumeDown` and `VolumeMute`
* `MediaNextTrack`, `MediaPreviousTrack`, `MediaStop` and `MediaPlayPause`
* `PrintScreen`
* NumPad Keys
	+ `num0` - `num9`
	+ `numdec` - decimal key
	+ `numadd` - numpad `+` key
	+ `numsub` - numpad `-` key
	+ `nummult` - numpad `*` key
	+ `numdiv` - numpad `÷` key



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/accelerator>

Testing Widevine CDM
====================


In Electron you can use the Widevine CDM library shipped with Chrome browser.


Widevine Content Decryption Modules (CDMs) are how streaming services protect content using HTML5 video to web browsers without relying on an NPAPI plugin like Flash or Silverlight. Widevine support is an alternative solution for streaming services that currently rely on Silverlight for playback of DRM-protected video content. It will allow websites to show DRM-protected video content in Firefox without the use of NPAPI plugins. The Widevine CDM runs in an open-source CDM sandbox providing better user security than NPAPI plugins.


#### Note on VMP[​](#note-on-vmp "Direct link to heading")


As of [`Electron v1.8.0 (Chrome v59)`](https://electronjs.org/releases#1.8.1), the below steps are may only be some of the necessary steps to enable Widevine; any app on or after that version intending to use the Widevine CDM may need to be signed using a license obtained from [Widevine](https://www.widevine.com/) itself.


Per [Widevine](https://www.widevine.com/):



> 
> Chrome 59 (and later) includes support for Verified Media Path (VMP). VMP provides a method to verify the authenticity of a device platform. For browser deployments, this will provide an additional signal to determine if a browser-based implementation is reliable and secure.
> 
> 
> The proxy integration guide has been updated with information about VMP and how to issue licenses.
> 
> 
> Widevine recommends our browser-based integrations (vendors and browser-based applications) add support for VMP.
> 
> 
> 


To enable video playback with this new restriction, [castLabs](https://castlabs.com/open-source/downstream/) has created a [fork](https://github.com/castlabs/electron-releases) that has implemented the necessary changes to enable Widevine to be played in an Electron application if one has obtained the necessary licenses from widevine.


Getting the library[​](#getting-the-library "Direct link to heading")
---------------------------------------------------------------------


Open `chrome://components/` in Chrome browser, find `Widevine Content Decryption Module` and make sure it is up to date, then you can find the library files from the application directory.


### On Windows[​](#on-windows "Direct link to heading")


The library file `widevinecdm.dll` will be under `Program Files(x86)/Google/Chrome/Application/CHROME_VERSION/WidevineCdm/_platform_specific/win_(x86|x64)/` directory.


### On macOS[​](#on-macos "Direct link to heading")


The library file `libwidevinecdm.dylib` will be under `/Applications/Google Chrome.app/Contents/Versions/CHROME_VERSION/Google Chrome Framework.framework/Versions/A/Libraries/WidevineCdm/_platform_specific/mac_(x86|x64)/` directory.


**Note:** Make sure that chrome version used by Electron is greater than or equal to the `min_chrome_version` value of Chrome's widevine cdm component. The value can be found in `manifest.json` under `WidevineCdm` directory.


Using the library[​](#using-the-library "Direct link to heading")
-----------------------------------------------------------------


After getting the library files, you should pass the path to the file with `--widevine-cdm-path` command line switch, and the library's version with `--widevine-cdm-version` switch. The command line switches have to be passed before the `ready` event of `app` module gets emitted.


Example code:




```
const { app, BrowserWindow } = require('electron')

// You have to pass the directory that contains widevine library here, it is
// * `libwidevinecdm.dylib` on macOS,
// * `widevinecdm.dll` on Windows.
app.commandLine.appendSwitch('widevine-cdm-path', '/path/to/widevine_library')
// The version of plugin can be got from `chrome://components` page in Chrome.
app.commandLine.appendSwitch('widevine-cdm-version', '1.4.8.866')

let win = null
app.whenReady().then(() => {
  win = new BrowserWindow()
  win.show()
})
```


Verifying Widevine CDM support[​](#verifying-widevine-cdm-support "Direct link to heading")
-------------------------------------------------------------------------------------------


To verify whether widevine works, you can use following ways:


* Open <https://shaka-player-demo.appspot.com/> and load a manifest that uses `Widevine`.
* Open <http://www.dash-player.com/demo/drm-test-area/>, check whether the page says `bitdash uses Widevine in your browser`, then play the video.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/testing-widevine-cdm>

IpcMainEvent Object extends `Event`
===================================


* `processId` Integer - The internal ID of the renderer process that sent this message
* `frameId` Integer - The ID of the renderer frame that sent this message
* `returnValue` any - Set this to the value to be returned in a synchronous message
* `sender` WebContents - Returns the `webContents` that sent the message
* `senderFrame` WebFrameMain *Readonly* - The frame that sent this message
* `ports` MessagePortMain[] - A list of MessagePorts that were transferred with this message
* `reply` Function - A function that will send an IPC message to the renderer frame that sent the original message that you are currently handling. You should use this method to "reply" to the sent message in order to guarantee the reply will go to the correct process and frame.
	+ `channel` string
	+ `...args` any[]



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/ipc-main-event>

ScrubberItem Object
===================


* `label` string (optional) - The text to appear in this item.
* `icon` NativeImage (optional) - The image to appear in this item.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/scrubber-item>

UserDefaultTypes Object
=======================


* `string` string
* `boolean` boolean
* `integer` number
* `float` number
* `double` number
* `url` string
* `array` Array\<unknown>
* `dictionary` Record\<string, unknown>


This type is a helper alias, no object will never exist of this type.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/user-default-types>

WebSource Object
================


* `code` string
* `url` string (optional)



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/web-source>

SharedWorkerInfo Object
=======================


* `id` string - The unique id of the shared worker.
* `url` string - The url of the shared worker.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/shared-worker-info>

Class: IncomingMessage
======================

Class: IncomingMessage[​](#class-incomingmessage "Direct link to heading")
--------------------------------------------------------------------------



> Handle responses to HTTP/HTTPS requests.
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


`IncomingMessage` implements the [Readable Stream](https://nodejs.org/api/stream.html#stream_readable_streams) interface and is therefore an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter).


### Instance Events[​](#instance-events "Direct link to heading")


#### Event: 'data'[​](#event-data "Direct link to heading")


Returns:


* `chunk` Buffer - A chunk of response body's data.


The `data` event is the usual method of transferring response data into applicative code.


#### Event: 'end'[​](#event-end "Direct link to heading")


Indicates that response body has ended. Must be placed before 'data' event.


#### Event: 'aborted'[​](#event-aborted "Direct link to heading")


Emitted when a request has been canceled during an ongoing HTTP transaction.


#### Event: 'error'[​](#event-error "Direct link to heading")


Returns:


`error` Error - Typically holds an error string identifying failure root cause.


Emitted when an error was encountered while streaming response data events. For instance, if the server closes the underlying while the response is still streaming, an `error` event will be emitted on the response object and a `close` event will subsequently follow on the request object.


### Instance Properties[​](#instance-properties "Direct link to heading")


An `IncomingMessage` instance has the following readable properties:


#### 
`response.statusCode`[​](#responsestatuscode "Direct link to heading")


An `Integer` indicating the HTTP response status code.


#### 
`response.statusMessage`[​](#responsestatusmessage "Direct link to heading")


A `string` representing the HTTP status message.


#### 
`response.headers`[​](#responseheaders "Direct link to heading")


A `Record<string, string | string[]>` representing the HTTP response headers. The `headers` object is formatted as follows:


* All header names are lowercased.
* Duplicates of `age`, `authorization`, `content-length`, `content-type`, `etag`, `expires`, `from`, `host`, `if-modified-since`, `if-unmodified-since`, `last-modified`, `location`, `max-forwards`, `proxy-authorization`, `referer`, `retry-after`, `server`, or `user-agent` are discarded.
* `set-cookie` is always an array. Duplicates are added to the array.
* For duplicate `cookie` headers, the values are joined together with '; '.
* For all other headers, the values are joined together with ', '.


#### 
`response.httpVersion`[​](#responsehttpversion "Direct link to heading")


A `string` indicating the HTTP protocol version number. Typical values are '1.0' or '1.1'. Additionally `httpVersionMajor` and `httpVersionMinor` are two Integer-valued readable properties that return respectively the HTTP major and minor version numbers.


#### 
`response.httpVersionMajor`[​](#responsehttpversionmajor "Direct link to heading")


An `Integer` indicating the HTTP protocol major version number.


#### 
`response.httpVersionMinor`[​](#responsehttpversionminor "Direct link to heading")


An `Integer` indicating the HTTP protocol minor version number.


#### 
`response.rawHeaders`[​](#responserawheaders "Direct link to heading")


A `string[]` containing the raw HTTP response headers exactly as they were received. The keys and values are in the same list. It is not a list of tuples. So, the even-numbered offsets are key values, and the odd-numbered offsets are the associated values. Header names are not lowercased, and duplicates are not merged.




```
// Prints something like:
//
// [ 'user-agent',
//   'this is invalid because there can be only one',
//   'User-Agent',
//   'curl/7.22.0',
//   'Host',
//   '127.0.0.1:8000',
//   'ACCEPT',
//   '*/*' ]
console.log(request.rawHeaders)
```



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/incoming-message>

net
===



> Issue HTTP/HTTPS requests using Chromium's native networking library
> 
> 


Process: [Main](../glossary#main-process)


The `net` module is a client-side API for issuing HTTP(S) requests. It is similar to the [HTTP](https://nodejs.org/api/http.html) and [HTTPS](https://nodejs.org/api/https.html) modules of Node.js but uses Chromium's native networking library instead of the Node.js implementation, offering better support for web proxies. It also supports checking network status.


The following is a non-exhaustive list of why you may consider using the `net` module instead of the native Node.js modules:


* Automatic management of system proxy configuration, support of the wpad protocol and proxy pac configuration files.
* Automatic tunneling of HTTPS requests.
* Support for authenticating proxies using basic, digest, NTLM, Kerberos or negotiate authentication schemes.
* Support for traffic monitoring proxies: Fiddler-like proxies used for access control and monitoring.


The API components (including classes, methods, properties and event names) are similar to those used in Node.js.


Example usage:




```
const { app } = require('electron')
app.whenReady().then(() => {
  const { net } = require('electron')
  const request = net.request('https://github.com')
  request.on('response', (response) => {
    console.log(`STATUS: ${response.statusCode}`)
    console.log(`HEADERS: ${JSON.stringify(response.headers)}`)
    response.on('data', (chunk) => {
      console.log(`BODY: ${chunk}`)
    })
    response.on('end', () => {
      console.log('No more data in response.')
    })
  })
  request.end()
})
```


The `net` API can be used only after the application emits the `ready` event. Trying to use the module before the `ready` event will throw an error.


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `net` module has the following methods:


### 
`net.request(options)`[​](#netrequestoptions "Direct link to heading")


* `options` (ClientRequestConstructorOptions | string) - The `ClientRequest` constructor options.


Returns [`ClientRequest`](client-request)


Creates a [`ClientRequest`](client-request) instance using the provided `options` which are directly forwarded to the `ClientRequest` constructor. The `net.request` method would be used to issue both secure and insecure HTTP requests according to the specified protocol scheme in the `options` object.


### 
`net.isOnline()`[​](#netisonline "Direct link to heading")


Returns `boolean` - Whether there is currently internet connection.


A return value of `false` is a pretty strong indicator that the user won't be able to connect to remote sites. However, a return value of `true` is inconclusive; even if some link is up, it is uncertain whether a particular connection attempt to a particular remote site will be successful.


Properties[​](#properties "Direct link to heading")
---------------------------------------------------


### 
`net.online` *Readonly*[​](#netonline-readonly "Direct link to heading")


A `boolean` property. Whether there is currently internet connection.


A return value of `false` is a pretty strong indicator that the user won't be able to connect to remote sites. However, a return value of `true` is inconclusive; even if some link is up, it is uncertain whether a particular connection attempt to a particular remote site will be successful.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/net>

Online/Offline Event Detection
==============================


Overview[​](#overview "Direct link to heading")
-----------------------------------------------


[Online and offline event](https://developer.mozilla.org/en-US/docs/Online_and_offline_events) detection can be implemented in the Renderer process using the [`navigator.onLine`](http://html5index.org/Offline%20-%20NavigatorOnLine.html) attribute, part of standard HTML5 API.


The `navigator.onLine` attribute returns:


* `false` if all network requests are guaranteed to fail (e.g. when disconnected from the network).
* `true` in all other cases.


Since many cases return `true`, you should treat with care situations of getting false positives, as we cannot always assume that `true` value means that Electron can access the Internet. For example, in cases when the computer is running a virtualization software that has virtual Ethernet adapters in "always connected" state. Therefore, if you want to determine the Internet access status of Electron, you should develop additional means for this check.


Example[​](#example "Direct link to heading")
---------------------------------------------


Starting with an HTML file `index.html`, this example will demonstrate how the `navigator.onLine` API can be used to build a connection status indicator.



index.html


```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
    <h1>Connection status: <strong id='status'></strong></h1>
    <script src="renderer.js"></script>
</body>
</html>
```



In order to mutate the DOM, create a `renderer.js` file that adds event listeners to the `'online'` and `'offline'` `window` events. The event handler sets the content of the `<strong id='status'>` element depending on the result of `navigator.onLine`.



renderer.js


```
const updateOnlineStatus = () => {
  document.getElementById('status').innerHTML = navigator.onLine ? 'online' : 'offline'
}

window.addEventListener('online', updateOnlineStatus)
window.addEventListener('offline', updateOnlineStatus)

updateOnlineStatus()
```



Finally, create a `main.js` file for main process that creates the window.



main.js


```
const { app, BrowserWindow } = require('electron')

const createWindow = () => {
  const onlineStatusWindow = new BrowserWindow({
    width: 400,
    height: 100
  })

  onlineStatusWindow.loadFile('index.html')
}

app.whenReady().then(() => {
  createWindow()

  app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
      createWindow()
    }
  })
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})
```



After launching the Electron application, you should see the notification:


![Connection status]



> Note: If you need to communicate the connection status to the main process, use the [IPC renderer](../api/ipc-renderer) API.
> 
> 



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/online-offline-events>

Tray
====


Class: Tray[​](#class-tray "Direct link to heading")
----------------------------------------------------



> Add icons and context menus to the system's notification area.
> 
> 


Process: [Main](../glossary#main-process)


`Tray` is an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter).




```
const { app, Menu, Tray } = require('electron')

let tray = null
app.whenReady().then(() => {
  tray = new Tray('/path/to/my/icon')
  const contextMenu = Menu.buildFromTemplate([
    { label: 'Item1', type: 'radio' },
    { label: 'Item2', type: 'radio' },
    { label: 'Item3', type: 'radio', checked: true },
    { label: 'Item4', type: 'radio' }
  ])
  tray.setToolTip('This is my application.')
  tray.setContextMenu(contextMenu)
})
```


**Platform Considerations**


If you want to keep exact same behaviors on all platforms, you should not rely on the `click` event; instead, always attach a context menu to the tray icon.


**Linux**


* On Linux distributions that only have app indicator support, you have to install `libappindicator1` to make the tray icon work.
* The app indicator will be used if it is supported, otherwise `GtkStatusIcon` will be used instead.
* App indicator will only be shown when it has a context menu.
* The `click` event is ignored when using the app indicator.
* In order for changes made to individual `MenuItem`s to take effect, you have to call `setContextMenu` again. For example:




```
const { app, Menu, Tray } = require('electron')

let appIcon = null
app.whenReady().then(() => {
  appIcon = new Tray('/path/to/my/icon')
  const contextMenu = Menu.buildFromTemplate([
    { label: 'Item1', type: 'radio' },
    { label: 'Item2', type: 'radio' }
  ])

  // Make a change to the context menu
  contextMenu.items[1].checked = false

  // Call this again for Linux because we modified the context menu
  appIcon.setContextMenu(contextMenu)
})
```


**MacOS**


* Icons passed to the Tray constructor should be [Template Images](native-image#template-image).
* To make sure your icon isn't grainy on retina monitors, be sure your `@2x` image is 144dpi.
* If you are bundling your application (e.g., with webpack for development), be sure that the file names are not being mangled or hashed. The filename needs to end in Template, and the `@2x` image needs to have the same filename as the standard image, or MacOS will not magically invert your image's colors or use the high density image.
* 16x16 (72dpi) and 32x32@2x (144dpi) work well for most icons.


**Windows**


* It is recommended to use `ICO` icons to get best visual effects.


### 
`new Tray(image, [guid])`[​](#new-trayimage-guid "Direct link to heading")


* `image` ([NativeImage](native-image) | string)
* `guid` string (optional) *Windows* - Assigns a GUID to the tray icon. If the executable is signed and the signature contains an organization in the subject line then the GUID is permanently associated with that signature. OS level settings like the position of the tray icon in the system tray will persist even if the path to the executable changes. If the executable is not code-signed then the GUID is permanently associated with the path to the executable. Changing the path to the executable will break the creation of the tray icon and a new GUID must be used. However, it is highly recommended to use the GUID parameter only in conjunction with code-signed executable. If an App defines multiple tray icons then each icon must use a separate GUID.


Creates a new tray icon associated with the `image`.


### Instance Events[​](#instance-events "Direct link to heading")


The `Tray` module emits the following events:


#### Event: 'click'[​](#event-click "Direct link to heading")


Returns:


* `event` [KeyboardEvent](structures/keyboard-event)
* `bounds` [Rectangle](structures/rectangle) - The bounds of tray icon.
* `position` [Point](structures/point) - The position of the event.


Emitted when the tray icon is clicked.


#### Event: 'right-click' *macOS* *Windows*[​](#event-right-click-macos-windows "Direct link to heading")


Returns:


* `event` [KeyboardEvent](structures/keyboard-event)
* `bounds` [Rectangle](structures/rectangle) - The bounds of tray icon.


Emitted when the tray icon is right clicked.


#### Event: 'double-click' *macOS* *Windows*[​](#event-double-click-macos-windows "Direct link to heading")


Returns:


* `event` [KeyboardEvent](structures/keyboard-event)
* `bounds` [Rectangle](structures/rectangle) - The bounds of tray icon.


Emitted when the tray icon is double clicked.


#### Event: 'balloon-show' *Windows*[​](#event-balloon-show-windows "Direct link to heading")


Emitted when the tray balloon shows.


#### Event: 'balloon-click' *Windows*[​](#event-balloon-click-windows "Direct link to heading")


Emitted when the tray balloon is clicked.


#### Event: 'balloon-closed' *Windows*[​](#event-balloon-closed-windows "Direct link to heading")


Emitted when the tray balloon is closed because of timeout or user manually closes it.


#### Event: 'drop' *macOS*[​](#event-drop-macos "Direct link to heading")


Emitted when any dragged items are dropped on the tray icon.


#### Event: 'drop-files' *macOS*[​](#event-drop-files-macos "Direct link to heading")


Returns:


* `event` Event
* `files` string[] - The paths of the dropped files.


Emitted when dragged files are dropped in the tray icon.


#### Event: 'drop-text' *macOS*[​](#event-drop-text-macos "Direct link to heading")


Returns:


* `event` Event
* `text` string - the dropped text string.


Emitted when dragged text is dropped in the tray icon.


#### Event: 'drag-enter' *macOS*[​](#event-drag-enter-macos "Direct link to heading")


Emitted when a drag operation enters the tray icon.


#### Event: 'drag-leave' *macOS*[​](#event-drag-leave-macos "Direct link to heading")


Emitted when a drag operation exits the tray icon.


#### Event: 'drag-end' *macOS*[​](#event-drag-end-macos "Direct link to heading")


Emitted when a drag operation ends on the tray or ends at another location.


#### Event: 'mouse-up' *macOS*[​](#event-mouse-up-macos "Direct link to heading")


Returns:


* `event` [KeyboardEvent](structures/keyboard-event)
* `position` [Point](structures/point) - The position of the event.


Emitted when the mouse is released from clicking the tray icon.


Note: This will not be emitted if you have set a context menu for your Tray using `tray.setContextMenu`, as a result of macOS-level constraints.


#### Event: 'mouse-down' *macOS*[​](#event-mouse-down-macos "Direct link to heading")


Returns:


* `event` [KeyboardEvent](structures/keyboard-event)
* `position` [Point](structures/point) - The position of the event.


Emitted when the mouse clicks the tray icon.


#### Event: 'mouse-enter' *macOS*[​](#event-mouse-enter-macos "Direct link to heading")


Returns:


* `event` [KeyboardEvent](structures/keyboard-event)
* `position` [Point](structures/point) - The position of the event.


Emitted when the mouse enters the tray icon.


#### Event: 'mouse-leave' *macOS*[​](#event-mouse-leave-macos "Direct link to heading")


Returns:


* `event` [KeyboardEvent](structures/keyboard-event)
* `position` [Point](structures/point) - The position of the event.


Emitted when the mouse exits the tray icon.


#### Event: 'mouse-move' *macOS* *Windows*[​](#event-mouse-move-macos-windows "Direct link to heading")


Returns:


* `event` [KeyboardEvent](structures/keyboard-event)
* `position` [Point](structures/point) - The position of the event.


Emitted when the mouse moves in the tray icon.


### Instance Methods[​](#instance-methods "Direct link to heading")


The `Tray` class has the following methods:


#### 
`tray.destroy()`[​](#traydestroy "Direct link to heading")


Destroys the tray icon immediately.


#### 
`tray.setImage(image)`[​](#traysetimageimage "Direct link to heading")


* `image` ([NativeImage](native-image) | string)


Sets the `image` associated with this tray icon.


#### 
`tray.setPressedImage(image)` *macOS*[​](#traysetpressedimageimage-macos "Direct link to heading")


* `image` ([NativeImage](native-image) | string)


Sets the `image` associated with this tray icon when pressed on macOS.


#### 
`tray.setToolTip(toolTip)`[​](#traysettooltiptooltip "Direct link to heading")


* `toolTip` string


Sets the hover text for this tray icon.


#### 
`tray.setTitle(title[, options])` *macOS*[​](#traysettitletitle-options-macos "Direct link to heading")


* `title` string
* `options` Object (optional)
	+ `fontType` string (optional) - The font family variant to display, can be `monospaced` or `monospacedDigit`. `monospaced` is available in macOS 10.15+ and `monospacedDigit` is available in macOS 10.11+. When left blank, the title uses the default system font.


Sets the title displayed next to the tray icon in the status bar (Support ANSI colors).


#### 
`tray.getTitle()` *macOS*[​](#traygettitle-macos "Direct link to heading")


Returns `string` - the title displayed next to the tray icon in the status bar


#### 
`tray.setIgnoreDoubleClickEvents(ignore)` *macOS*[​](#traysetignoredoubleclickeventsignore-macos "Direct link to heading")


* `ignore` boolean


Sets the option to ignore double click events. Ignoring these events allows you to detect every individual click of the tray icon.


This value is set to false by default.


#### 
`tray.getIgnoreDoubleClickEvents()` *macOS*[​](#traygetignoredoubleclickevents-macos "Direct link to heading")


Returns `boolean` - Whether double click events will be ignored.


#### 
`tray.displayBalloon(options)` *Windows*[​](#traydisplayballoonoptions-windows "Direct link to heading")


* `options` Object
	+ `icon` ([NativeImage](native-image) | string) (optional) - Icon to use when `iconType` is `custom`.
	+ `iconType` string (optional) - Can be `none`, `info`, `warning`, `error` or `custom`. Default is `custom`.
	+ `title` string
	+ `content` string
	+ `largeIcon` boolean (optional) - The large version of the icon should be used. Default is `true`. Maps to [`NIIF_LARGE_ICON`](https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataa#niif_large_icon-0x00000020).
	+ `noSound` boolean (optional) - Do not play the associated sound. Default is `false`. Maps to [`NIIF_NOSOUND`](https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataa#niif_nosound-0x00000010).
	+ `respectQuietTime` boolean (optional) - Do not display the balloon notification if the current user is in "quiet time". Default is `false`. Maps to [`NIIF_RESPECT_QUIET_TIME`](https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataa#niif_respect_quiet_time-0x00000080).


Displays a tray balloon.


#### 
`tray.removeBalloon()` *Windows*[​](#trayremoveballoon-windows "Direct link to heading")


Removes a tray balloon.


#### 
`tray.focus()` *Windows*[​](#trayfocus-windows "Direct link to heading")


Returns focus to the taskbar notification area. Notification area icons should use this message when they have completed their UI operation. For example, if the icon displays a shortcut menu, but the user presses ESC to cancel it, use `tray.focus()` to return focus to the notification area.


#### 
`tray.popUpContextMenu([menu, position])` *macOS* *Windows*[​](#traypopupcontextmenumenu-position-macos-windows "Direct link to heading")


* `menu` Menu (optional)
* `position` [Point](structures/point) (optional) - The pop up position.


Pops up the context menu of the tray icon. When `menu` is passed, the `menu` will be shown instead of the tray icon's context menu.


The `position` is only available on Windows, and it is (0, 0) by default.


#### 
`tray.closeContextMenu()` *macOS* *Windows*[​](#trayclosecontextmenu-macos-windows "Direct link to heading")


Closes an open context menu, as set by `tray.setContextMenu()`.


#### 
`tray.setContextMenu(menu)`[​](#traysetcontextmenumenu "Direct link to heading")


* `menu` Menu | null


Sets the context menu for this icon.


#### 
`tray.getBounds()` *macOS* *Windows*[​](#traygetbounds-macos-windows "Direct link to heading")


Returns [Rectangle](structures/rectangle)


The `bounds` of this tray icon as `Object`.


#### 
`tray.isDestroyed()`[​](#trayisdestroyed "Direct link to heading")


Returns `boolean` - Whether the tray icon is destroyed.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/tray>

IpcMainInvokeEvent Object extends `Event`
=========================================


* `processId` Integer - The internal ID of the renderer process that sent this message
* `frameId` Integer - The ID of the renderer frame that sent this message
* `sender` WebContents - Returns the `webContents` that sent the message
* `senderFrame` WebFrameMain *Readonly* - The frame that sent this message



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/ipc-main-invoke-event>

inAppPurchase
=============



> In-app purchases on Mac App Store.
> 
> 


Process: [Main](../glossary#main-process)


Events[​](#events "Direct link to heading")
-------------------------------------------


The `inAppPurchase` module emits the following events:


### Event: 'transactions-updated'[​](#event-transactions-updated "Direct link to heading")


Emitted when one or more transactions have been updated.


Returns:


* `event` Event
* `transactions` Transaction[] - Array of [Transaction](structures/transaction) objects.


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `inAppPurchase` module has the following methods:


### 
`inAppPurchase.purchaseProduct(productID[, quantity])`[​](#inapppurchasepurchaseproductproductid-quantity "Direct link to heading")


* `productID` string - The identifiers of the product to purchase. (The identifier of `com.example.app.product1` is `product1`).
* `quantity` Integer (optional) - The number of items the user wants to purchase.


Returns `Promise<boolean>` - Returns `true` if the product is valid and added to the payment queue.


You should listen for the `transactions-updated` event as soon as possible and certainly before you call `purchaseProduct`.


### 
`inAppPurchase.getProducts(productIDs)`[​](#inapppurchasegetproductsproductids "Direct link to heading")


* `productIDs` string[] - The identifiers of the products to get.


Returns `Promise<Product[]>` - Resolves with an array of [Product](structures/product) objects.


Retrieves the product descriptions.


### 
`inAppPurchase.canMakePayments()`[​](#inapppurchasecanmakepayments "Direct link to heading")


Returns `boolean` - whether a user can make a payment.


### 
`inAppPurchase.restoreCompletedTransactions()`[​](#inapppurchaserestorecompletedtransactions "Direct link to heading")


Restores finished transactions. This method can be called either to install purchases on additional devices, or to restore purchases for an application that the user deleted and reinstalled.


[The payment queue](https://developer.apple.com/documentation/storekit/skpaymentqueue?language=objc) delivers a new transaction for each previously completed transaction that can be restored. Each transaction includes a copy of the original transaction.


### 
`inAppPurchase.getReceiptURL()`[​](#inapppurchasegetreceipturl "Direct link to heading")


Returns `string` - the path to the receipt.


### 
`inAppPurchase.finishAllTransactions()`[​](#inapppurchasefinishalltransactions "Direct link to heading")


Completes all pending transactions.


### 
`inAppPurchase.finishTransactionByDate(date)`[​](#inapppurchasefinishtransactionbydatedate "Direct link to heading")


* `date` string - The ISO formatted date of the transaction to finish.


Completes the pending transactions corresponding to the date.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/in-app-purchase>

Notifications
=============


Overview[​](#overview "Direct link to heading")
-----------------------------------------------


All three operating systems provide means for applications to send notifications to the user. The technique of showing notifications is different for the Main and Renderer processes.


For the Renderer process, Electron conveniently allows developers to send notifications with the [HTML5 Notification API](https://notifications.spec.whatwg.org/), using the currently running operating system's native notification APIs to display it.


To show notifications in the Main process, you need to use the [Notification](../api/notification) module.


Example[​](#example "Direct link to heading")
---------------------------------------------


### Show notifications in the Renderer process[​](#show-notifications-in-the-renderer-process "Direct link to heading")


Starting with a working application from the [Quick Start Guide](quick-start), add the following line to the `index.html` file before the closing `</body>` tag:




```
<script src="renderer.js"></script>
```


...and add the `renderer.js` file:




[docs/fiddles/features/notifications/renderer (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/features/notifications/renderer)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/features/notifications/renderer)


* main.js
* index.html
* renderer.js





```
const { app, BrowserWindow } = require('electron')

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600
  })

  win.loadFile('index.html')
}

app.whenReady().then(createWindow)

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})
```




```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
    <h1>Hello World!</h1>
    <p>After launching this application, you should see the system notification.</p>
    <p id="output">Click it to see the effect in this interface.</p>

    <script src="renderer.js"></script>
</body>
</html>
```




```
const NOTIFICATION_TITLE = 'Title'
const NOTIFICATION_BODY = 'Notification from the Renderer process. Click to log to console.'
const CLICK_MESSAGE = 'Notification clicked!'

new Notification(NOTIFICATION_TITLE, { body: NOTIFICATION_BODY })
  .onclick = () => document.getElementById("output").innerText = CLICK_MESSAGE
```





After launching the Electron application, you should see the notification:


![Notification in the Renderer process]


Additionally, if you click on the notification, the DOM will update to show "Notification clicked!".


### Show notifications in the Main process[​](#show-notifications-in-the-main-process "Direct link to heading")


Starting with a working application from the [Quick Start Guide](quick-start), update the `main.js` file with the following lines:




[docs/fiddles/features/notifications/main (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/features/notifications/main)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/features/notifications/main)


* main.js
* index.html





```
const { app, BrowserWindow, Notification } = require('electron')

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600
  })

  win.loadFile('index.html')
}

const NOTIFICATION_TITLE = 'Basic Notification'
const NOTIFICATION_BODY = 'Notification from the Main process'

function showNotification () {
  new Notification({ title: NOTIFICATION_TITLE, body: NOTIFICATION_BODY }).show()
}

app.whenReady().then(createWindow).then(showNotification)

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})
```




```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
    <h1>Hello World!</h1>
    <p>After launching this application, you should see the system notification.</p>
</body>
</html>
```





After launching the Electron application, you should see the system notification:


![Notification in the Main process]


Additional information[​](#additional-information "Direct link to heading")
---------------------------------------------------------------------------


While code and user experience across operating systems are similar, there are subtle differences.


### Windows[​](#windows "Direct link to heading")


* On Windows 10, a shortcut to your app with an [Application User Model ID](https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx) must be installed to the Start Menu. This can be overkill during development, so adding `node_modules\electron\dist\electron.exe` to your Start Menu also does the trick. Navigate to the file in Explorer, right-click and 'Pin to Start Menu'. You will then need to add the line `app.setAppUserModelId(process.execPath)` to your main process to see notifications.
* On Windows 8.1 and Windows 8, a shortcut to your app with an [Application User Model ID](https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx) must be installed to the Start screen. Note, however, that it does not need to be pinned to the Start screen.
* On Windows 7, notifications work via a custom implementation which visually resembles the native one on newer systems.


Electron attempts to automate the work around the Application User Model ID. When Electron is used together with the installation and update framework Squirrel, [shortcuts will automatically be set correctly](https://github.com/electron/windows-installer/blob/master/README.md#handling-squirrel-events). Furthermore, Electron will detect that Squirrel was used and will automatically call `app.setAppUserModelId()` with the correct value. During development, you may have to call [`app.setAppUserModelId()`](../api/app#appsetappusermodelidid-windows) yourself.


Furthermore, in Windows 8, the maximum length for the notification body is 250 characters, with the Windows team recommending that notifications should be kept to 200 characters. That said, that limitation has been removed in Windows 10, with the Windows team asking developers to be reasonable. Attempting to send gigantic amounts of text to the API (thousands of characters) might result in instability.


#### Advanced Notifications[​](#advanced-notifications "Direct link to heading")


Later versions of Windows allow for advanced notifications, with custom templates, images, and other flexible elements. To send those notifications (from either the main process or the renderer process), use the userland module [electron-windows-notifications](https://github.com/felixrieseberg/electron-windows-notifications), which uses native Node addons to send `ToastNotification` and `TileNotification` objects.


While notifications including buttons work with `electron-windows-notifications`, handling replies requires the use of [`electron-windows-interactive-notifications`](https://github.com/felixrieseberg/electron-windows-interactive-notifications), which helps with registering the required COM components and calling your Electron app with the entered user data.


#### Quiet Hours / Presentation Mode[​](#quiet-hours--presentation-mode "Direct link to heading")


To detect whether or not you're allowed to send a notification, use the userland module [electron-notification-state](https://github.com/felixrieseberg/electron-notification-state).


This allows you to determine ahead of time whether or not Windows will silently throw the notification away.


### macOS[​](#macos "Direct link to heading")


Notifications are straight-forward on macOS, but you should be aware of [Apple's Human Interface guidelines regarding notifications](https://developer.apple.com/macos/human-interface-guidelines/system-capabilities/notifications/).


Note that notifications are limited to 256 bytes in size and will be truncated if you exceed that limit.


#### Do not disturb / Session State[​](#do-not-disturb--session-state "Direct link to heading")


To detect whether or not you're allowed to send a notification, use the userland module [electron-notification-state](https://github.com/felixrieseberg/electron-notification-state).


This will allow you to detect ahead of time whether or not the notification will be displayed.


### Linux[​](#linux "Direct link to heading")


Notifications are sent using `libnotify` which can show notifications on any desktop environment that follows [Desktop Notifications Specification](https://developer-old.gnome.org/notification-spec/), including Cinnamon, Enlightenment, Unity, GNOME, KDE.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/notifications>

IOCounters Object
=================


* `readOperationCount` number - The number of I/O read operations.
* `writeOperationCount` number - The number of I/O write operations.
* `otherOperationCount` number - Then number of I/O other operations.
* `readTransferCount` number - The number of I/O read transfers.
* `writeTransferCount` number - The number of I/O write transfers.
* `otherTransferCount` number - Then number of I/O other transfers.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/io-counters>

powerSaveBlocker
================



> Block the system from entering low-power (sleep) mode.
> 
> 


Process: [Main](../glossary#main-process)


For example:




```
const { powerSaveBlocker } = require('electron')

const id = powerSaveBlocker.start('prevent-display-sleep')
console.log(powerSaveBlocker.isStarted(id))

powerSaveBlocker.stop(id)
```


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `powerSaveBlocker` module has the following methods:


### 
`powerSaveBlocker.start(type)`[​](#powersaveblockerstarttype "Direct link to heading")


* `type` string - Power save blocker type.
	+ `prevent-app-suspension` - Prevent the application from being suspended. Keeps system active but allows screen to be turned off. Example use cases: downloading a file or playing audio.
	+ `prevent-display-sleep` - Prevent the display from going to sleep. Keeps system and screen active. Example use case: playing video.


Returns `Integer` - The blocker ID that is assigned to this power blocker.


Starts preventing the system from entering lower-power mode. Returns an integer identifying the power save blocker.


**Note:** `prevent-display-sleep` has higher precedence over `prevent-app-suspension`. Only the highest precedence type takes effect. In other words, `prevent-display-sleep` always takes precedence over `prevent-app-suspension`.


For example, an API calling A requests for `prevent-app-suspension`, and another calling B requests for `prevent-display-sleep`. `prevent-display-sleep` will be used until B stops its request. After that, `prevent-app-suspension` is used.


### 
`powerSaveBlocker.stop(id)`[​](#powersaveblockerstopid "Direct link to heading")


* `id` Integer - The power save blocker id returned by `powerSaveBlocker.start`.


Stops the specified power save blocker.


### 
`powerSaveBlocker.isStarted(id)`[​](#powersaveblockerisstartedid "Direct link to heading")


* `id` Integer - The power save blocker id returned by `powerSaveBlocker.start`.


Returns `boolean` - Whether the corresponding `powerSaveBlocker` has started.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/power-save-blocker>

NewWindowWebContentsEvent Object extends `Event`
================================================


* `newGuest` BrowserWindow (optional)



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/new-window-web-contents-event>

contentTracing
==============



> Collect tracing data from Chromium to find performance bottlenecks and slow operations.
> 
> 


Process: [Main](../glossary#main-process)


This module does not include a web interface. To view recorded traces, use [trace viewer](https://chromium.googlesource.com/catapult/+/HEAD/tracing/README.md), available at `chrome://tracing` in Chrome.


**Note:** You should not use this module until the `ready` event of the app module is emitted.




```
const { app, contentTracing } = require('electron')

app.whenReady().then(() => {
  (async () => {
    await contentTracing.startRecording({
      included_categories: ['*']
    })
    console.log('Tracing started')
    await new Promise(resolve => setTimeout(resolve, 5000))
    const path = await contentTracing.stopRecording()
    console.log('Tracing data recorded to ' + path)
  })()
})
```


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `contentTracing` module has the following methods:


### 
`contentTracing.getCategories()`[​](#contenttracinggetcategories "Direct link to heading")


Returns `Promise<string[]>` - resolves with an array of category groups once all child processes have acknowledged the `getCategories` request


Get a set of category groups. The category groups can change as new code paths are reached. See also the [list of built-in tracing categories](https://chromium.googlesource.com/chromium/src/+/main/base/trace_event/builtin_categories.h).



> **NOTE:** Electron adds a non-default tracing category called `"electron"`. This category can be used to capture Electron-specific tracing events.
> 
> 


### 
`contentTracing.startRecording(options)`[​](#contenttracingstartrecordingoptions "Direct link to heading")


* `options` ([TraceConfig](structures/trace-config) | [TraceCategoriesAndOptions](structures/trace-categories-and-options))


Returns `Promise<void>` - resolved once all child processes have acknowledged the `startRecording` request.


Start recording on all processes.


Recording begins immediately locally and asynchronously on child processes as soon as they receive the EnableRecording request.


If a recording is already running, the promise will be immediately resolved, as only one trace operation can be in progress at a time.


### 
`contentTracing.stopRecording([resultFilePath])`[​](#contenttracingstoprecordingresultfilepath "Direct link to heading")


* `resultFilePath` string (optional)


Returns `Promise<string>` - resolves with a path to a file that contains the traced data once all child processes have acknowledged the `stopRecording` request


Stop recording on all processes.


Child processes typically cache trace data and only rarely flush and send trace data back to the main process. This helps to minimize the runtime overhead of tracing since sending trace data over IPC can be an expensive operation. So, to end tracing, Chromium asynchronously asks all child processes to flush any pending trace data.


Trace data will be written into `resultFilePath`. If `resultFilePath` is empty or not provided, trace data will be written to a temporary file, and the path will be returned in the promise.


### 
`contentTracing.getTraceBufferUsage()`[​](#contenttracinggettracebufferusage "Direct link to heading")


Returns `Promise<Object>` - Resolves with an object containing the `value` and `percentage` of trace buffer maximum usage


* `value` number
* `percentage` number


Get the maximum usage across processes of trace buffer as a percentage of the full state.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/content-tracing>

Transaction Object
==================


* `transactionIdentifier` string - A string that uniquely identifies a successful payment transaction.
* `transactionDate` string - The date the transaction was added to the App Store’s payment queue.
* `originalTransactionIdentifier` string - The identifier of the restored transaction by the App Store.
* `transactionState` string - The transaction state, can be `purchasing`, `purchased`, `failed`, `restored` or `deferred`.
* `errorCode` Integer - The error code if an error occurred while processing the transaction.
* `errorMessage` string - The error message if an error occurred while processing the transaction.
* `payment` Object
	+ `productIdentifier` string - The identifier of the purchased product.
	+ `quantity` Integer - The quantity purchased.
	+ `applicationUsername` string - An opaque identifier for the user’s account on your system.
	+ `paymentDiscount` [PaymentDiscount](payment-discount) (optional) - The details of the discount offer to apply to the payment.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/transaction>

ExtensionInfo Object
====================


* `name` string
* `version` string



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/extension-info>

Pull Requests
=============


* [Setting up your local environment](#setting-up-your-local-environment)
	+ [Step 1: Fork](#step-1-fork)
	+ [Step 2: Build](#step-2-build)
	+ [Step 3: Branch](#step-3-branch)
* [Making Changes](#making-changes)
	+ [Step 4: Code](#step-4-code)
	+ [Step 5: Commit](#step-5-commit)
		- [Commit message guidelines](#commit-message-guidelines)
	+ [Step 6: Rebase](#step-6-rebase)
	+ [Step 7: Test](#step-7-test)
	+ [Step 8: Push](#step-8-push)
	+ [Step 9: Opening the Pull Request](#step-9-opening-the-pull-request)
	+ [Step 10: Discuss and Update](#step-10-discuss-and-update)
		- [Approval and Request Changes Workflow](#approval-and-request-changes-workflow)
	+ [Step 11: Landing](#step-11-landing)
	+ [Continuous Integration Testing](#continuous-integration-testing)


Setting up your local environment[​](#setting-up-your-local-environment "Direct link to heading")
-------------------------------------------------------------------------------------------------


### Step 1: Fork[​](#step-1-fork "Direct link to heading")


Fork the project [on GitHub](https://github.com/electron/electron) and clone your fork locally.




```
$ git clone git@github.com:username/electron.git
$ cd electron
$ git remote add upstream https://github.com/electron/electron.git
$ git fetch upstream
```


### Step 2: Build[​](#step-2-build "Direct link to heading")


Build steps and dependencies differ slightly depending on your operating system. See these detailed guides on building Electron locally:


* [Building on macOS](build-instructions-macos)
* [Building on Linux](build-instructions-linux)
* [Building on Windows](build-instructions-windows)


Once you've built the project locally, you're ready to start making changes!


### Step 3: Branch[​](#step-3-branch "Direct link to heading")


To keep your development environment organized, create local branches to hold your work. These should be branched directly off of the `main` branch.




```
$ git checkout -b my-branch -t upstream/main
```


Making Changes[​](#making-changes "Direct link to heading")
-----------------------------------------------------------


### Step 4: Code[​](#step-4-code "Direct link to heading")


Most pull requests opened against the `electron/electron` repository include changes to either the C/C++ code in the `shell/` folder, the JavaScript code in the `lib/` folder, the documentation in `docs/api/` or tests in the `spec/` folder.


Please be sure to run `npm run lint` from time to time on any code changes to ensure that they follow the project's code style.


See [coding style](coding-style) for more information about best practice when modifying code in different parts of the project.


### Step 5: Commit[​](#step-5-commit "Direct link to heading")


It is recommended to keep your changes grouped logically within individual commits. Many contributors find it easier to review changes that are split across multiple commits. There is no limit to the number of commits in a pull request.




```
$ git add my/changed/files
$ git commit
```


Note that multiple commits get squashed when they are landed.


#### Commit message guidelines[​](#commit-message-guidelines "Direct link to heading")


A good commit message should describe what changed and why. The Electron project uses [semantic commit messages](https://conventionalcommits.org/) to streamline the release process.


Before a pull request can be merged, it **must** have a pull request title with a semantic prefix.


Examples of commit messages with semantic prefixes:


* `fix: don't overwrite prevent_default if default wasn't prevented`
* `feat: add app.isPackaged() method`
* `docs: app.isDefaultProtocolClient is now available on Linux`


Common prefixes:


* fix: A bug fix
* feat: A new feature
* docs: Documentation changes
* test: Adding missing tests or correcting existing tests
* build: Changes that affect the build system
* ci: Changes to our CI configuration files and scripts
* perf: A code change that improves performance
* refactor: A code change that neither fixes a bug nor adds a feature
* style: Changes that do not affect the meaning of the code (linting)


Other things to keep in mind when writing a commit message:


1. The first line should:
	* contain a short description of the change (preferably 50 characters or less, and no more than 72 characters)
	* be entirely in lowercase with the exception of proper nouns, acronyms, and the words that refer to code, like function/variable names
2. Keep the second line blank.
3. Wrap all other lines at 72 columns.


#### Breaking Changes[​](#breaking-changes "Direct link to heading")


A commit that has the text `BREAKING CHANGE:` at the beginning of its optional body or footer section introduces a breaking API change (correlating with Major in semantic versioning). A breaking change can be part of commits of any type. e.g., a `fix:`, `feat:` & `chore:` types would all be valid, in addition to any other type.


See [conventionalcommits.org](https://conventionalcommits.org) for more details.


### Step 6: Rebase[​](#step-6-rebase "Direct link to heading")


Once you have committed your changes, it is a good idea to use `git rebase` (not `git merge`) to synchronize your work with the main repository.




```
$ git fetch upstream
$ git rebase upstream/main
```


This ensures that your working branch has the latest changes from `electron/electron` main.


### Step 7: Test[​](#step-7-test "Direct link to heading")


Bug fixes and features should always come with tests. A [testing guide](testing) has been provided to make the process easier. Looking at other tests to see how they should be structured can also help.


Before submitting your changes in a pull request, always run the full test suite. To run the tests:




```
$ npm run test
```


Make sure the linter does not report any issues and that all tests pass. Please do not submit patches that fail either check.


If you are updating tests and want to run a single spec to check it:




```
$ npm run test -match=menu
```


The above would only run spec modules matching `menu`, which is useful for anyone who's working on tests that would otherwise be at the very end of the testing cycle.


### Step 8: Push[​](#step-8-push "Direct link to heading")


Once your commits are ready to go -- with passing tests and linting -- begin the process of opening a pull request by pushing your working branch to your fork on GitHub.




```
$ git push origin my-branch
```


### Step 9: Opening the Pull Request[​](#step-9-opening-the-pull-request "Direct link to heading")


From within GitHub, opening a new pull request will present you with a template that should be filled out. It can be found [here](https://github.com/electron/electron/blob/main/.github/PULL_REQUEST_TEMPLATE.md).


If you do not adequately complete this template, your PR may be delayed in being merged as maintainers seek more information or clarify ambiguities.


### Step 10: Discuss and update[​](#step-10-discuss-and-update "Direct link to heading")


You will probably get feedback or requests for changes to your pull request. This is a big part of the submission process so don't be discouraged! Some contributors may sign off on the pull request right away. Others may have detailed comments or feedback. This is a necessary part of the process in order to evaluate whether the changes are correct and necessary.


To make changes to an existing pull request, make the changes to your local branch, add a new commit with those changes, and push those to your fork. GitHub will automatically update the pull request.




```
$ git add my/changed/files
$ git commit
$ git push origin my-branch
```


There are a number of more advanced mechanisms for managing commits using `git rebase` that can be used, but are beyond the scope of this guide.


Feel free to post a comment in the pull request to ping reviewers if you are awaiting an answer on something. If you encounter words or acronyms that seem unfamiliar, refer to this [glossary](https://sites.google.com/a/chromium.org/dev/glossary).


#### Approval and Request Changes Workflow[​](#approval-and-request-changes-workflow "Direct link to heading")


All pull requests require approval from a [Code Owner](https://github.com/electron/electron/blob/main/.github/CODEOWNERS) of the area you modified in order to land. Whenever a maintainer reviews a pull request they may request changes. These may be small, such as fixing a typo, or may involve substantive changes. Such requests are intended to be helpful, but at times may come across as abrupt or unhelpful, especially if they do not include concrete suggestions on *how* to change them.


Try not to be discouraged. If you feel that a review is unfair, say so or seek the input of another project contributor. Often such comments are the result of a reviewer having taken insufficient time to review and are not ill-intended. Such difficulties can often be resolved with a bit of patience. That said, reviewers should be expected to provide helpful feedback.


### Step 11: Landing[​](#step-11-landing "Direct link to heading")


In order to land, a pull request needs to be reviewed and approved by at least one Electron Code Owner and pass CI. After that, if there are no objections from other contributors, the pull request can be merged.


Congratulations and thanks for your contribution!


### Continuous Integration Testing[​](#continuous-integration-testing "Direct link to heading")


Every pull request is tested on the Continuous Integration (CI) system to confirm that it works on Electron's supported platforms.


Ideally, the pull request will pass ("be green") on all of CI's platforms. This means that all tests pass and there are no linting errors. However, it is not uncommon for the CI infrastructure itself to fail on specific platforms or for so-called "flaky" tests to fail ("be red"). Each CI failure must be manually inspected to determine the cause.


CI starts automatically when you open a pull request, but only core maintainers can restart a CI run. If you believe CI is giving a false negative, ask a maintainer to restart the tests.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/pull-requests>

SharingItem Object
==================


* `texts` string[] (optional) - An array of text to share.
* `filePaths` string[] (optional) - An array of files to share.
* `urls` string[] (optional) - An array of URLs to share.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/sharing-item>

TraceConfig Object
==================


* `recording_mode` string (optional) - Can be `record-until-full`, `record-continuously`, `record-as-much-as-possible` or `trace-to-console`. Defaults to `record-until-full`.
* `trace_buffer_size_in_kb` number (optional) - maximum size of the trace recording buffer in kilobytes. Defaults to 100MB.
* `trace_buffer_size_in_events` number (optional) - maximum size of the trace recording buffer in events.
* `enable_argument_filter` boolean (optional) - if true, filter event data according to a specific list of events that have been manually vetted to not include any PII. See [the implementation in Chromium](https://chromium.googlesource.com/chromium/src/+/main/services/tracing/public/cpp/trace_event_args_allowlist.cc) for specifics.
* `included_categories` string[] (optional) - a list of tracing categories to include. Can include glob-like patterns using `*` at the end of the category name. See [tracing categories](https://chromium.googlesource.com/chromium/src/+/main/base/trace_event/builtin_categories.h) for the list of categories.
* `excluded_categories` string[] (optional) - a list of tracing categories to exclude. Can include glob-like patterns using `*` at the end of the category name. See [tracing categories](https://chromium.googlesource.com/chromium/src/+/main/base/trace_event/builtin_categories.h) for the list of categories.
* `included_process_ids` number[] (optional) - a list of process IDs to include in the trace. If not specified, trace all processes.
* `histogram_names` string[] (optional) - a list of [histogram](https://chromium.googlesource.com/chromium/src.git/+/HEAD/tools/metrics/histograms/README.md) names to report with the trace.
* `memory_dump_config` Record<string, any> (optional) - if the `disabled-by-default-memory-infra` category is enabled, this contains optional additional configuration for data collection. See the [Chromium memory-infra docs](https://chromium.googlesource.com/chromium/src/+/main/docs/memory-infra/memory_infra_startup_tracing.md#the-advanced-way) for more information.


An example TraceConfig that roughly matches what Chrome DevTools records:




```
{
  recording_mode: 'record-until-full',
  included_categories: [
    'devtools.timeline',
    'disabled-by-default-devtools.timeline',
    'disabled-by-default-devtools.timeline.frame',
    'disabled-by-default-devtools.timeline.stack',
    'v8.execute',
    'blink.console',
    'blink.user_timing',
    'latencyInfo',
    'disabled-by-default-v8.cpu_profiler',
    'disabled-by-default-v8.cpu_profiler.hires'
  ],
  excluded_categories: ['*']
}
```



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/trace-config>

DesktopCapturerSource Object
============================


* `id` string - The identifier of a window or screen that can be used as a `chromeMediaSourceId` constraint when calling [`navigator.webkitGetUserMedia`]. The format of the identifier will be `window:XX:YY` or `screen:ZZ:0`. XX is the windowID/handle. YY is 1 for the current process, and 0 for all others. ZZ is a sequential number that represents the screen, and it does not equal to the index in the source's name.
* `name` string - A screen source will be named either `Entire Screen` or `Screen <index>`, while the name of a window source will match the window title.
* `thumbnail` [NativeImage](../native-image) - A thumbnail image. **Note:** There is no guarantee that the size of the thumbnail is the same as the `thumbnailSize` specified in the `options` passed to `desktopCapturer.getSources`. The actual size depends on the scale of the screen or window.
* `display_id` string - A unique identifier that will correspond to the `id` of the matching [Display](display) returned by the [Screen API](../screen). On some platforms, this is equivalent to the `XX` portion of the `id` field above and on others it will differ. It will be an empty string if not available.
* `appIcon` [NativeImage](../native-image) - An icon image of the application that owns the window or null if the source has a type screen. The size of the icon is not known in advance and depends on what the application provides.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/desktop-capturer-source>

Notification
============



> Create OS desktop notifications
> 
> 


Process: [Main](../glossary#main-process)


Using in the renderer process[​](#using-in-the-renderer-process "Direct link to heading")
-----------------------------------------------------------------------------------------


If you want to show Notifications from a renderer process you should use the [HTML5 Notification API](../tutorial/notifications)


Class: Notification[​](#class-notification "Direct link to heading")
--------------------------------------------------------------------



> Create OS desktop notifications
> 
> 


Process: [Main](../glossary#main-process)


`Notification` is an [EventEmitter](https://nodejs.org/api/events.html#events_class_eventemitter).


It creates a new `Notification` with native properties as set by the `options`.


### Static Methods[​](#static-methods "Direct link to heading")


The `Notification` class has the following static methods:


#### 
`Notification.isSupported()`[​](#notificationissupported "Direct link to heading")


Returns `boolean` - Whether or not desktop notifications are supported on the current system


### 
`new Notification([options])`[​](#new-notificationoptions "Direct link to heading")


* `options` Object (optional)
	+ `title` string (optional) - A title for the notification, which will be shown at the top of the notification window when it is shown.
	+ `subtitle` string (optional) *macOS* - A subtitle for the notification, which will be displayed below the title.
	+ `body` string (optional) - The body text of the notification, which will be displayed below the title or subtitle.
	+ `silent` boolean (optional) - Whether or not to emit an OS notification noise when showing the notification.
	+ `icon` (string | [NativeImage](native-image)) (optional) - An icon to use in the notification.
	+ `hasReply` boolean (optional) *macOS* - Whether or not to add an inline reply option to the notification.
	+ `timeoutType` string (optional) *Linux* *Windows* - The timeout duration of the notification. Can be 'default' or 'never'.
	+ `replyPlaceholder` string (optional) *macOS* - The placeholder to write in the inline reply input field.
	+ `sound` string (optional) *macOS* - The name of the sound file to play when the notification is shown.
	+ `urgency` string (optional) *Linux* - The urgency level of the notification. Can be 'normal', 'critical', or 'low'.
	+ `actions` [NotificationAction[]](structures/notification-action) (optional) *macOS* - Actions to add to the notification. Please read the available actions and limitations in the `NotificationAction` documentation.
	+ `closeButtonText` string (optional) *macOS* - A custom title for the close button of an alert. An empty string will cause the default localized text to be used.
	+ `toastXml` string (optional) *Windows* - A custom description of the Notification on Windows superseding all properties above. Provides full customization of design and behavior of the notification.


### Instance Events[​](#instance-events "Direct link to heading")


Objects created with `new Notification` emit the following events:


**Note:** Some events are only available on specific operating systems and are labeled as such.


#### Event: 'show'[​](#event-show "Direct link to heading")


Returns:


* `event` Event


Emitted when the notification is shown to the user, note this could be fired multiple times as a notification can be shown multiple times through the `show()` method.


#### Event: 'click'[​](#event-click "Direct link to heading")


Returns:


* `event` Event


Emitted when the notification is clicked by the user.


#### Event: 'close'[​](#event-close "Direct link to heading")


Returns:


* `event` Event


Emitted when the notification is closed by manual intervention from the user.


This event is not guaranteed to be emitted in all cases where the notification is closed.


#### Event: 'reply' *macOS*[​](#event-reply-macos "Direct link to heading")


Returns:


* `event` Event
* `reply` string - The string the user entered into the inline reply field.


Emitted when the user clicks the "Reply" button on a notification with `hasReply: true`.


#### Event: 'action' *macOS*[​](#event-action-macos "Direct link to heading")


Returns:


* `event` Event
* `index` number - The index of the action that was activated.


#### Event: 'failed' *Windows*[​](#event-failed-windows "Direct link to heading")


Returns:


* `event` Event
* `error` string - The error encountered during execution of the `show()` method.


Emitted when an error is encountered while creating and showing the native notification.


### Instance Methods[​](#instance-methods "Direct link to heading")


Objects created with `new Notification` have the following instance methods:


#### 
`notification.show()`[​](#notificationshow "Direct link to heading")


Immediately shows the notification to the user, please note this means unlike the HTML5 Notification implementation, instantiating a `new Notification` does not immediately show it to the user, you need to call this method before the OS will display it.


If the notification has been shown before, this method will dismiss the previously shown notification and create a new one with identical properties.


#### 
`notification.close()`[​](#notificationclose "Direct link to heading")


Dismisses the notification.


### Instance Properties[​](#instance-properties "Direct link to heading")


#### 
`notification.title`[​](#notificationtitle "Direct link to heading")


A `string` property representing the title of the notification.


#### 
`notification.subtitle`[​](#notificationsubtitle "Direct link to heading")


A `string` property representing the subtitle of the notification.


#### 
`notification.body`[​](#notificationbody "Direct link to heading")


A `string` property representing the body of the notification.


#### 
`notification.replyPlaceholder`[​](#notificationreplyplaceholder "Direct link to heading")


A `string` property representing the reply placeholder of the notification.


#### 
`notification.sound`[​](#notificationsound "Direct link to heading")


A `string` property representing the sound of the notification.


#### 
`notification.closeButtonText`[​](#notificationclosebuttontext "Direct link to heading")


A `string` property representing the close button text of the notification.


#### 
`notification.silent`[​](#notificationsilent "Direct link to heading")


A `boolean` property representing whether the notification is silent.


#### 
`notification.hasReply`[​](#notificationhasreply "Direct link to heading")


A `boolean` property representing whether the notification has a reply action.


#### 
`notification.urgency` *Linux*[​](#notificationurgency-linux "Direct link to heading")


A `string` property representing the urgency level of the notification. Can be 'normal', 'critical', or 'low'.


Default is 'low' - see [NotifyUrgency](https://developer.gnome.org/notification-spec/#urgency-levels) for more information.


#### 
`notification.timeoutType` *Linux* *Windows*[​](#notificationtimeouttype-linux-windows "Direct link to heading")


A `string` property representing the type of timeout duration for the notification. Can be 'default' or 'never'.


If `timeoutType` is set to 'never', the notification never expires. It stays open until closed by the calling API or the user.


#### 
`notification.actions`[​](#notificationactions "Direct link to heading")


A [NotificationAction[]](structures/notification-action) property representing the actions of the notification.


#### 
`notification.toastXml` *Windows*[​](#notificationtoastxml-windows "Direct link to heading")


A `string` property representing the custom Toast XML of the notification.


### Playing Sounds[​](#playing-sounds "Direct link to heading")


On macOS, you can specify the name of the sound you'd like to play when the notification is shown. Any of the default sounds (under System Preferences > Sound) can be used, in addition to custom sound files. Be sure that the sound file is copied under the app bundle (e.g., `YourApp.app/Contents/Resources`), or one of the following locations:


* `~/Library/Sounds`
* `/Library/Sounds`
* `/Network/Library/Sounds`
* `/System/Library/Sounds`


See the [`NSSound`](https://developer.apple.com/documentation/appkit/nssound) docs for more information.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/notification>

Snapcraft Guide (Linux)
=======================


This guide provides information on how to package your Electron application for any Snapcraft environment, including the Ubuntu Software Center.


Background and Requirements[​](#background-and-requirements "Direct link to heading")
-------------------------------------------------------------------------------------


Together with the broader Linux community, Canonical aims to fix many of the common software installation problems with the [`snapcraft`](https://snapcraft.io/) project. Snaps are containerized software packages that include required dependencies, auto-update, and work on all major Linux distributions without system modification.


There are three ways to create a `.snap` file:


1) Using [`electron-forge`](https://github.com/electron-userland/electron-forge) or [`electron-builder`](https://github.com/electron-userland/electron-builder), both tools that come with `snap` support out of the box. This is the easiest option. 2) Using `electron-installer-snap`, which takes `electron-packager`'s output. 3) Using an already created `.deb` package.


In some cases, you will need to have the `snapcraft` tool installed. Instructions to install `snapcraft` for your particular distribution are available [here](https://snapcraft.io/docs/installing-snapcraft).


Using `electron-installer-snap`[​](#using-electron-installer-snap "Direct link to heading")
-------------------------------------------------------------------------------------------


The module works like [`electron-winstaller`](https://github.com/electron/windows-installer) and similar modules in that its scope is limited to building snap packages. You can install it with:




```
npm install --save-dev electron-installer-snap
```


### Step 1: Package Your Electron Application[​](#step-1-package-your-electron-application "Direct link to heading")


Package the application using [electron-packager](https://github.com/electron/electron-packager) (or a similar tool). Make sure to remove `node_modules` that you don't need in your final application, since any module you don't actually need will increase your application's size.


The output should look roughly like this:




```
.
└── dist
    └── app-linux-x64
        ├── LICENSE
        ├── LICENSES.chromium.html
        ├── content_shell.pak
        ├── app
        ├── icudtl.dat
        ├── libgcrypt.so.11
        ├── libnode.so
        ├── locales
        ├── resources
        ├── v8_context_snapshot.bin
        └── version
```


### Step 2: Running `electron-installer-snap`[​](#step-2-running-electron-installer-snap "Direct link to heading")


From a terminal that has `snapcraft` in its `PATH`, run `electron-installer-snap` with the only required parameter `--src`, which is the location of your packaged Electron application created in the first step.




```
npx electron-installer-snap --src=out/myappname-linux-x64
```


If you have an existing build pipeline, you can use `electron-installer-snap` programmatically. For more information, see the [Snapcraft API docs](https://docs.snapcraft.io/build-snaps/syntax).




```
const snap = require('electron-installer-snap')

snap(options)
  .then(snapPath => console.log(`Created snap at ${snapPath}!`))
```


Using `snapcraft` with `electron-packager`[​](#using-snapcraft-with-electron-packager "Direct link to heading")
---------------------------------------------------------------------------------------------------------------


### Step 1: Create Sample Snapcraft Project[​](#step-1-create-sample-snapcraft-project "Direct link to heading")


Create your project directory and add the following to `snap/snapcraft.yaml`:




```
name: electron-packager-hello-world
version: '0.1'
summary: Hello World Electron app
description: |
  Simple Hello World Electron app as an example
base: core18
confinement: strict
grade: stable

apps:
  electron-packager-hello-world:
    command: electron-quick-start/electron-quick-start --no-sandbox
    extensions: [gnome-3-34]
    plugs:
    - browser-support
    - network
    - network-bind
    environment:
      # Correct the TMPDIR path for Chromium Framework/Electron to ensure
      # libappindicator has readable resources.
      TMPDIR: $XDG_RUNTIME_DIR

parts:
  electron-quick-start:
    plugin: nil
    source: https://github.com/electron/electron-quick-start.git
    override-build: |
        npm install electron electron-packager
        npx electron-packager . --overwrite --platform=linux --output=release-build --prune=true
        cp -rv ./electron-quick-start-linux-* $SNAPCRAFT_PART_INSTALL/electron-quick-start
    build-snaps:
    - node/14/stable
    build-packages:
    - unzip
    stage-packages:
    - libnss3
    - libnspr4
```


If you want to apply this example to an existing project:


* Replace `source: https://github.com/electron/electron-quick-start.git` with `source: .`.
* Replace all instances of `electron-quick-start` with your project's name.


### Step 2: Build the snap[​](#step-2-build-the-snap "Direct link to heading")




```
$ snapcraft

<output snipped>
Snapped electron-packager-hello-world_0.1_amd64.snap
```


### Step 3: Install the snap[​](#step-3-install-the-snap "Direct link to heading")




```
sudo snap install electron-packager-hello-world_0.1_amd64.snap --dangerous
```


### Step 4: Run the snap[​](#step-4-run-the-snap "Direct link to heading")




```
electron-packager-hello-world
```


Using an Existing Debian Package[​](#using-an-existing-debian-package "Direct link to heading")
-----------------------------------------------------------------------------------------------


Snapcraft is capable of taking an existing `.deb` file and turning it into a `.snap` file. The creation of a snap is configured using a `snapcraft.yaml` file that describes the sources, dependencies, description, and other core building blocks.


### Step 1: Create a Debian Package[​](#step-1-create-a-debian-package "Direct link to heading")


If you do not already have a `.deb` package, using `electron-installer-snap` might be an easier path to create snap packages. However, multiple solutions for creating Debian packages exist, including [`electron-forge`](https://github.com/electron-userland/electron-forge), [`electron-builder`](https://github.com/electron-userland/electron-builder) or [`electron-installer-debian`](https://github.com/unindented/electron-installer-debian).


### Step 2: Create a snapcraft.yaml[​](#step-2-create-a-snapcraftyaml "Direct link to heading")


For more information on the available configuration options, see the [documentation on the snapcraft syntax](https://docs.snapcraft.io/build-snaps/syntax). Let's look at an example:




```
name: myApp
version: '2.0.0'
summary: A little description for the app.
description: |
 You know what? This app is amazing! It does all the things
 for you. Some say it keeps you young, maybe even happy.

grade: stable
confinement: classic

parts:
  slack:
    plugin: dump
    source: my-deb.deb
    source-type: deb
    after:
      - desktop-gtk3
    stage-packages:
      - libasound2
      - libnotify4
      - libnspr4
      - libnss3
      - libpcre3
      - libpulse0
      - libxss1
      - libxtst6
  electron-launch:
    plugin: dump
    source: files/
    prepare: |
      chmod +x bin/electron-launch

apps:
  myApp:
    command: bin/electron-launch $SNAP/usr/lib/myApp/myApp
    desktop: usr/share/applications/myApp.desktop
    # Correct the TMPDIR path for Chromium Framework/Electron to ensure
    # libappindicator has readable resources.
    environment:
      TMPDIR: $XDG_RUNTIME_DIR
```


As you can see, the `snapcraft.yaml` instructs the system to launch a file called `electron-launch`. In this example, it passes information on to the app's binary:




```
#!/bin/sh

exec "$@" --executed-from="$(pwd)" --pid=$$ > /dev/null 2>&1 &
```


Alternatively, if you're building your `snap` with `strict` confinement, you can use the `desktop-launch` command:




```
apps:
  myApp:
    # Correct the TMPDIR path for Chromium Framework/Electron to ensure
    # libappindicator has readable resources.
    command: env TMPDIR=$XDG_RUNTIME_DIR PATH=/usr/local/bin:${PATH} ${SNAP}/bin/desktop-launch $SNAP/myApp/desktop
    desktop: usr/share/applications/desktop.desktop
```



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/snapcraft>

webFrame
========



> Customize the rendering of the current web page.
> 
> 


Process: [Renderer](../glossary#renderer-process)


`webFrame` export of the Electron module is an instance of the `WebFrame` class representing the current frame. Sub-frames can be retrieved by certain properties and methods (e.g. `webFrame.firstChild`).


An example of zooming current page to 200%.




```
const { webFrame } = require('electron')

webFrame.setZoomFactor(2)
```


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `WebFrame` class has the following instance methods:


### 
`webFrame.setZoomFactor(factor)`[​](#webframesetzoomfactorfactor "Direct link to heading")


* `factor` Double - Zoom factor; default is 1.0.


Changes the zoom factor to the specified factor. Zoom factor is zoom percent divided by 100, so 300% = 3.0.


The factor must be greater than 0.0.


### 
`webFrame.getZoomFactor()`[​](#webframegetzoomfactor "Direct link to heading")


Returns `number` - The current zoom factor.


### 
`webFrame.setZoomLevel(level)`[​](#webframesetzoomlevellevel "Direct link to heading")


* `level` number - Zoom level.


Changes the zoom level to the specified level. The original size is 0 and each increment above or below represents zooming 20% larger or smaller to default limits of 300% and 50% of original size, respectively.



> **NOTE**: The zoom policy at the Chromium level is same-origin, meaning that the zoom level for a specific domain propagates across all instances of windows with the same domain. Differentiating the window URLs will make zoom work per-window.
> 
> 


### 
`webFrame.getZoomLevel()`[​](#webframegetzoomlevel "Direct link to heading")


Returns `number` - The current zoom level.


### 
`webFrame.setVisualZoomLevelLimits(minimumLevel, maximumLevel)`[​](#webframesetvisualzoomlevellimitsminimumlevel-maximumlevel "Direct link to heading")


* `minimumLevel` number
* `maximumLevel` number


Sets the maximum and minimum pinch-to-zoom level.



> 
> **NOTE**: Visual zoom is disabled by default in Electron. To re-enable it, call:
> 
> 
> 
> 
> ```
> webFrame.setVisualZoomLevelLimits(1, 3)
> ```
> 
> 
> 



> **NOTE**: Visual zoom only applies to pinch-to-zoom behavior. Cmd+/-/0 zoom shortcuts are controlled by the 'zoomIn', 'zoomOut', and 'resetZoom' MenuItem roles in the application Menu. To disable shortcuts, manually [define the Menu](menu#examples) and omit zoom roles from the definition.
> 
> 


### 
`webFrame.setSpellCheckProvider(language, provider)`[​](#webframesetspellcheckproviderlanguage-provider "Direct link to heading")


* `language` string
* `provider` Object
	+ `spellCheck` Function
		- `words` string[]
		- `callback` Function
			* `misspeltWords` string[]


Sets a provider for spell checking in input fields and text areas.


If you want to use this method you must disable the builtin spellchecker when you construct the window.




```
const mainWindow = new BrowserWindow({
  webPreferences: {
    spellcheck: false
  }
})
```


The `provider` must be an object that has a `spellCheck` method that accepts an array of individual words for spellchecking. The `spellCheck` function runs asynchronously and calls the `callback` function with an array of misspelt words when complete.


An example of using [node-spellchecker](https://github.com/atom/node-spellchecker) as provider:




```
const { webFrame } = require('electron')
const spellChecker = require('spellchecker')
webFrame.setSpellCheckProvider('en-US', {
  spellCheck (words, callback) {
    setTimeout(() => {
      const spellchecker = require('spellchecker')
      const misspelled = words.filter(x => spellchecker.isMisspelled(x))
      callback(misspelled)
    }, 0)
  }
})
```


### 
`webFrame.insertCSS(css[, options])`[​](#webframeinsertcsscss-options "Direct link to heading")


* `css` string
* `options` Object (optional)
	+ `cssOrigin` string (optional) - Can be either 'user' or 'author'. Sets the [cascade origin](https://www.w3.org/TR/css3-cascade/#cascade-origin) of the inserted stylesheet. Default is 'author'.


Returns `string` - A key for the inserted CSS that can later be used to remove the CSS via `webFrame.removeInsertedCSS(key)`.


Injects CSS into the current web page and returns a unique key for the inserted stylesheet.


### 
`webFrame.removeInsertedCSS(key)`[​](#webframeremoveinsertedcsskey "Direct link to heading")


* `key` string


Removes the inserted CSS from the current web page. The stylesheet is identified by its key, which is returned from `webFrame.insertCSS(css)`.


### 
`webFrame.insertText(text)`[​](#webframeinserttexttext "Direct link to heading")


* `text` string


Inserts `text` to the focused element.


### 
`webFrame.executeJavaScript(code[, userGesture, callback])`[​](#webframeexecutejavascriptcode-usergesture-callback "Direct link to heading")


* `code` string
* `userGesture` boolean (optional) - Default is `false`.
* `callback` Function (optional) - Called after script has been executed. Unless the frame is suspended (e.g. showing a modal alert), execution will be synchronous and the callback will be invoked before the method returns. For compatibility with an older version of this method, the error parameter is second.
	+ `result` Any
	+ `error` Error


Returns `Promise<any>` - A promise that resolves with the result of the executed code or is rejected if execution throws or results in a rejected promise.


Evaluates `code` in page.


In the browser window some HTML APIs like `requestFullScreen` can only be invoked by a gesture from the user. Setting `userGesture` to `true` will remove this limitation.


### 
`webFrame.executeJavaScriptInIsolatedWorld(worldId, scripts[, userGesture, callback])`[​](#webframeexecutejavascriptinisolatedworldworldid-scripts-usergesture-callback "Direct link to heading")


* `worldId` Integer - The ID of the world to run the javascript in, `0` is the default main world (where content runs), `999` is the world used by Electron's `contextIsolation` feature. Accepts values in the range 1..536870911.
* `scripts` [WebSource[]](structures/web-source)
* `userGesture` boolean (optional) - Default is `false`.
* `callback` Function (optional) - Called after script has been executed. Unless the frame is suspended (e.g. showing a modal alert), execution will be synchronous and the callback will be invoked before the method returns. For compatibility with an older version of this method, the error parameter is second.
	+ `result` Any
	+ `error` Error


Returns `Promise<any>` - A promise that resolves with the result of the executed code or is rejected if execution could not start.


Works like `executeJavaScript` but evaluates `scripts` in an isolated context.


Note that when the execution of script fails, the returned promise will not reject and the `result` would be `undefined`. This is because Chromium does not dispatch errors of isolated worlds to foreign worlds.


### 
`webFrame.setIsolatedWorldInfo(worldId, info)`[​](#webframesetisolatedworldinfoworldid-info "Direct link to heading")


* `worldId` Integer - The ID of the world to run the javascript in, `0` is the default world, `999` is the world used by Electrons `contextIsolation` feature. Chrome extensions reserve the range of IDs in `[1 << 20, 1 << 29)`. You can provide any integer here.
* `info` Object
	+ `securityOrigin` string (optional) - Security origin for the isolated world.
	+ `csp` string (optional) - Content Security Policy for the isolated world.
	+ `name` string (optional) - Name for isolated world. Useful in devtools.


Set the security origin, content security policy and name of the isolated world. Note: If the `csp` is specified, then the `securityOrigin` also has to be specified.


### 
`webFrame.getResourceUsage()`[​](#webframegetresourceusage "Direct link to heading")


Returns `Object`:


* `images` [MemoryUsageDetails](structures/memory-usage-details)
* `scripts` [MemoryUsageDetails](structures/memory-usage-details)
* `cssStyleSheets` [MemoryUsageDetails](structures/memory-usage-details)
* `xslStyleSheets` [MemoryUsageDetails](structures/memory-usage-details)
* `fonts` [MemoryUsageDetails](structures/memory-usage-details)
* `other` [MemoryUsageDetails](structures/memory-usage-details)


Returns an object describing usage information of Blink's internal memory caches.




```
const { webFrame } = require('electron')
console.log(webFrame.getResourceUsage())
```


This will generate:




```
{
  images: {
    count: 22,
    size: 2549,
    liveSize: 2542
  },
  cssStyleSheets: { /* same with "images" */ },
  xslStyleSheets: { /* same with "images" */ },
  fonts: { /* same with "images" */ },
  other: { /* same with "images" */ }
}
```


### 
`webFrame.clearCache()`[​](#webframeclearcache "Direct link to heading")


Attempts to free memory that is no longer being used (like images from a previous navigation).


Note that blindly calling this method probably makes Electron slower since it will have to refill these emptied caches, you should only call it if an event in your app has occurred that makes you think your page is actually using less memory (i.e. you have navigated from a super heavy page to a mostly empty one, and intend to stay there).


### 
`webFrame.getFrameForSelector(selector)`[​](#webframegetframeforselectorselector "Direct link to heading")


* `selector` string - CSS selector for a frame element.


Returns `WebFrame` - The frame element in `webFrame's` document selected by `selector`, `null` would be returned if `selector` does not select a frame or if the frame is not in the current renderer process.


### 
`webFrame.findFrameByName(name)`[​](#webframefindframebynamename "Direct link to heading")


* `name` string


Returns `WebFrame` - A child of `webFrame` with the supplied `name`, `null` would be returned if there's no such frame or if the frame is not in the current renderer process.


### 
`webFrame.findFrameByRoutingId(routingId)`[​](#webframefindframebyroutingidroutingid "Direct link to heading")


* `routingId` Integer - An `Integer` representing the unique frame id in the current renderer process. Routing IDs can be retrieved from `WebFrame` instances (`webFrame.routingId`) and are also passed by frame specific `WebContents` navigation events (e.g. `did-frame-navigate`)


Returns `WebFrame` - that has the supplied `routingId`, `null` if not found.


### 
`webFrame.isWordMisspelled(word)`[​](#webframeiswordmisspelledword "Direct link to heading")


* `word` string - The word to be spellchecked.


Returns `boolean` - True if the word is misspelled according to the built in spellchecker, false otherwise. If no dictionary is loaded, always return false.


### 
`webFrame.getWordSuggestions(word)`[​](#webframegetwordsuggestionsword "Direct link to heading")


* `word` string - The misspelled word.


Returns `string[]` - A list of suggested words for a given word. If the word is spelled correctly, the result will be empty.


Properties[​](#properties "Direct link to heading")
---------------------------------------------------


### 
`webFrame.top` *Readonly*[​](#webframetop-readonly "Direct link to heading")


A `WebFrame | null` representing top frame in frame hierarchy to which `webFrame` belongs, the property would be `null` if top frame is not in the current renderer process.


### 
`webFrame.opener` *Readonly*[​](#webframeopener-readonly "Direct link to heading")


A `WebFrame | null` representing the frame which opened `webFrame`, the property would be `null` if there's no opener or opener is not in the current renderer process.


### 
`webFrame.parent` *Readonly*[​](#webframeparent-readonly "Direct link to heading")


A `WebFrame | null` representing parent frame of `webFrame`, the property would be `null` if `webFrame` is top or parent is not in the current renderer process.


### 
`webFrame.firstChild` *Readonly*[​](#webframefirstchild-readonly "Direct link to heading")


A `WebFrame | null` representing the first child frame of `webFrame`, the property would be `null` if `webFrame` has no children or if first child is not in the current renderer process.


### 
`webFrame.nextSibling` *Readonly*[​](#webframenextsibling-readonly "Direct link to heading")


A `WebFrame | null` representing next sibling frame, the property would be `null` if `webFrame` is the last frame in its parent or if the next sibling is not in the current renderer process.


### 
`webFrame.routingId` *Readonly*[​](#webframeroutingid-readonly "Direct link to heading")


An `Integer` representing the unique frame id in the current renderer process. Distinct WebFrame instances that refer to the same underlying frame will have the same `routingId`.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/web-frame>

Goma
====



> Goma is a distributed compiler service for open-source projects such as Chromium and Android.
> 
> 


Electron has a deployment of a custom Goma Backend that we make available to all Electron Maintainers. See the [Access](#access) section below for details on authentication. There is also a `cache-only` Goma endpoint that will be used by default if you do not have credentials. Requests to the cache-only Goma will not hit our cluster, but will read from our cache and should result in significantly faster build times.


Enabling Goma[​](#enabling-goma "Direct link to heading")
---------------------------------------------------------


Currently the only supported way to use Goma is to use our [Build Tools](https://github.com/electron/build-tools). Goma configuration is automatically included when you set up `build-tools`.


If you are a maintainer and have access to our cluster, please ensure that you run `e init` with `--goma=cluster` in order to configure `build-tools` to use the Goma cluster. If you have an existing config, you can just set `"goma": "cluster"` in your config file.


Building with Goma[​](#building-with-goma "Direct link to heading")
-------------------------------------------------------------------


When you are using Goma you can run `ninja` with a substantially higher `j` value than would normally be supported by your machine.


Please do not set a value higher than **200**. We monitor Goma system usage, and users found to be abusing it with unreasonable concurrency will be de-activated.




```
ninja -C out/Testing electron -j 200
```


If you're using `build-tools`, appropriate `-j` values will automatically be used for you.


Monitoring Goma[​](#monitoring-goma "Direct link to heading")
-------------------------------------------------------------


If you access <http://localhost:8088> on your local machine you can monitor compile jobs as they flow through the goma system.


Access[​](#access "Direct link to heading")
-------------------------------------------


For security and cost reasons, access to Electron's Goma cluster is currently restricted to Electron Maintainers. If you want access please head to `#access-requests` in Slack and ping `@goma-squad` to ask for access. Please be aware that being a maintainer does not *automatically* grant access and access is determined on a case by case basis.


Uptime / Support[​](#uptime--support "Direct link to heading")
--------------------------------------------------------------


We have automated monitoring of our Goma cluster and cache at <https://status.notgoma.com>


We do not provide support for usage of Goma and any issues raised asking for help / having issues will *probably* be closed without much reason, we do not have the capacity to handle that kind of support.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/goma>

Coding Style
============


These are the style guidelines for coding in Electron.


You can run `npm run lint` to show any style issues detected by `cpplint` and `eslint`.


General Code[​](#general-code "Direct link to heading")
-------------------------------------------------------


* End files with a newline.
* Place requires in the following order:
	+ Built in Node Modules (such as `path`)
	+ Built in Electron Modules (such as `ipc`, `app`)
	+ Local Modules (using relative paths)
* Place class properties in the following order:
	+ Class methods and properties (methods starting with a `@`)
	+ Instance methods and properties
* Avoid platform-dependent code:
	+ Use `path.join()` to concatenate filenames.
	+ Use `os.tmpdir()` rather than `/tmp` when you need to reference the temporary directory.
* Using a plain `return` when returning explicitly at the end of a function.
	+ Not `return null`, `return undefined`, `null` or `undefined`


C++ and Python[​](#c-and-python "Direct link to heading")
---------------------------------------------------------


For C++ and Python, we follow Chromium's [Coding Style](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/styleguide.md). There is also a script `script/cpplint.py` to check whether all files conform.


The Python version we are using now is Python 3.9.


The C++ code uses a lot of Chromium's abstractions and types, so it's recommended to get acquainted with them. A good place to start is Chromium's [Important Abstractions and Data Structures](https://www.chromium.org/developers/coding-style/important-abstractions-and-data-structures) document. The document mentions some special types, scoped types (that automatically release their memory when going out of scope), logging mechanisms etc.


Documentation[​](#documentation "Direct link to heading")
---------------------------------------------------------


* Write [remark](https://github.com/remarkjs/remark) markdown style.


You can run `npm run lint-docs` to ensure that your documentation changes are formatted correctly.


JavaScript[​](#javascript "Direct link to heading")
---------------------------------------------------


* Write [standard](https://www.npmjs.com/package/standard) JavaScript style.
* File names should be concatenated with `-` instead of `_`, e.g. `file-name.js` rather than `file_name.js`, because in [github/atom](https://github.com/github/atom) module names are usually in the `module-name` form. This rule only applies to `.js` files.
* Use newer ES6/ES2015 syntax where appropriate
	+ [`const`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const) for requires and other constants. If the value is a primitive, use uppercase naming (eg `const NUMBER_OF_RETRIES = 5`).
	+ [`let`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let) for defining variables
	+ [Arrow functions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) instead of `function () { }`
	+ [Template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) instead of string concatenation using `+`


Naming Things[​](#naming-things "Direct link to heading")
---------------------------------------------------------


Electron APIs uses the same capitalization scheme as Node.js:


* When the module itself is a class like `BrowserWindow`, use `PascalCase`.
* When the module is a set of APIs, like `globalShortcut`, use `camelCase`.
* When the API is a property of object, and it is complex enough to be in a separate chapter like `win.webContents`, use `mixedCase`.
* For other non-module APIs, use natural titles, like `<webview> Tag` or `Process Object`.


When creating a new API, it is preferred to use getters and setters instead of jQuery's one-function style. For example, `.getText()` and `.setText(text)` are preferred to `.text([text])`. There is a [discussion](https://github.com/electron/electron/issues/46) on this.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/coding-style>

In-App Purchases
================


Preparing[​](#preparing "Direct link to heading")
-------------------------------------------------


### Paid Applications Agreement[​](#paid-applications-agreement "Direct link to heading")


If you haven't already, you’ll need to sign the Paid Applications Agreement and set up your banking and tax information in iTunes Connect.


[iTunes Connect Developer Help: Agreements, tax, and banking overview](https://help.apple.com/itunes-connect/developer/#/devb6df5ee51)


### Create Your In-App Purchases[​](#create-your-in-app-purchases "Direct link to heading")


Then, you'll need to configure your in-app purchases in iTunes Connect, and include details such as name, pricing, and description that highlights the features and functionality of your in-app purchase.


[iTunes Connect Developer Help: Create an in-app purchase](https://help.apple.com/itunes-connect/developer/#/devae49fb316)


### Change the CFBundleIdentifier[​](#change-the-cfbundleidentifier "Direct link to heading")


To test In-App Purchase in development with Electron you'll have to change the `CFBundleIdentifier` in `node_modules/electron/dist/Electron.app/Contents/Info.plist`. You have to replace `com.github.electron` by the bundle identifier of the application you created with iTunes Connect.




```
<key>CFBundleIdentifier</key>
<string>com.example.app</string>
```


Code example[​](#code-example "Direct link to heading")
-------------------------------------------------------


Here is an example that shows how to use In-App Purchases in Electron. You'll have to replace the product ids by the identifiers of the products created with iTunes Connect (the identifier of `com.example.app.product1` is `product1`). Note that you have to listen to the `transactions-updated` event as soon as possible in your app.




```
// Main process
const { inAppPurchase } = require('electron')
const PRODUCT_IDS = ['id1', 'id2']

// Listen for transactions as soon as possible.
inAppPurchase.on('transactions-updated', (event, transactions) => {
  if (!Array.isArray(transactions)) {
    return
  }

  // Check each transaction.
  transactions.forEach((transaction) => {
    const payment = transaction.payment

    switch (transaction.transactionState) {
      case 'purchasing':
        console.log(`Purchasing ${payment.productIdentifier}...`)
        break

      case 'purchased': {
        console.log(`${payment.productIdentifier} purchased.`)

        // Get the receipt url.
        const receiptURL = inAppPurchase.getReceiptURL()

        console.log(`Receipt URL: ${receiptURL}`)

        // Submit the receipt file to the server and check if it is valid.
        // @see https://developer.apple.com/library/content/releasenotes/General/ValidateAppStoreReceipt/Chapters/ValidateRemotely.html
        // ...
        // If the receipt is valid, the product is purchased
        // ...

        // Finish the transaction.
        inAppPurchase.finishTransactionByDate(transaction.transactionDate)

        break
      }

      case 'failed':

        console.log(`Failed to purchase ${payment.productIdentifier}.`)

        // Finish the transaction.
        inAppPurchase.finishTransactionByDate(transaction.transactionDate)

        break
      case 'restored':

        console.log(`The purchase of ${payment.productIdentifier} has been restored.`)

        break
      case 'deferred':

        console.log(`The purchase of ${payment.productIdentifier} has been deferred.`)

        break
      default:
        break
    }
  })
})

// Check if the user is allowed to make in-app purchase.
if (!inAppPurchase.canMakePayments()) {
  console.log('The user is not allowed to make in-app purchase.')
}

// Retrieve and display the product descriptions.
inAppPurchase.getProducts(PRODUCT_IDS).then(products => {
  // Check the parameters.
  if (!Array.isArray(products) || products.length <= 0) {
    console.log('Unable to retrieve the product informations.')
    return
  }

  // Display the name and price of each product.
  products.forEach(product => {
    console.log(`The price of ${product.localizedTitle} is ${product.formattedPrice}.`)
  })

  // Ask the user which product they want to purchase.
  const selectedProduct = products[0]
  const selectedQuantity = 1

  // Purchase the selected product.
  inAppPurchase.purchaseProduct(selectedProduct.productIdentifier, selectedQuantity).then(isProductValid => {
    if (!isProductValid) {
      console.log('The product is not valid.')
      return
    }

    console.log('The payment has been added to the payment queue.')
  })
})
```



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/in-app-purchases>

CustomScheme Object
===================


* `scheme` string - Custom schemes to be registered with options.
* `privileges` Object (optional)
	+ `standard` boolean (optional) - Default false.
	+ `secure` boolean (optional) - Default false.
	+ `bypassCSP` boolean (optional) - Default false.
	+ `allowServiceWorkers` boolean (optional) - Default false.
	+ `supportFetchAPI` boolean (optional) - Default false.
	+ `corsEnabled` boolean (optional) - Default false.
	+ `stream` boolean (optional) - Default false.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/custom-scheme>

Source Code Directory Structure
===============================


The source code of Electron is separated into a few parts, mostly following Chromium on the separation conventions.


You may need to become familiar with [Chromium's multi-process architecture](https://dev.chromium.org/developers/design-documents/multi-process-architecture) to understand the source code better.


Structure of Source Code[​](#structure-of-source-code "Direct link to heading")
-------------------------------------------------------------------------------




```
Electron
├── build/ - Build configuration files needed to build with GN.
├── buildflags/ - Determines the set of features that can be conditionally built.
├── chromium_src/ - Source code copied from Chromium that isn't part of the content layer.
├── default_app/ - A default app run when Electron is started without
|                  providing a consumer app.
├── docs/ - Electron's documentation.
|   ├── api/ - Documentation for Electron's externally-facing modules and APIs.
|   ├── development/ - Documentation to aid in developing for and with Electron.
|   ├── fiddles/ - A set of code snippets one can run in Electron Fiddle.
|   ├── images/ - Images used in documentation.
|   └── tutorial/ - Tutorial documents for various aspects of Electron.
├── lib/ - JavaScript/TypeScript source code.
|   ├── browser/ - Main process initialization code.
|   |   ├── api/ - API implementation for main process modules.
|   |   └── remote/ - Code related to the remote module as it is
|   |                 used in the main process.
|   ├── common/ - Relating to logic needed by both main and renderer processes.
|   |   └── api/ - API implementation for modules that can be used in
|   |              both the main and renderer processes
|   ├── isolated_renderer/ - Handles creation of isolated renderer processes when
|   |                        contextIsolation is enabled.
|   ├── renderer/ - Renderer process initialization code.
|   |   ├── api/ - API implementation for renderer process modules.
|   |   ├── extension/ - Code related to use of Chrome Extensions
|   |   |                in Electron's renderer process.
|   |   ├── remote/ - Logic that handles use of the remote module in
|   |   |             the main process.
|   |   └── web-view/ - Logic that handles the use of webviews in the
|   |                   renderer process.
|   ├── sandboxed_renderer/ - Logic that handles creation of sandboxed renderer
|   |   |                     processes.
|   |   └── api/ - API implementation for sandboxed renderer processes.
|   └── worker/ - Logic that handles proper functionality of Node.js
|                 environments in Web Workers.
├── patches/ - Patches applied on top of Electron's core dependencies
|   |          in order to handle differences between our use cases and
|   |          default functionality.
|   ├── boringssl/ - Patches applied to Google's fork of OpenSSL, BoringSSL.
|   ├── chromium/ - Patches applied to Chromium.
|   ├── node/ - Patches applied on top of Node.js.
|   └── v8/ - Patches applied on top of Google's V8 engine.
├── shell/ - C++ source code.
|   ├── app/ - System entry code.
|   ├── browser/ - The frontend including the main window, UI, and all of the
|   |   |          main process things. This talks to the renderer to manage web
|   |   |          pages.
|   |   ├── ui/ - Implementation of UI stuff for different platforms.
|   |   |   ├── cocoa/ - Cocoa specific source code.
|   |   |   ├── win/ - Windows GUI specific source code.
|   |   |   └── x/ - X11 specific source code.
|   |   ├── api/ - The implementation of the main process APIs.
|   |   ├── net/ - Network related code.
|   |   ├── mac/ - Mac specific Objective-C source code.
|   |   └── resources/ - Icons, platform-dependent files, etc.
|   ├── renderer/ - Code that runs in renderer process.
|   |   └── api/ - The implementation of renderer process APIs.
|   └── common/ - Code that used by both the main and renderer processes,
|       |         including some utility functions and code to integrate node's
|       |         message loop into Chromium's message loop.
|       └── api/ - The implementation of common APIs, and foundations of
|                  Electron's built-in modules.
├── spec/ - Components of Electron's test suite run in the renderer process.
├── spec-main/ - Components of Electron's test suite run in the main process.
└── BUILD.gn - Building rules of Electron.
```


Structure of Other Directories[​](#structure-of-other-directories "Direct link to heading")
-------------------------------------------------------------------------------------------


* **.circleci** - Config file for CI with CircleCI.
* **.github** - GitHub-specific config files including issues templates and CODEOWNERS.
* **dist** - Temporary directory created by `script/create-dist.py` script when creating a distribution.
* **node\_modules** - Third party node modules used for building.
* **npm** - Logic for installation of Electron via npm.
* **out** - Temporary output directory of `ninja`.
* **script** - Scripts used for development purpose like building, packaging, testing, etc.




```
script/ - The set of all scripts Electron runs for a variety of purposes.
├── codesign/ - Fakes codesigning for Electron apps; used for testing.
├── lib/ - Miscellaneous python utility scripts.
└── release/ - Scripts run during Electron's release process.
    ├── notes/ - Generates release notes for new Electron versions.
    └── uploaders/ - Uploads various release-related files during release.
```


* **typings** - TypeScript typings for Electron's internal code.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/source-code-directory-structure>

Issues In Electron
==================


* [How to Contribute to Issues](#how-to-contribute-to-issues)
* [Asking for General Help](#asking-for-general-help)
* [Submitting a Bug Report](#submitting-a-bug-report)
* [Triaging a Bug Report](#triaging-a-bug-report)
* [Resolving a Bug Report](#resolving-a-bug-report)


How to Contribute to Issues[​](#how-to-contribute-to-issues "Direct link to heading")
-------------------------------------------------------------------------------------


For any issue, there are fundamentally three ways an individual can contribute:


1. By opening the issue for discussion: If you believe that you have found a new bug in Electron, you should report it by creating a new issue in the [`electron/electron` issue tracker](https://github.com/electron/electron/issues).
2. By helping to triage the issue: You can do this either by providing assistive details (a reproducible test case that demonstrates a bug) or by providing suggestions to address the issue.
3. By helping to resolve the issue: This can be done by demonstrating that the issue is not a bug or is fixed; but more often, by opening a pull request that changes the source in `electron/electron` in a concrete and reviewable manner.


Asking for General Help[​](#asking-for-general-help "Direct link to heading")
-----------------------------------------------------------------------------


[The Electron website](https://electronjs.org/community) has a list of resources for getting programming help, reporting security issues, contributing, and more. Please use the issue tracker for bugs only!


Submitting a Bug Report[​](#submitting-a-bug-report "Direct link to heading")
-----------------------------------------------------------------------------


To submit a bug report:


When opening a new issue in the [`electron/electron` issue tracker](https://github.com/electron/electron/issues/new/choose), users will be presented with a template that should be filled in.


If you believe that you have found a bug in Electron, please fill out the template to the best of your ability.


The two most important pieces of information needed to evaluate the report are a description of the bug and a simple test case to recreate it. It is easier to fix a bug if it can be reproduced.


See [How to create a Minimal, Complete, and Verifiable example](https://stackoverflow.com/help/mcve).


Triaging a Bug Report[​](#triaging-a-bug-report "Direct link to heading")
-------------------------------------------------------------------------


It's common for open issues to involve discussion. Some contributors may have differing opinions, including whether the behavior is a bug or feature. This discussion is part of the process and should be kept focused, helpful, and professional.


Terse responses that provide neither additional context nor supporting detail are not helpful or professional. To many, such responses are annoying and unfriendly.


Contributors are encouraged to solve issues collaboratively and help one another make progress. If you encounter an issue that you feel is invalid, or which contains incorrect information, explain *why* you feel that way with additional supporting context, and be willing to be convinced that you may be wrong. By doing so, we can often reach the correct outcome faster.


Resolving a Bug Report[​](#resolving-a-bug-report "Direct link to heading")
---------------------------------------------------------------------------


Most issues are resolved by opening a pull request. The process for opening and reviewing a pull request is similar to that of opening and triaging issues, but carries with it a necessary review and approval workflow that ensures that the proposed changes meet the minimal quality and functional guidelines of the Electron project.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/issues>

SpellChecker
============


Electron has built-in support for Chromium's spellchecker since Electron 8. On Windows and Linux this is powered by Hunspell dictionaries, and on macOS it makes use of the native spellchecker APIs.


How to enable the spellchecker?[​](#how-to-enable-the-spellchecker "Direct link to heading")
--------------------------------------------------------------------------------------------


For Electron 9 and higher the spellchecker is enabled by default. For Electron 8 you need to enable it in `webPreferences`.




```
const myWindow = new BrowserWindow({
  webPreferences: {
    spellcheck: true
  }
})
```


How to set the languages the spellchecker uses?[​](#how-to-set-the-languages-the-spellchecker-uses "Direct link to heading")
----------------------------------------------------------------------------------------------------------------------------


On macOS as we use the native APIs there is no way to set the language that the spellchecker uses. By default on macOS the native spellchecker will automatically detect the language being used for you.


For Windows and Linux there are a few Electron APIs you should use to set the languages for the spellchecker.




```
// Sets the spellchecker to check English US and French
myWindow.session.setSpellCheckerLanguages(['en-US', 'fr'])

// An array of all available language codes
const possibleLanguages = myWindow.session.availableSpellCheckerLanguages
```


By default the spellchecker will enable the language matching the current OS locale.


How do I put the results of the spellchecker in my context menu?[​](#how-do-i-put-the-results-of-the-spellchecker-in-my-context-menu "Direct link to heading")
--------------------------------------------------------------------------------------------------------------------------------------------------------------


All the required information to generate a context menu is provided in the [`context-menu`](../api/web-contents#event-context-menu) event on each `webContents` instance. A small example of how to make a context menu with this information is provided below.




```
const { Menu, MenuItem } = require('electron')

myWindow.webContents.on('context-menu', (event, params) => {
  const menu = new Menu()

  // Add each spelling suggestion
  for (const suggestion of params.dictionarySuggestions) {
    menu.append(new MenuItem({
      label: suggestion,
      click: () => mainWindow.webContents.replaceMisspelling(suggestion)
    }))
  }

  // Allow users to add the misspelled word to the dictionary
  if (params.misspelledWord) {
    menu.append(
      new MenuItem({
        label: 'Add to dictionary',
        click: () => mainWindow.webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord)
      })
    )
  }

  menu.popup()
})
```


Does the spellchecker use any Google services?[​](#does-the-spellchecker-use-any-google-services "Direct link to heading")
--------------------------------------------------------------------------------------------------------------------------


Although the spellchecker itself does not send any typings, words or user input to Google services the hunspell dictionary files are downloaded from a Google CDN by default. If you want to avoid this you can provide an alternative URL to download the dictionaries from.




```
myWindow.session.setSpellCheckerDictionaryDownloadURL('https://example.com/dictionaries/')
```


Check out the docs for [`session.setSpellCheckerDictionaryDownloadURL`](../api/session#sessetspellcheckerdictionarydownloadurlurl) for more information on where to get the dictionary files from and how you need to host them.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/spellchecker>

Automated Testing
=================


Test automation is an efficient way of validating that your application code works as intended. While Electron doesn't actively maintain its own testing solution, this guide will go over a couple ways you can run end-to-end automated tests on your Electron app.


Using the WebDriver interface[​](#using-the-webdriver-interface "Direct link to heading")
-----------------------------------------------------------------------------------------


From [ChromeDriver - WebDriver for Chrome](https://sites.google.com/chromium.org/driver/):



> WebDriver is an open source tool for automated testing of web apps across many browsers. It provides capabilities for navigating to web pages, user input, JavaScript execution, and more. ChromeDriver is a standalone server which implements WebDriver's wire protocol for Chromium. It is being developed by members of the Chromium and WebDriver teams.
> 
> 


There are a few ways that you can set up testing using WebDriver.


### With WebdriverIO[​](#with-webdriverio "Direct link to heading")


[WebdriverIO](https://webdriver.io/) (WDIO) is a test automation framework that provides a Node.js package for testing with WebDriver. Its ecosystem also includes various plugins (e.g. reporter and services) that can help you put together your test setup.


#### Install the testrunner[​](#install-the-testrunner "Direct link to heading")


First you need to run the WebdriverIO starter toolkit in your project root directory:



* npm
* Yarn





```
npx wdio . --yes
```




```
npx wdio . --yes
```




This installs all necessary packages for you and generates a `wdio.conf.js` configuration file.


#### Connect WDIO to your Electron app[​](#connect-wdio-to-your-electron-app "Direct link to heading")


Update the capabilities in your configuration file to point to your Electron app binary:



wdio.conf.js


```
export.config = {
  // ...
  capabilities: [{
    browserName: 'chrome',
    'goog:chromeOptions': {
      binary: '/path/to/your/electron/binary', // Path to your Electron binary.
      args: [/* cli arguments */] // Optional, perhaps 'app=' + /path/to/your/app/
    }
  }]
  // ...
}
```



#### Run your tests[​](#run-your-tests "Direct link to heading")


To run your tests:




```
$ npx wdio run wdio.conf.js
```


### With Selenium[​](#with-selenium "Direct link to heading")


[Selenium](https://www.selenium.dev/) is a web automation framework that exposes bindings to WebDriver APIs in many languages. Their Node.js bindings are available under the `selenium-webdriver` package on NPM.


#### Run a ChromeDriver server[​](#run-a-chromedriver-server "Direct link to heading")


In order to use Selenium with Electron, you need to download the `electron-chromedriver` binary, and run it:



* npm
* Yarn





```
npm install --save-dev electron-chromedriver
./node_modules/.bin/chromedriver
Starting ChromeDriver (v2.10.291558) on port 9515
Only local connections are allowed.
```




```
yarn add --dev electron-chromedriver
./node_modules/.bin/chromedriver
Starting ChromeDriver (v2.10.291558) on port 9515
Only local connections are allowed.
```




Remember the port number `9515`, which will be used later.


#### Connect Selenium to ChromeDriver[​](#connect-selenium-to-chromedriver "Direct link to heading")


Next, install Selenium into your project:



* npm
* Yarn





```
npm install --save-dev selenium-webdriver
```




```
yarn add --dev selenium-webdriver
```




Usage of `selenium-webdriver` with Electron is the same as with normal websites, except that you have to manually specify how to connect ChromeDriver and where to find the binary of your Electron app:



test.js


```
const webdriver = require('selenium-webdriver')
const driver = new webdriver.Builder()
  // The "9515" is the port opened by ChromeDriver.
  .usingServer('http://localhost:9515')
  .withCapabilities({
    'goog:chromeOptions': {
      // Here is the path to your Electron binary.
      binary: '/Path-to-Your-App.app/Contents/MacOS/Electron'
    }
  })
  .forBrowser('chrome') // note: use .forBrowser('electron') for selenium-webdriver <= 3.6.0
  .build()
driver.get('http://www.google.com')
driver.findElement(webdriver.By.name('q')).sendKeys('webdriver')
driver.findElement(webdriver.By.name('btnG')).click()
driver.wait(() => {
  return driver.getTitle().then((title) => {
    return title === 'webdriver - Google Search'
  })
}, 1000)
driver.quit()
```



Using Playwright[​](#using-playwright "Direct link to heading")
---------------------------------------------------------------


[Microsoft Playwright](https://playwright.dev) is an end-to-end testing framework built using browser-specific remote debugging protocols, similar to the [Puppeteer](https://github.com/puppeteer/puppeteer) headless Node.js API but geared towards end-to-end testing. Playwright has experimental Electron support via Electron's support for the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/) (CDP).


### Install dependencies[​](#install-dependencies "Direct link to heading")


You can install Playwright through your preferred Node.js package manager. The Playwright team recommends using the `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` environment variable to avoid unnecessary browser downloads when testing an Electron app.



* npm
* Yarn





```
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm install --save-dev playwright
```




```
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 yarn add --dev playwright
```




Playwright also comes with its own test runner, Playwright Test, which is built for end-to-end testing. You can also install it as a dev dependency in your project:



* npm
* Yarn





```
npm install --save-dev @playwright/test
```




```
yarn add --dev @playwright/test
```






Dependencies
This tutorial was written `playwright@1.16.3` and `@playwright/test@1.16.3`. Check out [Playwright's releases](https://github.com/microsoft/playwright/releases) page to learn about changes that might affect the code below.





Using third-party test runners
If you're interested in using an alternative test runner (e.g. Jest or Mocha), check out Playwright's [Third-Party Test Runner](https://playwright.dev/docs/test-runners/) guide.



### Write your tests[​](#write-your-tests "Direct link to heading")


Playwright launches your app in development mode through the `_electron.launch` API. To point this API to your Electron app, you can pass the path to your main process entry point (here, it is `main.js`).




```
const { _electron: electron } = require('playwright')
const { test } = require('@playwright/test')

test('launch app', async () => {
  const electronApp = await electron.launch({ args: ['main.js'] })
  // close app
  await electronApp.close()
})
```


After that, you will access to an instance of Playwright's `ElectronApp` class. This is a powerful class that has access to main process modules for example:




```
const { _electron: electron } = require('playwright')
const { test } = require('@playwright/test')

test('get isPackaged', async () => {
  const electronApp = await electron.launch({ args: ['main.js'] })
  const isPackaged = await electronApp.evaluate(async ({ app }) => {
    // This runs in Electron's main process, parameter here is always
    // the result of the require('electron') in the main app script.
    return app.isPackaged
  })
  console.log(isPackaged) // false (because we're in development mode)
  // close app
  await electronApp.close()
})
```


It can also create individual [Page](https://playwright.dev/docs/api/class-page) objects from Electron BrowserWindow instances. For example, to grab the first BrowserWindow and save a screenshot:




```
const { _electron: electron } = require('playwright')
const { test } = require('@playwright/test')

test('save screenshot', async () => {
  const electronApp = await electron.launch({ args: ['main.js'] })
  const window = await electronApp.firstWindow()
  await window.screenshot({ path: 'intro.png' })
  // close app
  await electronApp.close()
})
```


Putting all this together using the PlayWright Test runner, let's create a `example.spec.js` test file with a single test and assertion:



example.spec.js


```
const { _electron: electron } = require('playwright')
const { test, expect } = require('@playwright/test')

test('example test', async () => {
  const electronApp = await electron.launch({ args: ['.'] })
  const isPackaged = await electronApp.evaluate(async ({ app }) => {
    // This runs in Electron's main process, parameter here is always
    // the result of the require('electron') in the main app script.
    return app.isPackaged;
  });

  expect(isPackaged).toBe(false);

  // Wait for the first BrowserWindow to open
  // and return its Page object
  const window = await electronApp.firstWindow()
  await window.screenshot({ path: 'intro.png' })

  // close app
  await electronApp.close()
});
```



Then, run Playwright Test using `npx playwright test`. You should see the test pass in your console, and have an `intro.png` screenshot on your filesystem.




```
☁  $ npx playwright test

Running 1 test using 1 worker

  ✓  example.spec.js:4:1 › example test (1s)
```




info
Playwright Test will automatically run any files matching the `.*(test|spec)\.(js|ts|mjs)` regex. You can customize this match in the [Playwright Test configuration options](https://playwright.dev/docs/api/class-testconfig#test-config-test-match).





Further reading
Check out Playwright's documentation for the full [Electron](https://playwright.dev/docs/api/class-electron/) and [ElectronApplication](https://playwright.dev/docs/api/class-electronapplication) class APIs.



Using a custom test driver[​](#using-a-custom-test-driver "Direct link to heading")
-----------------------------------------------------------------------------------


It's also possible to write your own custom driver using Node.js' built-in IPC-over-STDIO. Custom test drivers require you to write additional app code, but have lower overhead and let you expose custom methods to your test suite.


To create a custom driver, we'll use Node.js' [`child_process`](https://nodejs.org/api/child_process.html) API. The test suite will spawn the Electron process, then establish a simple messaging protocol:



testDriver.js


```
const childProcess = require('child_process')
const electronPath = require('electron')

// spawn the process
const env = { /* ... */ }
const stdio = ['inherit', 'inherit', 'inherit', 'ipc']
const appProcess = childProcess.spawn(electronPath, ['./app'], { stdio, env })

// listen for IPC messages from the app
appProcess.on('message', (msg) => {
  // ...
})

// send an IPC message to the app
appProcess.send({ my: 'message' })
```



From within the Electron app, you can listen for messages and send replies using the Node.js [`process`](https://nodejs.org/api/process.html) API:



main.js


```
// listen for messages from the test suite
process.on('message', (msg) => {
  // ...
})

// send a message to the test suite
process.send({ my: 'message' })
```



We can now communicate from the test suite to the Electron app using the `appProcess` object.


For convenience, you may want to wrap `appProcess` in a driver object that provides more high-level functions. Here is an example of how you can do this. Let's start by creating a `TestDriver` class:



testDriver.js


```
class TestDriver {
  constructor ({ path, args, env }) {
    this.rpcCalls = []

    // start child process
    env.APP_TEST_DRIVER = 1 // let the app know it should listen for messages
    this.process = childProcess.spawn(path, args, { stdio: ['inherit', 'inherit', 'inherit', 'ipc'], env })

    // handle rpc responses
    this.process.on('message', (message) => {
      // pop the handler
      const rpcCall = this.rpcCalls[message.msgId]
      if (!rpcCall) return
      this.rpcCalls[message.msgId] = null
      // reject/resolve
      if (message.reject) rpcCall.reject(message.reject)
      else rpcCall.resolve(message.resolve)
    })

    // wait for ready
    this.isReady = this.rpc('isReady').catch((err) => {
      console.error('Application failed to start', err)
      this.stop()
      process.exit(1)
    })
  }

  // simple RPC call
  // to use: driver.rpc('method', 1, 2, 3).then(...)
  async rpc (cmd, ...args) {
    // send rpc request
    const msgId = this.rpcCalls.length
    this.process.send({ msgId, cmd, args })
    return new Promise((resolve, reject) => this.rpcCalls.push({ resolve, reject }))
  }

  stop () {
    this.process.kill()
  }
}

module.exports = { TestDriver };
```



In your app code, can then write a simple handler to receive RPC calls:



main.js


```
const METHODS = {
  isReady () {
    // do any setup needed
    return true
  }
  // define your RPC-able methods here
}

const onMessage = async ({ msgId, cmd, args }) => {
  let method = METHODS[cmd]
  if (!method) method = () => new Error('Invalid method: ' + cmd)
  try {
    const resolve = await method(...args)
    process.send({ msgId, resolve })
  } catch (err) {
    const reject = {
      message: err.message,
      stack: err.stack,
      name: err.name
    }
    process.send({ msgId, reject })
  }
}

if (process.env.APP_TEST_DRIVER) {
  process.on('message', onMessage)
}
```



Then, in your test suite, you can use your `TestDriver` class with the test automation framework of your choosing. The following example uses [`ava`](https://www.npmjs.com/package/ava), but other popular choices like Jest or Mocha would work as well:



test.js


```
const test = require('ava')
const electronPath = require('electron')
const { TestDriver } = require('./testDriver')

const app = new TestDriver({
  path: electronPath,
  args: ['./app'],
  env: {
    NODE_ENV: 'test'
  }
})
test.before(async t => {
  await app.isReady
})
test.after.always('cleanup', async t => {
  await app.stop()
})
```




 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/automated-testing>

Class: TouchBarSlider
=====================

Class: TouchBarSlider[​](#class-touchbarslider "Direct link to heading")
------------------------------------------------------------------------



> Create a slider in the touch bar for native macOS applications
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


### 
`new TouchBarSlider(options)`[​](#new-touchbarslideroptions "Direct link to heading")


* `options` Object
	+ `label` string (optional) - Label text.
	+ `value` Integer (optional) - Selected value.
	+ `minValue` Integer (optional) - Minimum value.
	+ `maxValue` Integer (optional) - Maximum value.
	+ `change` Function (optional) - Function to call when the slider is changed.
		- `newValue` number - The value that the user selected on the Slider.


### Instance Properties[​](#instance-properties "Direct link to heading")


The following properties are available on instances of `TouchBarSlider`:


#### 
`touchBarSlider.label`[​](#touchbarsliderlabel "Direct link to heading")


A `string` representing the slider's current text. Changing this value immediately updates the slider in the touch bar.


#### 
`touchBarSlider.value`[​](#touchbarslidervalue "Direct link to heading")


A `number` representing the slider's current value. Changing this value immediately updates the slider in the touch bar.


#### 
`touchBarSlider.minValue`[​](#touchbarsliderminvalue "Direct link to heading")


A `number` representing the slider's current minimum value. Changing this value immediately updates the slider in the touch bar.


#### 
`touchBarSlider.maxValue`[​](#touchbarslidermaxvalue "Direct link to heading")


A `number` representing the slider's current maximum value. Changing this value immediately updates the slider in the touch bar.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/touch-bar-slider>

Class: TouchBarButton
=====================

Class: TouchBarButton[​](#class-touchbarbutton "Direct link to heading")
------------------------------------------------------------------------



> Create a button in the touch bar for native macOS applications
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


### 
`new TouchBarButton(options)`[​](#new-touchbarbuttonoptions "Direct link to heading")


* `options` Object
	+ `label` string (optional) - Button text.
	+ `accessibilityLabel` string (optional) - A short description of the button for use by screenreaders like VoiceOver.
	+ `backgroundColor` string (optional) - Button background color in hex format, i.e `#ABCDEF`.
	+ `icon` [NativeImage](native-image) | string (optional) - Button icon.
	+ `iconPosition` string (optional) - Can be `left`, `right` or `overlay`. Defaults to `overlay`.
	+ `click` Function (optional) - Function to call when the button is clicked.
	+ `enabled` boolean (optional) - Whether the button is in an enabled state. Default is `true`.


When defining `accessibilityLabel`, ensure you have considered macOS [best practices](https://developer.apple.com/documentation/appkit/nsaccessibilitybutton/1524910-accessibilitylabel?language=objc).


### Instance Properties[​](#instance-properties "Direct link to heading")


The following properties are available on instances of `TouchBarButton`:


#### 
`touchBarButton.accessibilityLabel`[​](#touchbarbuttonaccessibilitylabel "Direct link to heading")


A `string` representing the description of the button to be read by a screen reader. Will only be read by screen readers if no label is set.


#### 
`touchBarButton.label`[​](#touchbarbuttonlabel "Direct link to heading")


A `string` representing the button's current text. Changing this value immediately updates the button in the touch bar.


#### 
`touchBarButton.backgroundColor`[​](#touchbarbuttonbackgroundcolor "Direct link to heading")


A `string` hex code representing the button's current background color. Changing this value immediately updates the button in the touch bar.


#### 
`touchBarButton.icon`[​](#touchbarbuttonicon "Direct link to heading")


A `NativeImage` representing the button's current icon. Changing this value immediately updates the button in the touch bar.


#### 
`touchBarButton.iconPosition`[​](#touchbarbuttoniconposition "Direct link to heading")


A `string` - Can be `left`, `right` or `overlay`. Defaults to `overlay`.


#### 
`touchBarButton.enabled`[​](#touchbarbuttonenabled "Direct link to heading")


A `boolean` representing whether the button is in an enabled state.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/touch-bar-button>

ProtocolResponse Object
=======================


* `error` Integer (optional) - When assigned, the `request` will fail with the `error` number . For the available error numbers you can use, please see the [net error list](https://source.chromium.org/chromium/chromium/src/+/main:net/base/net_error_list.h).
* `statusCode` number (optional) - The HTTP response code, default is 200.
* `charset` string (optional) - The charset of response body, default is `"utf-8"`.
* `mimeType` string (optional) - The MIME type of response body, default is `"text/html"`. Setting `mimeType` would implicitly set the `content-type` header in response, but if `content-type` is already set in `headers`, the `mimeType` would be ignored.
* `headers` Record<string, string | string[]> (optional) - An object containing the response headers. The keys must be string, and values must be either string or Array of string.
* `data` (Buffer | string | ReadableStream) (optional) - The response body. When returning stream as response, this is a Node.js readable stream representing the response body. When returning `Buffer` as response, this is a `Buffer`. When returning `string` as response, this is a `string`. This is ignored for other types of responses.
* `path` string (optional) - Path to the file which would be sent as response body. This is only used for file responses.
* `url` string (optional) - Download the `url` and pipe the result as response body. This is only used for URL responses.
* `referrer` string (optional) - The `referrer` URL. This is only used for file and URL responses.
* `method` string (optional) - The HTTP `method`. This is only used for file and URL responses.
* `session` Session (optional) - The session used for requesting URL, by default the HTTP request will reuse the current session. Setting `session` to `null` would use a random independent session. This is only used for URL responses.
* `uploadData` [ProtocolResponseUploadData](protocol-response-upload-data) (optional) - The data used as upload data. This is only used for URL responses when `method` is `"POST"`.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/protocol-response>

MimeTypedBuffer Object
======================


* `mimeType` string (optional) - MIME type of the buffer.
* `charset` string (optional) - Charset of the buffer.
* `data` Buffer - The actual Buffer content.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/mime-typed-buffer>

SegmentedControlSegment Object
==============================


* `label` string (optional) - The text to appear in this segment.
* `icon` NativeImage (optional) - The image to appear in this segment.
* `enabled` boolean (optional) - Whether this segment is selectable. Default: true.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/segmented-control-segment>

ServiceWorkerInfo Object
========================


* `scriptUrl` string - The full URL to the script that this service worker runs
* `scope` string - The base URL that this service worker is active for.
* `renderProcessId` number - The virtual ID of the process that this service worker is running in. This is not an OS level PID. This aligns with the ID set used for `webContents.getProcessId()`.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/service-worker-info>

Event Object extends `GlobalEvent`
==================================


* `preventDefault` VoidFunction



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/event>

Recent Documents
================


Overview[​](#overview "Direct link to heading")
-----------------------------------------------


Windows and macOS provide access to a list of recent documents opened by the application via JumpList or dock menu, respectively.


**JumpList:**


![JumpList Recent Files]


**Application dock menu:**


![macOS Dock Menu](https://cloud.githubusercontent.com/assets/639601/5069610/2aa80758-6e97-11e4-8cfb-c1a414a10774.png)


Example[​](#example "Direct link to heading")
---------------------------------------------


### Managing recent documents[​](#managing-recent-documents "Direct link to heading")




[docs/fiddles/features/recent-documents (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/features/recent-documents)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/features/recent-documents)


* main.js
* index.html





```
const { app, BrowserWindow } = require('electron')
const fs = require('fs')
const path = require('path')

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600
  })

  win.loadFile('index.html')
}

const fileName = 'recently-used.md'
fs.writeFile(fileName, 'Lorem Ipsum', () => {
  app.addRecentDocument(path.join(__dirname, fileName))
})

app.whenReady().then(createWindow)

app.on('window-all-closed', () => {
  app.clearRecentDocuments()
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})
```




```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Recent Documents</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
    <h1>Recent Documents</h1>
    <p>
        Right click on the app icon to see recent documents.
        You should see `recently-used.md` added to the list of recent files
    </p>
</body>
</html>
```





#### Adding a recent document[​](#adding-a-recent-document "Direct link to heading")


To add a file to recent documents, use the [app.addRecentDocument](../api/app#appaddrecentdocumentpath-macos-windows) API.


After launching the Electron application, right click the application icon. In this guide, the item is a Markdown file located in the root of the project. You should see `recently-used.md` added to the list of recent files:


![Recent document]


#### Clearing the list of recent documents[​](#clearing-the-list-of-recent-documents "Direct link to heading")


To clear the list of recent documents, use the [app.clearRecentDocuments](../api/app#appclearrecentdocuments-macos-windows) API. In this guide, the list of documents is cleared once all windows have been closed.


Additional information[​](#additional-information "Direct link to heading")
---------------------------------------------------------------------------


### Windows Notes[​](#windows-notes "Direct link to heading")


To use this feature on Windows, your application has to be registered as a handler of the file type of the document, otherwise the file won't appear in JumpList even after you have added it. You can find everything on registering your application in [Application Registration](https://msdn.microsoft.com/en-us/library/cc144104(VS.85).aspx).


When a user clicks a file from the JumpList, a new instance of your application will be started with the path of the file added as a command line argument.


### macOS Notes[​](#macos-notes "Direct link to heading")


#### Add the Recent Documents list to the application menu[​](#add-the-recent-documents-list-to-the-application-menu "Direct link to heading")


You can add menu items to access and clear recent documents by adding the following code snippet to your menu template:




```
{
  "submenu":[
    {
      "label":"Open Recent",
      "role":"recentdocuments",
      "submenu":[
        {
          "label":"Clear Recent",
          "role":"clearrecentdocuments"
        }
      ]
    }
  ]
}
```


Make sure the application menu is added after the [`'ready'`](../api/app#event-ready) event and not before, or the menu item will be disabled:




```
const { app, Menu } = require('electron')

const template = [
  // Menu template here
]
const menu = Menu.buildFromTemplate(template)

app.whenReady().then(() => {
  Menu.setApplicationMenu(menu)
})
```


![macOS Recent Documents menu item]


When a file is requested from the recent documents menu, the `open-file` event of `app` module will be emitted for it.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/recent-documents>

TouchBar
========


Class: TouchBar[​](#class-touchbar "Direct link to heading")
------------------------------------------------------------



> Create TouchBar layouts for native macOS applications
> 
> 


Process: [Main](../glossary#main-process)


### 
`new TouchBar(options)`[​](#new-touchbaroptions "Direct link to heading")


* `options` Object
	+ `items` ([TouchBarButton](touch-bar-button) | [TouchBarColorPicker](touch-bar-color-picker) | [TouchBarGroup](touch-bar-group) | [TouchBarLabel](touch-bar-label) | [TouchBarPopover](touch-bar-popover) | [TouchBarScrubber](touch-bar-scrubber) | [TouchBarSegmentedControl](touch-bar-segmented-control) | [TouchBarSlider](touch-bar-slider) | [TouchBarSpacer](touch-bar-spacer))[] (optional)
	+ `escapeItem` ([TouchBarButton](touch-bar-button) | [TouchBarColorPicker](touch-bar-color-picker) | [TouchBarGroup](touch-bar-group) | [TouchBarLabel](touch-bar-label) | [TouchBarPopover](touch-bar-popover) | [TouchBarScrubber](touch-bar-scrubber) | [TouchBarSegmentedControl](touch-bar-segmented-control) | [TouchBarSlider](touch-bar-slider) | [TouchBarSpacer](touch-bar-spacer) | null) (optional)


Creates a new touch bar with the specified items. Use `BrowserWindow.setTouchBar` to add the `TouchBar` to a window.


**Note:** The TouchBar API is currently experimental and may change or be removed in future Electron releases.


**Tip:** If you don't have a MacBook with Touch Bar, you can use [Touch Bar Simulator](https://github.com/sindresorhus/touch-bar-simulator) to test Touch Bar usage in your app.


### Static Properties[​](#static-properties "Direct link to heading")


#### 
`TouchBarButton`[​](#touchbarbutton "Direct link to heading")


A [`typeof TouchBarButton`](touch-bar-button) reference to the `TouchBarButton` class.


#### 
`TouchBarColorPicker`[​](#touchbarcolorpicker "Direct link to heading")


A [`typeof TouchBarColorPicker`](touch-bar-color-picker) reference to the `TouchBarColorPicker` class.


#### 
`TouchBarGroup`[​](#touchbargroup "Direct link to heading")


A [`typeof TouchBarGroup`](touch-bar-group) reference to the `TouchBarGroup` class.


#### 
`TouchBarLabel`[​](#touchbarlabel "Direct link to heading")


A [`typeof TouchBarLabel`](touch-bar-label) reference to the `TouchBarLabel` class.


#### 
`TouchBarPopover`[​](#touchbarpopover "Direct link to heading")


A [`typeof TouchBarPopover`](touch-bar-popover) reference to the `TouchBarPopover` class.


#### 
`TouchBarScrubber`[​](#touchbarscrubber "Direct link to heading")


A [`typeof TouchBarScrubber`](touch-bar-scrubber) reference to the `TouchBarScrubber` class.


#### 
`TouchBarSegmentedControl`[​](#touchbarsegmentedcontrol "Direct link to heading")


A [`typeof TouchBarSegmentedControl`](touch-bar-segmented-control) reference to the `TouchBarSegmentedControl` class.


#### 
`TouchBarSlider`[​](#touchbarslider "Direct link to heading")


A [`typeof TouchBarSlider`](touch-bar-slider) reference to the `TouchBarSlider` class.


#### 
`TouchBarSpacer`[​](#touchbarspacer "Direct link to heading")


A [`typeof TouchBarSpacer`](touch-bar-spacer) reference to the `TouchBarSpacer` class.


#### 
`TouchBarOtherItemsProxy`[​](#touchbarotheritemsproxy "Direct link to heading")


A [`typeof TouchBarOtherItemsProxy`](touch-bar-other-items-proxy) reference to the `TouchBarOtherItemsProxy` class.


### Instance Properties[​](#instance-properties "Direct link to heading")


The following properties are available on instances of `TouchBar`:


#### 
`touchBar.escapeItem`[​](#touchbarescapeitem "Direct link to heading")


A `TouchBarItem` that will replace the "esc" button on the touch bar when set. Setting to `null` restores the default "esc" button. Changing this value immediately updates the escape item in the touch bar.


Examples[​](#examples "Direct link to heading")
-----------------------------------------------


Below is an example of a simple slot machine touch bar game with a button and some labels.




```
const { app, BrowserWindow, TouchBar } = require('electron')

const { TouchBarLabel, TouchBarButton, TouchBarSpacer } = TouchBar

let spinning = false

// Reel labels
const reel1 = new TouchBarLabel()
const reel2 = new TouchBarLabel()
const reel3 = new TouchBarLabel()

// Spin result label
const result = new TouchBarLabel()

// Spin button
const spin = new TouchBarButton({
  label: '🎰 Spin',
  backgroundColor: '#7851A9',
  click: () => {
    // Ignore clicks if already spinning
    if (spinning) {
      return
    }

    spinning = true
    result.label = ''

    let timeout = 10
    const spinLength = 4 * 1000 // 4 seconds
    const startTime = Date.now()

    const spinReels = () => {
      updateReels()

      if ((Date.now() - startTime) >= spinLength) {
        finishSpin()
      } else {
        // Slow down a bit on each spin
        timeout *= 1.1
        setTimeout(spinReels, timeout)
      }
    }

    spinReels()
  }
})

const getRandomValue = () => {
  const values = ['🍒', '💎', '7️⃣', '🍊', '🔔', '⭐', '🍇', '🍀']
  return values[Math.floor(Math.random() * values.length)]
}

const updateReels = () => {
  reel1.label = getRandomValue()
  reel2.label = getRandomValue()
  reel3.label = getRandomValue()
}

const finishSpin = () => {
  const uniqueValues = new Set([reel1.label, reel2.label, reel3.label]).size
  if (uniqueValues === 1) {
    // All 3 values are the same
    result.label = '💰 Jackpot!'
    result.textColor = '#FDFF00'
  } else if (uniqueValues === 2) {
    // 2 values are the same
    result.label = '😍 Winner!'
    result.textColor = '#FDFF00'
  } else {
    // No values are the same
    result.label = '🙁 Spin Again'
    result.textColor = null
  }
  spinning = false
}

const touchBar = new TouchBar({
  items: [
    spin,
    new TouchBarSpacer({ size: 'large' }),
    reel1,
    new TouchBarSpacer({ size: 'small' }),
    reel2,
    new TouchBarSpacer({ size: 'small' }),
    reel3,
    new TouchBarSpacer({ size: 'large' }),
    result
  ]
})

let window

app.whenReady().then(() => {
  window = new BrowserWindow({
    frame: false,
    titleBarStyle: 'hiddenInset',
    width: 200,
    height: 200,
    backgroundColor: '#000'
  })
  window.loadURL('about:blank')
  window.setTouchBar(touchBar)
})
```


### Running the above example[​](#running-the-above-example "Direct link to heading")


To run the example above, you'll need to (assuming you've got a terminal open in the directory you want to run the example):


1. Save the above file to your computer as `touchbar.js`
2. Install Electron via `npm install electron`
3. Run the example inside Electron: `./node_modules/.bin/electron touchbar.js`


You should then see a new Electron window and the app running in your touch bar (or touch bar emulator).



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/touch-bar>

PaymentDiscount Object
======================


* `identifier` string - A string used to uniquely identify a discount offer for a product.
* `keyIdentifier` string - A string that identifies the key used to generate the signature.
* `nonce` string - A universally unique ID (UUID) value that you define.
* `signature` string - A UTF-8 string representing the properties of a specific discount offer, cryptographically signed.
* `timestamp` number - The date and time of the signature's creation in milliseconds, formatted in Unix epoch time.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/payment-discount>

Display Object
==============


* `id` number - Unique identifier associated with the display.
* `rotation` number - Can be 0, 90, 180, 270, represents screen rotation in clock-wise degrees.
* `scaleFactor` number - Output device's pixel scale factor.
* `touchSupport` string - Can be `available`, `unavailable`, `unknown`.
* `monochrome` boolean - Whether or not the display is a monochrome display.
* `accelerometerSupport` string - Can be `available`, `unavailable`, `unknown`.
* `colorSpace` string - represent a color space (three-dimensional object which contains all realizable color combinations) for the purpose of color conversions
* `colorDepth` number - The number of bits per pixel.
* `depthPerComponent` number - The number of bits per color component.
* `displayFrequency` number - The display refresh rate.
* `bounds` [Rectangle](rectangle) - the bounds of the display in DIP points.
* `size` [Size](size)
* `workArea` [Rectangle](rectangle) - the work area of the display in DIP points.
* `workAreaSize` [Size](size)
* `internal` boolean - `true` for an internal display and `false` for an external display


The `Display` object represents a physical display connected to the system. A fake `Display` may exist on a headless system, or a `Display` may correspond to a remote, virtual display.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/structures/display>

safeStorage
===========



> Allows access to simple encryption and decryption of strings for storage on the local machine.
> 
> 


Process: [Main](../glossary#main-process)


This module protects data stored on disk from being accessed by other applications or users with full disk access.


Note that on Mac, access to the system Keychain is required and these calls can block the current thread to collect user input. The same is true for Linux, if a password management tool is available.


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `safeStorage` module has the following methods:


### 
`safeStorage.isEncryptionAvailable()`[​](#safestorageisencryptionavailable "Direct link to heading")


Returns `boolean` - Whether encryption is available.


On Linux, returns true if the app has emitted the `ready` event and the secret key is available. On MacOS, returns true if Keychain is available. On Windows, returns true once the app has emitted the `ready` event.


### 
`safeStorage.encryptString(plainText)`[​](#safestorageencryptstringplaintext "Direct link to heading")


* `plainText` string


Returns `Buffer` - An array of bytes representing the encrypted string.


This function will throw an error if encryption fails.


### 
`safeStorage.decryptString(encrypted)`[​](#safestoragedecryptstringencrypted "Direct link to heading")


* `encrypted` Buffer


Returns `string` - the decrypted string. Decrypts the encrypted buffer obtained with `safeStorage.encryptString` back into a string.


This function will throw an error if decryption fails.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/safe-storage>

Electron Fuses
==============



> Package time feature toggles
> 
> 


What are fuses?[​](#what-are-fuses "Direct link to heading")
------------------------------------------------------------


For a subset of Electron functionality it makes sense to disable certain features for an entire application. For example, 99% of apps don't make use of `ELECTRON_RUN_AS_NODE`, these applications want to be able to ship a binary that is incapable of using that feature. We also don't want Electron consumers building Electron from source as that is both a massive technical challenge and has a high cost of both time and money.


Fuses are the solution to this problem, at a high level they are "magic bits" in the Electron binary that can be flipped when packaging your Electron app to enable / disable certain features / restrictions. Because they are flipped at package time before you code sign your app the OS becomes responsible for ensuring those bits aren't flipped back via OS level code signing validation (Gatekeeper / App Locker).


How do I flip the fuses?[​](#how-do-i-flip-the-fuses "Direct link to heading")
------------------------------------------------------------------------------


### The easy way[​](#the-easy-way "Direct link to heading")


We've made a handy module, [`@electron/fuses`](https://npmjs.com/package/@electron/fuses), to make flipping these fuses easy. Check out the README of that module for more details on usage and potential error cases.




```
require('@electron/fuses').flipFuses(
  // Path to electron
  require('electron'),
  // Fuses to flip
  {
    runAsNode: false
  }
)
```


### The hard way[​](#the-hard-way "Direct link to heading")


#### Quick Glossary[​](#quick-glossary "Direct link to heading")


* **Fuse Wire**: A sequence of bytes in the Electron binary used to control the fuses
* **Sentinel**: A static known sequence of bytes you can use to locate the fuse wire
* **Fuse Schema**: The format / allowed values for the fuse wire


Manually flipping fuses requires editing the Electron binary and modifying the fuse wire to be the sequence of bytes that represent the state of the fuses you want.


Somewhere in the Electron binary there will be a sequence of bytes that look like this:




```
| ...binary | sentinel_bytes | fuse_version | fuse_wire_length | fuse_wire | ...binary |
```


* `sentinel_bytes` is always this exact string `dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX`
* `fuse_version` is a single byte whose unsigned integer value represents the version of the fuse schema
* `fuse_wire_length` is a single byte whose unsigned integer value represents the number of fuses in the following fuse wire
* `fuse_wire` is a sequence of N bytes, each byte represents a single fuse and its state.
	+ "0" (0x30) indicates the fuse is disabled
	+ "1" (0x31) indicates the fuse is enabled
	+ "r" (0x72) indicates the fuse has been removed and changing the byte to either 1 or 0 will have no effect.


To flip a fuse you find its position in the fuse wire and change it to "0" or "1" depending on the state you'd like.


You can view the current schema [here](https://github.com/electron/electron/blob/main/build/fuses/fuses.json5).



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/fuses>

Boilerplates and CLIs
=====================


Electron development is unopinionated - there is no "one true way" to develop, build, package, or release an Electron application. Additional features for Electron, both for build- and run-time, can usually be found on [npm](https://www.npmjs.com/search?q=electron) in individual packages, allowing developers to build both the app and build pipeline they need.


That level of modularity and extendability ensures that all developers working with Electron, both big and small in team-size, are never restricted in what they can or cannot do at any time during their development lifecycle. However, for many developers, one of the community-driven boilerplates or command line tools might make it dramatically easier to compile, package, and release an app.


Boilerplate vs CLI[​](#boilerplate-vs-cli "Direct link to heading")
-------------------------------------------------------------------


A boilerplate is only a starting point - a canvas, so to speak - from which you build your application. They usually come in the form of a repository you can clone and customize to your heart's content.


A command line tool on the other hand continues to support you throughout the development and release. They are more helpful and supportive but enforce guidelines on how your code should be structured and built. *Especially for beginners, using a command line tool is likely to be helpful*.


electron-forge[​](#electron-forge "Direct link to heading")
-----------------------------------------------------------


A "complete tool for building modern Electron applications". Electron Forge unifies the existing (and well maintained) build tools for Electron development into a cohesive package so that anyone can jump right in to Electron development.


Forge comes with [a ready-to-use template](https://electronforge.io/templates) using Webpack as a bundler. It includes an example typescript configuration and provides two configuration files to enable easy customization. It uses the same core modules used by the greater Electron community (like [`electron-packager`](https://github.com/electron/electron-packager)) – changes made by Electron maintainers (like Slack) benefit Forge's users, too.


You can find more information and documentation on [electronforge.io](https://electronforge.io/).


electron-builder[​](#electron-builder "Direct link to heading")
---------------------------------------------------------------


A "complete solution to package and build a ready-for-distribution Electron app" that focuses on an integrated experience. [`electron-builder`](https://github.com/electron-userland/electron-builder) adds one single dependency focused on simplicity and manages all further requirements internally.


`electron-builder` replaces features and modules used by the Electron maintainers (such as the auto-updater) with custom ones. They are generally tighter integrated but will have less in common with popular Electron apps like Atom, Visual Studio Code, or Slack.


You can find more information and documentation in [the repository](https://github.com/electron-userland/electron-builder).


electron-react-boilerplate[​](#electron-react-boilerplate "Direct link to heading")
-----------------------------------------------------------------------------------


If you don't want any tools but only a solid boilerplate to build from, CT Lin's [`electron-react-boilerplate`](https://github.com/chentsulin/electron-react-boilerplate) might be worth a look. It's quite popular in the community and uses `electron-builder` internally.


Other Tools and Boilerplates[​](#other-tools-and-boilerplates "Direct link to heading")
---------------------------------------------------------------------------------------


The ["Awesome Electron" list](https://github.com/sindresorhus/awesome-electron#boilerplates) contains more tools and boilerplates to choose from. If you find the length of the list intimidating, don't forget that adding tools as you go along is a valid approach, too.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/boilerplates-and-clis>

Progress Bars
=============


Overview[​](#overview "Direct link to heading")
-----------------------------------------------


A progress bar enables a window to provide progress information to the user without the need of switching to the window itself.


On Windows, you can use a taskbar button to display a progress bar.


![Windows Progress Bar]


On macOS, the progress bar will be displayed as a part of the dock icon.


![macOS Progress Bar]


On Linux, the Unity graphical interface also has a similar feature that allows you to specify the progress bar in the launcher.


![Linux Progress Bar]



> NOTE: on Windows, each window can have its own progress bar, whereas on macOS and Linux (Unity) there can be only one progress bar for the application.
> 
> 




---


All three cases are covered by the same API - the [`setProgressBar()`](../api/browser-window#winsetprogressbarprogress-options) method available on an instance of `BrowserWindow`. To indicate your progress, call this method with a number between `0` and `1`. For example, if you have a long-running task that is currently at 63% towards completion, you would call it as `setProgressBar(0.63)`.


Setting the parameter to negative values (e.g. `-1`) will remove the progress bar. Setting it to a value greater than `1` will indicate an indeterminate progress bar in Windows or clamp to 100% in other operating systems. An indeterminate progress bar remains active but does not show an actual percentage, and is used for situations when you do not know how long an operation will take to complete.


See the [API documentation for more options and modes](../api/browser-window#winsetprogressbarprogress-options).


Example[​](#example "Direct link to heading")
---------------------------------------------


In this example, we add a progress bar to the main window that increments over time using Node.js timers.




[docs/fiddles/features/progress-bar (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/features/progress-bar)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/features/progress-bar)


* main.js
* index.html





```
const { app, BrowserWindow } = require('electron')

let progressInterval

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600
  })

  win.loadFile('index.html')

  const INCREMENT = 0.03
  const INTERVAL_DELAY = 100 // ms

  let c = 0
  progressInterval = setInterval(() => {
    // update progress bar to next value
    // values between 0 and 1 will show progress, >1 will show indeterminate or stick at 100%
    win.setProgressBar(c)

    // increment or reset progress bar
    if (c < 2) {
      c += INCREMENT
    } else {
      c = (-INCREMENT * 5) // reset to a bit less than 0 to show reset state
    }
  }, INTERVAL_DELAY)
}

app.whenReady().then(createWindow)

// before the app is terminated, clear both timers
app.on('before-quit', () => {
  clearInterval(progressInterval)
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})
```




```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
    <h1>Hello World!</h1>
    <p>Keep an eye on the dock (Mac) or taskbar (Windows, Unity) for this application!</p>
    <p>It should indicate a progress that advances from 0 to 100%.</p>
    <p>It should then show indeterminate (Windows) or pin at 100% (other operating systems)
      briefly and then loop.</p>
</body>
</html>
```





After launching the Electron application, the dock (macOS) or taskbar (Windows, Unity) should show a progress bar that starts at zero and progresses through 100% to completion. It should then show indeterminate (Windows) or pin to 100% (other operating systems) briefly and then loop.


![macOS dock progress bar]


For macOS, the progress bar will also be indicated for your application when using [Mission Control](https://support.apple.com/en-us/HT204100):


![Mission Control Progress Bar]



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/progress-bar>

Desktop Launcher Actions
========================


Overview[​](#overview "Direct link to heading")
-----------------------------------------------


On many Linux environments, you can add custom entries to the system launcher by modifying the `.desktop` file. For Canonical's Unity documentation, see [Adding Shortcuts to a Launcher](https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher). For details on a more generic implementation, see the [freedesktop.org Specification](https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html).


![audacious]



> NOTE: The screenshot above is an example of launcher shortcuts in Audacious audio player
> 
> 


To create a shortcut, you need to provide `Name` and `Exec` properties for the entry you want to add to the shortcut menu. Unity will execute the command defined in the `Exec` field after the user clicked the shortcut menu item. An example of the `.desktop` file may look as follows:




```
Actions=PlayPause;Next;Previous

[Desktop Action PlayPause]
Name=Play-Pause
Exec=audacious -t
OnlyShowIn=Unity;

[Desktop Action Next]
Name=Next
Exec=audacious -f
OnlyShowIn=Unity;

[Desktop Action Previous]
Name=Previous
Exec=audacious -r
OnlyShowIn=Unity;
```


The preferred way for Unity to instruct your application on what to do is using parameters. You can find them in your application in the global variable `process.argv`.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/linux-desktop-actions>

powerMonitor
============



> Monitor power state changes.
> 
> 


Process: [Main](../glossary#main-process)


Events[​](#events "Direct link to heading")
-------------------------------------------


The `powerMonitor` module emits the following events:


### Event: 'suspend'[​](#event-suspend "Direct link to heading")


Emitted when the system is suspending.


### Event: 'resume'[​](#event-resume "Direct link to heading")


Emitted when system is resuming.


### Event: 'on-ac' *macOS* *Windows*[​](#event-on-ac-macos-windows "Direct link to heading")


Emitted when the system changes to AC power.


### Event: 'on-battery' *macOS* *Windows*[​](#event-on-battery-macos--windows "Direct link to heading")


Emitted when system changes to battery power.


### Event: 'shutdown' *Linux* *macOS*[​](#event-shutdown-linux-macos "Direct link to heading")


Emitted when the system is about to reboot or shut down. If the event handler invokes `e.preventDefault()`, Electron will attempt to delay system shutdown in order for the app to exit cleanly. If `e.preventDefault()` is called, the app should exit as soon as possible by calling something like `app.quit()`.


### Event: 'lock-screen' *macOS* *Windows*[​](#event-lock-screen-macos-windows "Direct link to heading")


Emitted when the system is about to lock the screen.


### Event: 'unlock-screen' *macOS* *Windows*[​](#event-unlock-screen-macos-windows "Direct link to heading")


Emitted as soon as the systems screen is unlocked.


### Event: 'user-did-become-active' *macOS*[​](#event-user-did-become-active-macos "Direct link to heading")


Emitted when a login session is activated. See [documentation](https://developer.apple.com/documentation/appkit/nsworkspacesessiondidbecomeactivenotification?language=objc) for more information.


### Event: 'user-did-resign-active' *macOS*[​](#event-user-did-resign-active-macos "Direct link to heading")


Emitted when a login session is deactivated. See [documentation](https://developer.apple.com/documentation/appkit/nsworkspacesessiondidresignactivenotification?language=objc) for more information.


Methods[​](#methods "Direct link to heading")
---------------------------------------------


The `powerMonitor` module has the following methods:


### 
`powerMonitor.getSystemIdleState(idleThreshold)`[​](#powermonitorgetsystemidlestateidlethreshold "Direct link to heading")


* `idleThreshold` Integer


Returns `string` - The system's current state. Can be `active`, `idle`, `locked` or `unknown`.


Calculate the system idle state. `idleThreshold` is the amount of time (in seconds) before considered idle. `locked` is available on supported systems only.


### 
`powerMonitor.getSystemIdleTime()`[​](#powermonitorgetsystemidletime "Direct link to heading")


Returns `Integer` - Idle time in seconds


Calculate system idle time in seconds.


### 
`powerMonitor.isOnBatteryPower()`[​](#powermonitorisonbatterypower "Direct link to heading")


Returns `boolean` - Whether the system is on battery power.


To monitor for changes in this property, use the `on-battery` and `on-ac` events.


Properties[​](#properties "Direct link to heading")
---------------------------------------------------


### 
`powerMonitor.onBatteryPower`[​](#powermonitoronbatterypower "Direct link to heading")


A `boolean` property. True if the system is on battery power.


See [`powerMonitor.isOnBatteryPower()`](#powermonitorisonbatterypower).



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/power-monitor>

Using clang-tidy on C++ Code
============================


[`clang-tidy`](https://clang.llvm.org/extra/clang-tidy/) is a tool to automatically check C/C++/Objective-C code for style violations, programming errors, and best practices.


Electron's `clang-tidy` integration is provided as a linter script which can be run with `npm run lint:clang-tidy`. While `clang-tidy` checks your on-disk files, you need to have built Electron so that it knows which compiler flags were used. There is one required option for the script `--output-dir`, which tells the script which build directory to pull the compilation information from. A typical usage would be: `npm run lint:clang-tidy --out-dir ../out/Testing`


With no filenames provided, all C/C++/Objective-C files will be checked. You can provide a list of files to be checked by passing the filenames after the options: `npm run lint:clang-tidy --out-dir ../out/Testing shell/browser/api/electron_api_app.cc`


While `clang-tidy` has a [long list](https://clang.llvm.org/extra/clang-tidy/checks/list.html) of possible checks, in Electron only a few are enabled by default. At the moment Electron doesn't have a `.clang-tidy` config, so `clang-tidy` will find the one from Chromium at `src/.clang-tidy` and use the checks which Chromium has enabled. You can change which checks are run by using the `--checks=` option. This is passed straight through to `clang-tidy`, so see its documentation for full details. Wildcards can be used, and checks can be disabled by prefixing a `-`. By default any checks listed are added to those in `.clang-tidy`, so if you'd like to limit the checks to specific ones you should first exclude all checks then add back what you want, like `--checks=-*,performance*`.


Running `clang-tidy` is rather slow - internally it compiles each file and then runs the checks so it will always be some factor slower than compilation. While you can use parallel runs to speed it up using the `--jobs|-j` option, `clang-tidy` also uses a lot of memory during its checks, so it can easily run into out-of-memory errors. As such the default number of jobs is one.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/clang-tidy>

Class: TouchBarSegmentedControl
===============================

Class: TouchBarSegmentedControl[​](#class-touchbarsegmentedcontrol "Direct link to heading")
--------------------------------------------------------------------------------------------



> Create a segmented control (a button group) where one button has a selected state
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


### 
`new TouchBarSegmentedControl(options)`[​](#new-touchbarsegmentedcontroloptions "Direct link to heading")


* `options` Object
	+ `segmentStyle` string (optional) - Style of the segments:
		- `automatic` - Default. The appearance of the segmented control is automatically determined based on the type of window in which the control is displayed and the position within the window. Maps to `NSSegmentStyleAutomatic`.
		- `rounded` - The control is displayed using the rounded style. Maps to `NSSegmentStyleRounded`.
		- `textured-rounded` - The control is displayed using the textured rounded style. Maps to `NSSegmentStyleTexturedRounded`.
		- `round-rect` - The control is displayed using the round rect style. Maps to `NSSegmentStyleRoundRect`.
		- `textured-square` - The control is displayed using the textured square style. Maps to `NSSegmentStyleTexturedSquare`.
		- `capsule` - The control is displayed using the capsule style. Maps to `NSSegmentStyleCapsule`.
		- `small-square` - The control is displayed using the small square style. Maps to `NSSegmentStyleSmallSquare`.
		- `separated` - The segments in the control are displayed very close to each other but not touching. Maps to `NSSegmentStyleSeparated`.
	+ `mode` string (optional) - The selection mode of the control:
		- `single` - Default. One item selected at a time, selecting one deselects the previously selected item. Maps to `NSSegmentSwitchTrackingSelectOne`.
		- `multiple` - Multiple items can be selected at a time. Maps to `NSSegmentSwitchTrackingSelectAny`.
		- `buttons` - Make the segments act as buttons, each segment can be pressed and released but never marked as active. Maps to `NSSegmentSwitchTrackingMomentary`.
	+ `segments` [SegmentedControlSegment[]](structures/segmented-control-segment) - An array of segments to place in this control.
	+ `selectedIndex` Integer (optional) - The index of the currently selected segment, will update automatically with user interaction. When the mode is `multiple` it will be the last selected item.
	+ `change` Function (optional) - Called when the user selects a new segment.
		- `selectedIndex` Integer - The index of the segment the user selected.
		- `isSelected` boolean - Whether as a result of user selection the segment is selected or not.


### Instance Properties[​](#instance-properties "Direct link to heading")


The following properties are available on instances of `TouchBarSegmentedControl`:


#### 
`touchBarSegmentedControl.segmentStyle`[​](#touchbarsegmentedcontrolsegmentstyle "Direct link to heading")


A `string` representing the controls current segment style. Updating this value immediately updates the control in the touch bar.


#### 
`touchBarSegmentedControl.segments`[​](#touchbarsegmentedcontrolsegments "Direct link to heading")


A `SegmentedControlSegment[]` array representing the segments in this control. Updating this value immediately updates the control in the touch bar. Updating deep properties inside this array **does not update the touch bar**.


#### 
`touchBarSegmentedControl.selectedIndex`[​](#touchbarsegmentedcontrolselectedindex "Direct link to heading")


An `Integer` representing the currently selected segment. Changing this value immediately updates the control in the touch bar. User interaction with the touch bar will update this value automatically.


#### 
`touchBarSegmentedControl.mode`[​](#touchbarsegmentedcontrolmode "Direct link to heading")


A `string` representing the current selection mode of the control. Can be `single`, `multiple` or `buttons`.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/touch-bar-segmented-control>

Class: TouchBarColorPicker
==========================

Class: TouchBarColorPicker[​](#class-touchbarcolorpicker "Direct link to heading")
----------------------------------------------------------------------------------



> Create a color picker in the touch bar for native macOS applications
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


### 
`new TouchBarColorPicker(options)`[​](#new-touchbarcolorpickeroptions "Direct link to heading")


* `options` Object
	+ `availableColors` string[] (optional) - Array of hex color strings to appear as possible colors to select.
	+ `selectedColor` string (optional) - The selected hex color in the picker, i.e `#ABCDEF`.
	+ `change` Function (optional) - Function to call when a color is selected.
		- `color` string - The color that the user selected from the picker.


### Instance Properties[​](#instance-properties "Direct link to heading")


The following properties are available on instances of `TouchBarColorPicker`:


#### 
`touchBarColorPicker.availableColors`[​](#touchbarcolorpickeravailablecolors "Direct link to heading")


A `string[]` array representing the color picker's available colors to select. Changing this value immediately updates the color picker in the touch bar.


#### 
`touchBarColorPicker.selectedColor`[​](#touchbarcolorpickerselectedcolor "Direct link to heading")


A `string` hex code representing the color picker's currently selected color. Changing this value immediately updates the color picker in the touch bar.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/touch-bar-color-picker>

Windows on ARM
==============


If your app runs with Electron 6.0.8 or later, you can now build it for Windows 10 on Arm. This considerably improves performance, but requires recompilation of any native modules used in your app. It may also require small fixups to your build and packaging scripts.


Running a basic app[​](#running-a-basic-app "Direct link to heading")
---------------------------------------------------------------------


If your app doesn't use any native modules, then it's really easy to create an Arm version of your app.


1. Make sure that your app's `node_modules` directory is empty.
2. Using a *Command Prompt*, run `set npm_config_arch=arm64` before running `npm install`/`yarn install` as usual.
3. [If you have Electron installed as a development dependency](quick-start#prerequisites), npm will download and unpack the arm64 version. You can then package and distribute your app as normal.


General considerations[​](#general-considerations "Direct link to heading")
---------------------------------------------------------------------------


### Architecture-specific code[​](#architecture-specific-code "Direct link to heading")


Lots of Windows-specific code contains if... else logic that selects between either the x64 or x86 architectures.




```
if (process.arch === 'x64') {
  // Do 64-bit thing...
} else {
  // Do 32-bit thing...
}
```


If you want to target arm64, logic like this will typically select the wrong architecture, so carefully check your application and build scripts for conditions like this. In custom build and packaging scripts, you should always check the value of `npm_config_arch` in the environment, rather than relying on the current process arch.


### Native modules[​](#native-modules "Direct link to heading")


If you use native modules, you must make sure that they compile against v142 of the MSVC compiler (provided in Visual Studio 2017). You must also check that any pre-built `.dll` or `.lib` files provided or referenced by the native module are available for Windows on Arm.


### Testing your app[​](#testing-your-app "Direct link to heading")


To test your app, use a Windows on Arm device running Windows 10 (version 1903 or later). Make sure that you copy your application over to the target device - Chromium's sandbox will not work correctly when loading your application assets from a network location.


Development prerequisites[​](#development-prerequisites "Direct link to heading")
---------------------------------------------------------------------------------


### Node.js/node-gyp[​](#nodejsnode-gyp "Direct link to heading")


[Node.js v12.9.0 or later is recommended.](https://nodejs.org/en/) If updating to a new version of Node is undesirable, you can instead [update npm's copy of node-gyp manually](https://github.com/nodejs/node-gyp/wiki/Updating-npm's-bundled-node-gyp) to version 5.0.2 or later, which contains the required changes to compile native modules for Arm.


### Visual Studio 2017[​](#visual-studio-2017 "Direct link to heading")


Visual Studio 2017 (any edition) is required for cross-compiling native modules. You can download Visual Studio Community 2017 via Microsoft's [Visual Studio Dev Essentials program](https://visualstudio.microsoft.com/dev-essentials/). After installation, you can add the Arm-specific components by running the following from a *Command Prompt*:




```
vs_installer.exe ^
--add Microsoft.VisualStudio.Workload.NativeDesktop ^
--add Microsoft.VisualStudio.Component.VC.ATLMFC ^
--add Microsoft.VisualStudio.Component.VC.Tools.ARM64 ^
--add Microsoft.VisualStudio.Component.VC.MFC.ARM64 ^
--includeRecommended
```


#### Creating a cross-compilation command prompt[​](#creating-a-cross-compilation-command-prompt "Direct link to heading")


Setting `npm_config_arch=arm64` in the environment creates the correct arm64 `.obj` files, but the standard *Developer Command Prompt for VS 2017* will use the x64 linker. To fix this:


1. Duplicate the *x64\_x86 Cross Tools Command Prompt for VS 2017* shortcut (e.g. by locating it in the start menu, right clicking, selecting *Open File Location*, copying and pasting) to somewhere convenient.
2. Right click the new shortcut and choose *Properties*.
3. Change the *Target* field to read `vcvarsamd64_arm64.bat` at the end instead of `vcvarsamd64_x86.bat`.


If done successfully, the command prompt should print something similar to this on startup:




```
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.9.15
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64_arm64'
```


If you want to develop your application directly on a Windows on Arm device, substitute `vcvarsx86_arm64.bat` in *Target* so that cross-compilation can happen with the device's x86 emulation.


### Linking against the correct `node.lib`[​](#linking-against-the-correct-nodelib "Direct link to heading")


By default, `node-gyp` unpacks Electron's node headers and downloads the x86 and x64 versions of `node.lib` into `%APPDATA%\..\Local\node-gyp\Cache`, but it does not download the arm64 version ([a fix for this is in development](https://github.com/nodejs/node-gyp/pull/1875).) To fix this:


1. Download the arm64 `node.lib` from <https://electronjs.org/headers/v6.0.9/win-arm64/node.lib>
2. Move it to `%APPDATA%\..\Local\node-gyp\Cache\6.0.9\arm64\node.lib`


Substitute `6.0.9` for the version you're using.


Cross-compiling native modules[​](#cross-compiling-native-modules "Direct link to heading")
-------------------------------------------------------------------------------------------


After completing all of the above, open your cross-compilation command prompt and run `set npm_config_arch=arm64`. Then use `npm install` to build your project as normal. As with cross-compiling x86 modules, you may need to remove `node_modules` to force recompilation of native modules if they were previously compiled for another architecture.


Debugging native modules[​](#debugging-native-modules "Direct link to heading")
-------------------------------------------------------------------------------


Debugging native modules can be done with Visual Studio 2017 (running on your development machine) and corresponding [Visual Studio Remote Debugger](https://docs.microsoft.com/en-us/visualstudio/debugger/remote-debugging-cpp?view=vs-2019) running on the target device. To debug:


1. Launch your app `.exe` on the target device via the *Command Prompt* (passing `--inspect-brk` to pause it before any native modules are loaded).
2. Launch Visual Studio 2017 on your development machine.
3. Connect to the target device by selecting *Debug > Attach to Process...* and enter the device's IP address and the port number displayed by the Visual Studio Remote Debugger tool.
4. Click *Refresh* and select the [appropriate Electron process to attach](../development/debugging-on-windows).
5. You may need to make sure that any symbols for native modules in your app are loaded correctly. To configure this, head to *Debug > Options...* in Visual Studio 2017, and add the folders containing your `.pdb` symbols under *Debugging > Symbols*.
6. Once attached, set any appropriate breakpoints and resume JavaScript execution using Chrome's [remote tools for Node](debugging-main-process).


Getting additional help[​](#getting-additional-help "Direct link to heading")
-----------------------------------------------------------------------------


If you encounter a problem with this documentation, or if your app works when compiled for x86 but not for arm64, please [file an issue](../development/issues) with "Windows on Arm" in the title.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/windows-arm>

Electron Debugging
==================


There are many different approaches to debugging issues and bugs in Electron, many of which are platform specific.


Some of the more common approaches are outlined below.


Generic Debugging[​](#generic-debugging "Direct link to heading")
-----------------------------------------------------------------


Chromium contains logging macros which can aid debugging by printing information to console in C++ and Objective-C++.


You might use this to print out variable values, function names, and line numbers, amonst other things.


Some examples:




```
LOG(INFO) << "bitmap.width(): " << bitmap.width();

LOG(INFO, bitmap.width() > 10) << "bitmap.width() is greater than 10!";
```


There are also different levels of logging severity: `INFO`, `WARN`, and `ERROR`.


See [logging.h](https://chromium.googlesource.com/chromium/src/base/+/refs/heads/main/logging.h) in Chromium's source tree for more information and examples.


Printing Stacktraces[​](#printing-stacktraces "Direct link to heading")
-----------------------------------------------------------------------


Chromium contains a helper to print stack traces to console without interrrupting the program.




```
#include "base/debug/stack_trace.h"
...
base::debug::StackTrace().Print();
```


This will allow you to observe call chains and identify potential issue areas.


Breakpoint Debugging[​](#breakpoint-debugging "Direct link to heading")
-----------------------------------------------------------------------



> Note that this will increase the size of the build significantly, taking up around 50G of disk space
> 
> 


Write the following file to `electron/.git/info/exclude/debug.gn`




```
import("//electron/build/args/testing.gn")
is_debug = true
symbol_level = 2
forbid_non_component_debug_builds = false
```


Then execute:




```
$ gn gen out/Debug --args="import(\"//electron/.git/info/exclude/debug.gn\") $GN_EXTRA_ARGS"
$ ninja -C out/Debug electron
```


Now you can use `LLDB` for breakpoint debugging.


Platform-Specific Debugging[​](#platform-specific-debugging "Direct link to heading")
-------------------------------------------------------------------------------------


* [macOS Debugging](debugging-on-macos)
	+ [Debugging with Xcode](debugging-with-xcode)
* [Windows Debugging](debugging-on-windows)


Debugging with the Symbol Server[​](#debugging-with-the-symbol-server "Direct link to heading")
-----------------------------------------------------------------------------------------------


Debug symbols allow you to have better debugging sessions. They have information about the functions contained in executables and dynamic libraries and provide you with information to get clean call stacks. A Symbol Server allows the debugger to load the correct symbols, binaries and sources automatically without forcing users to download large debugging files.


For more information about how to set up a symbol server for Electron, see [debugging with a symbol server](debugging-with-symbol-server).



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/debugging>

Patches in Electron
===================


Electron is built on two major upstream projects: Chromium and Node.js. Each of these projects has several of their own dependencies, too. We try our best to use these dependencies exactly as they are but sometimes we can't achieve our goals without patching those upstream dependencies to fit our use cases.


Patch justification[​](#patch-justification "Direct link to heading")
---------------------------------------------------------------------


Every patch in Electron is a maintenance burden. When upstream code changes, patches can break—sometimes without even a patch conflict or a compilation error. It's an ongoing effort to keep our patch set up-to-date and effective. So we strive to keep our patch count at a minimum. To that end, every patch must describe its reason for existence in its commit message. That reason must be one of the following:


1. The patch is temporary, and is intended to be (or has been) committed upstream or otherwise eventually removed. Include a link to an upstream PR or code review if available, or a procedure for verifying whether the patch is still needed at a later date.
2. The patch allows the code to compile in the Electron environment, but cannot be upstreamed because it's Electron-specific (e.g. patching out references to Chrome's `Profile`). Include reasoning about why the change cannot be implemented without a patch (e.g. by subclassing or copying the code).
3. The patch makes Electron-specific changes in functionality which are fundamentally incompatible with upstream.


In general, all the upstream projects we work with are friendly folks and are often happy to accept refactorings that allow the code in question to be compatible with both Electron and the upstream project. (See e.g. [this](https://chromium-review.googlesource.com/c/chromium/src/+/1637040) change in Chromium, which allowed us to remove a patch that did the same thing, or [this](https://github.com/nodejs/node/pull/22110) change in Node, which was a no-op for Node but fixed a bug in Electron.) **We should aim to upstream changes whenever we can, and avoid indefinite-lifetime patches**.


Patch system[​](#patch-system "Direct link to heading")
-------------------------------------------------------


If you find yourself in the unfortunate position of having to make a change which can only be made through patching an upstream project, you'll need to know how to manage patches in Electron.


All patches to upstream projects in Electron are contained in the `patches/` directory. Each subdirectory of `patches/` contains several patch files, along with a `.patches` file which lists the order in which the patches should be applied. Think of these files as making up a series of git commits that are applied on top of the upstream project after we check it out.




```
patches
├── config.json   <-- this describes which patchset directory is applied to what project
├── chromium
│   ├── .patches
│   ├── accelerator.patch
│   ├── add_contentgpuclient_precreatemessageloop_callback.patch
│   ⋮
├── node
│   ├── .patches
│   ├── add_openssl_is_boringssl_guard_to_oaep_hash_check.patch
│   ├── build_add_gn_build_files.patch
│   ⋮
⋮
```


To help manage these patch sets, we provide two tools: `git-import-patches` and `git-export-patches`. `git-import-patches` imports a set of patch files into a git repository by applying each patch in the correct order and creating a commit for each one. `git-export-patches` does the reverse; it exports a series of git commits in a repository into a set of files in a directory and an accompanying `.patches` file.



> Side note: the reason we use a `.patches` file to maintain the order of applied patches, rather than prepending a number like `001-` to each file, is because it reduces conflicts related to patch ordering. It prevents the situation where two PRs both add a patch at the end of the series with the same numbering and end up both getting merged resulting in a duplicate identifier, and it also reduces churn when a patch is added or deleted in the middle of the series.
> 
> 


### Usage[​](#usage "Direct link to heading")


#### Adding a new patch[​](#adding-a-new-patch "Direct link to heading")




```
$ cd src/third_party/electron_node
$ vim some/code/file.cc
$ git commit
$ ../../electron/script/git-export-patches -o ../../electron/patches/node
```



> **NOTE**: `git-export-patches` ignores any uncommitted files, so you must create a commit if you want your changes to be exported. The subject line of the commit message will be used to derive the patch file name, and the body of the commit message should include the reason for the patch's existence.
> 
> 


Re-exporting patches will sometimes cause shasums in unrelated patches to change. This is generally harmless and can be ignored (but go ahead and add those changes to your PR, it'll stop them from showing up for other people).


#### Editing an existing patch[​](#editing-an-existing-patch "Direct link to heading")




```
$ cd src/v8
$ vim some/code/file.cc
$ git log
# Find the commit sha of the patch you want to edit.
$ git commit --fixup [COMMIT_SHA]
$ git rebase --autosquash -i [COMMIT_SHA]^
$ ../electron/script/git-export-patches -o ../electron/patches/v8
```


#### Removing a patch[​](#removing-a-patch "Direct link to heading")




```
$ vim src/electron/patches/node/.patches
# Delete the line with the name of the patch you want to remove
$ cd src/third_party/electron_node
$ git reset --hard refs/patches/upstream-head
$ ../../electron/script/git-import-patches ../../electron/patches/node
$ ../../electron/script/git-export-patches -o ../../electron/patches/node
```


Note that `git-import-patches` will mark the commit that was `HEAD` when it was run as `refs/patches/upstream-head`. This lets you keep track of which commits are from Electron patches (those that come after `refs/patches/upstream-head`) and which commits are in upstream (those before `refs/patches/upstream-head`).


#### Resolving conflicts[​](#resolving-conflicts "Direct link to heading")


When updating an upstream dependency, patches may fail to apply cleanly. Often, the conflict can be resolved automatically by git with a 3-way merge. You can instruct `git-import-patches` to use the 3-way merge algorithm by passing the `-3` argument:




```
$ cd src/third_party/electron_node
# If the patch application failed midway through, you can reset it with:
$ git am --abort
# And then retry with 3-way merge:
$ ../../electron/script/git-import-patches -3 ../../electron/patches/node
```


If `git-import-patches -3` encounters a merge conflict that it can't resolve automatically, it will pause and allow you to resolve the conflict manually. Once you have resolved the conflict, `git add` the resolved files and continue to apply the rest of the patches by running `git am --continue`.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/patches>

Representing Files in a BrowserWindow
=====================================


Overview[​](#overview "Direct link to heading")
-----------------------------------------------


On macOS, you can set a represented file for any window in your application. The represented file's icon will be shown in the title bar, and when users `Command-Click` or `Control-Click`, a popup with a path to the file will be shown.


![Represented File]



> NOTE: The screenshot above is an example where this feature is used to indicate the currently opened file in the Atom text editor.
> 
> 


You can also set the edited state for a window so that the file icon can indicate whether the document in this window has been modified.


To set the represented file of window, you can use the [BrowserWindow.setRepresentedFilename](../api/browser-window#winsetrepresentedfilenamefilename-macos) and [BrowserWindow.setDocumentEdited](../api/browser-window#winsetdocumenteditededited-macos) APIs.


Example[​](#example "Direct link to heading")
---------------------------------------------




[docs/fiddles/features/represented-file (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/features/represented-file)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/features/represented-file)


* main.js
* index.html





```
const { app, BrowserWindow } = require('electron')
const os = require('os');

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600
  })

  win.loadFile('index.html')
}

app.whenReady().then(() => {
  const win = new BrowserWindow()

  win.setRepresentedFilename(os.homedir())
  win.setDocumentEdited(true)
})

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})
```




```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
    <link rel="stylesheet" type="text/css" href="./styles.css">
</head>
<body>
    <h1>Hello World!</h1>
    <p>
      Click on the title with the <pre>Command</pre> or <pre>Control</pre> key pressed.
      You should see a popup with the represented file at the top.
    </p>
  </body>
</body>
</html>
```





After launching the Electron application, click on the title with `Command` or `Control` key pressed. You should see a popup with the represented file at the top. In this guide, this is the current user's home directory:


![Represented file]



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/represented-file>

Class: TouchBarGroup
====================

Class: TouchBarGroup[​](#class-touchbargroup "Direct link to heading")
----------------------------------------------------------------------



> Create a group in the touch bar for native macOS applications
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


### 
`new TouchBarGroup(options)`[​](#new-touchbargroupoptions "Direct link to heading")


* `options` Object
	+ `items` [TouchBar](touch-bar) - Items to display as a group.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/touch-bar-group>

Class: TouchBarLabel
====================

Class: TouchBarLabel[​](#class-touchbarlabel "Direct link to heading")
----------------------------------------------------------------------



> Create a label in the touch bar for native macOS applications
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


### 
`new TouchBarLabel(options)`[​](#new-touchbarlabeloptions "Direct link to heading")


* `options` Object
	+ `label` string (optional) - Text to display.
	+ `accessibilityLabel` string (optional) - A short description of the button for use by screenreaders like VoiceOver.
	+ `textColor` string (optional) - Hex color of text, i.e `#ABCDEF`.


When defining `accessibilityLabel`, ensure you have considered macOS [best practices](https://developer.apple.com/documentation/appkit/nsaccessibilitybutton/1524910-accessibilitylabel?language=objc).


### Instance Properties[​](#instance-properties "Direct link to heading")


The following properties are available on instances of `TouchBarLabel`:


#### 
`touchBarLabel.label`[​](#touchbarlabellabel "Direct link to heading")


A `string` representing the label's current text. Changing this value immediately updates the label in the touch bar.


#### 
`touchBarLabel.accessibilityLabel`[​](#touchbarlabelaccessibilitylabel "Direct link to heading")


A `string` representing the description of the label to be read by a screen reader.


#### 
`touchBarLabel.textColor`[​](#touchbarlabeltextcolor "Direct link to heading")


A `string` hex code representing the label's current text color. Changing this value immediately updates the label in the touch bar.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/touch-bar-label>

Class: TouchBarPopover
======================

Class: TouchBarPopover[​](#class-touchbarpopover "Direct link to heading")
--------------------------------------------------------------------------



> Create a popover in the touch bar for native macOS applications
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


### 
`new TouchBarPopover(options)`[​](#new-touchbarpopoveroptions "Direct link to heading")


* `options` Object
	+ `label` string (optional) - Popover button text.
	+ `icon` [NativeImage](native-image) (optional) - Popover button icon.
	+ `items` [TouchBar](touch-bar) - Items to display in the popover.
	+ `showCloseButton` boolean (optional) - `true` to display a close button on the left of the popover, `false` to not show it. Default is `true`.


### Instance Properties[​](#instance-properties "Direct link to heading")


The following properties are available on instances of `TouchBarPopover`:


#### 
`touchBarPopover.label`[​](#touchbarpopoverlabel "Direct link to heading")


A `string` representing the popover's current button text. Changing this value immediately updates the popover in the touch bar.


#### 
`touchBarPopover.icon`[​](#touchbarpopovericon "Direct link to heading")


A `NativeImage` representing the popover's current button icon. Changing this value immediately updates the popover in the touch bar.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/touch-bar-popover>

Class: TouchBarScrubber
=======================

Class: TouchBarScrubber[​](#class-touchbarscrubber "Direct link to heading")
----------------------------------------------------------------------------



> Create a scrubber (a scrollable selector)
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


### 
`new TouchBarScrubber(options)`[​](#new-touchbarscrubberoptions "Direct link to heading")


* `options` Object
	+ `items` [ScrubberItem[]](structures/scrubber-item) - An array of items to place in this scrubber.
	+ `select` Function (optional) - Called when the user taps an item that was not the last tapped item.
		- `selectedIndex` Integer - The index of the item the user selected.
	+ `highlight` Function (optional) - Called when the user taps any item.
		- `highlightedIndex` Integer - The index of the item the user touched.
	+ `selectedStyle` string (optional) - Selected item style. Can be `background`, `outline` or `none`. Defaults to `none`.
	+ `overlayStyle` string (optional) - Selected overlay item style. Can be `background`, `outline` or `none`. Defaults to `none`.
	+ `showArrowButtons` boolean (optional) - Whether to show arrow buttons. Defaults to `false` and is only shown if `items` is non-empty.
	+ `mode` string (optional) - Can be `fixed` or `free`. The default is `free`.
	+ `continuous` boolean (optional) - Defaults to `true`.


### Instance Properties[​](#instance-properties "Direct link to heading")


The following properties are available on instances of `TouchBarScrubber`:


#### 
`touchBarScrubber.items`[​](#touchbarscrubberitems "Direct link to heading")


A `ScrubberItem[]` array representing the items in this scrubber. Updating this value immediately updates the control in the touch bar. Updating deep properties inside this array **does not update the touch bar**.


#### 
`touchBarScrubber.selectedStyle`[​](#touchbarscrubberselectedstyle "Direct link to heading")


A `string` representing the style that selected items in the scrubber should have. Updating this value immediately updates the control in the touch bar. Possible values:


* `background` - Maps to `[NSScrubberSelectionStyle roundedBackgroundStyle]`.
* `outline` - Maps to `[NSScrubberSelectionStyle outlineOverlayStyle]`.
* `none` - Removes all styles.


#### 
`touchBarScrubber.overlayStyle`[​](#touchbarscrubberoverlaystyle "Direct link to heading")


A `string` representing the style that selected items in the scrubber should have. This style is overlayed on top of the scrubber item instead of being placed behind it. Updating this value immediately updates the control in the touch bar. Possible values:


* `background` - Maps to `[NSScrubberSelectionStyle roundedBackgroundStyle]`.
* `outline` - Maps to `[NSScrubberSelectionStyle outlineOverlayStyle]`.
* `none` - Removes all styles.


#### 
`touchBarScrubber.showArrowButtons`[​](#touchbarscrubbershowarrowbuttons "Direct link to heading")


A `boolean` representing whether to show the left / right selection arrows in this scrubber. Updating this value immediately updates the control in the touch bar.


#### 
`touchBarScrubber.mode`[​](#touchbarscrubbermode "Direct link to heading")


A `string` representing the mode of this scrubber. Updating this value immediately updates the control in the touch bar. Possible values:


* `fixed` - Maps to `NSScrubberModeFixed`.
* `free` - Maps to `NSScrubberModeFree`.


#### 
`touchBarScrubber.continuous`[​](#touchbarscrubbercontinuous "Direct link to heading")


A `boolean` representing whether this scrubber is continuous or not. Updating this value immediately updates the control in the touch bar.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/touch-bar-scrubber>

Class: TouchBarOtherItemsProxy
==============================

Class: TouchBarOtherItemsProxy[​](#class-touchbarotheritemsproxy "Direct link to heading")
------------------------------------------------------------------------------------------



> 
> Instantiates a special "other items proxy", which nests TouchBar elements inherited from Chromium at the space indicated by the proxy. By default, this proxy is added to each TouchBar at the end of the input. For more information, see the AppKit docs on [NSTouchBarItemIdentifierOtherItemsProxy](https://developer.apple.com/documentation/appkit/nstouchbaritemidentifierotheritemsproxy)
> 
> 
> Note: Only one instance of this class can be added per TouchBar.
> 
> 
> 


Process: [Main](../glossary#main-process)  
 *This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API.*


### 
`new TouchBarOtherItemsProxy()`[​](#new-touchbarotheritemsproxy "Direct link to heading")



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/api/touch-bar-other-items-proxy>

Creating a New Electron Browser Module
======================================


Welcome to the Electron API guide! If you are unfamiliar with creating a new Electron API module within the [`browser`](https://github.com/electron/electron/tree/main/shell/browser) directory, this guide serves as a checklist for some of the necessary steps that you will need to implement.


This is not a comprehensive end-all guide to creating an Electron Browser API, rather an outline documenting some of the more unintuitive steps.


Add your files to Electron's project configuration[​](#add-your-files-to-electrons-project-configuration "Direct link to heading")
----------------------------------------------------------------------------------------------------------------------------------


Electron uses [GN](https://gn.googlesource.com/gn) as a meta build system to generate files for its compiler, [Ninja](https://ninja-build.org/). This means that in order to tell Electron to compile your code, we have to add your API's code and header file names into [`filenames.gni`](https://github.com/electron/electron/blob/main/filenames.gni).


You will need to append your API file names alphabetically into the appropriate files like so:



filenames.gni


```
lib_sources = [
    "path/to/api/api_name.cc",
    "path/to/api/api_name.h",
]

lib_sources_mac = [
    "path/to/api/api_name_mac.h",
    "path/to/api/api_name_mac.mm",
]

lib_sources_win = [
    "path/to/api/api_name_win.cc",
    "path/to/api/api_name_win.h",
]

lib_sources_linux = [
    "path/to/api/api_name_linux.cc",
    "path/to/api/api_name_linux.h",
]
```



Note that the Windows, macOS and Linux array additions are optional and should only be added if your API has specific platform implementations.


Create API documentation[​](#create-api-documentation "Direct link to heading")
-------------------------------------------------------------------------------


Type definitions are generated by Electron using [`@electron/docs-parser`](https://github.com/electron/docs-parser) and [`@electron/typescript-definitions`](https://github.com/electron/typescript-definitions). This step is necessary to ensure consistency across Electron's API documentation. This means that for your API type definition to appear in the `electron.d.ts` file, we must create a `.md` file. Examples can be found in [this folder](https://github.com/electron/electron/tree/main/docs/api).


Set up `ObjectTemplateBuilder` and `Wrappable`[​](#set-up-objecttemplatebuilder-and-wrappable "Direct link to heading")
-----------------------------------------------------------------------------------------------------------------------


Electron constructs its modules using [`object_template_builder`](https://www.electronjs.org/blog/from-native-to-js#mateobjecttemplatebuilder).


[`wrappable`](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/gin/wrappable.h) is a base class for C++ objects that have corresponding v8 wrapper objects.


Here is a basic example of code that you may need to add, in order to incorporate `object_template_builder` and `wrappable` into your API. For further reference, you can find more implementations [here](https://github.com/electron/electron/tree/main/shell/browser/api).


In your `api_name.h` file:



api\_name.h


```

#ifndef ELECTRON_SHELL_BROWSER_API_ELECTRON_API_{API_NAME}_H_
#define ELECTRON_SHELL_BROWSER_API_ELECTRON_API_{API_NAME}_H_

#include "gin/handle.h"
#include "gin/wrappable.h"

namespace electron {

namespace api {

class ApiName : public gin::Wrappable<ApiName>  {
 public:
  static gin::Handle<ApiName> Create(v8::Isolate* isolate);

  // gin::Wrappable
  static gin::WrapperInfo kWrapperInfo;
  gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
      v8::Isolate* isolate) override;
  const char* GetTypeName() override;
} // namespace api
} // namespace electron
```



In your `api_name.cc` file:



api\_name.cc


```
#include "shell/browser/api/electron_api_safe_storage.h"

#include "shell/browser/browser.h"
#include "shell/common/gin_converters/base_converter.h"
#include "shell/common/gin_converters/callback_converter.h"
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/object_template_builder.h"
#include "shell/common/node_includes.h"
#include "shell/common/platform_util.h"

namespace electron {

namespace api {

gin::WrapperInfo ApiName::kWrapperInfo = {gin::kEmbedderNativeGin};

gin::ObjectTemplateBuilder ApiName::GetObjectTemplateBuilder(
    v8::Isolate* isolate) {
  return gin::ObjectTemplateBuilder(isolate)
      .SetMethod("methodName", &ApiName::methodName);
}

const char* ApiName::GetTypeName() {
  return "ApiName";
}

// static
gin::Handle<ApiName> ApiName::Create(v8::Isolate* isolate) {
  return gin::CreateHandle(isolate, new ApiName());
}

} // namespace api

} // namespace electron

namespace {

void Initialize(v8::Local<v8::Object> exports,
                v8::Local<v8::Value> unused,
                v8::Local<v8::Context> context,
                void* priv) {
  v8::Isolate* isolate = context->GetIsolate();
  gin_helper::Dictionary dict(isolate, exports);
  dict.Set("apiName", electron::api::ApiName::Create(isolate));
}

}  // namespace
```



Link your Electron API with Node[​](#link-your-electron-api-with-node "Direct link to heading")
-----------------------------------------------------------------------------------------------


In the [`typings/internal-ambient.d.ts`](https://github.com/electron/electron/blob/main/typings/internal-ambient.d.ts) file, we need to append a new property onto the `Process` interface like so:



typings/internal-ambient.d.ts


```
interface Process {
    _linkedBinding(name: 'electron_browser_{api_name}', Electron.ApiName);
}
```



At the very bottom of your `api_name.cc` file:



api\_name.cc


```
NODE_LINKED_MODULE_CONTEXT_AWARE(electron_browser_{api_name},Initialize)
```



In your [`shell/common/node_bindings.cc`](https://github.com/electron/electron/blob/main/shell/common/node_bindings.cc) file, add your node binding name to Electron's built-in modules.



shell/common/node\_bindings.cc


```
#define ELECTRON_BUILTIN_MODULES(V)      \
  V(electron_browser_{api_name})
```




> Note: More technical details on how Node links with Electron can be found on [our blog](https://www.electronjs.org/blog/electron-internals-using-node-as-a-library#link-node-with-electron).
> 
> 


Expose your API to TypeScript[​](#expose-your-api-to-typescript "Direct link to heading")
-----------------------------------------------------------------------------------------


### Export your API as a module[​](#export-your-api-as-a-module "Direct link to heading")


We will need to create a new TypeScript file in the path that follows:


`"lib/browser/api/{electron_browser_{api_name}}.ts"`


An example of the contents of this file can be found [here](https://github.com/electron/electron/blob/main/lib/browser/api/native-image.ts).


### Expose your module to TypeScript[​](#expose-your-module-to-typescript "Direct link to heading")


Add your module to the module list found at `"lib/browser/api/module-list.ts"` like so:



lib/browser/api/module-list.ts


```
export const browserModuleList: ElectronInternal.ModuleEntry[] = [
  { name: 'apiName', loader: () => require('./api-name') },
];
```




 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/creating-api>

Updating an Appveyor Azure Image
================================


Electron CI on Windows uses AppVeyor, which in turn uses Azure VM images to run. Occasionally, these VM images need to be updated due to changes in Chromium requirements. In order to update you will need [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-6) and the [Azure PowerShell module](https://docs.microsoft.com/en-us/powershell/azure/install-az-ps?view=azps-1.8.0&viewFallbackFrom=azurermps-6.13.0).


Occasionally we need to update these images owing to changes in Chromium or other miscellaneous build requirement changes.


Example Use Case:




```
* We need `VS15.9` and we have `VS15.7` installed; this would require us to update an Azure image.
```


1. Identify the image you wish to modify.


	* In [appveyor.yml](https://github.com/electron/electron/blob/main/appveyor.yml), the image is identified by the property *image*.
		+ The names used correspond to the *"images"* defined for a build cloud, eg the [libcc-20 cloud](https://windows-ci.electronjs.org/build-clouds/8).
	* Find the image you wish to modify in the build cloud and make note of the **VHD Blob Path** for that image, which is the value for that corresponding key.
		+ You will need this URI path to copy into a new image.
	* You will also need the storage account name which is labeled in AppVeyor as the **Disk Storage Account Name**
2. Get the Azure storage account key


	* Log into Azure using credentials stored in LastPass (under Azure Enterprise) and then find the storage account corresponding to the name found in AppVeyor.
		+ Example, for `appveyorlibccbuilds` **Disk Storage Account Name** you'd look for `appveyorlibccbuilds` in the list of storage accounts @ Home < Storage Accounts
			- Click into it and look for `Access Keys`, and then you can use any of the keys present in the list.
3. Get the full virtual machine image URI from Azure


	* Navigate to Home < Storage Accounts < `$ACCT_NAME` < Blobs < Images
		+ In the following list, look for the VHD path name you got from Appveyor and then click on it.
			- Copy the whole URL from the top of the subsequent window.
4. Copy the image using the [Copy Master Image PowerShell script](https://github.com/appveyor/ci/blob/master/scripts/enterprise/copy-master-image-azure.ps1).


	* It is essential to copy the VM because if you spin up a VM against an image that image cannot at the same time be used by AppVeyor.
	* Use the storage account name, key, and URI obtained from Azure to run this script.
		+ See Step 3 for URI & when prompted, press enter to use same storage account as destination.
		+ Use default destination container name `(images)`
		+ Also, when naming the copy, use a name that indicates what the new image will contain (if that has changed) and date stamp.
			- Ex. `libcc-20core-vs2017-15.9-2019-04-15.vhd`
	* Go into Azure and get the URI for the newly created image as described in a previous step
5. Spin up a new VM using the [Create Master VM from VHD PowerShell](https://github.com/appveyor/ci/blob/master/scripts/enterprise/create_master_vm_from_vhd.ps1).


	* From PowerShell, execute `ps1` file with `./create_master_vm_from_vhd.ps1`
	* You will need the credential information available in the AppVeyor build cloud definition.
		+ This includes:
			- Client ID
			- Client Secret
			- Tenant ID
			- Subscription ID
			- Resource Group
			- Virtual Network
	* You will also need to specify
		+ Master VM name - just a unique name to identify the temporary VM
		+ Master VM size - use `Standard_F32s_v2`
		+ Master VHD URI - use URI obtained @ end of previous step
		+ Location use `East US`
6. Log back into Azure and find the VM you just created in Home < Virtual Machines < `$YOUR_NEW_VM`


	* You can download a RDP (Remote Desktop) file to access the VM.
7. Using Microsoft Remote Desktop, click `Connect` to connect to the VM.


	* Credentials for logging into the VM are found in LastPass under the `AppVeyor Enterprise master VM` credentials.
8. Modify the VM as required.
9. Shut down the VM and then delete it in Azure.
10. Add the new image to the Appveyor Cloud settings or modify an existing image to point to the new VHD.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/azure-vm-setup>

Debugging with XCode
====================

Debugging with XCode[​](#debugging-with-xcode "Direct link to heading")
-----------------------------------------------------------------------


### Generate xcode project for debugging sources (cannot build code from xcode)[​](#generate-xcode-project-for-debugging-sources-cannot-build-code-from-xcode "Direct link to heading")


Run `gn gen` with the --ide=xcode argument.




```
$ gn gen out/Testing --ide=xcode
```


This will generate the electron.ninja.xcworkspace. You will have to open this workspace to set breakpoints and inspect.


See `gn help gen` for more information on generating IDE projects with GN.


### Debugging and breakpoints[​](#debugging-and-breakpoints "Direct link to heading")


Launch Electron app after build. You can now open the xcode workspace created above and attach to the Electron process through the Debug > Attach To Process > Electron debug menu. [Note: If you want to debug the renderer process, you need to attach to the Electron Helper as well.]


You can now set breakpoints in any of the indexed files. However, you will not be able to set breakpoints directly in the Chromium source. To set break points in the Chromium source, you can choose Debug > Breakpoints > Create Symbolic Breakpoint and set any function name as the symbol. This will set the breakpoint for all functions with that name, from all the classes if there are more than one. You can also do this step of setting break points prior to attaching the debugger, however, actual breakpoints for symbolic breakpoint functions may not show up until the debugger is attached to the app.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/debugging-with-xcode>

Setting Up Symbol Server in Debugger
====================================


Debug symbols allow you to have better debugging sessions. They have information about the functions contained in executables and dynamic libraries and provide you with information to get clean call stacks. A Symbol Server allows the debugger to load the correct symbols, binaries and sources automatically without forcing users to download large debugging files. The server functions like [Microsoft's symbol server](https://support.microsoft.com/kb/311503) so the documentation there can be useful.


Note that because released Electron builds are heavily optimized, debugging is not always easy. The debugger will not be able to show you the content of all variables and the execution path can seem strange because of inlining, tail calls, and other compiler optimizations. The only workaround is to build an unoptimized local build.


The official symbol server URL for Electron is <https://symbols.electronjs.org.> You cannot visit this URL directly, you must add it to the symbol path of your debugging tool. In the examples below, a local cache directory is used to avoid repeatedly fetching the PDB from the server. Replace `c:\code\symbols` with an appropriate cache directory on your machine.


Using the Symbol Server in Windbg[​](#using-the-symbol-server-in-windbg "Direct link to heading")
-------------------------------------------------------------------------------------------------


The Windbg symbol path is configured with a string value delimited with asterisk characters. To use only the Electron symbol server, add the following entry to your symbol path (**Note:** you can replace `c:\code\symbols` with any writable directory on your computer, if you'd prefer a different location for downloaded symbols):




```
SRV*c:\code\symbols\*https://symbols.electronjs.org
```


Set this string as `_NT_SYMBOL_PATH` in the environment, using the Windbg menus, or by typing the `.sympath` command. If you would like to get symbols from Microsoft's symbol server as well, you should list that first:




```
SRV*c:\code\symbols\*https://msdl.microsoft.com/download/symbols;SRV*c:\code\symbols\*https://symbols.electronjs.org
```


Using the symbol server in Visual Studio[​](#using-the-symbol-server-in-visual-studio "Direct link to heading")
---------------------------------------------------------------------------------------------------------------


![Tools -&gt; Options]


![Symbols Settings]


Troubleshooting: Symbols will not load[​](#troubleshooting-symbols-will-not-load "Direct link to heading")
----------------------------------------------------------------------------------------------------------


Type the following commands in Windbg to print why symbols are not loading:




```
> !sym noisy
> .reload /f electron.exe
```



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/debugging-with-symbol-server>

Debugging on Windows
====================


If you experience crashes or issues in Electron that you believe are not caused by your JavaScript application, but instead by Electron itself, debugging can be a little bit tricky, especially for developers not used to native/C++ debugging. However, using Visual Studio, Electron's hosted Symbol Server, and the Electron source code, you can enable step-through debugging with breakpoints inside Electron's source code.


**See also**: There's a wealth of information on debugging Chromium, much of which also applies to Electron, on the Chromium developers site: [Debugging Chromium on Windows](https://www.chromium.org/developers/how-tos/debugging-on-windows).


Requirements[​](#requirements "Direct link to heading")
-------------------------------------------------------


* **A debug build of Electron**: The easiest way is usually building it yourself, using the tools and prerequisites listed in the [build instructions for Windows](build-instructions-windows). While you can attach to and debug Electron as you can download it directly, you will find that it is heavily optimized, making debugging substantially more difficult: The debugger will not be able to show you the content of all variables and the execution path can seem strange because of inlining, tail calls, and other compiler optimizations.
* **Visual Studio with C++ Tools**: The free community editions of Visual Studio 2013 and Visual Studio 2015 both work. Once installed, [configure Visual Studio to use Electron's Symbol server](debugging-with-symbol-server). It will enable Visual Studio to gain a better understanding of what happens inside Electron, making it easier to present variables in a human-readable format.
* **ProcMon**: The [free SysInternals tool](https://technet.microsoft.com/en-us/sysinternals/processmonitor.aspx) allows you to inspect a processes parameters, file handles, and registry operations.


Attaching to and Debugging Electron[​](#attaching-to-and-debugging-electron "Direct link to heading")
-----------------------------------------------------------------------------------------------------


To start a debugging session, open up PowerShell/CMD and execute your debug build of Electron, using the application to open as a parameter.




```
$ ./out/Testing/electron.exe ~/my-electron-app/
```


### Setting Breakpoints[​](#setting-breakpoints "Direct link to heading")


Then, open up Visual Studio. Electron is not built with Visual Studio and hence does not contain a project file - you can however open up the source code files "As File", meaning that Visual Studio will open them up by themselves. You can still set breakpoints - Visual Studio will automatically figure out that the source code matches the code running in the attached process and break accordingly.


Relevant code files can be found in `./shell/`.


### Attaching[​](#attaching "Direct link to heading")


You can attach the Visual Studio debugger to a running process on a local or remote computer. After the process is running, click Debug / Attach to Process (or press `CTRL+ALT+P`) to open the "Attach to Process" dialog box. You can use this capability to debug apps that are running on a local or remote computer, debug multiple processes simultaneously.


If Electron is running under a different user account, select the `Show processes from all users` check box. Notice that depending on how many BrowserWindows your app opened, you will see multiple processes. A typical one-window app will result in Visual Studio presenting you with two `Electron.exe` entries - one for the main process and one for the renderer process. Since the list only gives you names, there's currently no reliable way of figuring out which is which.


### Which Process Should I Attach to?[​](#which-process-should-i-attach-to "Direct link to heading")


Code executed within the main process (that is, code found in or eventually run by your main JavaScript file) will run inside the main process, while other code will execute inside its respective renderer process.


You can be attached to multiple programs when you are debugging, but only one program is active in the debugger at any time. You can set the active program in the `Debug Location` toolbar or the `Processes window`.


Using ProcMon to Observe a Process[​](#using-procmon-to-observe-a-process "Direct link to heading")
---------------------------------------------------------------------------------------------------


While Visual Studio is fantastic for inspecting specific code paths, ProcMon's strength is really in observing everything your application is doing with the operating system - it captures File, Registry, Network, Process, and Profiling details of processes. It attempts to log **all** events occurring and can be quite overwhelming, but if you seek to understand what and how your application is doing to the operating system, it can be a valuable resource.


For an introduction to ProcMon's basic and advanced debugging features, go check out [this video tutorial](https://channel9.msdn.com/shows/defrag-tools/defrag-tools-4-process-monitor) provided by Microsoft.


Using WinDbg[​](#using-windbg "Direct link to heading")
-------------------------------------------------------


It's possible to debug crashes and issues in the Renderer process with [WinDbg](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/getting-started-with-windbg).


To attach to a debug a process with WinDbg:


1. Add `--renderer-startup-dialog` as a command line flag to Electron.
2. Launch the app you are intending to debug.
3. A dialog box will appear with a pid: “Renderer starting with pid: 1234”.
4. Launch WinDbg and choose “File > Attach to process” in the application menu.
5. Enter in pid from the dialog box in Step 3.
6. See that the debugger will be in a paused state, and that there is a command line in the app to enter text into.
7. Type “g” into the above command line to start the debuggee.
8. Press the enter key to continue the program.
9. Go back to the dialog box and press “ok”.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/debugging-on-windows>

Debugging on macOS
==================


If you experience crashes or issues in Electron that you believe are not caused by your JavaScript application, but instead by Electron itself, debugging can be a little bit tricky especially for developers not used to native/C++ debugging. However, using `lldb` and the Electron source code, you can enable step-through debugging with breakpoints inside Electron's source code. You can also use [XCode for debugging](debugging-with-xcode) if you prefer a graphical interface.


Requirements[​](#requirements "Direct link to heading")
-------------------------------------------------------


* **A testing build of Electron**: The easiest way is usually to build it from source, which you can do by following the instructions in the [build instructions](build-instructions-macos). While you can attach to and debug Electron as you can download it directly, you will find that it is heavily optimized, making debugging substantially more difficult. In this case the debugger will not be able to show you the content of all variables and the execution path can seem strange because of inlining, tail calls, and other compiler optimizations.
* **Xcode**: In addition to Xcode, you should also install the Xcode command line tools. They include [LLDB](https://lldb.llvm.org/), the default debugger in Xcode on macOS. It supports debugging C, Objective-C and C++ on the desktop and iOS devices and simulator.
* **.lldbinit**: Create or edit `~/.lldbinit` to allow Chromium code to be properly source-mapped.




```
# e.g: ['~/electron/src/tools/lldb']
script sys.path[:0] = ['<...path/to/electron/src/tools/lldb>']
script import lldbinit
```


Attaching to and Debugging Electron[​](#attaching-to-and-debugging-electron "Direct link to heading")
-----------------------------------------------------------------------------------------------------


To start a debugging session, open up Terminal and start `lldb`, passing a non-release build of Electron as a parameter.




```
$ lldb ./out/Testing/Electron.app
(lldb) target create "./out/Testing/Electron.app"
Current executable set to './out/Testing/Electron.app' (x86_64).
```


### Setting Breakpoints[​](#setting-breakpoints "Direct link to heading")


LLDB is a powerful tool and supports multiple strategies for code inspection. For this basic introduction, let's assume that you're calling a command from JavaScript that isn't behaving correctly - so you'd like to break on that command's C++ counterpart inside the Electron source.


Relevant code files can be found in `./shell/`.


Let's assume that you want to debug `app.setName()`, which is defined in `browser.cc` as `Browser::SetName()`. Set the breakpoint using the `breakpoint` command, specifying file and line to break on:




```
(lldb) breakpoint set --file browser.cc --line 117
Breakpoint 1: where = Electron Framework`atom::Browser::SetName(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) + 20 at browser.cc:118, address = 0x000000000015fdb4
```


Then, start Electron:




```
(lldb) run
```


The app will immediately be paused, since Electron sets the app's name on launch:




```
(lldb) run
Process 25244 launched: '/Users/fr/Code/electron/out/Testing/Electron.app/Contents/MacOS/Electron' (x86_64)
Process 25244 stopped
* thread #1: tid = 0x839a4c, 0x0000000100162db4 Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 20 at browser.cc:118, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
    frame #0: 0x0000000100162db4 Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 20 at browser.cc:118
   115  }
   116
   117  void Browser::SetName(const std::string& name) {
-> 118    name_override_ = name;
   119  }
   120
   121  int Browser::GetBadgeCount() {
(lldb)
```


To show the arguments and local variables for the current frame, run `frame variable` (or `fr v`), which will show you that the app is currently setting the name to "Electron".




```
(lldb) frame variable
(atom::Browser *) this = 0x0000000108b14f20
(const string &) name = "Electron": {
    [...]
}
```


To do a source level single step in the currently selected thread, execute `step` (or `s`). This would take you into `name_override_.empty()`. To proceed and do a step over, run `next` (or `n`).




```
(lldb) step
Process 25244 stopped
* thread #1: tid = 0x839a4c, 0x0000000100162dcc Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 44 at browser.cc:119, queue = 'com.apple.main-thread', stop reason = step in
    frame #0: 0x0000000100162dcc Electron Framework`atom::Browser::SetName(this=0x0000000108b14f20, name="Electron") + 44 at browser.cc:119
   116
   117  void Browser::SetName(const std::string& name) {
   118    name_override_ = name;
-> 119  }
   120
   121  int Browser::GetBadgeCount() {
   122    return badge_count_;
```


**NOTE:** If you don't see source code when you think you should, you may not have added the `~/.lldbinit` file above.


To finish debugging at this point, run `process continue`. You can also continue until a certain line is hit in this thread (`thread until 100`). This command will run the thread in the current frame till it reaches line 100 in this frame or stops if it leaves the current frame.


Now, if you open up Electron's developer tools and call `setName`, you will once again hit the breakpoint.


### Further Reading[​](#further-reading "Direct link to heading")


LLDB is a powerful tool with a great documentation. To learn more about it, consider Apple's debugging documentation, for instance the [LLDB Command Structure Reference](https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/gdb_to_lldb_transition_guide/document/lldb-basics.html#//apple_ref/doc/uid/TP40012917-CH2-SW2) or the introduction to [Using LLDB as a Standalone Debugger](https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/gdb_to_lldb_transition_guide/document/lldb-terminal-workflow-tutorial.html).


You can also check out LLDB's fantastic [manual and tutorial](https://lldb.llvm.org/tutorial.html), which will explain more complex debugging scenarios.



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/development/debugging-on-macos>

Keyboard Shortcuts
==================


Overview[​](#overview "Direct link to heading")
-----------------------------------------------


This feature allows you to configure local and global keyboard shortcuts for your Electron application.


Example[​](#example "Direct link to heading")
---------------------------------------------


### Local Shortcuts[​](#local-shortcuts "Direct link to heading")


Local keyboard shortcuts are triggered only when the application is focused. To configure a local keyboard shortcut, you need to specify an [`accelerator`](../api/accelerator) property when creating a [MenuItem](../api/menu-item) within the [Menu](../api/menu) module.


Starting with a working application from the [Quick Start Guide](quick-start), update the `main.js` file with the following lines:




[docs/fiddles/features/keyboard-shortcuts/local (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/features/keyboard-shortcuts/local)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/features/keyboard-shortcuts/local)


* main.js
* index.html





```
const { app, BrowserWindow, Menu, MenuItem } = require('electron')

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
  })

  win.loadFile('index.html')
}

const menu = new Menu()
menu.append(new MenuItem({
  label: 'Electron',
  submenu: [{
    role: 'help',
    accelerator: process.platform === 'darwin' ? 'Alt+Cmd+I' : 'Alt+Shift+I',
    click: () => { console.log('Electron rocks!') }
  }]
}))

Menu.setApplicationMenu(menu)

app.whenReady().then(createWindow)

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})
```




```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
    <h1>Hello World!</h1>
    <p>Hit Alt+Shift+I on Windows, or Opt+Cmd+I on mac to see a message printed to the console.</p>
</body>
</html>
```






> NOTE: In the code above, you can see that the accelerator differs based on the user's operating system. For MacOS, it is `Alt+Cmd+I`, whereas for Linux and Windows, it is `Alt+Shift+I`.
> 
> 


After launching the Electron application, you should see the application menu along with the local shortcut you just defined:


![Menu with a local shortcut]


If you click `Help` or press the defined accelerator and then open the terminal that you ran your Electron application from, you will see the message that was generated after triggering the `click` event: "Electron rocks!".


### Global Shortcuts[​](#global-shortcuts "Direct link to heading")


To configure a global keyboard shortcut, you need to use the [globalShortcut](../api/global-shortcut) module to detect keyboard events even when the application does not have keyboard focus.


Starting with a working application from the [Quick Start Guide](quick-start), update the `main.js` file with the following lines:




[docs/fiddles/features/keyboard-shortcuts/global (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/features/keyboard-shortcuts/global)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/features/keyboard-shortcuts/global)


* main.js
* index.html





```
const { app, BrowserWindow, globalShortcut } = require('electron')

function createWindow () {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
  })

  win.loadFile('index.html')
}

app.whenReady().then(() => {
  globalShortcut.register('Alt+CommandOrControl+I', () => {
    console.log('Electron loves global shortcuts!')
  })
}).then(createWindow)

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow()
  }
})
```




```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
    <h1>Hello World!</h1>
    <p>Hit Alt+Ctrl+I on Windows or Opt+Cmd+I on Mac to see a message printed to the console.</p>
</body>
</html>
```






> NOTE: In the code above, the `CommandOrControl` combination uses `Command` on macOS and `Control` on Windows/Linux.
> 
> 


After launching the Electron application, if you press the defined key combination then open the terminal that you ran your Electron application from, you will see that Electron loves global shortcuts!


### Shortcuts within a BrowserWindow[​](#shortcuts-within-a-browserwindow "Direct link to heading")


#### Using web APIs[​](#using-web-apis "Direct link to heading")


If you want to handle keyboard shortcuts within a [BrowserWindow](../api/browser-window), you can listen for the `keyup` and `keydown` [DOM events](https://developer.mozilla.org/en-US/docs/Web/Events) inside the renderer process using the [addEventListener() API](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener).




[docs/fiddles/features/keyboard-shortcuts/web-apis (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/features/keyboard-shortcuts/web-apis)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/features/keyboard-shortcuts/web-apis)


* main.js
* index.html
* renderer.js





```
// Modules to control application life and create native browser window
const {app, BrowserWindow} = require('electron')
const path = require('path')

function createWindow () {
  // Create the browser window.
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
  })

  // and load the index.html of the app.
  mainWindow.loadFile('index.html')

}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
  createWindow()
  
  app.on('activate', function () {
    // On macOS it's common to re-create a window in the app when the
    // dock icon is clicked and there are no other windows open.
    if (BrowserWindow.getAllWindows().length === 0) createWindow()
  })
})

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})
```




```
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
    <title>Hello World!</title>
  </head>
  <body>
    <h1>Hello World!</h1>
    
    <p>Hit any key with this window focused to see it captured here.</p>
    <div><span>Last Key Pressed: </span><span id="last-keypress"></span></div>
    <script src="./renderer.js"></script>
  </body>
</html>
```




```
function handleKeyPress (event) {
  // You can put code here to handle the keypress.
  document.getElementById("last-keypress").innerText = event.key
  console.log(`You pressed ${event.key}`)
}

window.addEventListener('keyup', handleKeyPress, true)
```






> Note: the third parameter `true` indicates that the listener will always receive key presses before other listeners so they can't have `stopPropagation()` called on them.
> 
> 


#### Intercepting events in the main process[​](#intercepting-events-in-the-main-process "Direct link to heading")


The [`before-input-event`](../api/web-contents#event-before-input-event) event is emitted before dispatching `keydown` and `keyup` events in the page. It can be used to catch and handle custom shortcuts that are not visible in the menu.


Starting with a working application from the [Quick Start Guide](quick-start), update the `main.js` file with the following lines:




[docs/fiddles/features/keyboard-shortcuts/interception-from-main (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/features/keyboard-shortcuts/interception-from-main)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/features/keyboard-shortcuts/interception-from-main)


* main.js
* index.html





```
const { app, BrowserWindow } = require('electron')

app.whenReady().then(() => {
  const win = new BrowserWindow({ width: 800, height: 600 })

  win.loadFile('index.html')
  win.webContents.on('before-input-event', (event, input) => {
    if (input.control && input.key.toLowerCase() === 'i') {
      console.log('Pressed Control+I')
      event.preventDefault()
    }
  })
})
```




```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello World!</title>
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
</head>
<body>
    <h1>Hello World!</h1>
    <p>Hit Ctrl+I to see a message printed to the console.</p>
</body>
</html>
```





After launching the Electron application, if you open the terminal that you ran your Electron application from and press `Ctrl+I` key combination, you will see that this key combination was successfully intercepted.


#### Using third-party libraries[​](#using-third-party-libraries "Direct link to heading")


If you don't want to do manual shortcut parsing, there are libraries that do advanced key detection, such as [mousetrap](https://github.com/ccampbell/mousetrap). Below are examples of usage of the `mousetrap` running in the Renderer process:




```
Mousetrap.bind('4', () => { console.log('4') })
Mousetrap.bind('?', () => { console.log('show shortcuts!') })
Mousetrap.bind('esc', () => { console.log('escape') }, 'keyup')

// combinations
Mousetrap.bind('command+shift+k', () => { console.log('command shift k') })

// map multiple combinations to the same callback
Mousetrap.bind(['command+k', 'ctrl+k'], () => {
  console.log('command k or control k')

  // return false to prevent default behavior and stop event from bubbling
  return false
})

// gmail style sequences
Mousetrap.bind('g i', () => { console.log('go to inbox') })
Mousetrap.bind('* a', () => { console.log('select all') })

// konami code!
Mousetrap.bind('up up down down left right left right b a enter', () => {
  console.log('konami code')
})
```



 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/keyboard-shortcuts>

Deep Links
==========


Overview[​](#overview "Direct link to heading")
-----------------------------------------------


This guide will take you through the process of setting your Electron app as the default handler for a specific [protocol](https://www.electronjs.org/docs/api/protocol).


By the end of this tutorial, we will have set our app to intercept and handle any clicked URLs that start with a specific protocol. In this guide, the protocol we will use will be "`electron-fiddle://`".


Examples[​](#examples "Direct link to heading")
-----------------------------------------------


### Main Process (main.js)[​](#main-process-mainjs "Direct link to heading")


First, we will import the required modules from `electron`. These modules help control our application lifecycle and create a native browser window.




```
const { app, BrowserWindow, shell } = require('electron')
const path = require('path')
```


Next, we will proceed to register our application to handle all "`electron-fiddle://`" protocols.




```
if (process.defaultApp) {
  if (process.argv.length >= 2) {
    app.setAsDefaultProtocolClient('electron-fiddle', process.execPath, [path.resolve(process.argv[1])])
  }
} else {
  app.setAsDefaultProtocolClient('electron-fiddle')
}
```


We will now define the function in charge of creating our browser window and load our application's `index.html` file.




```
const createWindow = () => {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    }
  })

  mainWindow.loadFile('index.html')
}
```


In this next step, we will create our `BrowserWindow` and tell our application how to handle an event in which an external protocol is clicked.


This code will be different in Windows compared to MacOS and Linux. This is due to Windows requiring additional code in order to open the contents of the protocol link within the same Electron instance. Read more about this [here](https://www.electronjs.org/docs/api/app#apprequestsingleinstancelock).


#### Windows code:[​](#windows-code "Direct link to heading")




```
const gotTheLock = app.requestSingleInstanceLock()

if (!gotTheLock) {
  app.quit()
} else {
  app.on('second-instance', (event, commandLine, workingDirectory) => {
    // Someone tried to run a second instance, we should focus our window.
    if (mainWindow) {
      if (mainWindow.isMinimized()) mainWindow.restore()
      mainWindow.focus()
    }
  })

  // Create mainWindow, load the rest of the app, etc...
  app.whenReady().then(() => {
    createWindow()
  })

  // Handle the protocol. In this case, we choose to show an Error Box.
  app.on('open-url', (event, url) => {
    dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
  })
}
```


#### MacOS and Linux code:[​](#macos-and-linux-code "Direct link to heading")




```
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
  createWindow()
})

// Handle the protocol. In this case, we choose to show an Error Box.
app.on('open-url', (event, url) => {
  dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
})
```


Finally, we will add some additional code to handle when someone closes our application.




```
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit()
})
```


Important notes[​](#important-notes "Direct link to heading")
-------------------------------------------------------------


### Packaging[​](#packaging "Direct link to heading")


On macOS and Linux, this feature will only work when your app is packaged. It will not work when you're launching it in development from the command-line. When you package your app you'll need to make sure the macOS `Info.plist` and the Linux `.desktop` files for the app are updated to include the new protocol handler. Some of the Electron tools for bundling and distributing apps handle this for you.


#### 
[Electron Forge](https://electronforge.io)[​](#electron-forge "Direct link to heading")


If you're using Electron Forge, adjust `packagerConfig` for macOS support, and the configuration for the appropriate Linux makers for Linux support, in your [Forge configuration](https://www.electronforge.io/configuration) *(please note the following example only shows the bare minimum needed to add the configuration changes)*:




```
{
  "config": {
    "forge": {
      "packagerConfig": {
        "protocols": [
          {
            "name": "Electron Fiddle",
            "schemes": ["electron-fiddle"]
          }
        ]
      },
      "makers": [
        {
          "name": "@electron-forge/maker-deb",
          "config": {
            "mimeType": ["x-scheme-handler/electron-fiddle"]
          }
        }
      ]
    }
  }
}
```


#### 
[Electron Packager](https://github.com/electron/electron-packager)[​](#electron-packager "Direct link to heading")


For macOS support:


If you're using Electron Packager's API, adding support for protocol handlers is similar to how Electron Forge is handled, except `protocols` is part of the Packager options passed to the `packager` function.




```
const packager = require('electron-packager')

packager({
  // ...other options...
  protocols: [
    {
      name: 'Electron Fiddle',
      schemes: ['electron-fiddle']
    }
  ]

}).then(paths => console.log(`SUCCESS: Created ${paths.join(', ')}`))
  .catch(err => console.error(`ERROR: ${err.message}`))
```


If you're using Electron Packager's CLI, use the `--protocol` and `--protocol-name` flags. For example:




```
npx electron-packager . --protocol=electron-fiddle --protocol-name="Electron Fiddle"
```


Conclusion[​](#conclusion "Direct link to heading")
---------------------------------------------------


After you start your Electron app, you can enter in a URL in your browser that contains the custom protocol, for example `"electron-fiddle://open"` and observe that the application will respond and show an error dialog box.




[docs/fiddles/system/protocol-handler/launch-app-from-URL-in-another-app (20.1.0)](https://github.com/electron/electron/tree/v20.1.0/docs/fiddles/system/protocol-handler/launch-app-from-URL-in-another-app)[Open in Fiddle](https://fiddle.electronjs.org/launch?target=electron/v20.1.0/docs/fiddles/system/protocol-handler/launch-app-from-URL-in-another-app)


* main.js
* preload.js
* index.html
* renderer.js





```
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, shell, dialog } = require('electron')
const path = require('path')

let mainWindow;

if (process.defaultApp) {
  if (process.argv.length >= 2) {
    app.setAsDefaultProtocolClient('electron-fiddle', process.execPath, [path.resolve(process.argv[1])])
  }
} else {
    app.setAsDefaultProtocolClient('electron-fiddle')
}

const gotTheLock = app.requestSingleInstanceLock()

if (!gotTheLock) {
  app.quit()
} else {
  app.on('second-instance', (event, commandLine, workingDirectory) => {
    // Someone tried to run a second instance, we should focus our window.
    if (mainWindow) {
      if (mainWindow.isMinimized()) mainWindow.restore()
      mainWindow.focus()
    }
  })

  // Create mainWindow, load the rest of the app, etc...
  app.whenReady().then(() => {
    createWindow()
  })
  
  app.on('open-url', (event, url) => {
    dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
  })
}

function createWindow () {
  // Create the browser window.
  mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
    }
  })

  mainWindow.loadFile('index.html')
}

// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit()
})

// Handle window controls via IPC
ipcMain.on('shell:open', () => {
  const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
  const pagePath = path.join('file://', pageDirectory, 'index.html')
  shell.openExternal(pagePath)
})
```




```
// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
const { contextBridge, ipcRenderer } = require('electron')

// Set up context bridge between the renderer process and the main process
contextBridge.exposeInMainWorld(
  'shell',
  {
    open: () => ipcRenderer.send('shell:open'),
  }
)
```




```
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
  <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
  <meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
  <title>app.setAsDefaultProtocol Demo</title>
</head>

<body>
  <h1>App Default Protocol Demo</h1>

  <p>The protocol API allows us to register a custom protocol and intercept existing protocol requests.</p>
  <p>These methods allow you to set and unset the protocols your app should be the default app for. Similar to when a
    browser asks to be your default for viewing web pages.</p>

  <p>Open the <a href="https://www.electronjs.org/docs/api/protocol">full protocol API documentation</a> in your
    browser.</p>

  -----

  <h3>Demo</h3>
  <p>
    First: Launch current page in browser
    <button id="open-in-browser" class="js-container-target demo-toggle-button">
        Click to Launch Browser
      </button>
  </p>

  <p>
    Then: Launch the app from a web link!
    <a href="electron-fiddle://open">Click here to launch the app</a>
  </p>

  ----

  <p>You can set your app as the default app to open for a specific protocol. For instance, in this demo we set this app
    as the default for <code>electron-fiddle://</code>. The demo button above will launch a page in your default
    browser with a link. Click that link and it will re-launch this app.</p>


  <h3>Packaging</h3>
  <p>This feature will only work on macOS when your app is packaged. It will not work when you're launching it in
    development from the command-line. When you package your app you'll need to make sure the macOS <code>plist</code>
    for the app is updated to include the new protocol handler. If you're using <code>electron-packager</code> then you
    can add the flag <code>--extend-info</code> with a path to the <code>plist</code> you've created. The one for this
    app is below:</p>

  <p>
  <h5>macOS plist</h5>
  <pre><code>
    &lt;?xml version="1.0" encoding="UTF-8"?&gt;
    &lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
            &lt;plist version="1.0"&gt;
                &lt;dict&gt;
                    &lt;key&gt;CFBundleURLTypes&lt;/key&gt;
                    &lt;array&gt;
                        &lt;dict&gt;
                            &lt;key&gt;CFBundleURLSchemes&lt;/key&gt;
                            &lt;array&gt;
                                &lt;string&gt;electron-api-demos&lt;/string&gt;
                            &lt;/array&gt;
                            &lt;key&gt;CFBundleURLName&lt;/key&gt;
                            &lt;string&gt;Electron API Demos Protocol&lt;/string&gt;
                        &lt;/dict&gt;
                    &lt;/array&gt;
                    &lt;key&gt;ElectronTeamID&lt;/key&gt;
                    &lt;string&gt;VEKTX9H2N7&lt;/string&gt;
                &lt;/dict&gt;
            &lt;/plist&gt;
        </code>
    </pre>
  <p>

    <!-- You can also require other files to run in this process -->
    <script src="./renderer.js"></script>
</body>

</html>
```




```
// This file is required by the index.html file and will
// be executed in the renderer process for that window.
// All APIs exposed by the context bridge are available here.

// Binds the buttons to the context bridge API.
document.getElementById('open-in-browser').addEventListener('click', () => {
  shell.open();
});
```






 © GitHub Inc.  
Licensed under the MIT license.  

<https://www.electronjs.org/docs/latest/tutorial/launch-app-from-url-in-another-app>

electron