How to Publish a Chrome Extension to the Chrome Web Store
This post covers how I published a Chrome extension to the Chrome Web Store, from registering as a developer to passing review.
1. Register a Developer Account
Go to the Chrome Web Store Developer Dashboard and sign up as a developer.
- Sign in with your Google account
- Pay the one-time $5 registration fee (non-refundable)
- Fill in your developer profile: name, email, website, etc.
You can choose between an individual account or a group (organization) account. For personal projects, an individual account is enough.
Note for users outside the US: If your country isn't listed or the payment doesn't go through, try selecting United States as your country and entering 10001 (New York) as the ZIP code. Note that this means entering a country and address that aren't your real ones, which can cause problems later during identity verification or payouts.
2. Build and Package as a ZIP
Package your extension into a ZIP file. The exact steps depend on your build tool, but in most cases you just compress the output folder after building.
# Using WXT
npm run zip
# Manual compression
cd dist && zip -r ../extension.zip .
Required files to include in the ZIP:
manifest.json- Icon files
- Build output: HTML, JS, CSS, etc.
Important: Exclude unnecessary files like node_modules, source maps, and .git.
3. Prepare Store Listing Assets
Having these ready before you upload will save you time.
Required
| Item | Spec |
|---|---|
| Extension icon | 128×128 PNG |
| Screenshots | At least 1, 1280×800 or 640×400 PNG/JPG |
| Small promo tile | 440×280. Shown on the homepage, category pages, and in search results |
| Description | Up to 132 characters (summary); detailed description separate |
| Category | Choose from Developer Tools, Productivity, etc. |
| Language | Select your primary language |
Optional
- Marquee promotional image (1400×560) — needed to be featured in the marquee
- Homepage URL
- Support URL
- Privacy policy URL (required if you handle user data)
4. Upload via the Dashboard
- Click "New Item" in the Developer Dashboard
- Upload your ZIP file
- After uploading, fill in the tabs:
- Store listing: description, screenshots, category
- Privacy practices: explain why each permission is needed
- Distribution: visibility and region settings
Visibility Options
- Public: Anyone can search and install it
- Unlisted: Only people with the direct link can install it (not shown in search)
- Private: Only specified users can install it (useful for testing)
If it's your first time, consider publishing as Unlisted first to verify everything looks right, then switching to Public.
5. Justify Your Permissions
For every permission declared in manifest.json, you need to explain why it's needed. A vague or incomplete justification is a common reason for rejection.
Example:
| Permission | Justification |
|---|---|
storage | Required to save user settings (API keys, theme preferences) locally |
activeTab | Required to extract information from the current tab's URL |
host_permissions | Required to make calls to external APIs |
Key principle: Only declare permissions you actually use. Unused permissions can get your submission rejected.
6. Submit for Review
Once everything is filled in, click "Submit for Review".
Review Timeline
- Per the Chrome docs, most reviews finish within a few days, but some take up to a few weeks
- Requesting broad host permissions (e.g.,
<all_urls>) or sensitive execution permissions, or shipping a lot of code or hard-to-review code, makes review take longer - New developers, new extensions, and updates with significant code changes also get a closer look
Common Rejection Reasons
- Unnecessary permissions — permissions in the manifest that aren't actually used
- Unclear description — it's not obvious what the extension does
- Missing privacy policy — required when handling user data
- Single-purpose violation — one extension containing unrelated features
If rejected, you'll receive a reason. Fix the issue and resubmit.
7. Publishing Updates
To update an already-published extension:
- Bump the
versioninmanifest.json - Build a new ZIP file
- In the Dashboard, go to the "Package" tab → "Upload New Package"
- Submit for review again
Updates go through review too. Existing users will receive the update automatically after it passes.
Tips
- Always increment the version in
manifest.json— you cannot upload a package with the same version number. - Use real screenshots of the extension in action. Mock-ups or text-only images may be rejected.
- If you're using privacy-related permissions, set up a privacy policy page in advance. A GitHub Pages or Notion page is sufficient.
- You can automate publishing via the Chrome Web Store API for CI/CD deployments. The
chrome-webstore-uploadnpm package makes this easy.
Wrap-Up
After the first listing, updates are: bump version → upload ZIP → submit for review. In review, what mattered was to request only the permissions you need and explain why you use each one.