• Chrome Web Store
  • Manifest V3
  • Cross-platform
  • Store Data

Chrome extension ID: how to find it and keep it stable

Chrome extension ID guide: find any extension's 32-letter ID, keep yours stable with the manifest key, and match IDs across Chrome, Edge and Firefox.

Author
Extenify Team
Published
Reading time
12 min read
A long row of identical gray mailboxes on metal posts beside a dirt road in the sun

A Chrome extension ID is the 32-letter string that identifies one extension everywhere Chrome needs to know which extension it is talking to: the chrome-extension:// origin, the Chrome Web Store listing URL, OAuth redirect URLs, native messaging hosts and enterprise policies. Finding an ID takes a few seconds. Keeping your own ID from changing while you develop is the part that trips people up, because an unpacked extension gets a new ID every time you load it from a different folder.

This guide covers both. It shows every place to find a Chrome extension ID, explains exactly how Chrome derives it (we checked the Chromium source and tested it in Chrome 156), shows how to pin your ID with the manifest key, and explains why the same extension has a different ID on Edge and Firefox.

Key takeaways

  • A Chrome extension ID is 32 letters from a to p. Chrome takes the SHA-256 hash of the extension's public key, keeps the first 16 bytes and writes each hex digit as a letter.
  • Find any ID at the end of its Chrome Web Store URL, or on chrome://extensions with Developer mode on. Inside your code, use chrome.runtime.id.
  • An unpacked extension without a key gets an ID from its folder path. In our test, copying the same folder to a new path produced a new ID; with a key, the ID stayed the same.
  • Copy the public key from the Developer Dashboard into manifest.json as "key" so local builds match your store ID.
  • Edge Add-ons and Firefox give the same product different identifiers, so map them together before you compare stats.

What a Chrome extension ID is

Chrome does not let you pick an ID. It computes one from the extension's public key. The Chromium source describes the ID as the "First 16 bytes of SHA256 hashed public key", hex encoded, and then converts each hex digit 0 to f into a letter a to p. The comment explains why: the letters are used "to avoid ever having a completely numeric host, since some software interprets that as an IP address."

So every valid ID has exactly 32 characters, all between a and p. A string with a z or a digit in it is not a Chrome extension ID, which makes a cheap validation rule for any form or API that accepts IDs:

const isChromeExtensionId = (value) => /^[a-p]{32}$/.test(value);

We checked the derivation against a real store package. The CRX file that Chrome's update service serves for uBlock Origin Lite carries three public keys in its signed header. Hashing them gave three candidate IDs, and one of them was ddkjiahejlhfcafbddmgiahcphecmpfh, the extension's ID in the store and the crx_id recorded in the package's signed header.

The ID shows up in more places than most developers expect:

Where What it looks like
Extension origin chrome-extension://<id>/popup.html
Chrome Web Store listing https://chromewebstore.google.com/detail/<name>/<id>
OAuth redirect for chrome.identity https://<id>.chromiumapp.org/
Native messaging host manifest "allowed_origins": ["chrome-extension://<id>/"]
Another extension's externally_connectable "ids": ["<id>"]
Enterprise force-install policy <id>;https://clients2.google.com/service/update2/crx

Every one of these breaks if the ID changes, which is why the rest of this guide spends more time on stability than on lookup.

How to find a Chrome extension ID

There are five ways, depending on whether you are a user, a developer or writing code.

From chrome://extensions

Open chrome://extensions, turn on Developer mode in the top right corner, and the ID appears under each extension's name. Without Developer mode, click Details on an extension: the address bar changes to chrome://extensions/?id=<id>. Chrome's own enterprise policy documentation points administrators to the same place: "The extension ID is the 32-letter string found, for example, on chrome://extensions when in Developer mode."

From the Chrome Web Store URL

The ID is the last path segment of a listing URL. In https://chromewebstore.google.com/detail/grammarly-ai-writing-assi/kbfnbcaeplbcioakkpcpgfkobkghlhen, the ID is kbfnbcaeplbcioakkpcpgfkobkghlhen. The name part is cosmetic: when we requested https://chromewebstore.google.com/detail/kbfnbcaeplbcioakkpcpgfkobkghlhen with no name, the store redirected to the full listing. Old chrome.google.com/webstore/detail/... links also redirect to the new store with the same ID.

That makes the ID the stable thing to store in a database or spreadsheet. Names and URL slugs change when a developer renames the extension; the ID does not.

From inside your extension

In any extension context, chrome.runtime.id returns your own ID, and chrome.runtime.getURL('') returns your origin with a trailing slash:

console.log(chrome.runtime.id);        // "kbfnbcaeplbcioakkpcpgfkobkghlhen"
console.log(chrome.runtime.getURL('')); // "chrome-extension://kbfnbcaeplbcioakkpcpgfkobkghlhen/"

Log it from the service worker after loading an unpacked build when you need to copy your current development ID quickly.

From the profile folder

