Chrome Extension manifest.json: The Complete Guide to Every Field You'll Actually Use

Oct 25, 2025
10 min read
BasharathBy Basharath
Share:

The manifest.json file is the brain of your Chrome extension. It's the first file Chrome reads when loading your extension, and it determines everything from what your extension can do to how it appears in the browser. Get it wrong, and your extension won't even load. Get it right, and you unlock the full potential of Chrome's extension API.

But here's the thing: the manifest file has evolved over the years, and if you're reading outdated tutorials, you might be using deprecated fields or missing out on new features. In this guide, we'll break down every field you'll actually use in Manifest V3 (the current standard), explain what each one does, and show you practical examples.

What is manifest.json?

Think of manifest.json as your extension's ID card and instruction manual combined. It tells Chrome:

  • What your extension is called and what it does

  • Which permissions it needs

  • What files to load and when

  • How users interact with it

  • What version of the manifest format you're using

Every Chrome extension must have a manifest.json file in its root directory. Without it, Chrome won't recognize your folder as an extension.

Manifest V2 vs V3: What's the Difference?

Chrome has had three versions of the manifest format, but only two matter today:

Manifest V2 (Deprecated)

Used from 2012 to 2022. If you see "manifest_version": 2 in tutorials, that code is outdated. Chrome stopped accepting new V2 extensions in 2022 and will fully disable them by 2024.

Manifest V3 (Current Standard)

Released in 2021 and required for all new extensions since 2022. V3 brings better security, performance, and privacy. Key changes include:

  • Background pages → Service workers

  • Blocking web requests → Declarative net request

  • Better permission handling

  • Improved security model

Always use Manifest V3 for new extensions. That's what we'll cover in this guide.

The Essential Fields (Required)

These fields are mandatory. Your extension won't load without them.

1. manifest_version

"manifest_version": 3

What it does: Tells Chrome which version of the manifest format you're using.

Always use: 3 for new extensions. Never use 2 anymore.


2. name

"name": "My Awesome Extension"

What it does: The name of your extension as it appears in the Chrome Web Store and extensions page.

Best practices:

  • Keep it under 45 characters

  • Make it descriptive and searchable

  • Avoid generic names like "Extension" or "Tool"

Example: "Todo Master - Task Manager" is better than "Todo Extension"


3. version

"version": "1.0.0"

What it does: Your extension's version number. Chrome uses this to detect updates.

Format: Must be 1-4 numbers separated by dots (e.g., 1.0, 1.2.3, 2.0.0.1)

Best practices:

  • Start with 1.0 or 1.0.0

  • Increment for each update (1.0 → 1.1 → 2.0)

  • Major changes = increment first number

  • Minor updates = increment second number

  • Bug fixes = increment third number


Important Fields (Highly Recommended)

These aren't technically required, but you'll almost always need them.

4. description

"description": "A simple and elegant todo list extension for managing your daily tasks"

What it does: Brief description of what your extension does. Appears in the Chrome Web Store and extensions page.

Best practices:

  • Maximum 132 characters

  • Be specific about what it does

  • Include keywords for Chrome Web Store SEO

  • Don't use generic descriptions


5. icons

"icons": {
  "16": "icons/icon16.png",
  "48": "icons/icon48.png",
  "128": "icons/icon128.png"
}

What it does: Specifies icon files for different display sizes.

Sizes explained:

  • 16x16: Favicon on extension pages

  • 48x48: Extensions management page

  • 128x128: Chrome Web Store and installation dialog

Best practices:

  • Always provide at least a 128x128 icon

  • Use PNG format with transparency

  • Keep designs simple and recognizable at small sizes

  • Can use a single icon for all sizes: "default_icon": "icon.png"


6. action

"action": {
  "default_popup": "popup.html",
  "default_icon": {
    "16": "icons/icon16.png",
    "24": "icons/icon24.png",
    "32": "icons/icon32.png"
  },
  "default_title": "Click to open Todo List"
}

What it does: Defines the toolbar button and what happens when users click it.

Fields inside action:

  • default_popup: HTML file that opens when icon is clicked

  • default_icon: Icon shown in toolbar (can be string or object with sizes)

  • default_title: Tooltip text when hovering over icon

When to use: Almost every extension has an action. Omit it only if your extension runs entirely in the background.


Permission Fields

Permissions tell Chrome what APIs and features your extension needs access to.

7. permissions

"permissions": [
  "storage",
  "activeTab",
  "notifications"
]

What it does: Lists Chrome APIs your extension needs. Users must approve these during installation.

Common permissions:

  • storage: Access to chrome.storage API (local data storage)

  • activeTab: Access to currently active tab when user invokes extension

  • tabs: Access to tab information (URLs, titles)

  • notifications: Show system notifications

  • alarms: Schedule code to run periodically

  • scripting: Inject scripts into web pages

  • cookies: Read and modify cookies

  • bookmarks: Access bookmark data

  • history: Access browsing history

