CRX viewer

By Michael Lip. Updated 2026-08-25.

Drop a .crx file into the box below and the page unpacks it in this tab. You get the manifest, every declared permission in the wording Chrome shows at install time, the host patterns including the ones that hide inside content scripts, the file tree, and the extension ID read out of the signed header, checked against the header's own signatures. Nothing is uploaded. The file never leaves your browser, so no server, including ours, learns which extension you were curious about.

The other viewers in this search result stop at the file browser. This one also tells you whether what you're looking at is the usual ask. Measured 2026-08-25 from the manifest.json inside each signed package served by Google's update service, 15 of the sixteen widely installed extensions in the fixed sample further down can run on every site from the moment they're installed, either through host_permissions or through a content script match pattern. Sixteen is a convenience sample picked for recognisability, not a random draw and not a ranking. So when your file shows <all_urls>, you'll see how many well known extensions ask for the same thing, and you'll know the one in the sample that doesn't.

Open a CRX file

Runs in your browser. The file is read with the File API and unzipped in the page. No upload, no server, no log.

The unpacker needs JavaScript. Without it the rest of this page still reads correctly, and you can open the package with any unzip tool once the CRX header is stripped, as described in the format section below.

Get the package first, because the page can't fetch it for you

Paste a listing URL or an item ID and the page builds the download address that Chrome's own update client uses. Chromium's source defines that address as https://clients2.google.com/service/update2/crx, and Chrome's enterprise policy templates give the same URL as the update URL for a Chrome Web Store item, written as extension ID, semicolon, update URL. The link asks for the CRX3 format and passes the current stable milestone, Chrome 151, which the page reads from the Chromium Dash release feed at build time. Save the file, then open it in the box above.

The page doesn't fetch the package for you, and that's a deliberate trade rather than a missing feature. Browsers restrict cross-origin HTTP requests initiated from scripts, and a script on this page can only read a response from another origin if that response includes the right CORS headers, such as Access-Control-Allow-Origin. A viewer that takes an item ID and hands you the contents in one step has to get around that restriction somewhere, and the only way I know is a server in the middle. A server in the middle can keep a record of which extension you were suspicious of. We can't fetch it for you, and that is the trade.

The other tools take a different route. Rob Wu's viewer at robwu.nl accepts the URL of a Chrome extension, Firefox addon or zip file, or a store page on the Chrome Web Store, Firefox addon gallery, Edge Addons Store or Opera addon gallery, as well as a local file. CRXViewer.com describes itself as an online extractor, source code viewer, file converter and downloader for .crx, .xpi and .nex files and takes a local file by upload from your disk. Both work. What this page refuses is the one step where a file or an address leaves your machine.

Already installed? Read it from the profile folder

For an extension you already have, the package is on disk. Chromium installs extensions into a directory named Extensions inside the profile directory, and the manifest is the file named manifest.json. Each profile is a subdirectory, often named Default, within the user data directory, which by default is ~/Library/Application Support/Google/Chrome on macOS, %LOCALAPPDATA%\Google\Chrome\User Data on Windows and ~/.config/google-chrome on Linux. If you're not sure which profile you're in, chrome://version shows it in the Profile Path field. With Developer mode on, chrome://extensions shows each extension's ID, which is what you need to find it in that folder. Zip the extension's folder and drop the zip into the tool, and if you want to run it again from that copy, Load unpacked on chrome://extensions with Developer mode enabled takes the directory as it is.

What sixteen signed packages ask for

Every count in this section is recomputed at build time from the manifest.json inside the signed CRX3 package of each extension in the roster, read from Google's update service, with the sample date next to each figure. The sample is sixteen widely installed extensions, fixed and named below with their item IDs, chosen for recognisability across ad blocking, password management, privacy, translation, theming, scripting and developer tooling. It isn't a random sample, it isn't ranked by installs, and it isn't a census of the store. Read the counts as an illustration of how common broad access is among extensions people recognise, and nothing larger.

