30-second answer
Sites.Read.All, the application role published by Office 365 SharePoint
Online, was enough for every read below. Nine operations were tested against a
live tenant with an application identity that held that role and nothing else.
Two tenant-level reads were refused, and their minimum has not been
established.
What this proves
The identity was registered with no permissions at all, then given
Sites.Read.All (d13f72ca-a275-4b96-b789-48ebcc4da984) and nothing else.
Each operation ran in its own session against a real tenant.
| Operation | Permission tested | Result | Verified |
|---|---|---|---|
Get-PnPWeb | Sites.Read.All | succeeded | 18 Aug 2026 |
Get-PnPSite | Sites.Read.All | succeeded | 18 Aug 2026 |
Get-PnPList | Sites.Read.All | succeeded | 18 Aug 2026 |
Get-PnPListItem | Sites.Read.All | succeeded | 18 Aug 2026 |
Get-PnPSiteCollectionAdmin | Sites.Read.All | succeeded | 18 Aug 2026 |
Get-PnPFeature -Scope Web | Sites.Read.All | succeeded | 18 Aug 2026 |
Get-PnPPage | Sites.Read.All | succeeded | 18 Aug 2026 |
Get-PnPApp | Sites.Read.All | succeeded | 18 Aug 2026 |
Get-PnPCopilotAgent | Sites.Read.All | succeeded | 18 Aug 2026 |
Get-PnPTenantSite | Sites.Read.All | refused | 18 Aug 2026 |
Get-PnPTenant | Sites.Read.All | refused | 18 Aug 2026 |
Nine site-scoped reads need that one role and nothing more. That is a floor somebody measured, not a ceiling somebody copied out of documentation.
What it does not prove
It does not establish the minimum for the two refusals. The error is an
authorisation error, it is identical on the tenant administration host, and
connecting to https://<tenant>-admin.sharepoint.com does not change it. Which
role those two operations need has not been established, and this article
does not guess at one.
It also does not say that Sites.Read.All is narrow. It is broad: it grants
read access to every site collection in the organisation. That is uncomfortable
for a script that only needs one site, and it is what the model offers. The
SharePoint application roles are Sites.Read.All, Sites.Manage.All,
Sites.ReadWrite.All and Sites.FullControl.All, and none of them is narrower
than the first while still reading a site. It is the minimum available, not
the minimum imaginable.
There is a narrower model, Sites.Selected, where an administrator grants
an application access to named sites individually. It is a different mechanism
rather than a smaller version of the same one, and it was not part of this
test. If your script reads a fixed, known set of sites, it is the direction
worth investigating before accepting tenant-wide read.
PowerShell
Connect-PnPOnline -Url "https://<tenant>.sharepoint.com" `
-ClientId $appId -Tenant $tenantId -CertificatePath ./app.pfx
Get-PnPWeb # succeeds with Sites.Read.All alone
Get-PnPTenantSite # refused with Sites.Read.All aloneExample output
Attempted to perform an unauthorized operation.Explanation
Permissions read off documentation describe what an API is documented to require. They do not establish what your version of a module, against your tenant, actually needs. Starting from an identity with nothing and adding one role produces a different kind of answer.
It also surfaces the thing documentation never mentions. Connect-PnPOnline
succeeded here before any permission existed at all, which is covered
separately in Why Connect-PnPOnline succeeds when the next command is
refused.
Production considerations
- This is an application permission, consented once by an administrator, and it applies with no user present. It is not the same as the delegated permission of the same name, which is bounded by what the signed-in user can already see.
- Application-only through Entra ID needs a certificate on this path, not a client secret. See Certificate or client secret for PnP app-only.
- Grant it to a purpose-built identity. An application that reads every site in the organisation is worth naming, dating and reviewing.
Related governance rules
None directly. This establishes what an identity can read, which is a precondition for collecting evidence rather than a claim about a tenant.
References
- SharePoint application permissions (Microsoft, checked 18 August 2026)
- Granting access via Azure AD App-Only (Microsoft, checked 18 August 2026)
- Sites.Selected permission (Microsoft, checked 18 August 2026)
Found something wrong? Suggest a correction. The article source is not public; the engine it cites is.
What this answer underwrites
The engine reads these Microsoft operations to collect evidence, so what is established here is what those collectors rest on.
activitywhen a person last changed something on one siteagentsthe Copilot agents in one site, and the sources each declaresclassificationwhat a site records about the kind of content it holdsmodernityhow one site is built: template, branding, publishingownerswho administers one sitepermissionsevery visible list on a site, and its inheritancesharingwhat one site permits, and its default linksitesevery site this identity can enumeratespfxa site's app catalog: which solutions lag their version