Best practices:

  • Only request permissions you actually need

  • More permissions = users less likely to install

  • Use activeTab instead of tabs when possible (requires less permission)


8. host_permissions

"host_permissions": [
  "https://*/*",
  "http://*/*",
  "*://example.com/*"
]

What it does: Specifies which websites your extension can interact with.

When to use: When your extension needs to run code on specific websites or all websites.

Patterns:

  • "*://*/*": All URLs (HTTP and HTTPS)

  • "https://*/*": All HTTPS URLs only

  • "*://google.com/*": All Google.com pages

  • "<all_urls>": All URLs including file:// and ftp://

Best practices:

  • Be as specific as possible

  • Don't request all URLs if you only need specific sites

  • Requesting all URLs triggers a warning during installation


9. optional_permissions

"optional_permissions": [
  "geolocation",
  "clipboardWrite"
],
"optional_host_permissions": [
  "https://api.example.com/*"
]

What it does: Permissions that can be granted later, not during installation.

When to use: For features users might not use immediately, reducing initial permission requests.

Example use case: A translation extension might not need API access until user enables a premium feature.


Content Scripts

10. content_scripts

"content_scripts": [
  {
    "matches": ["https://*/*", "http://*/*"],
    "js": ["content.js"],
    "css": ["content.css"],
    "run_at": "document_idle"
  }
]

What it does: Injects JavaScript and CSS files directly into web pages.

Fields:

  • matches: URL patterns where scripts should run (required)

  • js: Array of JavaScript files to inject

  • css: Array of CSS files to inject

  • run_at: When to inject

    • document_start: Before page loads

    • document_end: After DOM loads, before images

    • document_idle: After page fully loads (default)

When to use: When your extension modifies web pages (ad blockers, theme changers, page enhancers)

Example use case: Dark mode extension that injects CSS to make all websites dark. Clipboard extension that uses Content Script to display copied text within the page.


Background Scripts (Service Workers)

11. background

"background": {
  "service_worker": "background.js"
}

What it does: Runs a service worker in the background to handle events, API calls, and long-running tasks.

Important notes:

  • Manifest V3 uses service workers, not background pages

  • Service workers are event-driven and don't run continuously

  • No DOM access in service workers (no document or window)

  • Only one file allowed (unlike content_scripts which can have multiple)

When to use:

  • Handling extension events (installation, updates)

  • Managing state across tabs

  • Making API calls

  • Processing messages from content scripts

Example use case: Opening a tab when users click the extension icon.

// background.js
chrome.action.onClicked.addListener((tab) => {
  chrome.tabs.create({ url: 'popup.html' });
});

Page Overrides

12. chrome_url_overrides

"chrome_url_overrides": {
  "newtab": "newtab.html"
}

What it does: Replaces Chrome's default pages with your custom pages.