Chrome stores installed extensions in the profile's Extensions folder, with one subfolder per ID and a version folder inside it. The user data directory is documented in Chromium's user data directory guide; with the default profile, the folders are:

  • Windows: %LOCALAPPDATA%\Google\Chrome\User Data\Default\Extensions
  • macOS: ~/Library/Application Support/Google/Chrome/Default/Extensions
  • Linux: ~/.config/google-chrome/Default/Extensions

This is the way to recover the ID of an extension that is installed but no longer listed. When we opened the listing URL of an extension that had been taken down, the store served its generic home page instead.

For every installed extension, in code

An extension can list other extensions with chrome.management.getAll(), which returns each extension's id, name, version and enabled state. It needs the "management" permission, which shows users the warning "Manage your apps, extensions, and themes" according to the permissions list. Only request it if listing extensions is a core feature, because a scary warning costs installs.

Why your unpacked extension ID keeps changing

When an unpacked extension has no key in its manifest, Chrome has no public key to hash. The same id_util.cc file shows what it uses instead: GenerateIdForPath hashes the extension's folder path. A different folder means a different ID.

We tested this in Chrome for Testing 156 with Playwright. We created a minimal Manifest V3 extension, loaded it with --load-extension, and read the ID from the service worker URL. Then we compared that with the ID we computed ourselves:

Case ID Chrome assigned Matches our calculation
No key, loaded from folder A ffcooelokhaajdcbnndiogbibbdfgico Yes, SHA-256 of the folder path
No key, same files copied to folder B ghdamckfndemlholfpadakgbaogkicha Yes, a new ID from the new path
With key, loaded from folder C alpmbjpooioeiankmimmbbalgidiciil Yes, SHA-256 of the public key
With key, copied to folder D alpmbjpooioeiankmimmbbalgidiciil Yes, unchanged

In practice the path changes more often than you think: a teammate clones the repo to a different directory, CI builds into a temporary folder, or your bundler writes to dist-dev one day and build the next. Each of those is a new extension as far as Chrome is concerned, with its own storage and its own permissions. Anything that was registered against the old ID stops working:

  • chrome.identity sign-in fails because the OAuth client is tied to the old ID. The Chrome extension Google sign-in guide walks through that setup.
  • The native messaging host rejects the connection, because allowed_origins "can't contain wildcards", as the native messaging docs put it.
  • A companion extension or web page that lists your ID in externally_connectable can no longer message you.
  • Your backend allowlist of extension origins no longer matches.

How to keep a Chrome extension ID stable with the manifest key

The fix is the manifest key field, which "maintains the unique ID of an extension (or theme) when it's loaded during development." With a key, Chrome hashes the key instead of the folder path, and the ID is the same everywhere.

Use the key from the Developer Dashboard

This is the method Google documents, and it gives your local builds the same ID as your store listing:

  1. Zip your extension and upload it to the Chrome Web Store Developer Dashboard with Add new item. You do not have to publish it.
  2. Open the item's Package tab and click View public key.
  3. Copy the text between -----BEGIN PUBLIC KEY----- and -----END PUBLIC KEY----- and remove the line breaks.
  4. Add it to manifest.json:
{
  "manifest_version": 3,
  "name": "My extension",
  "version": "1.0.0",
  "key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
}
  1. Load the folder on chrome://extensions and check that the ID matches the Item ID in the dashboard.

The key is a public key, so committing it to your repository is fine. It does not let anyone publish as you.

Generate a key before you have a store item

If you need a stable ID before you upload anything, for example to register an OAuth client on day one, generate a key pair yourself:

# Private key: keep it out of the repository
openssl genrsa 2048 | openssl pkcs8 -topk8 -nocrypt -out key.pem

# Public key for the manifest "key" field
openssl rsa -in key.pem -pubout -outform DER | openssl base64 -A

# The extension ID that key produces
openssl rsa -in key.pem -pubout -outform DER | shasum -a 256 | head -c 32 | tr 0-9a-f a-p

We checked that the last command prints the same ID that Chrome assigns when the key is in the manifest. Remember that this ID belongs to your key, not to a store item. Once you create the listing, the store's Item ID is the one users will have, so switch your development manifest to the dashboard key and update anything you registered against the temporary ID.

Compute an ID in Node.js

The same calculation in Node.js is useful in build scripts, for example to print the expected ID in CI or to generate a native messaging host manifest with the right origin:

// extension-id.mjs: the Chrome extension ID for a manifest "key" (base64 SPKI public key)
import { createHash } from 'node:crypto';

export function extensionIdFromKey(base64Key) {
  const hex = createHash('sha256').update(Buffer.from(base64Key, 'base64')).digest('hex').slice(0, 32);
  return [...hex].map((c) => String.fromCharCode(97 + parseInt(c, 16))).join('');
}

Chrome extension IDs in Edge and Firefox

If you publish the same extension in several stores, expect a different identifier in each one. Here is what Grammarly, a large extension published in all three stores, looks like when we looked it up in October 2026:

Store Identifier Format
Chrome Web Store kbfnbcaeplbcioakkpcpgfkobkghlhen 32 letters a to p
Microsoft Edge Add-ons cnlefmmeadmemmdciolhbnfeacpdfbkd 32 letters a to p, different from the Chrome ID
Firefox Add-ons (AMO) 87677a2c52b84ad3a151a4a72f5bd3c4@jetpack, slug grammarly-1, numeric ID 566314 Gecko ID set by the developer, plus AMO's own slug and number

