Ver en Español
The Options Page in Chrome Extensions
Jun 24, 2026
Updated: Jun 25, 2026

The Options Page in Chrome Extensions

Just as extensions let users customize the Chrome browser, the options page lets users customize the extension itself. Use the options page to enable features and let users choose which capabilities are relevant to their needs.

Accessing the options page

Users can reach the options page through a direct link, or by right clicking the extension icon in the toolbar and selecting "Options". They can also navigate to it by opening chrome://extensions, locating the desired extension, clicking "Details", and selecting the options link. Next, I'll show you how to create and configure an options page.

Right-click menu on the extension toolbar icon in Chrome with the "Options" item highlighted

Create the options.html file

In your project folder, create a file named options.html and add the following code:

<!DOCTYPE html>
<html>

<head>
    <title>Mi color favorito</title>
</head>

<body>
    <select id="color">
        <option value="red">rojo</option>
        <option value="green">verde</option>
        <option value="blue">azul</option>
        <option value="yellow">amarillo</option>
    </select>

    <label>
        <input type="checkbox" id="like" />
        Me gustan los colores
    </label>

    <div id="status"></div>
    <button id="save">Guardar</button>

    <script src="options.js"></script>
</body>

</html>

Update the Manifest

Open your manifest.json file and add the reference to the options page:

{
  "manifest_version": 3,
  "name": "Mi Extensión",
  "version": "0.0.1",
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "icon-16.png",
      "48": "icon-48.png",
      "128": "icon-128.png"
    }
  },
  "options_page": "options.html"
}

CSS and JavaScript

Just like popup.html, the options page lets you use HTML, CSS, and JavaScript. Keep in mind that the options page has no direct link to the popup or to other parts of the application, so interaction with it is limited and we can only communicate through Chrome storage. For example, let's add JavaScript in options.js so the color chosen by the user gets saved.

Since Chrome 88, the chrome.storage APIs return Promises, so we can write them with async/await, which is the idiomatic style today. Here is the modernized options.js:

// Save the options to chrome.storage
const saveOptions = async () => {
  // Read the selected color value and the checkbox state
  const color = document.getElementById('color').value;
  const likesColor = document.getElementById('like').checked;

  // Save the values to chrome.storage.sync
  await chrome.storage.sync.set({ favoriteColor: color, likesColor });

  // Update the status to let the user know the options were saved
  const status = document.getElementById('status');
  status.textContent = 'Opciones guardadas.';
  setTimeout(() => {
    status.textContent = '';
  }, 750);
};

// Restore the select and checkbox state using the preferences
// stored in chrome.storage
const restoreOptions = async () => {
  const items = await chrome.storage.sync.get({ favoriteColor: 'red', likesColor: true });

  // Set the retrieved values on the form elements
  document.getElementById('color').value = items.favoriteColor;
  document.getElementById('like').checked = items.likesColor;
};

// Restore the options when the document content has loaded
document.addEventListener('DOMContentLoaded', restoreOptions);

// Save the options when the save button is clicked
document.getElementById('save').addEventListener('click', saveOptions);

Note: if you prefer to keep compatibility with older code, these same APIs also accept a callback as their last argument, for example chrome.storage.sync.get({ favoriteColor: 'red' }, (items) => {... }). It works, but the async/await form is cleaner and is the recommended approach today.

Before using storage you must add the corresponding permission in your manifest.json:

"permissions": [
  "storage"
]

Note on permissions: if you've been following this series, you may already have activeTab and scripting in your permissions list from earlier chapters. For this chapter's options page the only permission you need is storage; the other two are not used by the code we see here.

How to declare the options page behavior in Chrome extensions

When developing a Chrome extension, it's essential to define how the configuration options will be presented to the user. There are two main types of options pages for extensions: full page and embedded. The type is determined by how you declare it in the manifest.json file.

Full page options

