Live training: next batches coming soon. Join the waitlist:Waitlists open:Developer Training →Developer →Copilot Studio Training →Copilot Studio →

How to Get Microsoft 365 Group Members Using PowerShell (PnP, Graph and Exchange)

To get M365 group members in PowerShell, connect with PnP PowerShell and run Get-PnPMicrosoft365GroupMember with the group name. One line gives you every member’s name and sign-in address:

Get-PnPMicrosoft365GroupMember -Identity "Marketing Team" |
    Select-Object DisplayName, UserPrincipalName

It returns the group’s direct members as user objects, so you can sort, filter or export them like any other PowerShell output.

In this tutorial, we’ll build the get M365 group members PowerShell scripts I actually use: members and owners with PnP, the same with Microsoft Graph and Get-UnifiedGroupLinks, a CSV export of every group, adding members, and finding which groups a user belongs to.

What do you need before you run these commands?

For PnP you need PowerShell 7 and the PnP.PowerShell module. If it isn’t on your machine yet, follow installing PnP PowerShell for SharePoint Online first.

Connect to any SharePoint site in the tenant. The group cmdlets talk to Microsoft Graph, so the site you pick doesn’t matter:

# Your own Entra ID app registration (Connect-PnPOnline needs a client ID)
Connect-PnPOnline -Url "https://spguides.sharepoint.com/sites/SPGuides" `
    -ClientId "00000000-0000-0000-0000-000000000000" -Interactive

Your app needs the Graph permission Group.Read.All to read groups and members. If PowerShell says the cmdlet isn’t recognized, see how to fix Connect-PnPOnline is not recognized.

The old AzureAD module (Get-AzureADGroupMember) is retired, so don’t build new scripts on it. Use PnP, Microsoft Graph PowerShell or Exchange Online instead.

Get Microsoft 365 group members with Get-PnPMicrosoft365GroupMember

I created a demo group called SPGDemo Marketing Team with four members. Here’s the script that looks the group up and lists them:

$group = Get-PnPMicrosoft365Group -Identity "SPGDemo Marketing Team"

$members = Get-PnPMicrosoft365GroupMember -Identity $group.Id
$members | Select-Object DisplayName, UserPrincipalName, UserType |
    Sort-Object DisplayName | Format-Table -AutoSize

"Members in $($group.DisplayName): $($members.Count)"
Get-PnPMicrosoft365GroupMember listing four members of a Microsoft 365 group in PowerShell 7

All four came back with UserType Member. Guests show Guest here instead, which is handy when you audit external access.

-Identity takes the group ID, the display name or the mail nickname. I pass $group.Id because two groups can share a display name, but an ID is always unique.

How do I get the owners of a Microsoft 365 group?

Owners are a separate list. A user can be an owner without being a member, so don’t assume the member list includes them:

Get-PnPMicrosoft365GroupOwner -Identity "SPGDemo Marketing Team" |
    Select-Object DisplayName, UserPrincipalName

# Or get the group and its owners in one call
Get-PnPMicrosoft365Group -Identity "SPGDemo Marketing Team" -IncludeOwners |
    Select-Object DisplayName, Mail, Visibility, CreatedDateTime,
        @{ Name = "Owners"; Expression = { $_.Owners.DisplayName -join ", " } }
Get-PnPMicrosoft365GroupOwner and Get-PnPMicrosoft365Group -IncludeOwners showing the group owner

Miller is the only owner, and the group is Private. Group owners also own the connected SharePoint site; getting the SharePoint site owner with PowerShell covers that side.

Get group members with Microsoft Graph PowerShell (Get-MgGroupMember)

If your scripts already use the Microsoft Graph PowerShell SDK, you don’t need PnP at all. First find the group’s ID with Get-MgGroup, then read its members:

Connect-MgGraph -Scopes "GroupMember.Read.All"

$group = Get-MgGroup -Filter "displayName eq 'Marketing Team'"

# Members typed as users, so DisplayName and UserPrincipalName are filled in
Get-MgGroupMemberAsUser -GroupId $group.Id -All |
    Select-Object DisplayName, UserPrincipalName

# Get-MgGroupMember returns every member type (users, devices, groups) as IDs
Get-MgGroupMember -GroupId $group.Id -All |
    Select-Object Id, @{ Name = "Name"; Expression = { $_.AdditionalProperties.displayName } }

# Owners
Get-MgGroupOwner -GroupId $group.Id -All |
    Select-Object @{ Name = "Owner"; Expression = { $_.AdditionalProperties.userPrincipalName } }

Get-MgGroupMember returns directory objects, so the name sits in AdditionalProperties. Get-MgGroupMemberAsUser skips that step for users. Add -All, or you only get the first page.

Building an app rather than a script? Power Apps reads the same member list through a connector; see getting Office 365 group members in Power Apps.

Get-UnifiedGroup members with Get-UnifiedGroupLinks (Exchange Online)

Exchange admins usually reach for Get-UnifiedGroupLinks. It needs the ExchangeOnlineManagement module and an Exchange Online connection:

Connect-ExchangeOnline -UserPrincipalName admin@spguides.onmicrosoft.com

# Members (default ResultSize is 1000, so ask for all)
Get-UnifiedGroupLinks -Identity "Marketing Team" -LinkType Members -ResultSize Unlimited |
    Select-Object DisplayName, PrimarySmtpAddress

# Owners
Get-UnifiedGroupLinks -Identity "Marketing Team" -LinkType Owners

-LinkType is required and takes Members, Owners or Subscribers. Watch the default -ResultSize of 1000: a bigger group gets cut off silently unless you pass Unlimited.

Export all Microsoft 365 group members to CSV

For an audit, I loop through every group and write one row per member. Here’s the PnP version:

$groups = Get-PnPMicrosoft365Group

$rows = foreach ($group in $groups) {
    foreach ($member in Get-PnPMicrosoft365GroupMember -Identity $group.Id) {
        [PSCustomObject]@{
            GroupName   = $group.DisplayName
            GroupEmail  = $group.Mail
            MemberName  = $member.DisplayName
            MemberEmail = $member.UserPrincipalName
            UserType    = $member.UserType
        }
    }
}
$rows | Export-Csv -Path ".\M365GroupMembers.csv" -NoTypeInformation -Encoding UTF8
PowerShell exporting all Microsoft 365 group members to a CSV file with PnP PowerShell

In my tenant it wrote 394 rows from 121 groups in one run. The check at the end filters the file to the two SPGDemo groups, so you can confirm the columns before you open it in Excel.

Prefer Exchange Online? This version gives the same file from Get-UnifiedGroup:

Get-UnifiedGroup -ResultSize Unlimited | ForEach-Object {
    $group = $_
    Get-UnifiedGroupLinks -Identity $group.Identity -LinkType Members -ResultSize Unlimited |
        Select-Object @{ Name = "GroupName"; Expression = { $group.DisplayName } },
            DisplayName, PrimarySmtpAddress, RecipientType
} | Export-Csv -Path ".\M365GroupMembers.csv" -NoTypeInformation -Encoding UTF8

Both scripts make one call per group, so a large tenant takes a few minutes. For site-level permissions instead, see getting SharePoint site members with PowerShell.

Add members to an Office 365 group with PowerShell

Add-PnPMicrosoft365GroupMember takes one or more UPNs in -Users. I added Daniel to the demo Sales group:

Add-PnPMicrosoft365GroupMember -Identity "SPGDemo Sales Team" `
    -Users "daniel@spguides.onmicrosoft.com"
Add-PnPMicrosoft365GroupMember adding a user to a Microsoft 365 group, member count from 2 to 3

The group went from 2 to 3 members right away. This cmdlet needs Group.ReadWrite.All, not just read access.

The Graph and Exchange equivalents look like this:

# Microsoft Graph PowerShell (scope GroupMember.ReadWrite.All)
$user = Get-MgUser -UserId "alex@spguides.onmicrosoft.com"
New-MgGroupMember -GroupId $group.Id -DirectoryObjectId $user.Id

# Exchange Online: add as member first, then as owner if needed
Add-UnifiedGroupLinks -Identity "Marketing Team" -LinkType Members `
    -Links "alex@spguides.onmicrosoft.com", "adele@spguides.onmicrosoft.com"

With Add-UnifiedGroupLinks, a user must be a member before you can make them an owner. Guests can never be owners.

Once the membership is right, the group is a clean way to give access, for example by sharing a canvas app with a Microsoft 365 group.

How do I find which groups a user belongs to?

PnP has no reverse lookup, so this script checks each group’s members for one user:

$user = "mike@spguides.onmicrosoft.com"

$myGroups = foreach ($group in Get-PnPMicrosoft365Group) {
    $members = Get-PnPMicrosoft365GroupMember -Identity $group.Id
    if ($members.UserPrincipalName -contains $user) {
        [PSCustomObject]@{ Group = $group.DisplayName; Visibility = $group.Visibility }
    }
}
$myGroups | Sort-Object Group | Format-Table -AutoSize
PowerShell script listing the Microsoft 365 groups a user is a member of

Mike turned up in 3 groups: one public training group and the two private SPGDemo groups. In Power Apps you’d do this check in a formula instead, as shown in checking group membership in Power Apps.

With Microsoft Graph it’s a single call, because the user object knows its own memberships:

Get-MgUserMemberOfAsGroup -UserId "mike@spguides.onmicrosoft.com" -All |
    Where-Object { $_.GroupTypes -contains "Unified" } |
    Select-Object DisplayName, Mail

The Unified filter keeps Microsoft 365 groups and drops security groups. Like the member list, it shows direct memberships only.

Common errors and gotchas

One surprise I hit while testing: -IncludeSiteUrl failed on the demo group with a 403, even though I’m a tenant admin:

Get-PnPMicrosoft365Group -IncludeSiteUrl returning Forbidden (403) Access denied

The same switch worked on a group I belong to. Drop it, or read the site URL from the admin side as shown in getting all SharePoint Online sites with PnP PowerShell.

  • Nested groups are missing: all three methods return direct members only. Expand a member group yourself if your tenant nests groups.
  • Only 1,000 members came back: add -ResultSize Unlimited to Get-UnifiedGroupLinks, or -All to the Graph cmdlets.
  • Insufficient privileges: reading needs Group.Read.All (or GroupMember.Read.All); adding needs a ReadWrite scope.
  • Add-UnifiedGroupLinks fails in an unattended script: Exchange can’t change group members over certificate-based app-only auth. Use Graph there.

Working on more Microsoft 365 group tasks? These guides pick up from here:

Frequently Asked Questions

How do I get members of a Microsoft 365 group in PowerShell?

Connect with Connect-PnPOnline and run Get-PnPMicrosoft365GroupMember -Identity “Group name”. With Microsoft Graph PowerShell, use Get-MgGroupMemberAsUser -GroupId -All; with Exchange Online, use Get-UnifiedGroupLinks -LinkType Members.

What is Get-UnifiedGroupLinks used for?

It lists the members, owners or subscribers of a Microsoft 365 group in Exchange Online. -LinkType is required, and -ResultSize defaults to 1000, so add Unlimited for big groups. See the Get-UnifiedGroupLinks reference.

How do I export Office 365 group members to CSV?

Loop through Get-PnPMicrosoft365Group (or Get-UnifiedGroup -ResultSize Unlimited), get each group’s members, build one object per member with the group name, and pipe the result to Export-Csv -NoTypeInformation.

Does Get-MgGroupMember return nested group members?

No. Microsoft documents it as direct members only, and it returns users, devices, contacts and groups as directory objects. The Get-MgGroupMember reference lists the permissions.

How do I add a user to an Office 365 group with PowerShell?

Run Add-PnPMicrosoft365GroupMember -Identity “Group name” -Users user@domain.com. Graph uses New-MgGroupMember -GroupId -DirectoryObjectId, and Exchange uses Add-UnifiedGroupLinks -LinkType Members -Links.