To find unused public IP addresses in Azure, query Resource Graph for public IP resources with no IP configuration and no NAT gateway reference. Treat each result as a candidate to check, not proof that it can be removed: the index can lag and an address may be reserved for a planned service.
| 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
Use an Azure account with read access to every subscription you want to review. The built-in Reader role is enough for these read-only queries; assign it at the subscription or a parent scope. The PowerShell example uses Az.Accounts for sign-in and Az.ResourceGraph for queries. Microsoft does not list a separate licence for Azure Resource Graph.
Resource Graph is a near real-time index and is not strongly consistent with the resource provider. A newly attached address can briefly appear unattached. This query excludes an address with an IP configuration or a NAT gateway reference, but it does not decide whether a detached address is reserved for a future deployment. The query covers the selected subscriptions and follows Resource Graph continuation tokens after the first 1,000 results. The examples only read Azure and export a CSV; they do not change resources or release addresses. Their finally block disconnects the account and clears its local Azure contexts, so you may need to sign in again to use them.
Option 1
Find unused public IP addresses with PowerShell
Install the modules once, sign in and build a CSV from every result page. The resource ID is retained in each row so you can identify the exact address when you review it.
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.network/publicipaddresses"'
'| where isempty(properties.ipConfiguration)'
'| where isempty(properties.natGateway)'
'| project id, name, resourceGroup, subscriptionId, location,'
'address = tostring(properties.ipAddress), sku = tostring(sku.name),'
'allocation = tostring(properties.publicIPAllocationMethod)'
'| 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 unused public IP addresses were found.'
} else {
$rows | Select-Object name, resourceGroup, subscriptionId, location,
address, sku, allocation, id |
Export-Csv -Path './unused-public-ip-addresses.csv' -NoTypeInformation -Encoding utf8
Write-Output "$($rows.Count) address rows saved to unused-public-ip-addresses.csv."
}
} finally {
Disconnect-AzAccount | Out-Null
}The export includes the address value when Azure has assigned one, along with its SKU, allocation method and resource ID. An empty result prints a message and does not create a blank file. The two association filters are deliberate: remove neither unless you mean to include addresses that Azure records as connected.
The pagination helper keeps id in the result and requests another page only when Azure returns a continuation token. This avoids silently treating the first page as the full list when a tenant has more than 1,000 matches.
Option 2
Review public IP addresses in Azure Resource Graph Explorer
- Sign in to the Azure portal with an account that can read the target 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.network/publicipaddresses' | where isempty(properties.ipConfiguration) | where isempty(properties.natGateway) | project id, name, resourceGroup, subscriptionId, location, address = tostring(properties.ipAddress), sku = tostring(sku.name), allocation = tostring(properties.publicIPAllocationMethod) | order by id asc - Review the candidate addresses in Results.
Explorer is useful for a quick interactive check in a subscription. PowerShell is better when you need a repeatable CSV export or must collect pages beyond the first response. Neither result determines whether an address is safe to release; confirm its owner and intended use first.
Option 3 ยท Recommended for recurring reviews
Review unused Azure addresses with Altivane
- Open Altivane and choose the tenant.
- Run the Azure Unused Resources report.
- Open the Excel workbook and read the Unused public IP addresses table for address, allocation method and resource ID.
Altivane reads every subscription the tenant's certificate can read in 1 run and writes an Excel workbook to keep. If a subscription could not be read, the result is marked partial rather than shown as an empty list. Use the report to find candidates, then verify an address in Azure before releasing it.
Contact usCommon questions
Does an unused address have no cost?
This result shows association state, not billing. Check current Azure pricing and billing details for the address before deciding whether to release it.
Why is an address missing from the results?
The query deliberately excludes addresses with an IP configuration or a NAT gateway reference. It also only searches subscriptions selected in the query scope. Check the scope and the address's current associations in Azure if you expected it to appear.
How do I check for other unused Azure resources?
The same Altivane report includes unattached disks and empty resource groups. See how to find unattached Azure disks for a separate PowerShell query and review.
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
- Public IP addresses in Azure
- Choose a query strategy for Azure Resource Graph
- Azure built-in roles: Reader