Full page options open in a new browser tab. This approach is useful if your extension needs a larger interface for complex configurations. To register a full page options page, you include the corresponding HTML file in the options_page field of the manifest.

Example in the manifest.json file:

{
  "name": "Mi extensión",
  "options_page": "options.html"
}

When the user opens the extension's options, a new tab opens showing the content of options.html.

Embedded options

Embedded options let users adjust the extension's settings without leaving Chrome's extensions management page. This type of options page appears inside an embedded box on that same page. To declare embedded options, register the HTML file in the options_ui field of the extension manifest and set the open_in_tab key to false.

Example in the manifest.json file:

{
  "name": "Mi extensión",
  "options_ui": {
    "page": "options.html",
    "open_in_tab": false
  }
}

With this setup, users can access and adjust the extension's options directly from Chrome's extensions management page, without needing to open a new tab.

Using the saved options from the popup

Communication from our main popup works in a similar way, using the Storage API to fetch the data and apply it as needed. For example, in our case we can change the backgroundColor of the .login-container element to the color the user chose in the options. Let's modify the popup.js file to do this:

const restoreOptions = async () => {
  const items = await chrome.storage.sync.get({ favoriteColor: 'red', likesColor: true });
  document.querySelector('.login-container').style.backgroundColor = items.favoriteColor;
};

document.addEventListener('DOMContentLoaded', restoreOptions);

Notice that here we read storage with the same pattern as in options.js: we pass an object with default values to chrome.storage.sync.get and use await. That way, both the options page and the popup share exactly the same way of reading and recoloring, without mixing styles.

Linking to the options page

An extension can link directly to its options page by calling chrome.runtime.openOptionsPage(). For example, you can add a button in the popup to take the user to the options page.

Code in popup.html:

<button id="go-to-options">Ir a opciones</button>
<script src="popup.js"></script>

Code in popup.js:

document.querySelector('#go-to-options').addEventListener('click', () => {
  chrome.runtime.openOptionsPage();
});

Note: chrome.runtime.openOptionsPage() has existed since Chrome 42, so it's always available in any Manifest V3 capable browser. That's why you no longer need the old window.open(chrome.runtime.getURL('options.html')) fallback: it was defensive code that never actually ran.

If you want to combine both pieces, recoloring the container when the popup opens and opening the options from the button, just merge them inside the same popup.js:

document.addEventListener('DOMContentLoaded', async () => {
  // Recolor the container based on the saved configuration
  const items = await chrome.storage.sync.get({ favoriteColor: 'red', likesColor: true });
  document.querySelector('.login-container').style.backgroundColor = items.favoriteColor;

  // Open the options page from the button
  document.querySelector('#go-to-options').addEventListener('click', () => {
    chrome.runtime.openOptionsPage();
  });
});

This code makes sure the container background changes to the user's preferred color, stored in chrome.storage, and provides a direct link to the options page from the popup.

Suggested exercises

  1. Add a third control to options.html (for example, a text field for a username), save it to chrome.storage.sync, and read it from the popup.
  2. Convert your extension to embedded options using options_ui with open_in_tab: false and compare the experience with the full page one.
  3. Replace the default values passed to each get with a shared defaults constant and reuse it in both options.js and popup.js.

3-point summary

  1. The options page lets you customize your extension and only communicates with the rest of the app through chrome.storage.
  2. You can declare it as a full page (options_page) or embedded (options_ui with open_in_tab: false), depending on how complex your configuration is.
  3. Since Chrome 88 the storage APIs return Promises, so use async/await and a single read pattern in both the options and the popup.

I hope you found this guide useful and that you can apply it to a project you have in mind. Don't forget to leave a comment if it helped, subscribe for more content, and share the post using the social links below. Good luck and keep building.

Sebastian Gomez

Sebastian Gomez

Creador de contenido principalmente acerca de tecnología.

Leave a Reply

0 Comments

Advertisements

Related Posts

Categorias