crxpull
v1.0.2
Published
Download Chrome extensions as .crx files from the terminal
Maintainers
Readme
crxpull
Download Chrome extensions as .zip + extracted source folder — by ID or Chrome Web Store URL.
npx crxpull cjpalhdlnbpafiamejdnhcphjbkeiagm
# saves a .zip and extracts source files, ready to inspectDisclaimer: crxpull uses an unofficial Google endpoint to fetch CRX files. Intended for legitimate personal use — security research, extension auditing, offline backup, and developer tooling. Ensure your usage complies with the Chrome Web Store Terms of Service. Do not redistribute extensions without the original author's permission.
Install
npm install -g crxpullbun add -g crxpullOr run without installing:
npx crxpull <id-or-url>
bunx crxpull <id-or-url>Usage
crxpull <id-or-url> [options]
crxpull -f extensions.txt [options]Options
| Flag | Description | Default |
|------|-------------|---------|
| -o, --output <dir> | Output directory | Current directory |
| -n, --name <filename> | Custom filename (no extension) | Extension ID |
| --crx | Also keep the raw .crx file | false |
| --info | Show metadata from the Chrome Web Store | — |
| -f, --file <path> | Read IDs/URLs from a text file (one per line) | — |
| -c, --concurrency <n> | Parallel downloads in batch mode | 3 |
| --json | Output results as JSON | false |
| -v, --version | Show version | — |
| -h, --help | Show help | — |
Examples
# Download by extension ID
crxpull mihcahmgecmbnbcchbopgniflfhgnkff
# Download from a Chrome Web Store URL
crxpull https://chromewebstore.google.com/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm
# Save to a custom directory with a custom filename
crxpull cjpalhdlnbpafiamejdnhcphjbkeiagm -o ./extensions -n ublock
# Also keep the raw .crx file
crxpull cjpalhdlnbpafiamejdnhcphjbkeiagm --crx
# Show extension metadata without downloading
crxpull cjpalhdlnbpafiamejdnhcphjbkeiagm --info
# Batch download from a file
crxpull -f my-extensions.txt -o ./extensions -c 5
# JSON output — great for scripting
crxpull cjpalhdlnbpafiamejdnhcphjbkeiagm --jsonBatch file format
Lines starting with # are treated as comments and ignored.
# my-extensions.txt
cjpalhdlnbpafiamejdnhcphjbkeiagm
mihcahmgecmbnbcchbopgniflfhgnkff
https://chromewebstore.google.com/detail/dark-reader/eimadpbcbfnmbkopoojfekhnkhdbieehProgrammatic API
import { download, downloadBatch, fetchExtensionInfo, extractId } from 'crxpull'download(input, options?)
Downloads a single extension. Returns { id, zipPath, folderPath, crxPath? }.
const result = await download('cjpalhdlnbpafiamejdnhcphjbkeiagm', {
outputDir: './extensions',
name: 'ublock',
crx: false, // set true to also keep the raw .crx
onProgress: (bytes, total) => {
process.stdout.write(`\r${Math.round(bytes / total * 100)}%`)
}
})
console.log(result.zipPath) // ./extensions/ublock.zip
console.log(result.folderPath) // ./extensions/ublock/downloadBatch(inputs, options?)
Downloads multiple extensions in parallel. Always resolves — failed items include an error field.
const results = await downloadBatch([
'cjpalhdlnbpafiamejdnhcphjbkeiagm',
'mihcahmgecmbnbcchbopgniflfhgnkff',
], {
outputDir: './extensions',
concurrency: 5,
})
for (const r of results) {
if (r.error) console.error(`${r.id} failed: ${r.error}`)
else console.log(`${r.id} → ${r.zipPath}`)
}fetchExtensionInfo(id)
Fetches extension metadata from the Chrome Web Store.
const info = await fetchExtensionInfo('cjpalhdlnbpafiamejdnhcphjbkeiagm')
console.log(info.name) // "uBlock Origin"
console.log(info.version) // "1.59.0"
console.log(info.users) // "10,000,000+"
console.log(info.rating) // 4.8
console.log(info.storeUrl) // https://chromewebstore.google.com/...extractId(input)
Parses a 32-character extension ID from a raw ID string or any Chrome Web Store URL.
extractId('cjpalhdlnbpafiamejdnhcphjbkeiagm')
// => 'cjpalhdlnbpafiamejdnhcphjbkeiagm'
extractId('https://chromewebstore.google.com/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm')
// => 'cjpalhdlnbpafiamejdnhcphjbkeiagm'How it works
crxpull fetches the extension from Google's CRX update service endpoint. The raw .crx file is downloaded to a temp path, then crxpull strips the CRX binary header (CRX2 or CRX3 format) to expose the embedded ZIP. It then:
- Saves a clean
.zipfile — portable, shareable, openable anywhere - Extracts a folder with all source files ready to edit —
manifest.json, scripts, assets, locales
The temporary .crx is deleted automatically. Use --crx if you want to keep it.
Publishing
A PowerShell publish script is included for Windows. It handles token management, version bumping, and retries.
# First time — save your npm token
.\publish.ps1 -Token npm_xxxx -Save
# Bump patch and publish
.\publish.ps1
# Bump minor version
.\publish.ps1 -Minor
# Dry run — preview without publishing
.\publish.ps1 -DryRunToken resolution order: -Token param → NPM_TOKEN env var → .npmtoken file (gitignored).
Disclaimer
crxpull relies on an unofficial, undocumented Google endpoint. There is no guarantee it will remain available or stable. Intended for legitimate personal use only — security research, auditing, developer workflows, and offline backup. Always respect the rights of extension authors and the Chrome Web Store Terms of Service.
Requirements
- Node.js 18 or later
Contributing
Issues and pull requests are welcome. Feel free to fork, improve, and share.
Credits
Built in collaboration with Claude by Anthropic.
License
MIT