Can override:

  • newtab: New tab page

  • bookmarks: Bookmarks page (chrome://bookmarks)

  • history: History page (chrome://history)

Limitation: Can only override ONE page per extension.

When to use: Custom new tab page extensions (like Momentum, Infinity New Tab)


Side Panel

13. side_panel

"side_panel": {
  "default_path": "sidepanel.html"
}

What it does: Opens your extension in Chrome's side panel (left or right side of browser).

Requires: "sidePanel" permission

When to use: Extensions that need to stay visible while users browse (notes, reading lists, bookmarks)

Example manifest:

{
  "manifest_version": 3,
  "name": "Side Panel Extension",
  "permissions": ["sidePanel"],
  "side_panel": {
    "default_path": "panel.html"
  }
}

Options and Settings

14. options_page

"options_page": "options.html"

What it does: Creates a settings page accessible by right-clicking your extension icon and selecting "Options".

When to use: Your extension has user preferences, settings, or configuration.

Alternative: Use options_ui for embedded options in Chrome's extension management page:

"options_ui": {
  "page": "options.html",
  "open_in_tab": false
}
  • open_in_tab: false: Opens in an embedded dialog (recommended)

  • open_in_tab: true: Opens in a full tab


Web Accessible Resources

15. web_accessible_resources

"web_accessible_resources": [
  {
    "resources": ["images/*", "styles.css"],
    "matches": ["https://*/*"]
  }
]

What it does: Makes extension files accessible to web pages.

When to use:

  • Content scripts need to inject images or assets from your extension

  • Web pages need to load resources from your extension

  • Showing extension images on modified web pages

Security note: Only expose files that absolutely need to be public.


Commands (Keyboard Shortcuts)

16. commands

"commands": {
  "open-todo": {
    "suggested_key": {
      "default": "Ctrl+Shift+T",
      "mac": "Command+Shift+T"
    },
    "description": "Open todo list"
  },
  "_execute_action": {
    "suggested_key": {
      "default": "Ctrl+Shift+E"
    }
  }
}

What it does: Defines keyboard shortcuts for your extension.

Special commands:

  • executeaction: Triggers the default action (opens popup)

  • executebrowser_action: Same as above (legacy name)

Best practices:

  • Use Ctrl+Shift+[Letter] format

  • Separate Mac shortcuts with Command instead of Ctrl

  • Don't use already common shortcuts

  • Keep descriptions short and clear


Content Security Policy

17. content_security_policy

"content_security_policy": {
  "extension_pages": "script-src 'self'; object-src 'self'"
}

What it does: Defines security restrictions for your extension's pages.

Default policy in V3: Very strict, doesn't allow inline scripts or eval().

Most developers: Don't need to change this. The default is secure and sufficient.

When to modify: Only if you need to load external scripts (not recommended for security).


Internationalization

18. default_locale

"default_locale": "en"

What it does: Specifies the default language when using internationalization (i18n).

Required when: You have a _locales folder with translation files.

Example structure:

my-extension/
├── _locales/
│   ├── en/
│   │   └── messages.json
│   ├── es/
│   │   └── messages.json

When to use: Building multilingual extensions.


Other Useful Fields

19. author

"author": "Your Name"

or

"author": {
  "email": "you@example.com"
}

What it does: Identifies the extension's creator (metadata only).


20. homepage_url

"homepage_url": "https://yourwebsite.com"

What it does: Links to your extension's website or documentation.


21. minimum_chrome_version

"minimum_chrome_version": "88"

What it does: Specifies the minimum Chrome version required to run your extension.

When to use: If you're using newer APIs not available in older Chrome versions.


22. externally_connectable

"externally_connectable": {
  "matches": ["https://yourwebsite.com/*"]
}

What it does: Allows specific websites to communicate with your extension using chrome.runtime.sendMessage().

When to use: Building extensions that interact with your website.


A Complete Example Manifest

Here's what a real-world todo list extension manifest looks like with commonly used fields:

{
  "manifest_version": 3,
  "name": "Todo Master - Task Manager",
  "version": "1.2.0",
  "description": "A beautiful and simple todo list extension for managing daily tasks",
  
  "icons": {
    "16": "icons/icon16.png",
    "48": "icons/icon48.png",
    "128": "icons/icon128.png"
  },
  
  "action": {
    "default_popup": "popup.html",
    "default_icon": "icons/icon48.png",
    "default_title": "Open Todo List"
  },
  
  "permissions": [
    "storage",
    "alarms",
    "notifications"
  ],
  
  "background": {
    "service_worker": "background.js"
  },
  
  "options_ui": {
    "page": "options.html",
    "open_in_tab": false
  },
  
  "commands": {
    "open-todo": {
      "suggested_key": {
        "default": "Ctrl+Shift+T",
        "mac": "Command+Shift+T"
      },
      "description": "Open todo list"
    }
  },
  
  "author": "Your Name",
  "homepage_url": "https://yourwebsite.com"
}

Common Mistakes and How to Avoid Them

Mistake 1: Using Manifest V2

Problem: Your extension won't be accepted to the Chrome Web Store.
Solution: Always start with "manifest_version": 3

Mistake 2: Requesting Too Many Permissions

Problem: Users won't install your extension because it looks suspicious.
Solution: Only request permissions you actually use. Test without unnecessary permissions.

Mistake 3: Wrong File Paths

Problem: Chrome can't find your HTML/JS/CSS files.
Solution: Double-check all paths in manifest. They're relative to the manifest.json file location.

Mistake 4: Invalid Version Numbers

Problem: Extension won't load.
Solution: Version must be 1-4 dot-separated integers (e.g., 1.0, 1.2.3, not 1.2.3.4.5)

Mistake 5: Missing Icons

Problem: Extension loads but looks unprofessional.
Solution: Always include at least a 128x128 icon, even if it's just a simple design.


Quick Reference: Which Fields Do I Need?

Minimum viable extension:

{
  "manifest_version": 3,
  "name": "My Extension",
  "version": "1.0"
}

Popup extension: Add action with default_popup

Extension that modifies web pages: Add content_scripts and host_permissions

Extension that runs in background: Add background with service_worker

Extension with settings: Add options_page or options_ui

Extension that stores data: Add "storage" to permissions


Key Takeaways

The manifest.json file is simple once you understand what each field does. Most extensions only use 5-10 fields total. Start with the required fields (manifest_version, name, version), add the fields for your extension type (action, content_scripts, etc.), and request only the permissions you need.

Remember: Chrome is very strict about the manifest format. One wrong comma or quote, and your extension won't load. Use a JSON validator if you're getting errors, and always test your manifest by loading it as an unpacked extension before publishing.

Now you have a complete reference for every manifest field you'll actually use. Bookmark this guide and refer back whenever you're building a new Chrome extension!

B

Written by Basharath

Chrome extension developer sharing insights, tutorials, and best practices for building better browser extensions.

Related Articles