> ## Documentation Index
> Fetch the complete documentation index at: https://extension.js.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Get your Chrome Web Store credentials

> Register the $5 Chrome Web Store developer account, create the first listing by hand, and mint the OAuth or service-account credentials that automated submissions need.

Automated Chrome Web Store submissions need two identifiers and one credential set:

| Value                | What it looks like                                                   | Where it comes from                                                  |
| -------------------- | -------------------------------------------------------------------- | -------------------------------------------------------------------- |
| Extension ID         | 32 lowercase letters, for example `abcdefghijklmnopabcdefghijklmnop` | The Developer Dashboard item URL, after the first manual upload      |
| Publisher ID         | A UUID, for example `f1e2d3c4-0000-4000-8000-a1b2c3d4e5f6`           | Your dev console URL: `chrome.google.com/webstore/devconsole/<UUID>` |
| OAuth client ID      | Ends in `.apps.googleusercontent.com`                                | Google Cloud Console credentials page                                |
| OAuth client secret  | Starts with `GOCSPX-`                                                | Generated with the client ID                                         |
| OAuth refresh token  | Starts with `1//`                                                    | Minted by `npx extension-deploy init` (see below)                    |
| Service account JSON | A JSON key file                                                      | Google Cloud Console, alternative to the OAuth trio                  |

You need either the OAuth trio or the service account, not both. When both are configured, the service account wins.

## Prerequisites

<Warning>
  The Chrome Web Store API cannot create a new item. The first upload of a new
  extension must happen by hand in the Developer Dashboard. The 32-character
  extension ID only exists after that upload.
</Warning>

1. Register a developer account at the
   [Chrome Web Store Developer Dashboard](https://chrome.google.com/webstore/devconsole).
   Registration has a one-time \$5 fee.
2. Build a store zip (`npx extension build --browser chrome --zip`).
3. Upload that zip manually in the dashboard to create the item.
4. Copy the extension ID from the item's dashboard URL.
5. Copy the publisher ID: it is the UUID in your dev console URL,
   `chrome.google.com/webstore/devconsole/<UUID>`.

## The easy path: `npx extension-deploy init`

The wizard in [`@extension.dev/deploy`](https://www.npmjs.com/package/@extension.dev/deploy)
acquires and verifies every Chrome value, and it mints the refresh token for
you through a local loopback consent flow:

```bash theme={null}
npx extension-deploy init
```

It prompts for the extension ID, the publisher ID, and your OAuth client ID
and secret. It then opens the Google consent page, receives the authorization
code on a local `127.0.0.1` receiver, exchanges it for a refresh token,
verifies the result against the live Chrome Web Store API, and writes
everything to `.env.submit`.

Before you run it, create the OAuth client (steps 1 to 3 below). The wizard
handles the rest.

<Note>
  Do not use the Google OAuth Playground to mint the refresh token. The
  Playground requires a Web application client with its redirect URI, and the
  Chrome Web Store flow requires a Desktop app client. Combining them fails with
  `redirect_uri_mismatch`. The `init` wizard's loopback flow is the supported
  path for Desktop app clients.
</Note>

## Create the OAuth client

1. Create or choose a project in the
   [Google Cloud Console](https://console.cloud.google.com).
2. Enable the
   [Chrome Web Store API](https://console.cloud.google.com/apis/library/chromewebstore.googleapis.com)
   for that project.
3. On the [credentials page](https://console.cloud.google.com/apis/credentials),
   create an OAuth client ID with application type **Desktop app**. A Web
   application client does not work here.
4. Copy the client ID and the client secret.
5. Run `npx extension-deploy init` to mint the refresh token, as described
   above. The token authorizes the `https://www.googleapis.com/auth/chromewebstore`
   scope.

<Warning>
  If your OAuth consent screen is in **Testing** status, Google revokes the
  refresh token after 7 days. Your first submission works and the credential
  dies a week later. Publish the consent screen (In production), or use a
  service account, which has no such expiry.
</Warning>

## Alternative: a service account

A Google Cloud service account avoids OAuth consent entirely and is the most
stable choice for CI:

1. In the Google Cloud Console, create a service account in the same project
   that has the Chrome Web Store API enabled.
2. Create a JSON key for it and download the file.
3. In the Chrome Web Store dev console, open **Account** and add the service
   account's email address to your publisher. One service account per
   publisher.

Provide the JSON key content (or a path to the file) as the credential. When
a service account is configured, it is preferred over the OAuth trio.

## Blast radius and rotation

<Warning>
  Chrome credentials are publisher-wide, not per extension. A token that can
  publish one item can publish every item under the same publisher account.
  Treat the refresh token and the service account key accordingly, and prefer a
  separate publisher account per client if you manage extensions for others.
</Warning>

To rotate, mint a new refresh token with `npx extension-deploy init` (or a new
service account key) and re-enter it wherever it is stored. Saved platform
secrets are write-only, so rotation always means re-entering the value.

## Name map

The same values wear different names on each surface:

| Value                | Direct mode env var           | Platform mirror secret                      | Console field        |
| -------------------- | ----------------------------- | ------------------------------------------- | -------------------- |
| OAuth client ID      | `CHROME_CLIENT_ID`            | `STORE_CHROME_CLIENT_ID`                    | OAuth client ID      |
| OAuth client secret  | `CHROME_CLIENT_SECRET`        | `STORE_CHROME_CLIENT_SECRET`                | OAuth client secret  |
| Refresh token        | `CHROME_REFRESH_TOKEN`        | `STORE_CHROME_REFRESH_TOKEN`                | Refresh token        |
| Service account JSON | `CHROME_SERVICE_ACCOUNT_JSON` | `STORE_CHROME_SERVICE_ACCOUNT_JSON`         | Service account JSON |
| Extension ID         | `CHROME_EXTENSION_ID`         | `settings.json` `stores.chrome.storeId`     | Extension ID         |
| Publisher ID         | `CHROME_PUBLISHER_ID`         | `settings.json` `stores.chrome.publisherId` | Publisher ID         |

## Listing metadata stays manual

The Chrome Web Store API accepts no listing metadata. Store listing copy,
screenshots, and permission justifications are entered in the Developer
Dashboard by hand. Keep them in the Chrome section of
[STORE.md](/docs/workflows/store-metadata) so every resubmission copies from
one tracked source.
