To find unattached Azure disks, query Azure Resource Graph for managed disks whose state is Unattached and that have no managing virtual machine. The index can lag behind a recent change, and the result does not tell you whether a disk is a backup that should be kept.
| Method | Best fit |
|---|---|
| PowerShell | A repeatable, sortable CSV across selected subscriptions. |
| Admin centre | A quick review in Azure Resource Graph Explorer without installing tools. |
| Altivane | Recommended for recurring reviews across readable subscriptions, with report files to keep. |
Before you start
For PowerShell or Resource Graph Explorer, use an Azure account with read access to the subscriptions you want to review. The built-in Reader role provides that access; assign it at each subscription or a parent scope. The example connects interactively and uses the Az.Accounts and Az.ResourceGraph modules. The Microsoft references do not list a separate Resource Graph licence.
Azure Resource Graph is a near real-time index, not a strongly consistent copy of the resource provider. A recent attach or detach can take time to appear. The query covers managed disks in the selected subscriptions; it does not inventory unmanaged VHD files in storage accounts. It returns at most 1,000 rows per request and follows the continuation token for additional pages. The examples read Azure and export a CSV; they make no changes to Azure resources. Their finally block disconnects the account and clears its local Azure contexts, so you may need to sign in again to use them. Check the disk's purpose and current state before acting on a result.
Option 1
Find unattached Azure disks with PowerShell
Install the modules once, sign in, and query the subscriptions the account can read. The script retrieves every result page, including when the list is larger than the service's first response.
Install-Module -Name Az.Accounts, Az.ResourceGraph -Repository PSGallery -Scope CurrentUser$ErrorActionPreference = 'Stop'
Connect-AzAccount -ErrorAction Stop
try {
$subscriptionIds = @(
Get-AzSubscription |
Where-Object State -eq 'Enabled' |
Select-Object -ExpandProperty Id
)
if ($subscriptionIds.Count -eq 0) {
Write-Output 'No enabled subscriptions are available to this account.'
return
}
$query = @(
'Resources'
'| where type =~ "microsoft.compute/disks"'
'| where tostring(properties.diskState) =~ "Unattached"'
'| where isempty(managedBy)'
'| project id, name, resourceGroup, subscriptionId, location,'
'sizeGb = tolong(properties.diskSizeGB), sku = tostring(sku.name),'
'created = todatetime(properties.timeCreated)'
'| order by id asc'
) -join ' '
function Get-AzGraphRows {
param([string]$Query, [string[]]$SubscriptionIds)
$results = [System.Collections.Generic.List[object]]::new()
$skipToken = $null
do {
$arguments = @{
Query = $Query
Subscription = $SubscriptionIds
First = 1000
}
if ($skipToken) { $arguments.SkipToken = $skipToken }
$page = Search-AzGraph @arguments
foreach ($record in $page.Data) { $results.Add($record) }
$skipToken = $page.SkipToken
} while ($skipToken)
return $results.ToArray()
}
$rows = @(Get-AzGraphRows -Query $query -SubscriptionIds $subscriptionIds)
if ($rows.Count -eq 0) {
Write-Output 'No unattached managed disks were found.'
} else {
$rows | Select-Object name, resourceGroup, subscriptionId, location,
sizeGb, sku, created, id |
Export-Csv -Path './unattached-disks.csv' -NoTypeInformation -Encoding utf8
Write-Output "$($rows.Count) disk rows saved to unattached-disks.csv."
}
} finally {
Disconnect-AzAccount | Out-Null
}The CSV includes the disk name, subscription, resource group, location, size, SKU, creation time and resource ID. An empty result prints a message instead of creating an empty file. Change the type or state filters only if you intend to widen the search; this example deliberately includes managed disks in the Unattached state with no managedBy value.
Resource Graph pagination requires id in the projected results. Keep that column in the query if you edit it.
Option 2
Review unattached disks in Azure Resource Graph Explorer
- Sign in to the Azure portal with an account that can read the subscriptions.
- Search for resource graph > choose Resource Graph Explorer.
- To change its scope, choose Directory, then choose the directory, management group or subscription to query.
- Paste this read-only query in Query 1 and choose Run query:
Resources | where type =~ 'microsoft.compute/disks' | where tostring(properties.diskState) =~ 'Unattached' | where isempty(managedBy) | project id, name, resourceGroup, subscriptionId, location, sizeGb = tolong(properties.diskSizeGB), sku = tostring(sku.name), created = todatetime(properties.timeCreated) | order by id asc - Review the matching disks in Results.
This method suits an occasional check when you want to inspect results straight away. Use PowerShell for a repeatable CSV export and automatic retrieval of pages beyond the first 1,000 rows. A disk can be unattached on purpose, so confirm its owner and retention role before scheduling any cleanup.
Option 3 ยท Recommended for recurring reviews
Review unused Azure disks with Altivane
- Open Altivane and choose the tenant.
- Run the Azure Unused Resources report.
- Open the Excel workbook and read the Unattached disks table for the disk names, sizes and resource IDs.
Altivane reads every subscription it can in 1 run and writes an Excel workbook to keep. It marks the results partial when a subscription could not be read; an unread subscription is not treated as an empty one. Resource Graph can lag behind Azure's current state, so verify a disk in Azure before making a decision.
Contact usCommon questions
Does unattached mean safe to delete?
No. The query reports disks not attached to a virtual machine, but a disk may be an intentional backup or retained data. Confirm its owner, recovery purpose and current state with the resource provider before deleting it.
Why is a disk missing just after I detached it?
Resource Graph indexes changes asynchronously. Wait for the index to catch up, then run the query again. For a decision that depends on the disk's current state, check the disk directly in Azure rather than relying only on the index.
Does this include unused public IP addresses?
No. Those are a separate table in the same report. See how to find unused public IP addresses in Azure.
Microsoft references
Technical references checked on 7 October 2026. The example scripts have been reviewed and syntax checked; they have not been run against a live tenant.
- Install-Module cmdlet reference
- Connect-AzAccount cmdlet reference
- Get-AzSubscription cmdlet reference
- Disconnect-AzAccount cmdlet reference
- Run a Resource Graph query using Azure PowerShell
- Search-AzGraph cmdlet reference
- Run a Resource Graph query in the Azure portal
- Azure Resource Graph query language
- Azure Resource Graph overview
- Find unattached Azure managed and unmanaged disks
- Choose a query strategy for Azure Resource Graph
- Azure built-in roles: Reader