Azure resource management

How to list the tags in use in Azure

List each tag name in use and how many resources carry it with Azure PowerShell and Resource Graph, browse Tags in the Azure portal, or run Altivane's Azure Tags report for a workbook.

By the Published

To list the tags in use in Azure, read the tags of every resource and resource group through Resource Graph and count each tag name and its values. Azure treats tag names without regard to case but keeps values as written, so Env and env are 1 tag, while Prod and prod are 2 values.

Choose the method that fits the job
MethodBest fit
PowerShellA CSV of each tag name with how many resources and groups carry it and its values.
Admin centreA quick look at the tags in use, and the resources that carry 1 of them.
AltivaneRecommended for regular tagging reviews, with the untagged resources listed beside the tags in use.

Before you start

Use an Azure account with read access to the subscriptions you want to check. The built-in Reader role is enough to run Resource Graph queries; assign it at each subscription or a scope above. The Microsoft references list no separate Resource Graph licence.

Know what the count covers. The script reads resources and resource groups; subscriptions can carry tags too and are left out, and management groups can't be tagged. It leaves out tag names that start with hidden-, as Microsoft's own sample does. Resource Graph is a near real-time index, so a tag added a moment ago may not show yet. The examples read Azure and export a CSV; they don't add, rename or remove any tag. The script's finally block disconnects the account and clears its saved Azure contexts.

Option 1

List the tags in use with PowerShell

Install the modules once, sign in, and query the subscriptions the account can read. The script reads every tagged resource and resource group, then counts each tag name and its different values.

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
    }
    $groupType = '"microsoft.resources/subscriptions/resourcegroups"'
    $queries = @(
        'Resources | where isnotempty(tags) | project id, tags | order by id asc'
        "ResourceContainers | where type =~ $groupType | where isnotempty(tags)" +
            ' | project id, tags | order by id asc'
    )
    $uses = [System.Collections.Generic.List[object]]::new()
    foreach ($query in $queries) {
        $skipToken = $null
        do {
            $arguments = @{ Query = $query; Subscription = $subscriptionIds; First = 1000 }
            if ($skipToken) { $arguments.SkipToken = $skipToken }
            $page = Search-AzGraph @arguments
            foreach ($row in $page.Data) {
                foreach ($tag in $row.tags.PSObject.Properties) {
                    if ($tag.Name -like 'hidden-*') { continue }
                    $uses.Add([pscustomobject]@{ Name = $tag.Name; Value = [string]$tag.Value })
                }
            }
            $skipToken = $page.SkipToken
        } while ($skipToken)
    }
    if ($uses.Count -eq 0) {
        Write-Output 'No resource or resource group in these subscriptions has a tag.'
        return
    }
    $report = @($uses | Group-Object Name | ForEach-Object {
        $values = @($_.Group | Group-Object Value -CaseSensitive | Sort-Object Count -Descending)
        [pscustomobject]@{
            Tag       = $_.Name
            Resources = $_.Count
            Values    = $values.Count
            Examples  = ($values | Select-Object -First 3 -ExpandProperty Name) -join ', '
        }
    } | Sort-Object Resources -Descending)
    $report | Export-Csv -Path './tags-in-use.csv' -NoTypeInformation -Encoding utf8
    Write-Output "$($report.Count) tag names saved to tags-in-use.csv."
} finally {
    Disconnect-AzAccount | Out-Null
}

The CSV has 1 row per tag name, the most used first: how many resources and resource groups carry it, how many different values it holds and the 3 values used most. Names are grouped without regard to case, as Azure treats them, and shown in the spelling found first; values keep their case. To include subscriptions, add a third query like the second, with the type microsoft.resources/subscriptions.

Option 2

Review the tags in use in the Azure portal

  1. Sign in to the Azure portal with an account that can read the subscriptions.
  2. Search for tags and choose Tags to see the tags in use.
  3. Select a tag to list the resources that carry it.
  4. For every name and value in 1 list, search for resource graph, choose Resource Graph Explorer, paste this read-only query in Query 1 and choose Run query:
    KQL
    ResourceContainers
    | where isnotempty(tags)
    | project tags
    | mv-expand tags
    | extend tagKey = tostring(bag_keys(tags)[0])
    | extend tagValue = tostring(tags[tagKey])
    | union (
        Resources
        | where isnotempty(tags)
        | project tags
        | mv-expand tags
        | extend tagKey = tostring(bag_keys(tags)[0])
        | extend tagValue = tostring(tags[tagKey])
    )
    | distinct tagKey, tagValue
    | where tagKey !startswith "hidden-"
  5. Choose Download as CSV to keep the pairs.

The query follows Microsoft's sample: it lists each name and value once, from subscriptions and resource groups as well as resources, but doesn't count them. It suits a quick look; for counts you can compare each month, use PowerShell or Altivane.

Common questions

Why does the portal show a tag name twice?

A tag with a large set of values comes back over more than 1 page, and the tag's name is repeated on the next page. Microsoft says this can make tools such as the Azure portal show the name twice; it's still 1 tag.

Do resources take the tags of their resource group?

No. Resources don't inherit the tags of their resource group or subscription; Azure Policy definitions for tags can copy them down. To find the resources with none, see how to find resources without tags in Azure.

Is there a limit to how many tags a resource can have?

Yes. Each resource, resource group and subscription can hold up to 50 name and value pairs. A name can be up to 512 characters and a value up to 256, and a storage account's names stop at 128. Tags are stored as plain text, so keep sensitive values out of them.

Microsoft references

Technical references checked on 7 November 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