Sample measurements, read from each signed package on the date shown
MeasureResultRead from
Can run on every site at install, through a required host pattern or a content script match covering every site15 of sixteenmanifest.json in each signed package, 2026-08-25
Manifest V316 of sixteenmanifest.json in each signed package, 2026-08-25
Entries in the permissions arrays, summed142 across sixteenmanifest.json in each signed package, 2026-08-25
Chrome stable milestone at buildChrome 151Chromium Dash stable release feed, cross checked against the Chrome VersionHistory API, 2026-08-25

Broad here means a pattern in host_permissions, or in a content script's matches list, that is one of <all_urls>, *://*/*, http://*/*, https://*/*, *://*, file://*/* or file:///*. In Google's match pattern reference, <all_urls> matches any URL that starts with a permitted scheme, https://*/* matches any URL using the https scheme, and a wildcard scheme matches only http or https. Optional host permissions aren't counted, because they're granted by the user at runtime, instead of at install time. To test one pattern against a URL, use the match pattern tester.

The case that makes the content script check matter

Google Translate, item aapbdbdomjkkjkaonfhkkikfgjllcleb, is the reason the count reads content scripts and not just host_permissions. Its signed package, version 2.0.17, has no host_permissions key at all, not even an empty array, and no optional_host_permissions key, and its permissions are activeTab, contextMenus, storage, offscreen and scripting. Read that far and it looks like an extension with no site access. But the same manifest has a content_scripts entry whose matches is <all_urls> with all_frames true. Content scripts are files that run in the context of web pages, and using the standard DOM they can read details of the web pages the browser visits, make changes to them, and pass information to their parent extension. Google's own permissions guide lists content_scripts.matches as a route to host access, one or more match patterns that allow content scripts to inject into one or more hosts, and says adding or changing match patterns in either host_permissions or content_scripts.matches triggers a permission warning. So a manifest with no host_permissions key is not a manifest with no site access. The tool above prints content script matches in the same host access table as everything else, and says so in plain words when that is the only route.

The one that doesn't ask at install

Momentum, item laookkfknpbbblfpciffpaejjkokdgca, is the one member of the sample that doesn't request broad access at install. Its signed package, version 2.27.4, declares the permissions offscreen, unlimitedStorage and idle, has no host_permissions key, and lists file:///* and *://*/* under optional_host_permissions. Its only content script match pattern is https://*.momentumdash.com/*, and its optional_permissions are bookmarks, tabs, sessions, topSites, favicon, scripting, alarms, notifications, tabGroups and search. Optional means granted by the user at runtime, instead of at install time. Optional permissions must be declared in the manifest before they can be requested at runtime, and when they are requested, Chrome prompts the user if adding the permissions results in different warning messages than the user has already seen and accepted. So the honest reading is that Momentum doesn't request every-site access at install, and can ask for it later.

The fixed sample. Titles, user counts and versions are what each live Chrome Web Store listing showed on 2026-08-26, and the store rounds its public user counts.
Store titleItem ID and listingUsers on the listing, 2026-08-26Version
uBlock Origin Liteddkjiahejlhfcafbddmgiahcphecmpfh18,000,0002026.820.1159
Dark Readereimadpbcbfnmbkopoojfekhnkhdbieeh7,000,0004.9.129
Google Translateaapbdbdomjkkjkaonfhkkikfgjllcleb32,000,0002.0.17
Bitwarden Password Managernngceckbapebfimnlniiiahkandclblb7,000,0002026.8.0
AdBlockgighmmpiobklfepjocnamgkkbiglidom61,000,0006.45.3
Adblock Plus - free ad blockercfhdojbkjhnklbpkdaibdccddilifddb38,000,0004.43.2
PayPal Honey: Automated Coupons & Rewardsbmnlcjabgnpnenekpadlanbbkooimhnj12,000,00019.5.0
Grammarly: AI Writing Assistant and Grammar Checker Appkbfnbcaeplbcioakkpcpgfkobkghlhen38,000,00014.1323.0
LastPass: Free Password Managerhdokiejnpimakedhajhdlcegeplioahd8,000,0004.155.0
Momentumlaookkfknpbbblfpciffpaejjkokdgca2,000,0002.27.4
ColorZillabhlhnicpbhignbdhedgjhgdocnmhomnp4,000,0004.1
Ghostery AdBlocker for Privacymlomiejdfkolichcflejclcbmpeaniij2,000,00010.5.58
Privacy Badgerpkehgijcmpdhfbdbbnkijodmdjhbjlgp1,000,0002026.8.7
Video Download Helperlmjnegcaeklhafolokijcfjliaokphfk6,000,00010.5.24.2
Tampermonkeydhdgffkkebhmkfjojejmpbldmpobfkfo12,000,0005.5.0
Wappalyzer - Technology profilergppongmhjkpfnbhagpmjfkannfbllamg3,000,0006.12.5

