Skip to content

Instantly share code, notes, and snippets.

@j1cs
Created October 27, 2025 20:48
Show Gist options
  • Select an option

  • Save j1cs/1e6dfe5d96e7f8b23ea72d8a88a6a399 to your computer and use it in GitHub Desktop.

Select an option

Save j1cs/1e6dfe5d96e7f8b23ea72d8a88a6a399 to your computer and use it in GitHub Desktop.
Download ISO MacOS
#!/usr/bin/env bash
set -Eeuo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Functions for printing messages
info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
success() {
echo -e "${GREEN}[SUCCESS]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1"
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
# Function to generate random hexadecimal numbers
getRandom() {
local length="$1"
local result=""
local chars=("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "A" "B" "C" "D" "E" "F")
for ((i=0; i<length; i++)); do
result+="${chars[$((RANDOM % 16))]}"
done
echo "$result"
}
# Function to format bytes
formatBytes() {
local bytes="$1"
if [ "$bytes" -lt 1024 ]; then
echo "${bytes}B"
elif [ "$bytes" -lt 1048576 ]; then
echo "$((bytes / 1024))KB"
elif [ "$bytes" -lt 1073741824 ]; then
echo "$((bytes / 1048576))MB"
else
echo "$((bytes / 1073741824))GB"
fi
}
# Main download function
download() {
local dest="$1"
local board="$2"
local version="$3"
local type="latest"
local appleSession=""
local downloadLink=""
local downloadSession=""
local mlb="00000000000000000"
local rc total size
info "Downloading macOS ${version^} recovery image..."
# Get Apple session
info "Connecting to Apple servers..."
appleSession=$(curl --disable -v -H "Host: osrecovery.apple.com" \
-H "Connection: close" \
-A "InternetRecovery/1.0" \
https://osrecovery.apple.com/ 2>&1 | tr ';' '\n' | awk -F'session=|;' '{print $2}' | grep 1)
if [ -z "$appleSession" ]; then
error "Failed to obtain Apple session"
return 1
fi
# Request download information
info "Fetching download information..."
local info_response
info_response=$(curl --disable -s -X POST \
-H "Host: osrecovery.apple.com" \
-H "Connection: close" \
-A "InternetRecovery/1.0" \
-b "session=\"${appleSession}\"" \
-H "Content-Type: text/plain" \
-d $'cid='"$(getRandom 16)"$'\nsn='"${mlb}"$'\nbid='"${board}"$'\nk='"$(getRandom 64)"$'\nfg='"$(getRandom 64)"$'\nos='"${type}" \
https://osrecovery.apple.com/InstallationPayload/RecoveryImage | tr ' ' '\n')
downloadLink=$(echo "$info_response" | grep 'oscdn' | grep 'dmg')
downloadSession=$(echo "$info_response" | grep 'expires' | grep 'dmg')
if [ -z "$downloadLink" ] || [ -z "$downloadSession" ]; then
error "Failed to obtain download link"
# Check connectivity
if ! curl --silent --max-time 10 --output /dev/null --fail \
-H "Host: osrecovery.apple.com" \
-H "Connection: close" \
-A "InternetRecovery/1.0" \
https://osrecovery.apple.com/; then
error "No connection to Apple servers"
fi
return 1
fi
info "Download link obtained successfully"
info "Downloading file..."
# Download the image
rm -f "$dest"
if wget "$downloadLink" -O "$dest" \
--header "Host: oscdn.apple.com" \
--header "Connection: close" \
--header "User-Agent: InternetRecovery/1.0" \
--header "Cookie: AssetToken=${downloadSession}" \
--timeout=30 \
--no-http-keep-alive \
--show-progress \
--progress=bar:force:noscroll; then
if [ -f "$dest" ]; then
total=$(stat -c%s "$dest")
size=$(formatBytes "$total")
if [ "$total" -lt 100000 ]; then
error "Invalid recovery image, file is only $size"
rm -f "$dest"
return 1
fi
success "Download completed successfully!"
success "File saved at: $dest"
success "Size: $size"
return 0
fi
fi
error "Download failed"
return 1
}
# Function to convert DMG to ISO
convert_to_iso() {
local dmg_file="$1"
local iso_file="${dmg_file%.dmg}.img"
info "Converting DMG to IMG format..."
if ! command -v dmg2img &> /dev/null; then
warn "dmg2img is not installed. Skipping conversion."
warn "To install: sudo apt-get install dmg2img (Debian/Ubuntu)"
warn " or: sudo yum install dmg2img (RedHat/CentOS)"
return 1
fi
if dmg2img "$dmg_file" "$iso_file"; then
local total size
total=$(stat -c%s "$iso_file")
size=$(formatBytes "$total")
success "Conversion completed successfully!"
success "IMG file saved at: $iso_file"
success "Size: $size"
return 0
else
error "Conversion failed"
return 1
fi
}
# Function to show menu
show_menu() {
echo ""
echo "=========================================="
echo " macOS Recovery Image Downloader"
echo "=========================================="
echo ""
echo "Select the macOS version to download:"
echo ""
echo " 1) Tahoe (macOS 16.x / 26.x)"
echo " 2) Sequoia (macOS 15.x)"
echo " 3) Sonoma (macOS 14.x)"
echo " 4) Ventura (macOS 13.x)"
echo " 5) Monterey (macOS 12.x)"
echo " 6) Big Sur (macOS 11.x)"
echo " 7) Catalina (macOS 10.x)"
echo " 0) Exit"
echo ""
}
# Main function
main() {
local choice
local version
local board
local dest
# Check dependencies
if ! command -v curl &> /dev/null; then
error "curl is not installed. Please install it first."
exit 1
fi
if ! command -v wget &> /dev/null; then
error "wget is not installed. Please install it first."
exit 1
fi
show_menu
read -p "Enter your choice [0-7]: " choice
case "$choice" in
1)
version="Tahoe"
board="Mac-CFF7D910A743CAAF"
;;
2)
version="Sequoia"
board="Mac-937A206F2EE63C01"
;;
3)
version="Sonoma"
board="Mac-827FAC58A8FDFA22"
;;
4)
version="Ventura"
board="Mac-4B682C642B45593E"
;;
5)
version="Monterey"
board="Mac-B809C3757DA9BB8D"
;;
6)
version="Big Sur"
board="Mac-2BD1B31983FE1663"
;;
7)
version="Catalina"
board="Mac-00BE6ED71E35EB86"
;;
0)
info "Exiting..."
exit 0
;;
*)
error "Invalid option"
exit 1
;;
esac
echo ""
info "You selected: macOS $version"
echo ""
# Ask for destination path
read -p "Enter the path to save the file (default: ./macos_${version,,}.dmg): " dest
if [ -z "$dest" ]; then
dest="./macos_${version,,}.dmg"
fi
# Check if file already exists
if [ -f "$dest" ]; then
warn "File $dest already exists"
read -p "Do you want to overwrite it? (y/N): " overwrite
if [[ ! "$overwrite" =~ ^[yY]$ ]]; then
info "Operation cancelled"
exit 0
fi
fi
echo ""
info "Starting download..."
echo ""
# Perform the download
if download "$dest" "$board" "$version"; then
echo ""
success "Download completed!"
echo ""
# Ask if user wants to convert to IMG
read -p "Do you want to convert the DMG to IMG format for bootable USB? (y/N): " convert_choice
if [[ "$convert_choice" =~ ^[yY]$ ]]; then
echo ""
if convert_to_iso "$dest"; then
echo ""
success "Process completed!"
success "Your macOS $version recovery image is ready"
success "DMG file: $dest"
success "IMG file: ${dest%.dmg}.img"
echo ""
info "To create a bootable USB, use:"
info " sudo dd if=${dest%.dmg}.img of=/dev/sdX bs=4M status=progress"
info " (Replace /dev/sdX with your USB device)"
else
echo ""
warn "Conversion skipped or failed"
success "DMG file is still available at: $dest"
fi
else
success "Your macOS $version recovery image is ready at: $dest"
fi
else
echo ""
error "Download failed. Please try again."
exit 1
fi
}
# Run the script
main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment