Managing permissions in a SharePoint Online document library can become difficult when the library contains multiple folders, subfolders, files, and unique permission assignments. A permissions report helps administrators identify who has access to each folder or file, which permission level they have, and whether the permission is inherited or assigned directly.
In this tutorial, you will learn how to use PnP PowerShell to get SharePoint folder permissions, file permissions, and list item permissions. The script exports the results to a CSV file that you can open in Microsoft Excel for review, auditing, or compliance reporting.
The report includes:
- Folder, file, list item, or library name
- Direct URL to the SharePoint object
- Whether the object has unique permissions
- User or SharePoint group name
- Email address
- Principal type
- Assigned permission levels
- Whether access was granted directly or through a SharePoint group
Prerequisites
Before running the script, make sure you have completed the following requirements:
- Install the latest PnP PowerShell module.
- Register a Microsoft Entra ID application and copy its client ID.
- Ensure that the signed-in account has sufficient access to read permissions from the target SharePoint site, library, folders, and files.
- Create a local folder to the CSV permissions report. Note: The output file is a CSV file. You can open it directly in Microsoft Excel after the script finishes.
PnP PowerShell Script to Get SharePoint Folder Permissions
The following PnP PowerShell script retrieves permissions from a SharePoint document library. It can scan the library itself and, when enabled, every folder, subfolder, file, and list item in that library.
Keep the script unchanged and update the configuration values at the beginning.
$SiteURL="https://.sharepoint.com/sites/RetailManagementSite"
$ListName = "Employee Satisfaction Survey PDF Files"
$ReportFile="D:\Temp Folder\Employee Satisfaction Survey PDF Files.csv"
If (Test-Path $ReportFile) {
Remove-Item $ReportFile
}
Function Get-LibraryPermissions([Microsoft.SharePoint.Client.SecurableObject] $Object) {
Switch($Object.TypedObject.ToString()) {
"Microsoft.SharePoint.Client.ListItem" {
If($Object.FileSystemObjectType -eq "Folder") {
$ObjectType = "Folder"
#Get the URL of the Folder
$Folder = Get-PnPProperty -ClientObject $Object -Property Folder
$ObjectTitle = $Object.Folder.Name
$ObjectURL = ("{0}{1}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''),$Object.Folder.ServerRelativeUrl)
}
Else {
Get-PnPProperty -ClientObject $Object -Property File, ParentList
If($Object.File.Name -ne $Null) {
$ObjectType = "File"
$ObjectTitle = $Object.File.Name
$ObjectURL = ("{0}{1}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''),$Object.File.ServerRelativeUrl)
}
else {
$ObjectType = "List Item"
$ObjectTitle = $Object["Title"]
#Get the URL of the List Item
$DefaultDisplayFormUrl = Get-PnPProperty -ClientObject $Object.ParentList -Property DefaultDisplayFormUrl
$ObjectURL = ("{0}{1}?ID={2}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''), $DefaultDisplayFormUrl,$Object.ID)
}
}
}
Default {
$ObjectType = "List or Library"
$ObjectTitle = $Object.Title
#Get the URL of the List or Library
$RootFolder = Get-PnPProperty -ClientObject $Object -Property RootFolder
$ObjectURL = ("{0}{1}" -f $Web.Url.Replace($Web.ServerRelativeUrl,''), $RootFolder.ServerRelativeUrl)
}
}
Get-PnPProperty -ClientObject $Object -Property HasUniqueRoleAssignments, RoleAssignments
$HasUniquePermissions = $Object.HasUniqueRoleAssignments
$PermissionCollection = @()
Foreach($RoleAssignment in $Object.RoleAssignments) {
Get-PnPProperty -ClientObject $RoleAssignment -Property RoleDefinitionBindings, Member
$PermissionType = $RoleAssignment.Member.PrincipalType
$PermissionLevels = $RoleAssignment.RoleDefinitionBindings | Select -ExpandProperty Name
$PermissionLevels = ($PermissionLevels | Where { $_ -ne "Limited Access"}) -join ","
If($PermissionLevels.Length -eq 0) {
Continue
}
If($PermissionType -eq "SharePointGroup") {
$GroupMembers = Get-PnPGroupMember -Identity $RoleAssignment.Member.LoginName
If($GroupMembers.count -eq 0) {
Continue
}
$GroupUsers = ($GroupMembers | Select -ExpandProperty Title) -join "; "
$Permissions = New-Object PSObject
$Permissions | Add-Member NoteProperty Object($ObjectType)
$Permissions | Add-Member NoteProperty Title($ObjectTitle)
$Permissions | Add-Member NoteProperty URL($ObjectURL)
$Permissions | Add-Member NoteProperty HasUniquePermissions($HasUniquePermissions)
$Permissions | Add-Member NoteProperty Users($GroupUsers)
$Permissions | Add-Member NoteProperty Email($RoleAssignment.Member.Email)
$Permissions | Add-Member NoteProperty Type($PermissionType)
$Permissions | Add-Member NoteProperty Permissions($PermissionLevels)
$Permissions | Add-Member NoteProperty GrantedThrough("SharePoint Group: $($RoleAssignment.Member.LoginName)")
$PermissionCollection += $Permissions
}
Else {
$Permissions = New-Object PSObject
$Permissions | Add-Member NoteProperty Object($ObjectType)
$Permissions | Add-Member NoteProperty Title($ObjectTitle)
$Permissions | Add-Member NoteProperty URL($ObjectURL)
$Permissions | Add-Member NoteProperty HasUniquePermissions($HasUniquePermissions)
$Permissions | Add-Member NoteProperty Users($RoleAssignment.Member.Title)
$Permissions | Add-Member NoteProperty Email($RoleAssignment.Member.Email)
$Permissions | Add-Member NoteProperty Type($PermissionType)
$Permissions | Add-Member NoteProperty Permissions($PermissionLevels)
$Permissions | Add-Member NoteProperty GrantedThrough("Direct Permissions")
$PermissionCollection += $Permissions
}
}
$PermissionCollection | Export-CSV $ReportFile -NoTypeInformation -Append
}
Function Generate-LibraryPermissionsReport() {
[cmdletbinding()]
Param (
[Parameter(Mandatory=$false)]
[String] $SiteURL,
[Parameter(Mandatory=$false)]
[String] $ListName,
[Parameter(Mandatory=$false)]
[String] $ReportFile,
[Parameter(Mandatory=$false)]
[switch] $ScanItemLevel,
[Parameter(Mandatory=$false)]
[switch] $IncludeInheritedPermissions
)
Try {
Function Get-PnPListItemsPermission([Microsoft.SharePoint.Client.List]$List) {
Write-host -f Yellow "`t `t Getting Permissions of List Items in the List:"$List.Title
$ListItems = Get-PnPListItem -List $List -PageSize 500
$ItemCounter = 0
ForEach($ListItem in $ListItems) {
If($IncludeInheritedPermissions) {
Get-LibraryPermissions -Object $ListItem
}
Else {
$HasUniquePermissions = Get-PnPProperty -ClientObject $ListItem -Property HasUniqueRoleAssignments
If($HasUniquePermissions -eq $True) {
Get-LibraryPermissions -Object $ListItem
}
}
$ItemCounter++
Write-Progress -PercentComplete ($ItemCounter / ($List.ItemCount) * 100) `
-Activity "Processing Items $ItemCounter of $($List.ItemCount)" `
-Status "Searching Unique Permissions in List Items of '$($List.Title)'"
}
}
$List = Get-PnpList -Identity $ListName -Includes RoleAssignments
Write-host -f Yellow "Getting Permissions of the List '$ListName'..."
Get-LibraryPermissions -Object $List
If($ScanItemLevel) {
Get-PnPListItemsPermission -List $List
}
Write-host -f Green "`t List Permission Report Generated Successfully!"
}
Catch {
write-host -f Red "Error Generating List Permission Report!"
$_.Exception.Message
}
}
Connect-PnPOnline -URL $SiteURL -ClientId "Provide your client ID" -Interactive
$Web = Get-PnPWeb
Generate-LibraryPermissionsReport -SiteURL $SiteURL -ListName $ListName -ReportFile $ReportFile -ScanItemLevel
Update the Script Variables
Before you run the script, update these values with information from your SharePoint environment.
$SiteURL="https://.sharepoint.com/sites/RetailManagementSite"
$ListName = "Employee Satisfaction Survey PDF Files"
$ReportFile="D:\Temp Folder\Employee Satisfaction Survey PDF Files.csv"
- $SiteURL: Enter the URL of the SharePoint Online site that contains the target library.
- $ListName: Enter the display name of the SharePoint document library or list.
- $ReportFile: Enter the complete local path and file name for the CSV report.
For example:
$SiteURL = "https://contoso.sharepoint.com/sites/HR"
$ListName = "Employee Documents"
$ReportFile = "C:\Reports\SharePointFolderPermissions.csv"
If the report file already exists at the selected location, the script removes it before generating a new report.
If (Test-Path $ReportFile) {
Remove-Item $ReportFile
}
Add Your Microsoft Entra ID Client ID
Locate the following line in the script:
Connect-PnPOnline -URL $SiteURL -ClientId "Provide your client ID" -Interactive
Replace "Provide your client ID" with the application or client ID from your Microsoft Entra ID app registration.
Connect-PnPOnline -URL $SiteURL -ClientId "YOUR-CLIENT-ID" -Interactive
The -Interactive parameter opens the Microsoft sign-in window. Sign in with an account that has permission to access the SharePoint site and inspect the library permissions.
Run the SharePoint Permission Report Script
Save the script as a .ps1 file, such as:
Get-SharePoint-Folder-Permissions.ps1
Open PowerShell, navigate to the folder where you saved the script, and run it.
The script connects to your SharePoint Online site, retrieves permissions from the selected library, scans files and folders, and exports the details to the configured CSV file.
When the script completes successfully, you will see the following message:
List Permission Report Generated Successfully!
Open the generated CSV file in Microsoft Excel to review the SharePoint folder permissions and file permissions.
Understanding the Permission Report
The exported CSV report provides a detailed view of permission assignments across the selected SharePoint document library.

| Column | Description |
|---|---|
| Object | Identifies whether the entry is a library, folder, file, or list item |
| Title | Shows the name of the SharePoint object |
| URL | Provides a direct link to the folder, file, list item, or library |
| HasUniquePermissions | Shows whether the object has unique permissions instead of inheriting permissions |
| Users | Lists the user name or members of the assigned SharePoint group |
| Shows the email address associated with the assigned user or group | |
| Type | Identifies the principal type, such as a SharePoint group or user |
| Permissions | Displays assigned permission levels, such as Read, Edit, or Full Control |
| GrantedThrough | Shows whether access was assigned directly or through a SharePoint group |
This report is particularly useful for identifying folders and files with broken permission inheritance. You can also use it to detect unexpected direct permissions, external access, or users who have access through SharePoint groups.
How the Get-LibraryPermissions Function Works
The Get-LibraryPermissions function is responsible for retrieving permission information for a SharePoint object.
It works with the following SharePoint object types:
- SharePoint list or document library
- Folder
- File
- List item
The function first identifies the object type and retrieves its title and URL. It then checks whether the object has unique role assignments by reading the HasUniqueRoleAssignments property.
Get-PnPProperty -ClientObject $Object -Property HasUniqueRoleAssignments, RoleAssignments
If an object inherits permissions, the HasUniquePermissions value in the report is set to False. If permission inheritance has been broken and the object has its own assignments, the value is set to True.
The function then loops through each role assignment, retrieves the assigned permission levels, and excludes the Limited Access role from the report. This keeps the output focused on meaningful permissions such as Read, Edit, Contribute, Design, or Full Control.
For SharePoint groups, the script retrieves the group members and adds them to the report. For individual users, it records direct permissions and identifies them as Direct Permissions in the GrantedThrough column.
How the Generate-LibraryPermissionsReport Function Works
The Generate-LibraryPermissionsReport function controls the overall permission-reporting process.
It accepts the following parameters:
$SiteURL
$ListName
$ReportFile
$ScanItemLevel
$IncludeInheritedPermissions
The function first retrieves the selected SharePoint list or document library.
$List = Get-PnpList -Identity $ListName -Includes RoleAssignments
It then retrieves the library-level permissions by calling the Get-LibraryPermissions function.
Get-LibraryPermissions -Object $List
When you use the -ScanItemLevel switch, the script also scans every item in the library. This includes folders, subfolders, files, and list items.
Generate-LibraryPermissionsReport -SiteURL $SiteURL -ListName $ListName -ReportFile $ReportFile -ScanItemLevel
For large document libraries, scanning every item can take time because the script must inspect each folder and file individually. The progress bar in PowerShell shows the number of items processed during the scan.
Include Inherited Permissions
By default, the script focuses on items with unique permissions when scanning item-level permissions. This is helpful when you want to identify folders and files where inheritance has been broken.
To include inherited permissions in the report as well, run the command with the -IncludeInheritedPermissions switch.
Generate-LibraryPermissionsReport `
-SiteURL $SiteURL `
-ListName $ListName `
-ReportFile $ReportFile `
-ScanItemLevel `
-IncludeInheritedPermissions
Use this option when you need a complete SharePoint permission inventory. Keep in mind that the CSV file can become large when the document library contains many files and folders.
Access Denied Error in PnP PowerShell
While running the script, you may encounter the following error:
Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
You can see the exact error message in the screenshot below.

This error usually occurs when the account used to connect through Connect-PnPOnline does not have sufficient access to read permissions from the SharePoint site, document library, folders, or files.
To resolve the issue, sign in with an account that has the required permissions. In many tenant-wide administrative scenarios, assigning the SharePoint Administrator role to the account can resolve the error.
You can assign the SharePoint Administrator role from the Microsoft 365 admin center:
- Open the Microsoft 365 admin center.
- Select Users and then Active users.
- Choose the user account.
- Open the Roles section.
- Select Admin center access.
- Assign the SharePoint Administrator role.
- Save the changes.
Here is a screenshot for your reference.

After the role assignment has taken effect, run the PnP PowerShell script again.
Important Notes
- The account running the script must have access to the site and the objects being scanned.
- The script can retrieve permissions for document libraries as well as SharePoint lists.
- Use
-ScanItemLevelto include folders, subfolders, files, and list items. - Use
-IncludeInheritedPermissionswhen you need both unique and inherited permission assignments. - The report excludes
Limited Accesspermissions to make the output easier to review. - For very large libraries, run the report during off-peak hours and allow enough time for the scan to complete.
- Review the CSV file in Excel and filter the
HasUniquePermissionscolumn to quickly find files and folders with broken permission inheritance.
Conclusion
Using PnP PowerShell is an efficient way to audit SharePoint folder permissions, file permissions, and item-level permissions in a SharePoint Online document library. The script gives you an exportable CSV report that clearly shows users, groups, permission levels, direct assignments, inherited access, and unique permissions.
This approach is useful for SharePoint permission audits, compliance reviews, security assessments, migration planning, and routine administration of document libraries with complex folder structures.
You may also like the following tutorials:
- Add More Than 5000 Items to a SharePoint Online List Using PnP PowerShell
- Create Document Library in SharePoint Using PnP PowerShell (With Multiple Folders)
- Delete All Items from a SharePoint List Using PnP PowerShell
- Enable Sensitivity Labels For Microsoft 365 Groups & SharePoint Sites Using PowerShell

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.