A PowerShell tool for checking Azure VM SKU availability across regions - find where your VMs can deploy.
- Lifecycle Recommendations — feed a CSV/JSON/XLSX of deployed VMs and get retirement risk analysis with up to 6 upgrade alternatives per SKU, powered by a curated upgrade-path knowledge base
-SubMap/-RGMap— new deployment mapping sheets in XLSX exports, grouping affected VMs by subscription or resource group with risk-level enrichment-Tagfilter — filter live VM inventory scans by Azure resource tags (key=value or key=*)-RateOptimization— opt-in Savings Plan and Reserved Instance pricing columns alongside PAYG
- HttpClient scan engine — concurrent SKU+quota fetch via
System.Net.Http.HttpClientwith runspace parallelism (~20% faster scans) -JsonOutput— suppresses allWrite-Hostoutput for clean JSON pipeline consumption- O(1) capability lookup — hashtable index replaces linear scan in
Get-CapValue
- GitHub Codespaces support and documentation updates
-FleetFile— load fleet BOM from CSV/JSON for capacity and quota validation-GenerateFleetTemplate— scaffolds example fleet template files- Module extraction — 34 functions extracted to
AzVMAvailability/module with inline fallback exit→throw— script no longer kills the caller's session when dot-sourced
-Fleethashtable — BOM-level capacity and quota validation with per-family pass/fail verdicts
Full history: CHANGELOG.md
The author is a Microsoft employee; however, this is a personal open-source project. It is not an official Microsoft product, nor is it endorsed, sponsored, or supported by Microsoft.
- No warranty: Provided "as-is" under the MIT License.
- No official support: For Azure platform issues, use Azure Support.
- No confidential information: This tool uses only publicly documented Azure APIs. Please do not share internal or confidential information in issues, pull requests, or discussions.
- Trademarks: "Microsoft" and "Azure" are trademarks of Microsoft Corporation. Their use here is for identification only and does not imply endorsement.
Get-AzVMAvailability helps you identify which Azure regions have available capacity for your VM deployments. It scans multiple regions in parallel and provides detailed insights into SKU availability, zone restrictions, quota limits, pricing, and image compatibility.
- Multi-Region Parallel Scanning - Scan 10+ regions in ~15 seconds using concurrent HttpClient-based REST calls
- SKU Filtering - Filter to specific SKUs with wildcard support (e.g.,
Standard_D*_v5) - Lifecycle Recommendations - Analyze deployed VMs for retirement risk; get up to 6 upgrade alternatives per SKU from a curated knowledge base + real-time scoring engine
- Live Lifecycle Scan - Pull VM inventory directly from Azure via Resource Graph with management group, resource group, and tag filters
- Deployment Mapping -
-SubMap/-RGMapsheets group affected VMs by subscription or resource group with risk enrichment - Pricing Information - Show hourly/monthly pricing (retail or negotiated EA/MCA rates) with optional Savings Plan and Reserved Instance comparisons
- Spot VM Pricing - Include Spot pricing alongside on-demand rates
- Placement Scores - Show allocation likelihood (High/Medium/Low) for each SKU via Azure Spot Placement API
- Image Compatibility - Verify Gen1/Gen2 and x64/ARM64 requirements
- Zone Availability - Per-zone availability details
- Quota Tracking - Available vCPU quota per family
- Multi-Region Matrix - Color-coded comparison view
- Interactive Drill-Down - Explore specific families and SKUs
- Export Options - CSV and styled XLSX with conditional formatting
- JSON Output - Structured JSON for AI agent integration and automation pipelines
- Inventory Readiness - Validate capacity and quota for an entire VM BOM in one command
- Compatibility-Validated Recommendations - Alternatives are validated to meet or exceed the target SKU's NICs, accelerated networking, premium IO, disk interface, ephemeral OS disk, and Ultra SSD requirements. Data disks and IOPS are scored as soft dimensions
| Task | Azure Portal | This Script |
|---|---|---|
| Check 10 regions | ~5 minutes | ~15 seconds |
| Get quota + availability | Multiple blades | Single view |
| Compare pricing across regions | Separate calculator | Integrated |
| Filter to specific SKUs | Scroll through hundreds | Wildcard filtering |
| Check image compatibility | Manual research | Automated validation |
| Analyze VM retirement risk | Azure Advisor + manual | Single command |
| Export results | Manual copy/paste | One command |
- VM Lifecycle & Retirement Planning - Identify old-gen and retiring SKUs across your fleet and get validated upgrade paths
- Disaster Recovery Planning - Identify backup regions with capacity
- Multi-Region Deployments - Find regions where all required SKUs are available
- GPU/HPC Workloads - NC, ND, NV series are often constrained; find where they're available
- Inventory Readiness Validation - Verify capacity and quota for an entire VM BOM before deployment
- Image Compatibility - Verify SKUs support your Gen2 or ARM64 images before deployment
- Troubleshooting Deployments - Quickly identify why a deployment might be failing
- PowerShell 7.0+ (required)
- Azure PowerShell Modules:
Az.Compute,Az.Resources - Optional:
ImportExcelmodule for styled XLSX export - Optional:
Az.ResourceGraphmodule for-LifecycleScanlive VM inventory
The script automatically detects your Azure environment and uses the correct API endpoints:
| Cloud | Environment Name | Supported |
|---|---|---|
| Azure Commercial | AzureCloud |
✅ |
| Azure Government | AzureUSGovernment |
✅ |
| Azure China | AzureChinaCloud |
✅ |
| Azure Germany | AzureGermanCloud |
✅ |
No configuration required - the script reads your current Az context and resolves endpoints automatically.
A pre-configured codespace that automatically installs the required modules when first created has been defined in the .devcontainer folder of this repo. This means no downloading or installing of any code on your local machine. Simply follow these steps:
- In GitHub, select the Codespaces tab from the Code dropdown in GitHub on the Repo's (or your fork's) main page.
- Click on the plus (+) icon to create a new codespace
- Wait for the codespace to finish installing/creating
- Run the following commands
# Use this instead if calling from a codespace
Connect-AzAccount -Tenant YourTenantIdHere -subscription YourSubIdHere -UseDeviceAuthentication
# Interactive mode - prompts for all options
.\Get-AzVMAvailability.ps1
# See further in this document for other examples outside of interactive mode# Clone the repository
git clone https://github.com/zacharyluz/Get-AzVMAvailability.git
cd Get-AzVMAvailability
# Install required Azure modules (if needed)
# Windows only: enable running scripts from the PowerShell Gallery in your profile
if ($IsWindows) {
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
}
Install-Module -Name Az.Compute -Scope CurrentUser -Repository PSGallery -Force
Install-Module -Name Az.Resources -Scope CurrentUser -Repository PSGallery -Force
# Optional: Install ImportExcel for styled exports
Install-Module -Name ImportExcel -Scope CurrentUser -Repository PSGallery -Force
# Register a local PowerShell repository for this repo (idempotent)
if (-not (Get-PSRepository -Name Get-AzVMAvailability -ErrorAction SilentlyContinue)) {
Register-PSRepository -Name Get-AzVMAvailability -SourceLocation . -InstallationPolicy Trusted
}
# Interactive Login to Azure
Connect-AzAccount -Tenant YourTenantIdHere -subscription YourSubIdHere
# Interactive mode - prompts for all options
.\Get-AzVMAvailability.ps1
# Automated mode - uses current subscription
.\Get-AzVMAvailability.ps1 -NoPrompt -Region "eastus","westus2"
# With auto-export
.\Get-AzVMAvailability.ps1 -Region "eastus","eastus2" -AutoExport
# Inventory readiness check from CSV file
.\Get-AzVMAvailability.ps1 -InventoryFile .\examples\fleet-bom.csv -Region "eastus" -NoPrompt
# Lifecycle analysis — find old-gen SKUs and recommend replacements
.\Get-AzVMAvailability.ps1 -LifecycleRecommendations .\my-vms.csv -Region "eastus" -NoPrompt
# Lifecycle analysis — from Azure portal VM export (XLSX)
.\Get-AzVMAvailability.ps1 -LifecycleRecommendations .\AzureVirtualMachines.xlsx -NoPrompt
# Live lifecycle scan — pull VM inventory directly from Azure
.\Get-AzVMAvailability.ps1 -LifecycleScan -NoPrompt💡 Tip: When copying multi-line commands, ensure backticks (
`) at the end of each line are preserved. If copying from GitHub, use the "Copy" button in code blocks.
.\Get-AzVMAvailability.ps1 -Region "eastus","westus2","centralus"# Multi-line with backticks for readability
.\Get-AzVMAvailability.ps1 `
-Region "eastus","eastus2","southcentralus" `
-FamilyFilter "NC","ND","NV".\Get-AzVMAvailability.ps1 `
-ExportPath "C:\Reports" `
-AutoExport `
-OutputFormat XLSX# Pricing auto-detects negotiated rates (EA/MCA/CSP), falls back to retail
.\Get-AzVMAvailability.ps1 `
-Region "eastus","westus2" `
-SkuFilter "Standard_D*_v5" `
-ShowPricing# Multi-line format with backticks for readability
.\Get-AzVMAvailability.ps1 `
-SubscriptionId "your-subscription-id" `
-Region "eastus","westus2","centralus" `
-ExportPath "C:\Reports" `
-AutoExport `
-EnableDrillDown `
-FamilyFilter "D","E","M" `
-OutputFormat "XLSX" `
-UseAsciiIcons| Parameter | Type | Description |
|---|---|---|
-SubscriptionId |
String[] | Azure subscription ID(s) to scan |
-Region |
String[] | Azure region code(s) (e.g., 'eastus', 'westus2') |
-RegionPreset |
String | Predefined region set (see table below). Auto-sets environment for sovereign clouds. |
-Environment |
String | Azure cloud (default: auto-detect). Options: AzureCloud, AzureUSGovernment, AzureChinaCloud, AzureGermanCloud |
-ExportPath |
String | Directory for export files |
-AutoExport |
Switch | Export without prompting |
-EnableDrillDown |
Switch | Interactive family/SKU exploration |
-FamilyFilter |
String[] | Filter to specific VM families |
-SkuFilter |
String[] | Filter to specific SKUs (supports wildcards) |
-ShowPricing |
Switch | Show pricing (auto-detects negotiated EA/MCA/CSP rates, falls back to retail) |
-ShowSpot |
Switch | Include Spot VM pricing in output. Requires -ShowPricing |
-ShowPlacement |
Switch | Show allocation likelihood scores (High/Medium/Low) for each SKU via Azure Spot Placement API |
-DesiredCount |
Int | Number of VMs to evaluate for placement scores (default 1). Affects allocation likelihood thresholds |
-RateOptimization |
Switch | Include Savings Plan and Reserved Instance savings columns in lifecycle reports. Requires -ShowPricing. Shows fleet-wide savings vs PAYG for each commitment term |
-ImageURN |
String | Check SKU compatibility with image (format: Publisher:Offer:Sku:Version) |
-CompactOutput |
Switch | Use compact output for narrow terminals |
-NoPrompt |
Switch | Skip interactive prompts |
-NoQuota |
Switch | Skip quota API calls in lifecycle modes. Useful when analyzing customer VM exports without subscription access |
-OutputFormat |
String | 'Auto', 'CSV', or 'XLSX' |
-UseAsciiIcons |
Switch | Force ASCII instead of Unicode icons |
-Recommend |
String | Find alternatives for a target SKU. Works interactively too — prompted after scan/drill-down if not specified |
-TopN |
Int | Number of alternatives to return in Recommend mode (default 5, max 25) |
-MinvCPU |
Int | Minimum vCPU count filter for recommended alternatives (optional) |
-MinMemoryGB |
Int | Minimum memory (GB) filter for recommended alternatives (optional) |
-MinScore |
Int | Minimum similarity score (0-100) for recommended alternatives; set 0 to show all (default 50) |
-AllowMixedArch |
Switch | Allow x64/ARM64 cross-architecture recommendations (excluded by default) |
-MaxRetries |
Int | Maximum retry attempts for transient API errors (default 3). Uses exponential backoff |
-JsonOutput |
Switch | Emit structured JSON for the AzVMAvailability-Agent or automation |
-SkipRegionValidation |
Switch | Skip Azure region metadata validation (use only when Azure metadata lookup is unavailable) |
-Inventory |
Hashtable | Inventory BOM as hashtable: @{'Standard_D2s_v5'=17; 'Standard_D4s_v5'=4} — validates capacity + quota for entire inventory |
-InventoryFile |
String | Path to CSV or JSON file with inventory BOM. CSV: columns SKU,Qty. JSON: array of {"SKU":"...","Qty":N} objects. Easiest input method for spreadsheet users |
-GenerateInventoryTemplate |
Switch | Creates inventory-template.csv and inventory-template.json in the current directory, then exits. No Azure login required |
-LifecycleRecommendations |
String | Path to CSV, JSON, or XLSX file listing current VM SKUs (column: SKU/Size/VmSize, optional: Region, Qty). XLSX files exported from the Azure portal VM blade are supported natively. Runs compatibility-validated recommendations with quantity-aware quota analysis |
-LifecycleScan |
Switch | Pull live VM inventory from Azure via Resource Graph for lifecycle analysis. No file required — queries all deployed VMs from your tenant. Requires Az.ResourceGraph module |
-ManagementGroup |
String[] | Scope -LifecycleScan to specific management group(s) for cross-subscription scanning |
-ResourceGroup |
String[] | Filter -LifecycleScan to specific resource group(s) |
-Tag |
Hashtable | Filter -LifecycleScan to VMs with specific tags. Hashtable of key=value pairs (e.g., @{Environment='prod'}). Use '*' as value to match any VM that has the tag key regardless of value |
-SubMap |
Switch | Include a Subscription Map sheet in lifecycle XLSX exports, grouping affected VMs by subscription with risk-level enrichment |
-RGMap |
Switch | Include a Resource Group Map sheet in lifecycle XLSX exports, grouping affected VMs by subscription + resource group with risk-level enrichment |
Backward compatibility: The previous parameter names
-Fleet,-FleetFile, and-GenerateFleetTemplatestill work as aliases.
Tuning tip: Use
-MinScore 0to see all candidates when capacity is tight, or raise it (e.g., 70) to prioritize closer matches.
Recommendations are compatibility-validated before scoring. A candidate SKU is only shown if it meets or exceeds the target on every critical dimension:
| Dimension | Rule |
|---|---|
| vCPU | Candidate ≥ Target (and ≤ 2× to avoid licensing risk) |
| Memory (GiB) | Candidate ≥ Target |
| Max NICs | Candidate ≥ Target (when target uses multi-NIC) |
| Accelerated networking | Required if target has it |
| Premium IO | Required if target has it |
| Disk interface | NVMe target requires NVMe candidate |
| Ephemeral OS disk | Required if target supports it |
| Ultra SSD | Required if target has it |
After passing the compatibility gate, candidates are ranked by an 8-dimension similarity score:
| Dimension | Weight |
|---|---|
| vCPU closeness | 20 pts |
| Memory closeness | 20 pts |
| Family match | 18 pts |
| Family version newness | 12 pts |
| Architecture match | 10 pts |
| Disk IOPS closeness | 8 pts |
| Data disk count closeness | 7 pts |
| Premium IO match | 5 pts |
Validate whether your entire VM deployment can be provisioned in a target region.
Option A — Generate a template (easiest):
.\Get-AzVMAvailability.ps1 -GenerateInventoryTemplate
# Creates inventory-template.csv and inventory-template.json in current directory
# Edit with your actual SKUs and quantitiesOption B — Write a CSV (Excel / text editor):
SKU,Qty
Standard_D2s_v5,17
Standard_D4s_v5,4
Standard_D8s_v5,5Option C — Write a JSON file:
[
{ "SKU": "Standard_D2s_v5", "Qty": 17 },
{ "SKU": "Standard_D4s_v5", "Qty": 4 },
{ "SKU": "Standard_D8s_v5", "Qty": 5 }
]Column names are flexible:
SKU,Name, orVmSizefor the SKU column;Qty,Quantity, orCountfor quantity. Duplicate SKU rows are summed automatically. TheStandard_prefix is optional.
.\Get-AzVMAvailability.ps1 -InventoryFile .\inventory-template.csv -Region "eastus" -NoPromptThe output shows per-SKU capacity status, per-family quota pass/fail (Used/Available/Limit), and an overall PASS/FAIL verdict.
Analyze your current VM inventory to identify SKUs that need lifecycle planning (old generation, capacity-constrained, or deprecated) and get compatibility-validated replacement recommendations for each.
SKU,Region,Qty
Standard_D4s_v3,eastus,10
Standard_E8s_v3,westus2,5
Standard_F4s_v2,eastus,3
Standard_D8s_v5,centralus,20All columns except SKU are optional:
- Region — where the SKU is deployed. When provided, capacity and quota are checked specifically in that region. Regions are auto-merged into the scan.
- Qty — number of VMs using this SKU (defaults to 1). Used to calculate required vCPUs for quota analysis. Duplicate SKU+Region rows have their quantities aggregated.
Minimal format (SKU only):
SKU
Standard_D4s_v3
Standard_E8s_v3
Standard_F4s_v2Column names are flexible:
SKU,Size, orVmSize(falls back toName) for the SKU column;Region,Location, orAzureRegionfor region;Qty,Quantity, orCountfor quantity.
.\Get-AzVMAvailability.ps1 -LifecycleRecommendations .\my-vms.csv -Region "eastus" -NoPromptExport your VM list directly from the Azure portal (Virtual Machines blade → Export to CSV/Excel) and pass the XLSX file with no reformatting:
.\Get-AzVMAvailability.ps1 -LifecycleRecommendations .\AzureVirtualMachines.xlsx -NoPromptThe parser automatically maps the SIZE column to SKU and LOCATION to Region, converts display names (e.g., "West US" → westus, "USGov Virginia" → usgovvirginia), and aggregates one-VM-per-row into SKU+Region quantities. Requires the ImportExcel module.
Pull your VM inventory directly from Azure using Resource Graph:
# Scan current subscription
.\Get-AzVMAvailability.ps1 -LifecycleScan -NoPrompt
# Scan specific subscriptions
.\Get-AzVMAvailability.ps1 -LifecycleScan -SubscriptionId "sub-id-1","sub-id-2" -NoPrompt
# Scan an entire management group (all child subscriptions)
.\Get-AzVMAvailability.ps1 -LifecycleScan -ManagementGroup "mg-production" -NoPrompt
# Scan specific resource groups within a subscription
.\Get-AzVMAvailability.ps1 -LifecycleScan -SubscriptionId "sub-id" -ResourceGroup "rg-app","rg-data" -NoPrompt
# Scan only VMs tagged with Environment=prod
.\Get-AzVMAvailability.ps1 -LifecycleScan -Tag @{Environment='prod'} -NoPrompt
# Combine tag filter with subscription and resource group
.\Get-AzVMAvailability.ps1 -LifecycleScan -SubscriptionId "sub-id" -Tag @{CostCenter='12345'; Environment='prod'} -NoPrompt
# Scan all VMs that have a "Department" tag (any value)
.\Get-AzVMAvailability.ps1 -LifecycleScan -Tag @{Department='*'} -NoPromptRequires the Az.ResourceGraph module (Install-Module Az.ResourceGraph -Scope CurrentUser).
Scoping rules:
-ManagementGroupand-SubscriptionIdare mutually exclusive.-ResourceGroupand-Tagcan be combined with either. If neither is specified, the current subscription context is used.
For each SKU in your list:
- Hybrid recommendations (3 AI + up to 3 weighted) — Up to 6 alternatives per SKU using a two-tier strategy:
- 3 upgrade path recommendations from a curated knowledge base (
data/UpgradePath.json) based on Microsoft's official migration guidance:Upgrade: Drop-in— lowest risk replacement (e.g., Dsv5 for Dv2)Upgrade: Future-proof— latest generation (e.g., Dsv6 with NVMe)Upgrade: Cost-optimized— AMD/alternative architecture at lower cost
- Up to 3 weighted recommendations from the real-time 8-dimension scoring engine, validated against actual region availability, capacity, and quota
- 3 upgrade path recommendations from a curated knowledge base (
- Lifecycle risk assessment — High / Medium / Low risk classification
- Quota analysis — current quota usage vs. limit for both the target SKU family and the recommended replacement's family, factoring in VM quantity (Qty × vCPUs)
- Details column — explains why each recommendation was selected (upgrade path rationale, family/version context, IOPS guarantees, resize impact, requirements like Gen2 OS or NVMe)
- Consolidated summary table — all SKUs with Qty, region, risk level, quota status, and top replacement
- VM-count-aware summary — footer shows total VM count at each risk level (e.g., "3 SKU(s) (35 VMs) at HIGH risk")
The upgrade path knowledge base covers 19 VM families (11 retired, 8 scheduled for retirement) with vCPU-matched size maps. See data/UpgradePath.md for the full reference.
Risk levels:
- High — Retired/retiring SKU, capacity issues, quota insufficient, or no compatible alternatives found
- Medium — Old generation (v3 or below); plan migration to current generation
- Low — Current generation with good availability and sufficient quota
By default, lifecycle reports include only PAYG (pay-as-you-go) cost columns when -ShowPricing is used:
# PAYG pricing only (Price Diff, Total, 1-Year Cost, 3-Year Cost)
.\Get-AzVMAvailability.ps1 -LifecycleRecommendations .\my-vms.csv -ShowPricing -NoPromptTo include Savings Plan (SP) and Reserved Instance (RI) savings columns, add -RateOptimization:
# Full pricing: PAYG + SP/RI savings vs PAYG fleet total
.\Get-AzVMAvailability.ps1 -LifecycleRecommendations .\my-vms.csv -ShowPricing -RateOptimization -NoPrompt
# Live scan with rate optimization and auto-export to XLSX
.\Get-AzVMAvailability.ps1 -LifecycleScan -ShowPricing -RateOptimization -AutoExport -NoPrompt
# Azure portal export with full pricing comparison
.\Get-AzVMAvailability.ps1 -LifecycleRecommendations .\AzureVirtualMachines.xlsx -ShowPricing -RateOptimization -NoQuota -AutoExportWith -RateOptimization, the XLSX report adds 4 savings columns: SP 1-Year Savings, SP 3-Year Savings, RI 1-Year Savings, RI 3-Year Savings — showing how much the fleet saves compared to PAYG by committing to each term.
Use -RegionPreset for quick access to common region sets:
| Preset | Regions | Use Case |
|---|---|---|
USEastWest |
eastus, eastus2, westus, westus2 | US coastal regions |
USCentral |
centralus, northcentralus, southcentralus, westcentralus | US central regions |
USMajor |
eastus, eastus2, centralus, westus, westus2 | Top 5 US regions by usage |
Europe |
westeurope, northeurope, uksouth, francecentral, germanywestcentral | European regions |
AsiaPacific |
eastasia, southeastasia, japaneast, australiaeast, koreacentral | Asia-Pacific regions |
Global |
eastus, westeurope, southeastasia, australiaeast, brazilsouth | Global distribution |
USGov |
usgovvirginia, usgovtexas, usgovarizona | Azure Government (auto-sets environment) |
China |
chinaeast, chinanorth, chinaeast2, chinanorth2 | Azure China / Mooncake (auto-sets env) |
ASR-EastWest |
eastus, westus2 | Azure Site Recovery DR pair |
ASR-CentralUS |
centralus, eastus2 | Azure Site Recovery DR pair |
Sovereign Clouds Note:
USGovandChinapresets are hardcoded becauseGet-AzLocationonly returns regions for the cloud you're logged into (commercial Azure won't show government regions)USGovautomatically sets-Environment AzureUSGovernment- you still need credentials for that environmentChinaautomatically sets-Environment AzureChinaCloud(Mooncake) - you still need credentials for that environment- Azure Germany (AzureGermanCloud) was deprecated in October 2021 and is no longer available
- There is no separate "European Government" cloud; EU data residency is handled via standard Azure regions with compliance certifications (e.g., France Central, Germany West Central)
# Quick US East/West scan
.\Get-AzVMAvailability.ps1 -RegionPreset USEastWest -NoPrompt
# Top 5 US regions
.\Get-AzVMAvailability.ps1 -RegionPreset USMajor -NoPrompt
# DR planning for Azure Site Recovery
.\Get-AzVMAvailability.ps1 -RegionPreset ASR-EastWest -FamilyFilter "D","E" -ShowPricing
# European regions with export
.\Get-AzVMAvailability.ps1 -RegionPreset Europe -AutoExport
# Azure Government (environment auto-detected)
.\Get-AzVMAvailability.ps1 -RegionPreset USGov -NoPrompt
# Azure China / Mooncake (environment auto-detected)
.\Get-AzVMAvailability.ps1 -RegionPreset China -NoPromptNote: Maximum 5 regions per scan for optimal performance and readability. Presets are limited accordingly. Lifecycle modes (
-LifecycleRecommendations,-LifecycleScan) are exempt — all deployed regions are scanned automatically.
You can still specify regions manually for custom scenarios:
| Scenario | Region Parameter |
|---|---|
| Custom regions | -Region "eastus","westus2","centralus" |
| Single region | -Region "eastus" |
The script can verify which VM SKUs are compatible with specific Azure Marketplace images, checking Generation (Gen1/Gen2) and Architecture (x64/ARM64) requirements.
Run the script without -NoPrompt and without -ImageURN:
.\Get-AzVMAvailability.ps1 -Region eastus -EnableDrillDownWhen prompted "Check SKU compatibility with a specific VM image?", answer y, then you'll see options:
Select image (1-16, custom, search, or Enter to skip): search
Type search and enter keywords like:
ubuntu- finds Ubuntu imagesdsvmordata science- finds Data Science VMswindows- finds Windows Server imagesrhel- finds Red Hat imagesmariner- finds Azure Linux (CBL-Mariner)
The script queries Azure Marketplace and shows matching publishers/offers, then lets you drill down to pick a specific SKU.
The interactive prompt shows 16 pre-defined common images organized by category:
| Category | Images |
|---|---|
| Linux | Ubuntu 22.04/24.04, RHEL 9, Debian 12, Azure Linux |
| Windows | Server 2022, Server 2019, Windows 11 |
| Data Science | DSVM Ubuntu/Windows, Azure ML Workstation |
| HPC | Ubuntu HPC, AlmaLinux HPC |
| Gen1 Legacy | Ubuntu 22.04 Gen1, Windows Server 2022 Gen1 |
Just type 1-16 to pick one directly, or type custom to enter a full URN manually.
If you already know the image URN, pass it directly:
# Check ARM64 compatibility for Ubuntu ARM64 image
.\Get-AzVMAvailability.ps1 `
-Region "eastus","westus2" `
-ImageURN "Canonical:0001-com-ubuntu-server-jammy:22_04-lts-arm64:latest" `
-SkuFilter "Standard_D*ps*"
# Check Gen2 compatibility for Windows Server 2022
.\Get-AzVMAvailability.ps1 `
-Region "eastus" `
-ImageURN "MicrosoftWindowsServer:WindowsServer:2022-datacenter-g2:latest" `
-EnableDrillDownUse -SkuFilter with wildcards to find specific VM types compatible with your image:
# Find all ARM64-compatible D-series SKUs for ARM64 Ubuntu
.\Get-AzVMAvailability.ps1 `
-Region "eastus" `
-SkuFilter "Standard_D*ps*" `
-ImageURN "Canonical:0001-com-ubuntu-server-jammy:22_04-lts-arm64:latest"Check SKU compatibility with a specific VM image? (y/N): y
COMMON VM IMAGES:
-------------------------------------------------------------------------------------
# Image Name Gen Arch Category
-------------------------------------------------------------------------------------
1 Ubuntu 22.04 LTS (Gen2) Gen2 x64 Linux
2 Ubuntu 24.04 LTS (Gen2) Gen2 x64 Linux
3 Ubuntu 22.04 ARM64 Gen2 ARM64 Linux
...
16 Windows Server 2022 (Gen1) Gen1 x64 Gen1
-------------------------------------------------------------------------------------
Or type: 'custom' for manual URN | 'search' to browse Azure Marketplace | Enter to skip
Select image (1-16, custom, search, or Enter to skip): search
Enter search term (e.g., 'ubuntu', 'data science', 'windows', 'dsvm'): data science
Searching Azure Marketplace...
Results matching 'data science':
1. [Offer ] microsoft-dsvm > ubuntu-2204
2. [Offer ] microsoft-dsvm > dsvm-win-2022
Select (1-2) or Enter to skip: 1
...
Selected: microsoft-dsvm:ubuntu-2204:2204-gen2:latest
When an image is specified, the drill-down view shows additional columns:
| Column | Description |
|---|---|
| Gen | SKU's supported generations (1, 2, or 1,2) |
| Arch | SKU's CPU architecture (x64 or Arm64) |
| Img | Compatibility: ✓ (compatible) or ✗ (incompatible) |
SKUs that are available but incompatible with your image are shown in dark yellow to help you quickly identify the issue.
====================================================================================
GET-AZVMAVAILABILITY v1.14.0
====================================================================================
SKU Filter: Standard_D2s_v5 | Pricing: Enabled
REGION: eastus
====================================================================================
SKU FAMILIES:
Family SKUs OK Largest Zones Status Quota $/Hr $/Mo
------------------------------------------------------------------------------------
D 1 0 2vCPU/8GB ⚠ Zones 1,2,3 LIMITED 100 $0.10 $70
====================================================================================
MULTI-REGION CAPACITY MATRIX
====================================================================================
Family | eastus | eastus2
------------------------------------------------------------------------------------
D | ⚠ LIMITED | ✓ OK
With -ShowPricing, the script automatically detects the best pricing source:
-
First, tries negotiated pricing (EA/MCA/CSP)
- Uses Azure Cost Management API
- Requires Billing Reader or Cost Management Reader role
- Shows your actual discounted rates
-
Falls back to retail pricing if negotiated rates unavailable
- Uses the public Azure Retail Prices API
- No special permissions required
- Shows Linux pay-as-you-go rates
Note: You'll see which pricing source is being used in the console output.
- Color-coded status cells (green/yellow/red)
- Filterable columns with auto-filter
- Alternating row colors
- Azure-blue header styling
| Icon | Status | Description |
|---|---|---|
| ✓ | OK | Full capacity available |
| ⚠ | CAPACITY-CONSTRAINED | Limited in some zones |
| ⚠ | LIMITED | Subscription-level restriction |
| ⚡ | PARTIAL | Mixed zone availability |
| ✗ | RESTRICTED | Not available |
This repo includes a Copilot skill that teaches AI coding agents (VS Code Copilot, Claude, Copilot CLI) how to invoke Get-AzVMAvailability for live capacity scanning. The skill provides routing logic, parameter mapping, and JSON output schema documentation so agents can translate natural language requests into the correct CLI invocations.
Skill file: .github/skills/azure-vm-availability/SKILL.md
| User says | Agent runs |
|---|---|
| "Where can I deploy NC-series GPUs?" | .\Get-AzVMAvailability.ps1 -NoPrompt -FamilyFilter "NC","ND","NV" -RegionPreset USMajor -JsonOutput |
| "E64pds_v6 is constrained, find alternatives" | .\Get-AzVMAvailability.ps1 -NoPrompt -Recommend "Standard_E64pds_v6" -Region "eastus","westus2" -JsonOutput |
| "Check placement scores for D4s_v5" | .\Get-AzVMAvailability.ps1 -NoPrompt -Recommend "Standard_D4s_v5" -Region "eastus" -ShowPlacement -JsonOutput |
This skill is already referenced in .github/copilot-instructions.md and loads automatically when you open this repo in VS Code with GitHub Copilot enabled.
To use it in other repositories, copy the skill to your local skills directory and reference it in that repo's Copilot instructions:
# Windows
Copy-Item -Recurse ".github\skills\azure-vm-availability" "$env:USERPROFILE\.agents\skills\azure-vm-availability"
# macOS/Linux
cp -r .github/skills/azure-vm-availability ~/.agents/skills/azure-vm-availabilityContributions are welcome! Please see CONTRIBUTING.md for guidelines.
See ROADMAP.md for planned features including:
- Azure Resource Graph integration for VM inventory
- HTML reports and trend tracking
- PowerShell module for PSGallery distribution
This project is licensed under the MIT License - see LICENSE for details.
Zachary Luz — Personal project (not an official Microsoft product)
This tool queries only public Azure APIs (SKU availability, quota, retail pricing) against your own Azure subscriptions. It reads subscription metadata (such as subscription IDs/names, regions, quotas, and usage) and writes results locally (console output and CSV/XLSX exports); it does not transmit this data off your machine except as required to call Azure APIs.
- Issues & PRs: Welcome! Please do not include subscription IDs, tenant IDs, internal URLs, or any confidential information.
- Azure support: For Azure platform issues or outages, contact Azure Support — not this repository.
- Exported files: Review CSV/XLSX exports before sharing externally — they may contain subscription IDs, region information, quotas, and usage details for your environment.
See CHANGELOG.md for version history.
If Windows warns that the script came from the internet, unblock it once:
Unblock-File .\Get-AzVMAvailability.ps1If you see an error like The property 'AzureEndpoints' cannot be found on this object, you are likely running an older script copy.
Select-String -Path .\Get-AzVMAvailability.ps1 -Pattern 'AzureEndpoints\s*=\s*\$null'No match indicates the file is stale. Download the latest Get-AzVMAvailability.ps1 from the repository and re-run.
PowerShell 5.1 is not supported. The script now warns and exits early if launched in 5.1.
Use PowerShell 7+ (pwsh):
pwsh -File .\Get-AzVMAvailability.ps1