It might be useful from time to time, and depending on the business requirements, to create custom permissions in SharePoint.
Best practice would want to copy (or duplicate) a default permission already in SharePoint (and not modify any built-ins), and then add/remove whatever you don’t need.
In this blog post, we are going to use SharePoint PnP PowerShell to create custom permissions for multiple Sites in SharePoint Online.
Before…
For brand new sites, this is what we’ve got as built-in permissions under Site Permissions –> Permission Levels (in the ribbon):
- Full Control
- Design
- Edit
- Contribute
- Read

The Script
For this scenario (add more to the READ permission level), and because we’re going to be using a built-in permission level as the source, we’re going to clone it, and add other permissions to it.
Remember that we’d like to create this custom permission for multiple sites, therefore, we can use a .csv file containing our sites, and integrate it in the script.
For the PowerShell script, let’s explain the steps first.
- Connect to SharePoint Online Admin Center using the Connect-PnPOnline cmdlet (my credentials are stored in the Credential Manager so I’m not using the
-Credentialparameter) - Import the Sites contained in the csv file using the Import-Csv cmdlet
- Create a foreach loop, where we:
- Connect to each site in the csv file to access it
- Retrieve the “Read” permission level using the Get-PnPRoleDefinition cmdlet + store it in a variable
- Run the Add-PnPRoleDefinition cmdlet by using splatting (not necessary, but just a way for the code to be easier to read by other colleagues for instance!)
#Connect to SPO admin center
Connect-PnPOnline -Url https://<TENANT_NAME>-admin.sharepoint.com
#Import sites from .csv
$mySites = Import-Csv -Path '<YOUR_FILE_PATH_LOCATION>'
#Create all for each site
foreach ($site in $mySites) {
#Connect to each site
Write-Host "Connecting to $($site.SiteUrl)" -ForegroundColor Green
Connect-PnPOnline -Url $site.SiteUrl
#Create the NEW permission level (clone the 'READ' default permissions)
$PermToClone = Get-PnPRoleDefinition -Identity "Read"
$addPnPRoleDefinitionSplat = @{
Include = 'ManagePersonalViews', 'UpdatePersonalWebParts', 'AddDelPrivateWebParts'
Description = "Copy of Read + Personal Permissions"
RoleName = "myCustomPermLevel"
Clone = $PermToClone
}
Add-PnPRoleDefinition @addPnPRoleDefinitionSplat
After…
The results after running the script should look like the below on each site.


What else?
Well… You could also use this script and, at the same time…
- Create a new SharePoint group using the New-PnPGroup
- Set this custom permission to the newly created SharePoint group using Set-PnPGroupPermissions
- And finally, add members to this group using the Add-PnPUserToGroup
Thanks for reading! 🙂