๐ Recipe ยท SharePoint & OneDrive
List All SharePoint Sites in a Microsoft 365 Tenant
Enumerate every SharePoint site collection in your tenant and export to CSV for governance, auditing, and cleanup planning
Complexity
Beginner
Impact
read-only + reporting + governance + safe
Context
Why This Matters
Knowing exactly which SharePoint sites exist in your tenant is the foundation of any governance, storage optimization, or security review. Over time, tenants accumulate sites from Teams creation, Project provisioning, one-off Communication sites, and legacy migrations โ most admins are surprised by how many sites actually exist.
Common scenarios where you need a full site inventory:
- Storage planning โ identifying which sites consume the most SharePoint quota
- Stale site cleanup โ finding sites that haven't been touched in 12+ months
- Security audits โ reviewing external sharing, permissions, and sensitive content per site
- Migration prep โ baselining before a tenant-to-tenant move or restructuring
- Compliance reporting โ producing an authoritative list for auditors
This recipe produces a CSV of every site with its display name, web URL, and site ID โ the starting point for every downstream governance task.
Expected Outcomes
- A complete list of all SharePoint site collections in the tenant
- CSV export (
sharepoint_sites_list.csv) with Display Name, Web URL, and Site ID columns - A count of total active sites for capacity and license planning
- A reusable baseline you can feed into follow-up recipes (usage reports, sharing audits, archival)
Risks & Considerations
Things to watch for
- Search-based enumeration has limits.
GET /sites?search=*returns sites indexed by SharePoint search and excludes the root site and some system sites. For a truly exhaustive list (including personal OneDrive sites), useGET /sites/getAllSites(beta) or SharePoint PnP PowerShell'sGet-PnPTenantSite. - Large tenants require pagination. Results are paged at ~200 sites. Always follow
@odata.nextLinkuntil it is absent. - OneDrive personal sites are technically site collections but are usually filtered out of governance inventories. If you need them, include
isPersonalSitefiltering. - Read-only operation. This recipe only enumerates โ it does not modify any site. Safe to run in production at any time.
- Data sensitivity. Site URLs can reveal project names, M&A codenames, and confidential initiatives. Treat the exported CSV as confidential.
Required Permissions
| Permission | Why It's Needed |
|---|---|
| Sites.Read.All | Required to enumerate all SharePoint site collections via Microsoft Graph |
| SharePoint Administrator (role) | Needed if using the SharePoint Admin Center GUI or SharePoint PnP PowerShell cmdlets |
The fastest way to get this done: just ask Dex. Copy the prompt below and paste it into your Dex conversation.
For IT Admins
Paste into Dex Pro
List SharePoint sites via the SharePoint Admin Center
- Sign in to https://admin.microsoft.com with a Global Administrator or SharePoint Administrator account.
- In the left navigation, expand . This opens the SharePoint Admin Center at
https://{tenant}-admin.sharepoint.com. - In the SharePoint Admin Center, select .
- The Active sites page lists every site collection in the tenant with columns for Site name, URL, Storage used, Primary admin, Hub, Template, Last activity, and Date created. Use the column chooser (gear icon) to show or hide fields.
- To filter, use the filter pane on the right (by template, hub, sensitivity label, etc.) or type in the search box at the top.
- To export the full list to CSV, click the Export button in the command bar. A file named
sites_{date}.csvwill be downloaded. - For deleted sites, switch to .
Tip: The Active sites view does not include personal OneDrive sites. For those, use or the Graph API approach below.
Enumerate sites with Microsoft Graph
Microsoft Graph exposes SharePoint sites under /sites. The fastest way to list every site indexed by search is with the search query parameter.
Single-page request
GET https://graph.microsoft.com/v1.0/sites?search=*&$select=displayName,webUrl,id
Authorization: Bearer {access_token}Example response
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites",
"@odata.nextLink": "https://graph.microsoft.com/v1.0/sites?search=*&$skiptoken=...",
"value": [
{
"id": "contoso.sharepoint.com,fd008f7d-...,314f0ec2-...",
"displayName": "Marketing Internal",
"webUrl": "https://contoso.sharepoint.com/sites/MarketingInternal"
}
]
}Pagination
When the response contains @odata.nextLink, issue a GET against that URL to retrieve the next page. Continue until @odata.nextLink is absent.
Alternative: complete enumeration (beta)
GET https://graph.microsoft.com/beta/sites/getAllSitesThis beta endpoint returns every site collection including those not surfaced by search, at the cost of higher latency on large tenants.
Required permission
Sites.Read.All(application or delegated)
Automate with PowerShell
You have two good options. The Microsoft Graph PowerShell SDK is modern and uses the same Graph endpoint as the API section. SharePoint PnP PowerShell (Get-PnPTenantSite) is the gold standard for exhaustive enumeration because it uses the SharePoint tenant admin endpoint and catches sites that Graph search misses.
Option A โ Microsoft Graph PowerShell SDK
# Install once
Install-Module Microsoft.Graph -Scope CurrentUser
# Connect with Sites.Read.All
Connect-MgGraph -Scopes "Sites.Read.All"
# List all sites (handles pagination automatically with -All)
$sites = Get-MgSite -Search "*" -All -Property displayName,webUrl,id
$sites | Select-Object displayName,webUrl,id |
Export-Csv -Path ".\sharepoint_sites_list.csv" -NoTypeInformationOption B โ SharePoint PnP PowerShell (most complete)
Install-Module PnP.PowerShell -Scope CurrentUser
Connect-PnPOnline -Url "https://{tenant}-admin.sharepoint.com" -Interactive
Get-PnPTenantSite | Select-Object Title,Url,Template,StorageUsageCurrent,LastContentModifiedDate |
Export-Csv -Path ".\sharepoint_sites_list.csv" -NoTypeInformationThe PnP approach additionally gives you storage, template, and last-modified data in the same call, which is why it's preferred for governance reports.
Next steps