Widely installed means what those listings showed on 2026-08-26, from 1,000,000 users for Privacy Badger, published by the Electronic Frontier Foundation, to 61,000,000 for AdBlock. AdBlock's listing title carries a tagline after the name, and I've shortened it to the name in the table. No Zovo extension is in the sample.

Permissions in the wording Chrome shows you

To access most extension APIs and features an extension must declare permissions in its manifest, and some permissions trigger warnings that users must allow to continue using the extension. Chrome displays that permission warnings dialog on installation. The tool uses the same strings, reproduced here from Google's permissions reference. A permission is not a verdict. It says what the extension is allowed to do, never what it does at runtime, and this page won't call a package safe or unsafe from its list.

Permission names and the warning text from Google's permissions list
PermissionWhat Chrome tells the userSource
activeTabGives temporary access to the active tab through a user gesture.permissions list
bookmarksRead and change your bookmarks.permissions list
clipboardReadRead data you copy and paste.permissions list
debuggerAccess the page debugger backend. Read and change all your data on all websites.permissions list
declarativeNetRequestBlock content on any page.permissions list
downloadsManage your downloads.permissions list
geolocationDetect your physical location.permissions list
historyRead and change your browsing history on all signed-in devices.permissions list
identity.emailKnow your email address.permissions list
managementManage your apps, extensions, and themes.permissions list
notificationsDisplay notifications.permissions list
privacyChange your privacy-related settings.permissions list
tabsRead your browsing history.permissions list
topSitesRead a list of your most frequently visited websites.permissions list
Host access to all websitesRead and change all your data on all websites.permissions list

Two details trip people up. Some permissions don't display a warning when paired with others, and the tabs warning doesn't show if the extension also requests <all_urls>, so a package can hold both and show only the broader warning. And when an update adds a new permission that triggers a warning, the extension is disabled until the user accepts the new permission.

The policy side is short. Chrome Web Store policy requires developers to request the narrowest permissions necessary to implement the product's features or services. It forbids requesting a permission to future proof a product for features not yet implemented, and where more than one permission could implement a feature, it requires the ones with the least access to data or functionality. Google also recommends optional permissions to give users informed control over access to resources and data. As a publisher, that's the policy I answer to on every listing, and it's the question I'd suggest for reading any list, whether each permission fits the job the extension says it does.

Host access is the part to read first

The permissions key enables use of particular extension APIs, and it holds items from a list of known strings. host_permissions lists the web pages the extension is allowed to interact with, and user permission for those sites is requested at install time. Host permissions are what let an extension make fetch() requests from the extension service worker and extension pages, read and query the sensitive tab properties url, title and favIconUrl through the chrome.tabs API, inject a content script programmatically, monitor and control network requests with chrome.webRequest, and access cookies with chrome.cookies. One pattern behaves differently. A file:/// pattern requires the user to manually grant access before the extension can run on local files.

In Google's help for users the same access reads as 'Your data on all the websites you visit', filed as a medium alert, while 'all data on your computer and the websites you visit' is filed as high alert. After installing, the extension's details page has a control labelled 'Allow this extension to read and change all your data on websites you visit', which can be set to On click, On specific sites, or On all sites.

