Skip to content

Instantly share code, notes, and snippets.

@hridaydutta123
Created May 3, 2025 14:36
Show Gist options
  • Save hridaydutta123/4cdefdb19b82b5345545881ff20ce428 to your computer and use it in GitHub Desktop.
Save hridaydutta123/4cdefdb19b82b5345545881ff20ce428 to your computer and use it in GitHub Desktop.
Download chrome extensions from Chrome Web Store
#!/usr/bin/env bash
#
# Download multiple Chrome extensions from the webstore using a CSV file of extension IDs.
#
# Author: Hridoy Sankar Dutta (modified)
set -e
# ==========================================================================
usage() {
echo "Usage: $0 [-h|--help] <extensionIdsFile> [outputDir] [extensionVersion]"
echo
echo "Download multiple Chrome extensions (.crx) from a file with extension IDs."
echo
echo "Options:"
echo " -h, --help Show this help message and exit"
echo
echo "Arguments:"
echo " extensionIdsFile File containing Chrome extension IDs (one per line)"
echo " outputDir (Optional) Directory to save the .crx files (default: ./original_crx)"
echo " extensionVersion (Optional) Specific version to download"
}
# Check arguments
if [ $# -lt 1 ]; then
usage
exit 1
fi
if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
usage
exit 0
fi
extensionIdsFile="$1"
outputPath="${2:-original_crx}"
extensionVersion="$3"
if [ ! -f "$extensionIdsFile" ]; then
echo "Error: Extension IDs file not found: $extensionIdsFile"
exit 1
fi
# Create output directory if it doesn't exist
mkdir -p "$outputPath"
# Use a default or hardcoded version of Chrome if google-chrome not found
if command -v google-chrome &> /dev/null; then
CHROME_VERSION=$(google-chrome --version | cut -d ' ' -f 3)
else
echo "Warning: google-chrome not found, using hardcoded version."
CHROME_VERSION="123.0.6312.86"
fi
# Detect OS
[ -n "$platformOs" ] || case "$OSTYPE" in
*darwin*) platformOs="mac" ;;
*linux*) platformOs="linux" ;;
*) echo "Unsupported platform: $OSTYPE"; exit 1 ;;
esac
# Detect architecture
arch="x86-64"
ARCH="$(uname -m)"
case "$ARCH" in
*arm*) arch="arm" ;;
"x86_64") arch="x86-64" ;;
esac
# Function to download a single extension
download_extension() {
local extensionId="$1"
echo "Downloading extension: $extensionId"
# Construct download URL
crxDownloadUrl='https://clients2.google.com/service/update2/crx?response=redirect'
crxDownloadUrl="${crxDownloadUrl}&os=${platformOs}"
crxDownloadUrl="${crxDownloadUrl}&arch=${arch}"
crxDownloadUrl="${crxDownloadUrl}&os_arch=${arch}"
crxDownloadUrl="${crxDownloadUrl}&prod=chromecrx"
crxDownloadUrl="${crxDownloadUrl}&prodchannel=unknown"
crxDownloadUrl="${crxDownloadUrl}&prodversion=${CHROME_VERSION}"
crxDownloadUrl="${crxDownloadUrl}&acceptformat=crx3"
# Add version string if provided
if [ -n "$extensionVersion" ]; then
crxDownloadUrl="${crxDownloadUrl}&x=id%3D${extensionId}%26uc%26v%3D${extensionVersion}"
else
crxDownloadUrl="${crxDownloadUrl}&x=id%3D${extensionId}%26uc"
fi
# Prepare output
downloadFilePath="$outputPath/$extensionId.crx"
# Download the CRX - continue on error
if ! wget \
--quiet \
--referer="https://chrome.google.com/webstore/detail/${extensionId}?hl=en" \
--user-agent="Mozilla/5.0 Chrome/$CHROME_VERSION" \
-O "$downloadFilePath" "$crxDownloadUrl" 2>/dev/null; then
echo "⚠️ Warning: Could not download extension $extensionId"
return 1
fi
if [ ! -s "$downloadFilePath" ]; then
echo "❌ Error: Downloaded file for $extensionId has 0 bytes."
return 1
else
echo "✅ Extension $extensionId downloaded to: $downloadFilePath"
return 0
fi
}
# Print info header
echo "=== Chrome Extension Downloader ==="
echo "Output directory: $outputPath"
echo "Chrome version: $CHROME_VERSION"
echo "Platform: $platformOs ($arch)"
echo "==============================="
# Read the CSV file line by line and download each extension
total_extensions=$(wc -l < "$extensionIdsFile")
success_count=0
fail_count=0
current=0
while IFS= read -r extensionId || [ -n "$extensionId" ]; do
# Skip empty lines
if [ -z "$extensionId" ]; then
continue
fi
# Remove any whitespace or carriage returns
extensionId=$(echo "$extensionId" | tr -d '[:space:]')
# Only process if we have a valid extension ID
if [ ${#extensionId} -eq 32 ]; then
current=$((current + 1))
echo "[$current/$total_extensions] Processing extension ID: $extensionId"
if download_extension "$extensionId"; then
success_count=$((success_count + 1))
else
fail_count=$((fail_count + 1))
echo "⏩ Skipping and continuing to next extension..."
fi
else
echo "Warning: Skipping invalid extension ID: $extensionId (not 32 characters)"
fail_count=$((fail_count + 1))
fi
done < "$extensionIdsFile"
echo "==============================="
echo "Download summary:"
echo "Total extensions processed: $total_extensions"
echo "Successful downloads: $success_count"
echo "Failed downloads: $fail_count"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment