A manager asks who can open the SPGuides site, and the Site permissions panel shows three group names instead of people. Click into Members and you find a Microsoft 365 group, not a list of names.
In this tutorial, we’ll build the get SharePoint site members PowerShell scripts our team runs before a permissions review. Every PnP command below ran read-only on our SPGuides site; real names are covered in the screenshots.
Quick answer: Connect with Connect-PnPOnline, then run Get-PnPGroupMember -Group (Get-PnPGroup -AssociatedMemberGroup), or the Owner/Visitor switches. On a group-connected site those groups only hold the Microsoft 365 group, so run Get-PnPMicrosoft365GroupMember for the people. Get-PnPUser lists the User Information List, including people who lost access.
What You Need Before You Start
- PnP PowerShell 3.x in PowerShell 7.4 or later; see our guide to install PnP PowerShell.
- Your own Entra ID app registration, because Connect-PnPOnline now needs a
-ClientId. Give it GraphGroup.Read.Allfor the Microsoft 365 group cmdlets. - Site owner or site collection admin rights on the site.
Connect-PnPOnline -Url "https://spguides.sharepoint.com/sites/SPGuides" `
-ClientId "00000000-0000-0000-0000-000000000000" -Interactive # your Entra ID app's client ID
Step 1: List the SharePoint Groups on the Site
Get-PnPGroup lists the groups. We hide the system SharingLinks and Limited Access groups, then use the three switches that return the default groups the SharePoint site owner sees under Site permissions.
Get-PnPGroup |
Where-Object { $_.Title -notlike "SharingLinks*" -and $_.Title -notlike "Limited Access*" } |
Select-Object Id, Title, OwnerTitle | Format-Table -AutoSize
"Owners group: " + (Get-PnPGroup -AssociatedOwnerGroup).Title
"Members group: " + (Get-PnPGroup -AssociatedMemberGroup).Title
"Visitors group: " + (Get-PnPGroup -AssociatedVisitorGroup).Title

Our site returned 11 groups, 7 after the filter.
Step 2: Get Owners, Members and Visitors with Get-PnPGroupMember
$groups = [ordered]@{
Owners = Get-PnPGroup -AssociatedOwnerGroup
Members = Get-PnPGroup -AssociatedMemberGroup
Visitors = Get-PnPGroup -AssociatedVisitorGroup
}
foreach ($role in $groups.Keys) {
"--- $role ($($groups[$role].Title))"
$people = Get-PnPGroupMember -Group $groups[$role]
if (-not $people) { " (no members)"; continue }
$people | Select-Object Title, PrincipalType, LoginName | Format-Table -AutoSize | Out-String -Width 130
}

On our group-connected site, Members held one SecurityGroup entry whose login starts with c:0o.c|federateddirectoryclaimprovider| plus the Microsoft 365 group ID. Owners held the same claim with an _o suffix, plus System Account, and Visitors was empty. To check one person, add -User "emily.carter@spguides.onmicrosoft.com".
Step 3: Expand Microsoft 365 Group Members
On a group-connected site, the group’s owners are site owners and its members are site members. For more ways to read them, see how to get Microsoft 365 group members using PowerShell.
$site = Get-PnPSite -Includes GroupId
"Microsoft 365 group ID: $($site.GroupId)"
Get-PnPMicrosoft365GroupOwner -Identity $site.GroupId |
Select-Object DisplayName, UserPrincipalName | Format-Table -AutoSize
Get-PnPMicrosoft365GroupMember -Identity $site.GroupId |
Select-Object DisplayName, UserPrincipalName, UserType | Format-Table -AutoSize

Our group had 4 owners and 5 members. Pull both lists; owners aren’t always members. Add Where-Object UserType -eq "Guest" to find external people.
Step 4: Compare Get-PnPUser with Real Site Access
Get-PnPUser doesn’t return site members. It reads the User Information List, which keeps everyone ever added, even after their access is removed. -WithRightsAssigned keeps only entries that still have rights:
$everyone = Get-PnPUser # every entry in the User Information List
$withAccess = Get-PnPUser -WithRightsAssigned # only entries that have access right now
"User Information List entries: $($everyone.Count)"
"Entries with access right now: $($withAccess.Count)"
$withAccess | Select-Object Id, Title, PrincipalType | Format-Table -AutoSize

Our site had 18 entries but only 5 with access: two users from other SharePoint groups, the two Microsoft 365 group claims and System Account. For a per-permission view, see checking site permissions in SharePoint Online.
Step 5: Export SharePoint Site Members to CSV
One row per person, with Microsoft 365 group claims expanded:
$groupId = (Get-PnPSite -Includes GroupId).GroupId
$roles = [ordered]@{
Owner = Get-PnPGroup -AssociatedOwnerGroup
Member = Get-PnPGroup -AssociatedMemberGroup
Visitor = Get-PnPGroup -AssociatedVisitorGroup
}
$report = foreach ($role in $roles.Keys) {
$group = $roles[$role]
foreach ($m in Get-PnPGroupMember -Group $group) {
if ($m.LoginName -like "*federateddirectoryclaimprovider*") {
# Microsoft 365 group claim: expand it to the real people
$people = if ($m.LoginName -like "*_o") { Get-PnPMicrosoft365GroupOwner -Identity $groupId }
else { Get-PnPMicrosoft365GroupMember -Identity $groupId }
foreach ($p in $people) {
[pscustomobject]@{ Role = $role; Group = $group.Title; Name = $p.DisplayName
Email = $p.UserPrincipalName; Via = "Microsoft 365 group" }
}
}
elseif ($m.PrincipalType -eq "User" -and $m.LoginName -ne "SHAREPOINT\system") {
[pscustomobject]@{ Role = $role; Group = $group.Title; Name = $m.Title
Email = $m.Email; Via = "Direct" }
}
}
}
$report | Export-Csv -Path "C:\Reports\SPGuides-site-members.csv" -NoTypeInformation
"Rows exported: $($report.Count)"

Our run exported 9 rows: 4 owners and 5 members. If a group contains a plain Entra ID security group, expand it with Get-PnPEntraIDGroupMember -Identity <group> -Transitive.
Get-SPOUser and Get-SPOSiteGroup Equivalents
In the SharePoint Online Management Shell (shown as code, not run), you need SharePoint admin and site collection admin rights. Get-SPOUser stops at 500 accounts without -Limit All, and Get-SPOSiteGroup at 200 groups.
Connect-SPOService -Url "https://spguides-admin.sharepoint.com"
Get-SPOUser -Site "https://spguides.sharepoint.com/sites/SPGuides" -Group "SPGuides Members" -Limit All
Get-SPOSiteGroup -Site "https://spguides.sharepoint.com/sites/SPGuides" | Select-Object Title, Users, Roles
| Cmdlet | Returns |
|---|---|
Get-PnPGroupMember | Users and security groups in one SharePoint group |
Get-PnPMicrosoft365GroupMember / Owner | People in the connected Microsoft 365 group |
Get-PnPUser | Every User Information List entry, current or not |
Get-SPOUser / Get-SPOSiteGroup | Users, or groups with users and roles (SPO shell) |
Common Mistakes to Avoid
- Reporting Get-PnPUser as the member list: 18 entries on our site, but 5 actual people.
- Stopping at the group claim on group-connected sites instead of expanding it.
- Group membership hidden from non-members; see the fix for permission to view group membership.
Can You Get Members of All SharePoint Sites at Once?
Yes. Connect to the admin center, list sites as in getting all SharePoint sites with PnP PowerShell, then connect to each site and run the Step 5 loop. Add SharePoint Online site details using PowerShell for storage data.
Next Steps
Once you know who’s on the site, check what they can open with SharePoint folder permissions using PowerShell, or grab more audit scripts from our PnP PowerShell scripts for SharePoint developers.
We also keep these guides handy when we clean up site access:
Frequently Asked Questions
How do I get all members of a SharePoint Online site using PowerShell?
Run Get-PnPGroupMember for the groups returned by Get-PnPGroup -AssociatedOwnerGroup, -AssociatedMemberGroup and -AssociatedVisitorGroup. On a group-connected site, also run Get-PnPMicrosoft365GroupMember and Get-PnPMicrosoft365GroupOwner.
What is the difference between Get-PnPUser and Get-PnPGroupMember?
Get-PnPUser reads the User Information List, which keeps people whose access was removed. Get-PnPGroupMember returns current members of one group. See the Get-PnPUser reference.
How do I use Get-SPOUser to list SharePoint group members?
After Connect-SPOService, run Get-SPOUser -Site -Group “”. Add -Limit All, because the default is 500. See the Get-SPOUser documentation.
Why does Get-PnPGroupMember return a group instead of people?
On a site connected to a Microsoft 365 group, the Owners and Members groups contain the group as one SecurityGroup entry. Expand it with the Microsoft 365 group cmdlets.

Hey! I’m Bijay Kumar, founder of SPGuides.com and a Microsoft Business Applications MVP (Power Automate, Power Apps). I launched this site in 2020 because I truly enjoy working with SharePoint, Power Platform, and SharePoint Framework (SPFx), and wanted to share that passion through step-by-step tutorials, guides, and training videos. My mission is to help you learn these technologies so you can utilize SharePoint, enhance productivity, and potentially build business solutions along the way.