A few days earlier, my manager asked me to send a report about who had permission (including external users) to access the files stored in the SharePoint library. This library has multiple levels of subfolders, so I need to make a report on the files present in those subfolders as well. To achieve this requirement, I used PnP PowerShell.
In this article, I will explain how to use PnP PowerShell to get permissions for each file in the SharePoint document library.
PnP PowerShell to Get SharePoint Library File Permissions And Export Them to CSV
Here is the Excel file generated after running the PnP PowerShell script, containing the permissions and URLs for each folder and file in the SharePoint document library, along with the users’ emails and the groups they belong to.

Run the PnP PowerShell script below and provide the site URL, list name, and the file path where the Excel file needs to be stored.
$SiteURL="https://<teanant name>.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-Library Permissions([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
Here:
- $SiteURL = Provide your SharePoint site URL.
- $ListName =Provide your SharePoint list or library name.
- $ReportFile = Provide the file path where the Excel file needs to be created.
- In the Connect-PnPOnline command for the -ClientId property, provide the client ID that you’ve registered in the Microsoft Entra ID.
Here, the Get-LibraryPermissions function retrieves the permissions for the specified SharePoint object, such as a list, library, list item, folder, or file, and returns the results.
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
$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
{
#Add the Data to Object
$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
}
- It first checks the object type and whether it is a list, list item, file, or folder, and stores its URLs into $ObjectURL.
- It also checks whether the object has unique permissions or inherited permissions.
- This function also iterates over each role assignment for the object, fetches the type of user or group, the assigned permission levels, and who granted the permission.
- Then, this function creates a list of permissions and exports them to an Excel file.
Then, the Generate-LibraryPermissionsReport() Function generates a permissions report for a SharePoint list, including item-level permissions.
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
}
}
Here,
- This function gets the inputs from the variables, $SiteURL, $ListName, $ReportFile, $ScanItemLevel, $IncludeInheritedPermissions.
- It calls the Get-PnPPermissions cmd to fetch permissions for the list.
- If we include -ScanItemLevel while calling this function, it will also retrieve permissions for each item in the list.
- It returns a permission report, including who has access to the library and its files and folders.
If (Test-Path $ReportFile) { Remove-Item $ReportFile }
In the provided file path, the output file is removed if it already exists.
Connect-PnPOnline -URL $SiteURL -ClientId 98979831-421-46wd-8e8b-35375d84-Interactive
This Connect-PnPOnline command will connect to the SharePoint site.
- -URL = Taking the site url
- -ClientId = Provide the client ID that you have registered in Microsoft Entra ID.
- -Interactive = It will ask you to provide credentials while the script is running.
Get-PnPWeb
This Get-PnPWeb command will return the current web object.
Generate-LibraryPermissionsReport -SiteURL $SiteURL -ListName $ListName -ReportFile $ReportFile -ScanItemLevel -IncludeInheritedPermissions
Here, we are calling the Generate-LibraryPermissionsReport function by providing the site URL, list name, and report file input values along with ScanItemLevel and IncludeInheritedPermissions properties.
Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
In the image below, you can see the error; I faced this when I tried to run the above PnP PowerShell script with the credentials of a person who doesn’t have SharePoint Administrator permissions.
Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))

So, in the Microsoft 365 admin center for that user, I assigned the SharePoint Administrator role. After some time, I ran the PowerShell script again; this time, the error was gone. This is because the user needs to have proper SharePoint permissions for fetching the permissions for items present in the SharePoint list or library.
To provide SharePoint Administrator access for the user, open the Microsoft 365 admin center -> Users -> Active users -> Choose user -> Click on Roles -> Admin center access -> Add SharePoint Administrator permissions -> Save changes.

I hope you understand the PnP PowerShell script above to retrieve permissions for files, folders, and list items in the SharePoint list/library. In this article, I also showed an error that might occur when running this script and how to resolve it.
Follow this article if you are also trying to fetch the SharePoint library files and list item permissions in Excel. While running this script, if you encounter any issues, please let me know in the comments below.
You can also have a look at the following PowerShell articles below:
- PowerShell unblock-file
- Create a Log File using PowerShell
- Add SharePoint List Fields From Excel Using PnP PowerShell
- Check If File Modified In Last 24 Hours Using PowerShell
- Create a Folder If Not Exists in PowerShell
- Create a File in PowerShell if it Doesn’t Exist

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.