Azure resource management

How to find unused public IP addresses in Azure

Find unused public IP addresses with Azure PowerShell, review them in Azure Resource Graph Explorer, or run Altivane's Azure Unused Resources report for a workbook.

By the Published Updated

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.

Choose the method that fits the job
MethodBest fit
PowerShellA repeatable, sortable CSV across selected subscriptions.
Admin centreA quick review in Azure Resource Graph Explorer without installing tools.
AltivaneRecommended 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.

PowerShell
Install-Module -Name Az.Accounts, Az.ResourceGraph -Repository PSGallery -Scope CurrentUser
PowerShell
$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

  1. Sign in to the Azure portal with an account that can read the target subscriptions.
  2. Search for resource graph > choose Resource Graph Explorer.
  3. To change its scope, choose Directory, then choose the directory, management group or subscription to query.
  4. Paste this read-only query in Query 1 and choose Run query:
    KQL
    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
  5. 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.

Common 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.

Talk to us about Altivane

Questions, or pricing? Get in touch.

Contact us