Find Over-Quota OneDrives and SharePoint Sites with PowerShell
To find every OneDrive or SharePoint Online site exceeding its allocated storage, run Get-SPOSite against your tenant and filter on StorageUsageCurrent versus StorageQuota. The scripts below cover OneDrive personal sites and SharePoint team/communication sites. Both work against any Microsoft 365 tenant with the SharePoint Online PowerShell module and a SharePoint Administrator account, with CSV export and a cross-reference to user account status at the end.
This audit is particularly relevant in the lead-up to Microsoft's OneDrive quota enforcement in July 2026 (MC1310684), where OneDrive users currently over their licensed quota will transition to read-only state during the rollout. The same scripts are useful for routine storage management - identifying which SharePoint sites are pushing tenant storage toward the cap.
Prerequisites
- Microsoft 365 tenant with SharePoint Online.
- PowerShell 5.1 or later (Windows) or PowerShell 7+ (any platform).
- The SharePoint Online Management Shell module. Install with
Install-Module -Name Microsoft.Online.SharePoint.PowerShell. - An account with the SharePoint Administrator role. Microsoft recommends using roles with the fewest permissions; Global Administrator is a highly privileged role that should be limited to emergency scenarios.
- For Step 5 (cross-referencing user account status), the Microsoft Graph PowerShell SDK:
Install-Module Microsoft.Graph.
Step 1: Connect to SharePoint Online
Connect-SPOService -Url https://<tenant>-admin.sharepoint.com
Replace <tenant> with your Microsoft 365 tenant name. Sign in with an account that holds the SharePoint Administrator role.
Step 2: Find OneDrive Accounts Over Their Licensed Quota
Get-SPOSite -IncludePersonalSite $true -Limit All |
Where-Object {
$_.Url -like "*-my.sharepoint.com/personal/*" -and
$_.StorageUsageCurrent -gt $_.StorageQuota
} |
Select-Object Url, Owner, StorageUsageCurrent, StorageQuota,
@{Name="OverByMB"; Expression={ $_.StorageUsageCurrent - $_.StorageQuota }} |
Sort-Object OverByMB -Descending
This enumerates every OneDrive personal site in the tenant, filters to those whose current usage exceeds the assigned quota, and sorts by how far over each one is.
StorageUsageCurrentandStorageQuotaare returned in MB. Divide by 1024 for GB.- The
OverByMBcalculated column surfaces the worst offenders first. -IncludePersonalSite $trueis required to enumerate OneDrives - they are not returned byGet-SPOSiteby default.- For very large tenants
Get-SPOSiteis slow. Allow several minutes per 10,000 personal sites.
Step 3: Find SharePoint Sites Approaching Their Quota
Get-SPOSite -Limit All |
Where-Object {
$_.StorageQuota -gt 0 -and
$_.StorageUsageCurrent -gt ($_.StorageQuota * 0.8)
} |
Select-Object Url, StorageUsageCurrent, StorageQuota,
@{Name="PercentUsed"; Expression={ [math]::Round(($_.StorageUsageCurrent / $_.StorageQuota) * 100, 1) }} |
Sort-Object PercentUsed -Descending
This returns SharePoint sites that have used more than 80% of their per-site quota. Adjust the 0.8 threshold to taste - 1.0 returns only fully-over sites; 0.5 returns anything past the halfway mark. The StorageQuota -gt 0 guard prevents a divide-by-zero on sites with no explicit quota set.
Per-site quota is set explicitly in the SharePoint admin centre or via PowerShell with Set-SPOSite -StorageQuota. If the tenant uses Storage Management set to "Automatic", sites can exceed their per-site quota as long as the tenant has headroom - in that case the per-site quota acts as a soft cap, not a hard cap.
Step 4: Export to CSV
For stakeholder conversations and helpdesk handoffs, export the results to CSV:
$over = Get-SPOSite -IncludePersonalSite $true -Limit All |
Where-Object {
$_.Url -like "*-my.sharepoint.com/personal/*" -and
$_.StorageUsageCurrent -gt $_.StorageQuota
} |
Select-Object Url, Owner, StorageUsageCurrent, StorageQuota,
@{Name="OverByMB"; Expression={ $_.StorageUsageCurrent - $_.StorageQuota }}
$over | Export-Csv -Path .\over-quota-onedrives.csv -NoTypeInformation
A clean spreadsheet for triage. Replace the OneDrive filter with the SharePoint version from Step 3 to export site-level data instead.
Step 5: Cross-Reference with User Account Status
The single largest cohort in most enterprise tenants is departed users whose OneDrives are still consuming space on active licences. Add user account status to the CSV:
Connect-MgGraph -Scopes "User.Read.All"
$over = Import-Csv .\over-quota-onedrives.csv
foreach ($row in $over) {
$upn = ($row.Url -split "/personal/")[1] -replace "_", "@"
$upn = $upn -replace "@(?=.*@)", "_" # restore underscores in the local part
$user = Get-MgUser -Filter "userPrincipalName eq '$upn'" `
-Property AccountEnabled, AssignedLicenses -ErrorAction SilentlyContinue
if ($user) {
$row | Add-Member -NotePropertyName AccountEnabled `
-NotePropertyValue $user.AccountEnabled -Force
$row | Add-Member -NotePropertyName LicenceCount `
-NotePropertyValue $user.AssignedLicenses.Count -Force
}
}
$over | Export-Csv -Path .\over-quota-onedrives-with-status.csv -NoTypeInformation
The output has two extra columns: whether the user account is enabled, and how many Microsoft 365 licences are currently assigned. Sort by AccountEnabled = False and LicenceCount > 0 to surface the departed users still holding licences open against their OneDrive data.
The UPN reconstruction from the OneDrive URL is approximate - it handles the standard john.smith_company_com to john.smith@company.com encoding, but edge cases (apostrophes, hyphens in domains, special characters) may need manual review.
What to Do Once You Have the List
The over-quota population usually splits three ways. Each has a different remediation path.
Departed users on active licences. The OneDrive should not be holding an active licence open. The standard pattern is to capture the data into a preservation store the customer controls and then release the licence. Chipmunk automates this for Microsoft 365 - OneDrive, Exchange mailbox, and Teams data is captured into the customer's own Azure Blob Storage and the licence is released. See Microsoft 365 departed user archiving for the broader pattern.
Admin-elevated quotas above the licence entitlement. These are the ones MC1310684 specifically targets. They usually need a stakeholder conversation - is the higher quota actually required, or is it a forgotten one-off from a migration years ago? See OneDrive quota enforcement July 2026 (MC1310684) for the full remediation pattern.
Genuine high-footprint active users. A small group of users whose storage need is real - large CAD assemblies, video, research datasets. The choice is between a licence upgrade and a workflow change (move bulk reference data into a SharePoint document library, Azure storage, or a dedicated file service). For SharePoint sites pushing tenant storage, Squirrel moves cold content into the customer's own Azure Blob Storage with stub files left in place across SharePoint, OneDrive sync, and Teams - the site stays live and the bytes leave SharePoint.
Frequently Asked Questions
How long does Get-SPOSite take on a large tenant?
For tenants under 10,000 users, the OneDrive scan typically completes within a few minutes. For tenants over 50,000 users, allow up to 30 minutes for -IncludePersonalSite $true -Limit All. The cmdlet pages through results internally and does not stream.
Do I need Global Administrator to run these scripts? No. The SharePoint Administrator role is sufficient. Microsoft documents Global Administrator as a highly privileged role to be limited to emergency scenarios.
Why are the storage values in MB?
Get-SPOSite returns StorageUsageCurrent and StorageQuota as integers in megabytes. Divide by 1024 for GB, or by 1024^2 for TB. The example scripts leave the values in MB for direct comparison and CSV clarity.
Can I run this against deleted OneDrives in the recycle bin?
No. Get-SPOSite returns active sites only. For deleted personal sites within the recycle bin retention window, use Get-SPODeletedSite -IncludePersonalSite $true.
Does this find Microsoft Teams sites and Communication sites?
Yes. Get-SPOSite -Limit All returns every SharePoint site in the tenant, including Microsoft 365 Group sites that back Teams, Communication sites, and classic sites. Filter by Template if you want to scope to a specific site type.
Where does Microsoft's official MC1310684 PnP script live?
Microsoft published a PnP PowerShell script inside the original Message Center post MC1310684 that identifies OneDrive users exceeding their licensed storage quota. The script in Step 2 above is a simpler Get-SPOSite equivalent that does not require the PnP module; either approach works.
Can I run this unattended on a schedule?
Yes. Register a certificate-based app in Entra ID with SharePoint Online application permissions, then connect with Connect-SPOService -Url <admin-url> -ClientId <appid> -Tenant <tenantid> -CertificateThumbprint <thumb>. For Microsoft Graph in Step 5, use Connect-MgGraph -ClientId <appid> -TenantId <tenantid> -CertificateThumbprint <thumb>.
What's the difference between StorageUsageCurrent and StorageQuotaWarningLevel?
StorageUsageCurrent is the current consumed storage in MB. StorageQuota is the hard cap in MB. StorageQuotaWarningLevel is the threshold at which SharePoint sends a warning email - typically set to 90% of the quota. For the MC1310684 audit, StorageUsageCurrent versus StorageQuota is what matters.
Related reading
- OneDrive quota enforcement July 2026 (MC1310684) - the change this audit is for.
- Microsoft 365 departed user archiving - the broader pattern for reclaiming licences.
- How to check SharePoint storage size - companion audit for tenant-level storage.
- SharePoint Online archiving - the complete enterprise guide - what to do once over-storage sites are identified.
- Microsoft 365 Backup vs Archive vs Retention vs Inactive Mailbox - the broader storage taxonomy.



