Microsoft Entra ID governance

How to find empty groups in Microsoft Entra ID

List groups with no members with Microsoft Graph PowerShell, check a group's member count in the Entra admin centre, or use Altivane's Identity report for a rated list of empty groups.

By the Published

To find empty groups in Microsoft Entra ID, count each group's members and keep the groups where the count is 0. The count is of direct members, so a group whose only member is another group is not empty. An empty group can still be in use, named in a policy or assigned licences ready for people to join, so check before you delete it.

Choose the method that fits the job
MethodBest fit
PowerShellA tenant-wide CSV of every group with no members, with its type.
Admin centreChecking the members of a few groups you already suspect.
AltivaneRecommended for recurring clean-ups, with the share of empty groups rated against a threshold.

Before you start

Use an account with a role that can read groups and their members, such as Directory Readers, Groups Administrator or User Administrator. No extra licence is needed: group management is part of Microsoft Entra ID Free, which comes with Microsoft 365. The PowerShell example requests GroupMember.Read.All; your organisation may require administrator consent.

Know what the count covers. It counts users, devices, contacts and other groups that are direct members. The count is an advanced query that uses an index, which might not be up to date with very recent changes. The examples cover every kind of group: Microsoft 365, security, mail-enabled security and distribution. They read and export; they don't delete or change any group.

Option 1

Find empty groups with PowerShell

Install the modules once, then connect, count each group's members and export the groups with none.

PowerShell
# Install once, if the modules are not already installed.
Install-Module Microsoft.Graph.Authentication, Microsoft.Graph.Groups -Scope CurrentUser
PowerShell
$ErrorActionPreference = 'Stop'
Connect-MgGraph -Scopes 'GroupMember.Read.All' -NoWelcome
try {
    $properties = 'id', 'displayName', 'groupTypes', 'mailEnabled', 'securityEnabled',
        'onPremisesSyncEnabled', 'resourceProvisioningOptions', 'createdDateTime'
    $groups = @(Get-MgGroup -All -Property $properties)
    $report = @(foreach ($group in ($groups | Sort-Object DisplayName)) {
        # A member count is an advanced query: it needs ConsistencyLevel set to eventual.
        $count = Get-MgGroupMemberCount -GroupId $group.Id -ConsistencyLevel eventual
        if ($count -ne 0) { continue }
        $type = 'Security'
        if ($group.GroupTypes -contains 'Unified') { $type = 'Microsoft 365' }
        elseif ($group.MailEnabled -and $group.SecurityEnabled) { $type = 'Mail-enabled security' }
        elseif ($group.MailEnabled) { $type = 'Distribution' }
        [pscustomobject]@{
            Group   = $group.DisplayName
            Type    = $type
            Dynamic = $group.GroupTypes -contains 'DynamicMembership'
            Team    = $group.ResourceProvisioningOptions -contains 'Team'
            Synced  = $group.OnPremisesSyncEnabled -eq $true
            Created = $group.CreatedDateTime
            Id      = $group.Id
        }
    })
    if ($report.Count -eq 0) {
        Write-Output "All $($groups.Count) groups have at least 1 member."
    } else {
        $report | Export-Csv -Path './empty-groups.csv' -NoTypeInformation -Encoding utf8
        Write-Output "$($report.Count) of $($groups.Count) groups have no members."
    }
} finally {
    Disconnect-MgGraph | Out-Null
}

The script makes 1 request for each group, so a large tenant takes a while. It marks dynamic groups, whose members come from a rule, groups behind a team and groups synced from an on-premises directory, whose membership is managed there. Keep only Microsoft 365 and Security rows to leave out the groups Exchange manages.

Check a single group

Reconnect with Connect-MgGraph, then count 1 group's members. The main export above disconnects when it finishes.

PowerShell
# Run while connected to Microsoft Graph. Replace the example group name.
$group = @(Get-MgGroup -Filter "displayName eq 'Contoso Sales'")
if ($group.Count -ne 1) { throw "Found $($group.Count) groups with that name; use its ID." }
$count = Get-MgGroupMemberCount -GroupId $group[0].Id -ConsistencyLevel eventual
Write-Output "$($group[0].DisplayName) has $count direct members."

Option 2

Check group members in the admin centre

  1. Sign in to the Microsoft Entra admin centre for the correct tenant.
  2. Go to Entra ID > Groups > All groups.
  3. Search for a group and select it. Its Overview page shows how many members it has.
  4. Select Members to see who they are, then leave without adding or removing anyone.

This suits checking a few groups you already suspect. The admin centre shows member counts 1 group at a time, so to find every empty group in a tenant, use PowerShell or a report.

Common questions

Is an empty group safe to delete?

Not always. An empty group can still be named in a Conditional Access policy, given access to an app or assigned licences, ready for people to be added. Microsoft says a group's licences must be removed before the group is deleted. Check what refers to the group first, and ask its owner.

Why is a dynamic group empty?

Its membership rule matches no one at the moment. The members of a dynamic group come from its rule, so read the rule and the properties it tests rather than adding people manually.

How do I find groups with no owner?

Empty and ownerless are separate checks: a group can be either, both or neither. See how to find groups without owners.

Microsoft references

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