A few months ago, I wrote about creating a MacOS/iOS script here.
The script worked well initially, automatically checking Apple's support pages and sending email alerts whenever new versions were detected. Life was good—until it wasn't.
The Problem: Ghost Notifications and False Alerts
Everything was running smoothly until one morning when I received email notifications claiming that iOS 18.4.1 had been released, followed by another alert about macOS 5.5. This immediately struck me as odd since I knew iOS 18.5 and macOS 15.5 were the current versions. My script had somehow traveled back in time and decided older (or completely wrong) versions were "new."
This was clearly a logic error somewhere in my script. The original approach was straightforward—scrape Apple's official support websites and use regex patterns to extract version numbers. But as I discovered, this method had a critical flaw.
The Root Cause: Legacy Device Version Confusion
After digging into the issue, I realized what was happening. Apple's support pages don't just list the latest iOS and macOS versions—they list the latest versions for every device category and compatibility level. The script was picking up version numbers for legacy devices that can't upgrade to the latest operating systems.
Here's what my original regex patterns were doing:
# Original problematic patterns
if ($content -match "iOS\s+(\d+\.\d+\.?\d*)\s+(?!beta|RC)") {
$version = $matches[1]
# This could match ANY iOS version on the page!
}
if ($content -match "macOS\s+[\w\s]+?(\d+\.\d+\.?\d*)") {
$version = $matches[1]
# This could grab macOS versions for unsupported Macs!
}
The Apple support pages contain text like:
- iOS: "iOS 18.5 for iPhone 12 and later" vs "iOS 16.7.10 for iPhone 8, iPhone 8 Plus, iPhone X" vs "iOS 15.8.4 for iPhone 6s, iPhone 7"
- macOS: "macOS 15.5 Sequoia" vs "macOS 14.7.6 Sonoma" vs "macOS 13.7.4 Ventura"
My script was essentially playing version roulette with both operating systems, sometimes grabbing the latest versions (iOS 18.5, macOS 15.5), sometimes grabbing legacy versions (iOS 16.7.10, macOS 14.7.6), and sometimes grabbing completely incorrect versions (like that mysterious "macOS 5.5"), depending on page layout changes or which pattern matched first.
First Attempt: Better Regex Patterns
My first instinct was to fix the regex patterns for both operating systems. I tried to target the specific bold text sections on Apple's support page:
# Attempted fixes - target the specific bold sections
if ($content -match "The latest version of iOS and iPadOS is (\d+\.\d+\.?\d*)\.") {
$iOSversion = $matches[1]
return $iOSversion
}
if ($content -match "The latest version of macOS is (\d+\.\d+\.?\d*)\.") {
$macOSversion = $matches[1]
return $macOSversion
}
While this was more precise, it still relied on web scraping, which is inherently fragile. Apple could change their page layout, wording, or structure at any time, breaking the script.
HTML Parsing with ipsw.me
After several failed attempts, I realized that ipsw.me's HTML pages actually contained the exact information I needed for both iOS and macOS in a more predictable format. The key insight came from examining a working macOS version checker script I had that used this approach successfully.
Here's the final working method for both operating systems:
function Get-LatestIOSVersion {
try {
# Query ipsw.me for iPhone models
$iPhoneModels = @("iPhone16,2", "iPhone15,4", "iPhone15,2")
$latestVersion = "0.0.0"
foreach ($model in $iPhoneModels) {
$url = "https://ipsw.me/$model"
$response = Invoke-WebRequest -Uri $url -Headers $headers -UseBasicParsing
# Look for iOS version pattern
$pattern = 'iOS\s+(\d+\.\d+\.?\d*)\s*\((\w+)\)'
if ($response.Content -match $pattern) {
$version = $Matches[1]
if ([version]$version -gt [version]$latestVersion) {
$latestVersion = $version
}
}
}
return $latestVersion
}
catch {
# Fallback to Apple support page for iOS
}
}
function Get-LatestMacOSVersion {
try {
# Query ipsw.me for Mac models
$url = "https://ipsw.me/Mac16,10"
$response = Invoke-WebRequest -Uri $url -Headers $headers -UseBasicParsing
# Look for macOS version pattern
$pattern = 'macOS\s+(\d+\.\d+\.?\d*)\s*\((\w+)\)'
if ($response.Content -match $pattern) {
$version = $Matches[1]
return $version
}
}
catch {
# Fallback to Apple support page for macOS
}
}
Updated Script Structure
The final working script combines the best approaches for both operating systems:
- Primary Method: Query ipsw.me HTML pages for specific iPhone and Mac device models
- Reliable Parsing: Use consistent patterns that match ipsw.me's format for both iOS and macOS
- Multiple Models: Check several device models and take the highest version found
- Dual Fallback Methods: Apple support pages as backup for both iOS and macOS
- Proper Error Handling: Graceful degradation when sources fail
# The winning combination for both operating systems
$iPhoneModels = @("iPhone16,2", "iPhone15,4", "iPhone15,2") # Recent iPhone models
$macModels = @("Mac16,10", "Mac15,3") # Recent Mac models
# Check iOS versions
foreach ($model in $iPhoneModels) {
# Query ipsw.me for each iPhone model
# Parse with reliable regex: 'iOS\s+(\d+\.\d+\.?\d*)\s*\((\w+)\)'
# Take the highest version found
}
# Check macOS versions
foreach ($model in $macModels) {
# Query ipsw.me for each Mac model
# Parse with reliable regex: 'macOS\s+(\d+\.\d+\.?\d*)\s*\((\w+)\)'
# Take the highest version found
}
Conclusion
The new script now correctly identifies iOS 18.5 and macOS 15.5 as the current versions, without getting confused by legacy device information or producing mysterious version numbers like "macOS 5.5". No more ghost notifications about iOS 18.4.1 or incorrect macOS versions!
Sometimes the best debugging session is the one that leads you to completely rethink your approach, like in this example.