activeTab is the narrow alternative. It gives temporary access to the currently active tab when the user invokes the extension, for example by clicking its action, lets the extension get the URL, title, and favicon for that tab, and displays no warning message during installation, unlike <all_urls>.

Why every package you open is Manifest V3 now

In the sample, 16 of the sixteen packages are Manifest V3, measured 2026-08-25, and the reason is a dated timeline rather than a mystery. The Chrome Web Store stopped accepting new public or unlisted Manifest V2 extensions in January 2022. In October 2024 Google announced it would begin disabling installed extensions still using Manifest V2 in Chrome stable. As of Jul 24th 2025, with Chrome 138, all users on all channels of Chrome have Manifest V2 extensions disabled and can no longer turn them back on. Chrome 138 is the final version to support Manifest V2 extensions, and only when paired with the ExtensionManifestV2Availability enterprise policy, and extensions installed on Chrome 138 or earlier remain installed but can't receive updates and can't be reinstalled from the store once removed. The last step on the timeline is Aug 31st 2026, the date on which all remaining Manifest V2 extensions are removed from the Chrome Web Store. Current Chrome stable is 151, read from the Chromium Dash release feed at build.

Google's manifest reference says the only supported value for manifest_version is 3, that the current manifest version is Manifest V3, and that the Chrome Web Store no longer accepts manifest V2 extensions. For a reader of the file tree, two changes matter most. The background context moved to service workers, which run only when needed. And Manifest V3 removes the ability for an extension to use remotely hosted code, so the JavaScript you can open in the file table is the JavaScript the extension can run. On the network side, Google states the declarativeNetRequest API provides a safer alternative for many use cases previously served by blocking webRequest.

What a CRX file is and how the tool reads it

The format is small. A CRX3 file begins with the four byte magic number Cr24, then four bytes holding the version of the file format, currently 3, followed by a little-endian header length and the binary CrxFileHeader, and after that header the remainder of the file is an ordinary ZIP archive. The header carries sha256_with_rsa proofs, and in the common developer-key case the first 128 bits of the SHA-256 hash of the public key must equal the crx_id, which is exactly 16 bytes long. ECDSA proofs use the NIST P-256 curve. Clients should reject a file whose header length is too large to safely handle in memory, and the tool refuses a header that runs past the end of the file.

The tool goes one step further than reading the header. It hashes each public key in the header, reports which one matches the crx_id, and then checks every RSA and ECDSA proof with the browser's own Web Crypto against the signed header and the archive. A file that has been truncated or edited after signing fails that check, and the tool says so next to the ID. The build time fetcher that measures the sample does not verify signatures, and the methodology section says so rather than implying otherwise.

The ZIP side is the standard layout. Local file headers and file data come first, then the central directory headers, then the end of central directory record. The tool finds that record by its signature 0x06054b50, walks each central directory file header, which begins with the signature 0x02014b50, and inflates only the entry you click. The build time fetcher works the same way over the network, using HTTP Range requests, which ask the server to send parts of a resource back to a client. A server that answers with an Accept-Ranges header carrying any value other than none supports them, and a successful range request gets a 206 Partial Content status, so the fetcher reads the directory and the one manifest entry instead of downloading each package whole.

The extension ID is in there too. A Chromium extension ID is generated by hex-encoding the first bytes of a SHA-256 hash and remapping the hex digits to a through p, and Chromium uses a to p in place of 0 to f to avoid ever having a completely numeric host that some software would interpret as an IP address. So the ID the tool shows comes from the signed header and the keys inside it, not from a listing page.

Where these numbers come from

I'm Michael Lip. I build and maintain the Zovo Chrome extensions on my own, which means I package, sign and ship CRX bundles to the Chrome Web Store as routine work, the same artefact this page reads. Zovo publishes Chrome extensions, so a page about extension permissions from me comes with an interest to declare, and I'd rather say it here than in a footer.

