A small node.js module to upload/publish extensions to the Chrome Web Store.
If you're looking to upload/publish from the CLI, then use chrome-webstore-upload-cli.
npm install --save-dev chrome-webstore-upload
You will need a Google API clientId, clientSecret and refreshToken. Use the guide.
You also need your Chrome Web Store publisherId (your developer account identifier, not the extension ID). You can find it in the Chrome Web Store Developer Dashboard URL when logged in.
All methods return a promise.
import chromeWebstoreUpload from 'chrome-webstore-upload';
const store = chromeWebstoreUpload({
extensionId: 'ecnglinljpjkbgmdpeiglonddahpbkeb',
publisherId: 'your-publisher-id',
clientId: 'xxxxxxxxxx',
clientSecret: 'xxxxxxxxxx',
refreshToken: 'xxxxxxxxxx',
});You can upload a zip file, crx file, or a directory. If you provide a directory, it will be automatically zipped. Crx files are only supported as path, not as stream.
import fs from 'fs';
// Upload a zip file
const myZipFile = fs.createReadStream('./mypackage.zip');
const token = 'xxxx'; // optional. One will be fetched if not provided
const maxAwaitInProgressResponseSeconds = 60; // optional. If the API response is IN_PROGRESS, this method will wait until it becomes successful, or until the specified timeout
const response = await store.uploadExisting(myZipFile, token, maxAwaitInProgressResponseSeconds);
// response is a Resource Representation
// https://developer.chrome.com/docs/webstore/api/reference/rest/v2/publishers.items/upload// Upload a directory (it will be zipped automatically)
const response = await store.uploadExisting('./path/to/extension-directory', token, maxAwaitInProgressResponseSeconds);
// The directory must contain a manifest.json file// Upload a .zip or .crx file by path
const response = await store.uploadExisting('./path/to/extension.zip', token, maxAwaitInProgressResponseSeconds);
// or
const response = await store.uploadExisting('./path/to/extension.crx', token, maxAwaitInProgressResponseSeconds);const publishType = 'DEFAULT_PUBLISH'; // optional. Can also be 'TRUSTED_TESTERS' or 'STAGED_PUBLISH'
const token = 'xxxx'; // optional. One will be fetched if not provided
const deployPercentage = 25; // optional. Sets the initial rollout percentage.
const response = await store.publish(publishType, token, deployPercentage);
// response is documented here:
// https://developer.chrome.com/docs/webstore/api/reference/rest/v2/publishers.items/publishUpdate the deployment percentage for an already-published extension without triggering a re-review:
const deployPercentage = 50; // required. Must be higher than the current value.
const token = 'xxxx'; // optional. One will be fetched if not provided
await store.setDeployPercentage(deployPercentage, token);
// https://developer.chrome.com/docs/webstore/api/reference/rest/v2/publishers.items/setPublishedDeployPercentageconst token = "xxxx"; // optional. One will be fetched if not provided
const response = await store.get(token);
// response is documented here:
// https://developer.chrome.com/docs/webstore/api/reference/rest/v2/publishers.items/fetchStatusconst token = store.fetchToken();
// token is astring- If you plan to upload and publish at the same time, use the
fetchTokenmethod, and pass it to bothuploadExistingandpublishas the optional second parameter. This will avoid those methods making duplicate calls for new tokens.
- webext-storage-cache - Map-like promised cache storage with expiration. Chrome and Firefox
- webext-dynamic-content-scripts - Automatically registers your content_scripts on domains added via permission.request
- Awesome-WebExtensions - A curated list of awesome resources for WebExtensions development.
- More…