Chrome Web Store Rejection Codes: What Blue Argon and Purple Potassium Mean
7 min readModerok team
Rejected with a two-word code like Blue Argon? Here is the full mapping of Chrome Web Store violation codes and how to fix the ones that hit real extensions.
Your extension got rejected and the email names a violation like Blue Argon or Purple Potassium without explaining it. Those two-word codes are not random: the Chrome Web Store gives every violation category an ID made of a color and an element, each mapping to a section of Google's Troubleshooting Chrome Web Store violations page. Blue Argon is remotely hosted code in a Manifest V3 extension, Purple Potassium is excessive permissions, Yellow Magnesium is an extension the reviewer could not get to work. The full mapping is below.
The code is an index, not a diagnosis
The email tells you which policy bucket you landed in, not what line of your code caused it. Google's page documents 26 policy sections and 34 IDs, since a few categories have several IDs pointing at one section. Finding the offending code or listing field is still on you.
Look up your exact code first, because neighbors mean very different things: Red Magnesium is single purpose, Red Titanium is obfuscation, Red Zinc is deceptive installation. If the bucket does not fit, the documented next step for several categories is to ask developer support which permission or flow triggered it rather than guessing and resubmitting.
Full list of Chrome Web Store violation codes
| Code | Policy category |
|---|---|
Blue Argon | Manifest V3 requirements (remotely hosted code) |
Yellow Magnesium | Functionality not working |
Purple Potassium | Excessive permissions |
Yellow Zinc | Missing or insufficient metadata |
Red Nickel, Red Potassium, Red Silicon | Deceptive behavior |
Purple Lithium | User data: disclosure policy |
Purple Nickel | User data: prominent disclosure |
Purple Copper | User data: secure transmission |
Purple Magnesium | User data: other requirements |
Red Magnesium, Red Copper, Red Lithium | Single purpose |
Red Titanium | Obfuscation |
Red Zinc | Deceptive installation |
Yellow Argon | Keyword stuffing |
Yellow Lithium | Redirection |
Yellow Nickel | Spam |
Yellow Potassium | Minimum functionality |
Blue Nickel, Blue Potassium | Circumvents the overrides API |
Blue Zinc, Blue Copper, Blue Lithium, Blue Magnesium | Prohibited products |
Grey Zinc | Illegal activities |
Grey Copper | Online gambling |
Grey Lithium | Pornographic content |
Grey Magnesium | Hate content |
Grey Nickel | Not family safe |
Grey Potassium | Violent content |
Grey Silicon | Cryptocurrency mining |
Grey Titanium | Affiliate ads |
Many of those rows are about what an extension is for: gambling, hate speech, cryptomining, pornography. The codes covered below are different in kind. They turn on how your package is built, which permissions you declared, and how your listing is filled in, so a benign extension can trip them.
Blue Argon: remotely hosted code in Manifest V3
Blue Argon covers the MV3 rule that an extension's logic must ship inside its package. Google lists three triggers: a <script> tag pointing outside the package, eval() or similar running a remotely fetched string, and an interpreter for remotely fetched commands, even when they arrive as data. Third-party integrations are an easy way in, since the standard web install snippet is a remote script tag:
<!-- Blue Argon waiting to happen -->
<script src="https://cdn.example.com/analytics.js"></script>
Fetching data is fine; fetching logic is not. A JSON config or a REST call to your API is allowed, a script or WASM module the browser then executes is not. That is why Google Analytics cannot be dropped into an extension the way it is dropped into a website, as covered in why Google Analytics doesn't work in a Chrome extension. To audit, grep your built output rather than your source for src="http, eval(, and new Function(, and check for bundler config that emits a CDN URL.
Purple Potassium: excessive permissions
Purple Potassium fires for two reasons: you requested a permission you do not use, or one broader than the feature needs. The policy is explicit that you should not "future proof" your product by requesting a permission that might benefit features that have not yet been implemented. Google's list of "commonly misunderstood permissions" is worth a read before you resubmit:
activeTabgrants temporary access to a tab when the user invokes your extension. Google puts the key point in capitals: it does NOT grant passive access to the currently focused tab. It is also not required if you hold host permissions for the relevant domains, when usingaction,browserAction, orpageActionmethods, or fortabs.sendMessageand basictabs.query.tabsonly grants theurl,pendingUrl,title, andfavIconUrlproperties ofTabobjects. Using thechrome.tabsAPI does not require it, and broad host permissions already cover that data.cookiesexposeschrome.cookiesand allows modifying cookies on origins you already have host permissions for. It is required forchrome.cookiescalls from the background context or an extension page such as your popup, or for detail such asSameSitevalues, and not required fordocument.cookieor the Cookie Store API.storageis only needed forchrome.storage. IndexedDB and the Web Storage API do not require it.
Before resubmitting, remove unused entries from permissions, optional_permissions, and host_permissions. Look hardest at host permissions, which also drive the install prompt discussed in why your extension says "read and change all your data". If a reviewer flags a permission you do use, the documented path is an appeal through developer support explaining what uses it.
Yellow Magnesium: functionality not working
Yellow Magnesium means the reviewer could not get the extension to do what the listing says. Google gives three reasons: packaging errors, a server side issue at review time, and an item that does not work as its listing describes. Packaging covers files named in manifest.json but missing from the package, most commonly images, and wrong paths or filenames. Case sensitivity gets its own warning, since Background.js and background.js are one file on some file systems and two on others.
The fix is to test the exact artifact you upload, not your dev build: pack the extension, drag the .crx onto chrome://extensions, and click through it, since packed and unpacked extensions can behave differently. Make failure states visible too. If your extension needs an account or a special network environment, say so in the UI, and test on a bad connection so timeouts and HTTP 400 and 500 responses are handled gracefully. If you cannot reproduce what the reviewer saw, the page says to ask developer support which flow failed.
Purple Lithium and friends: the user data policy
The user data policy splits across four IDs: disclosure (Purple Lithium), prominent disclosure (Purple Nickel), secure transmission (Purple Copper), and other requirements (Purple Magnesium). Despite the color, Purple Potassium is not one of them.
Purple Lithium is mostly mechanical. Google's reasons include collecting user data with no privacy policy, a broken or inaccessible policy URL, a URL that does not lead to a policy, and a policy that never discusses data collection, use, handling, or sharing. It singles out one as a common mistake: putting the policy in the description instead of the designated field. Check for a working link in the Privacy Policy box on the Privacy tab.
Purple Copper has two rules, not one. Do not transmit user data over HTTP. Also do not encode data in request headers or query parameters even over HTTPS, because headers and URLs often end up in server logs. Check the second against any URL you assemble by hand, including uninstall URLs, which have no request body and carry whatever is in the query string. Keep those to an opaque id.
Reduce your exposure
These codes reward the same habit: ship less. Fewer permissions, no remotely loaded logic, no personal data you did not need. That is the shape Moderok is built around. The SDK ships inside your bundle with zero dependencies, POSTs events in the request body to an HTTPS endpoint, needs only "permissions": ["storage"], and identifies users with a random UUID, so it adds no Blue Argon or Purple Potassium surface. The exception is the optional uninstall ping, which is off unless you turn it on: like every setUninstallURL, it has no request body, so the app key, the anonymous user id, and any redirect you configure ride in the query string.
None of that exempts you from the Purple codes. Any tool that sends data off the user's machine means you collect user data, so you still owe a working privacy policy in the designated field, a prominent disclosure of what you collect, and consent where the policy requires it. The manifest and permissions guide shows the manifest change the SDK needs.