Edge IDs look like Chrome IDs, but the Edge listing has its own value, so do not assume an Edge install shares the Chrome listing's ID. Firefox works differently. The ID is the browser_specific_settings.gecko.id value in your manifest, which MDN says is either an email-like string of up to 80 characters or a GUID in braces. For Manifest V3 it is "Mandatory for signing extensions", and MDN adds that "AMO does not assign an ID" for Manifest V3, so you must choose one. See MDN's browser_specific_settings reference.

One more Firefox difference catches people who port Chrome code: the moz-extension:// origin does not contain your ID. MDN's web_accessible_resources page says the UUID in that URL "is not your extension's ID. This ID is randomly generated for every browser instance." So a backend that allowlists your Chrome origin cannot allowlist Firefox users the same way.

For analytics, the practical consequence is a mapping table. Store each listing under its own store and ID, then link them to one product record, so that users, ratings and versions can be compared side by side. The guide to tracking one extension across Chrome, Edge and Firefox covers why the three listings drift apart and what to compare.

Look up any extension by its ID

Once you have an ID, you can open or query the listing directly:

  • Chrome: https://chromewebstore.google.com/detail/<id> opens the listing, and Chrome's update service returns the current version for an ID. The Chrome Web Store stats API guide shows how to read users, rating and version from the public listing and the update service responsibly.
  • Edge: https://microsoftedge.microsoft.com/addons/detail/<id> opens the listing. Edge add-on analytics explains what Partner Center reports for your own add-ons.
  • Firefox: AMO's public API accepts the gecko ID, the slug or the numeric ID, for example https://addons.mozilla.org/api/v5/addons/addon/<guid-or-slug>/. We confirmed that requesting uBlock Origin by its gecko ID [email protected] and by its slug ublock-origin returns the same add-on, number 607454. The Firefox add-on stats guide covers the rest of that API.

An ID is also the natural input for internal tools. The guide to building an MCP server in Node.js uses the ^[a-p]{32}$ pattern to let Claude look up stats for one extension safely.

If you would rather not maintain lookups for three stores, Extenify takes a store URL, works out the ID, finds the same extension on the other stores and records users, ratings, reviews and versions every day. It is built for browser extension analytics across Chrome, Edge and Firefox, including competitors you do not own, with alerts when something changes. Plans start with a 7-day free trial, no credit card required; see pricing.

Chrome extension ID checklist

Run through this when you set up a new project or onboard a teammate:

  • Put the dashboard public key in manifest.json as "key" for development builds.
  • Keep key.pem (if you generated one) in a secret store, never in the repository.
  • Validate IDs with /^[a-p]{32}$/ wherever users can paste one.
  • Store IDs, not names or slugs, as the primary identifier in your database.
  • Keep a mapping of Chrome, Edge and Firefox identifiers for each product.
  • Register OAuth clients, native messaging hosts and allowlists against the stable ID, and update them in one change if the ID ever changes.
  • Do not treat the ID as a secret or as proof of identity. It is public on every listing.

Frequently asked questions

Can I choose my own Chrome extension ID?

Not directly. The ID is derived from the public key, so the only way to change it is to use a different key. For a store listing, the store's key sets the ID when you create the item, and it stays the same for every later version.

Does a Chrome extension ID change when I publish an update?

No. Updates keep the same ID, which is why users keep their settings and data across versions. The ID only changes if you publish a new item, which users have to install separately.

Why is my unpacked extension ID different from the store ID?

Because an unpacked extension without a key gets an ID from its folder path. Add the public key from the Developer Dashboard's Package tab to manifest.json and the unpacked build will use the store ID.

Why does my extension have a different ID in Microsoft Edge?

Edge Add-ons is a separate store, and its listing carries its own ID, as the Grammarly example above shows. If you need a single identifier for both, keep your own product ID in your backend and map both store IDs to it.

Is a Chrome extension ID secret?

No. It is visible in the store URL and on chrome://extensions. Use it to identify an extension, not to authenticate it. A backend that needs to know who is calling should use real authentication, as described in how to hide an API key in a Chrome extension.

How do I find the ID of an extension that was removed from the store?

If it is still installed, open chrome://extensions with Developer mode on, or look in the profile's Extensions folder. The store listing itself no longer resolves once an item is taken down.

Summary

A Chrome extension ID is a 32-letter value derived from the extension's public key, or from the folder path for an unpacked extension without a key. Find it at the end of the store URL, on chrome://extensions with Developer mode on, or with chrome.runtime.id. Put the dashboard public key in your manifest so every build and every teammate gets the same ID, and keep a mapping for Edge and Firefox, which identify the same product differently. Then use the ID as the stable key for lookups, alerts and history.

Image credits

Put every store in one dashboard tonight.

Sign in with Google, paste one store link, and your unified view is live in under a minute. Then 7 days of Pro free, no credit card required, and you never touch your app's code.

Start free trial