How we know what's in the packages. The sample counts above are recomputed in code from the manifest.json inside each signed CRX3 package, read from Google's update service at build time and re-read from a second Google host as a transport check, with the sample date shown next to every figure. No count on this page is typed by hand. If any one of the sixteen packages fails to download or parse, the counts are withheld rather than computed on a smaller sample, because a shrinking denominator would change the number silently. The Chrome stable milestone is fetched at build time from the Chromium Dash release feed and cross checked against the Chrome VersionHistory API, a second Google service with a different response shape. Permission wording is quoted from Google's permissions reference and the Web Store warning strings, not paraphrased into a severity word.

The first-hand part. I've unpacked and read the shipped package of every extension I publish, the same way the tool above does it, and re-measured them on 2026-08-25 from the manifest.json inside each signed package rather than from a store listing. Every one of them is Manifest V3, nearly all declare storage, and a small minority request the <all_urls> host permission. I've also carried the Manifest V2 to V3 migration across the whole portfolio, so the permission model described here is one I've had to satisfy for every listing I own, including the rejections and resubmissions that come with store review. Nothing here is a code audit. A permission list says what an extension may do, never what it does at runtime.

Questions people ask before opening a package

Can I see an extension's source without installing it?

Yes. Build the download link above, save the file, and open it in the tool. Rob Wu's CRX Viewer is described as viewing the source code of any Chrome extension in the Chrome Web Store without installing it and is released under the Mozilla Public License 2.0, so it's a fair alternative if you'd rather have the browser button. Under Manifest V3 the code you see is the code that can run, because an extension can no longer use remotely hosted code.

Why does an extension say it can read and change all my data on all websites?

Because it declares a host pattern covering every site, or a permission that implies the same reach. Chrome's reference lists 'Read and change all your data on all websites' as the warning for host access to all websites, and the debugger permission shows that same line alongside 'Access the page debugger backend'. In the sample above, 15 of sixteen packages can run on every site at install, measured 2026-08-25, so the warning on its own doesn't separate one extension from another. What it allows is in Google's own words for users, 'Your data on all the websites you visit'.

My file has no host_permissions. Does that mean no site access?

Not by itself. Check content_scripts. The content_scripts key specifies a statically loaded JavaScript or CSS file to be used every time a page is opened that matches a certain URL pattern, its matches property is required and specifies which URL patterns to inject the content scripts into, and that matches key triggers a permission warning. Google Translate's package is the worked example above, no host_permissions key and a content script matching <all_urls>.

What does activeTab allow?

Temporary access to the active tab through a user gesture. In practice the extension gets the URL, title, and favicon for that tab when you invoke it, and no warning is shown for it during installation.

What happens when an update adds a permission?

If the new permission triggers a warning, the extension is disabled until you accept it. Optional permissions work the other way round. They're granted by the user at runtime, instead of at install time, and Chrome prompts you only if adding them results in warning messages you haven't already seen and accepted.

Is a CRX file just a ZIP?

Nearly. After the Cr24 magic number, the version and the header, the remainder is an ordinary ZIP archive. The tool offers that ZIP for download once it has read the header, with nothing else changed.

Does this page upload my file?

No. The file is read in the page with the File API and unzipped there, and the signature check runs on the browser's own Web Crypto. Free tools run in your browser and send nothing to a server. Results from financial, health or legal calculators are estimates, not advice.

Disclosures

Safety scores and tracking verdicts are computed from each extension's published permission list and store metadata as of the snapshot date shown. They are not a code audit and cannot detect what an extension does at runtime.

User counts and ratings are the Chrome Web Store's published figures as of the date shown and change daily. The live listing is the source of truth.

Zovo builds some of the extensions compared on this site. Where a Zovo extension appears in a ranking or comparison the page says so. No Zovo extension is in the sample on this page.

Free tools run in your browser and send nothing to a server. Results from financial, health or legal calculators are estimates, not advice.