Every tenant I clean up for a client has the same leftovers: test sites from a pilot, a project site nobody opened in a year, and three copies of the same team site. Clicking through the admin center works for one site, but it’s slow, and it won’t permanently remove a group-connected site at all.
In this tutorial, we’ll delete a SharePoint site with PowerShell the safe way. Using a real throwaway site in my tenant, I’ll check it, delete it, find it in Deleted sites, restore it and purge it. You’ll also get the SharePoint Online Management Shell versions, group and hub site steps, and fixes for the errors that block a delete.
Quick answer: Connect to the admin center with Connect-PnPOnline, then run Remove-PnPTenantSite -Url https://spguides.sharepoint.com/sites/OldProject -Force. The site moves to Deleted sites for 93 days. To remove it for good, run Remove-PnPTenantDeletedSite -Identity <url> -Force. With the Management Shell, the same pair is Remove-SPOSite and Remove-SPODeletedSite.
How site deletion works in SharePoint Online
Deleting a site is a two-stage process. First the site moves from Active sites to Deleted sites, where SharePoint keeps it for 93 days. Only a second command, or the end of those 93 days, removes it permanently. If you’d rather click through it, my guide on deleting a SharePoint site from the admin center covers the browser steps.
| Task | PnP PowerShell | SharePoint Online Management Shell |
|---|---|---|
| Delete a site (to Deleted sites) | Remove-PnPTenantSite | Remove-SPOSite |
| List deleted sites | Get-PnPTenantDeletedSite | Get-SPODeletedSite |
| Restore a deleted site | Restore-PnPTenantSite | Restore-SPODeletedSite |
| Delete permanently | Remove-PnPTenantDeletedSite | Remove-SPODeletedSite |
Deleting a site removes everything in it: libraries, lists, pages, permissions and subsites. Tell the site owners before you run anything, so they can move what they still need.
Before you start: permissions and connection
You need the SharePoint Administrator role or higher. For Remove-SPOSite, Microsoft also says you must be a site collection admin on the site. I use PnP PowerShell in PowerShell 7 with my own Entra ID app registration; if it isn’t set up yet, follow installing PnP PowerShell for SharePoint Online first.
Connect to the admin center URL, not the site itself, because every cmdlet here works on tenant-level data. My post on connecting to SharePoint Online using PowerShell explains the sign-in options.
# Admin center URL + your own Entra ID app registration
$adminUrl = "https://spguides-admin.sharepoint.com"
$clientId = "00000000-0000-0000-0000-000000000000" # your app's client ID
Connect-PnPOnline -Url $adminUrl -ClientId $clientId -Interactive
For this walkthrough I created a throwaway communication site called SPGDemo Delete Test. Provisioning with -Wait took more than a minute and a half in my tenant:
New-PnPSite -Type CommunicationSite `
-Title "SPGDemo Delete Test" `
-Url "https://spguides.sharepoint.com/sites/SPGDemoDeleteTest" `
-Lcid 1033 `
-TimeZone UTCMINUS0500_EASTERN_TIME_US_AND_CANADA `
-Wait
Check the site before you delete it
I never delete a site blind. One Get-PnPTenantSite call tells me whether the site is connected to a Microsoft 365 group, is a hub, is attached to Teams, or is under a hold, and each of those changes how the delete works:
$siteUrl = "https://spguides.sharepoint.com/sites/SPGDemoDeleteTest"
Get-PnPTenantSite -Identity $siteUrl |
Select-Object Title, Url, Template, Status, GroupId, IsHubSite,
IsTeamsConnected, HasHolds, LockState |
Format-List

- GroupId of all zeros means there’s no Microsoft 365 group, so a plain delete is fine. Any other value means a group-connected team site (see the group section below).
- IsHubSite must be False. A hub has to be unregistered first.
- HasHolds True means a retention policy or eDiscovery hold covers the site, and the delete will fail.
- LockState Unlock is normal. NoAccess or ReadOnly means someone locked the site on purpose, so ask before you remove it.
To review many sites at once, start from getting all SharePoint Online sites using PnP PowerShell and export these same columns to a CSV file.
Delete a SharePoint site with Remove-PnPTenantSite
With the checks clean, the delete itself is one line. -Force skips the confirmation prompt, which is what you want in a script. Note that this cmdlet takes -Url, not -Identity:
# Moves the site to Deleted sites (restorable for 93 days)
Remove-PnPTenantSite -Url $siteUrl -Force

In my tenant the delete finished in 6 seconds, and the follow-up Get-PnPTenantSite call failed with “Cannot get site”, because the site is no longer active.
There’s also a -SkipRecycleBin switch that deletes the site without the Deleted sites stage. I only use it for fresh test sites, because there’s no undo:
# No Deleted sites stage - only for sites you're sure about
Remove-PnPTenantSite -Url $siteUrl -SkipRecycleBin -Force
Find the site in Deleted sites with Get-PnPTenantDeletedSite
Deleted sites sit in the tenant recycle bin, the same list you see under Sites > Deleted sites in the admin center. Get-PnPTenantDeletedSite reads it, and DaysRemaining tells you how long you still have to change your mind:
# One deleted site
Get-PnPTenantDeletedSite -Identity $siteUrl |
Select-Object Url, Status, DeletionTime, DaysRemaining
# Everything in Deleted sites, newest first
Get-PnPTenantDeletedSite |
Sort-Object DeletionTime -Descending |
Select-Object Url, DeletionTime, DaysRemaining

The status is Recycled, and DaysRemaining already read 92 a minute after the delete, so count on the full 93 days minus the day you’re in. This is a different bin from the one users empty inside a site; the SharePoint recycle bin guide explains both stages for files and lists.
Restore a deleted site with Restore-PnPTenantSite
Restoring brings the site back at the same URL with its content, permissions and settings intact:
Restore-PnPTenantSite -Identity $siteUrl -Force

The site was Active again with its original communication site template (SITEPAGEPUBLISHING#0). Some older blog posts call this cmdlet Restore-PnPTenantDeletedSite, but that name doesn’t exist in PnP.PowerShell 3.3.0; Restore-PnPTenantSite is the one to use.
Permanently delete a site with Remove-PnPTenantDeletedSite
You need a permanent delete in two cases: you want to reuse the URL for a new site, or policy says the content must be gone now. Both steps run back to back:
Remove-PnPTenantSite -Url $siteUrl -Force # step 1: to Deleted sites
Remove-PnPTenantDeletedSite -Identity $siteUrl -Force # step 2: gone for good

Both checks returned 0, so the site is in neither list. Microsoft notes that the URL can take up to 24 hours to become available again. Once it is, you can rebuild the site by creating a site in SharePoint Online using PnP PowerShell.
What is the PowerShell cmdlet to delete sites from the admin center recycle bin?
The admin center’s recycle bin for sites is the Deleted sites page. In PnP PowerShell the cmdlet that deletes sites from it is Remove-PnPTenantDeletedSite; in the SharePoint Online Management Shell it’s Remove-SPODeletedSite. Both remove a site permanently, and neither can be undone.
Start by looking at what’s in there. This listing is read-only:
# Everything in SharePoint admin center > Sites > Deleted sites
$deleted = @(Get-PnPTenantDeletedSite)
"Sites in Deleted sites: $($deleted.Count)"
# The ones closest to automatic permanent deletion first
$deleted | Sort-Object DaysRemaining, Url |
Select-Object -First 10 @{n = "Path"; e = { ([uri]$_.Url).AbsolutePath }},
Status, DeletionTime, DaysRemaining |
Format-Table -AutoSize

My tenant had 39 sites in Deleted sites. Three were at 0 days remaining, so SharePoint was about to remove them anyway, and the rest still had 31 days.
To empty the whole list, loop through it. Remove-PnPTenantDeletedSite has no -WhatIf switch, so this script is a dry run unless you add -Purge, and -Match lets you limit it to some URLs:
# Clear-DeletedSites.ps1 - run it connected to the admin center
param(
[string]$Match = "*", # "*" = every deleted site; "*/sites/SPGDemo*" limits the purge
[switch]$Purge # without -Purge the script only lists (dry run)
)
$deleted = @(Get-PnPTenantDeletedSite | Where-Object Url -like $Match)
"Matched $($deleted.Count) site(s) in Deleted sites"
foreach ($site in $deleted) {
if (-not $Purge) { "Would purge: $($site.Url)"; continue }
try {
Remove-PnPTenantDeletedSite -Identity $site.Url -Force -ErrorAction Stop
"Purged: $($site.Url)"
}
catch { Write-Warning "Failed: $($site.Url) - $($_.Exception.Message)" }
}
if ($Purge) { "Left in Deleted sites: $(@(Get-PnPTenantDeletedSite | Where-Object Url -like $Match).Count)" }
Run it once without -Purge, read the list, then run it again with it:
.\Clear-DeletedSites.ps1 -Match "*/sites/SPGDemo*" # dry run: lists only
.\Clear-DeletedSites.ps1 -Match "*/sites/SPGDemo*" -Purge # permanent, no undo

I only purged a throwaway site I’d created for this test. The dry run matched 1 site, the -Purge run removed it, and the check at the end found 0 left. With the default -Match "*", the same script empties every deleted site.
With the Management Shell, Remove-SPODeletedSite supports -WhatIf, so the preview is built in. -Limit ALL matters, because Get-SPODeletedSite returns only 200 sites by default:
# SharePoint Online Management Shell: preview every purge first
Get-SPODeletedSite -Limit ALL | ForEach-Object {
Remove-SPODeletedSite -Identity $_.Url -WhatIf
}
# Happy with the list? Run it again without -WhatIf (-Confirm:$false skips the prompts)
Get-SPODeletedSite -Limit ALL | ForEach-Object {
Remove-SPODeletedSite -Identity $_.Url -Confirm:$false
}
Get-SPODeletedSite skips OneDrive sites unless you add -IncludePersonalSite. Microsoft also says you need to be a site collection admin of the deleted sites, on top of the SharePoint Administrator role. Purged sites free their URLs, so you can create new sites on them after up to 24 hours.
Delete a site with Remove-SPOSite and Remove-SPODeletedSite
If your scripts already use the SharePoint Online Management Shell, the same lifecycle uses the SPO cmdlets. They run in Windows PowerShell 5.1 and need an interactive admin sign-in. I’m showing them as verified code here, not a console run:
# SharePoint Online Management Shell (Windows PowerShell 5.1)
Connect-SPOService -Url "https://spguides-admin.sharepoint.com"
$siteUrl = "https://spguides.sharepoint.com/sites/ProjectAtlas"
# Move the site to Deleted sites (-WhatIf previews, -NoWait returns at once)
Remove-SPOSite -Identity $siteUrl -Confirm:$false
# See it in Deleted sites
Get-SPODeletedSite -Identity $siteUrl
# Undo: bring it back
Restore-SPODeletedSite -Identity $siteUrl
# Or remove it permanently (after Remove-SPOSite)
Remove-SPODeletedSite -Identity $siteUrl -Confirm:$false
- Remove-SPOSite never deletes permanently. It always sends the site to Deleted sites, and it has no switch to skip that stage.
- Remove-SPODeletedSite works only on a site that’s already in Deleted sites, so it always comes after Remove-SPOSite.
- -WhatIf works on both remove cmdlets and is worth running once on a production URL before the real delete.
A 403 error right after Connect-SPOService usually means the account lacks the admin role; see fixing Connect-SPOService (403) Forbidden.
Delete a group-connected team site
A group-connected team site belongs to its Microsoft 365 group. The clean way is to delete the group, which removes the site together with the shared mailbox, calendar, Planner plans and any connected team. You can list who’s in the group first with getting Microsoft 365 group members using PowerShell.
$siteUrl = "https://spguides.sharepoint.com/sites/Marketing"
# Find the Microsoft 365 group behind the site
$groupId = (Get-PnPTenantSite -Identity $siteUrl).GroupId
Get-PnPMicrosoft365Group -Identity $groupId | Select-Object DisplayName, Mail
# Deleting the group deletes the site, mailbox, calendar, Planner and team
Remove-PnPMicrosoft365Group -Identity $groupId
# Changed your mind within 30 days?
Restore-PnPDeletedMicrosoft365Group -Identity $groupId
Watch the timing. Microsoft keeps a deleted group for only 30 days, while the site stays in Deleted sites for 93. After 30 days, restoring the site alone won’t bring the mailbox or the team back.
Permanent removal of a group-connected site is PowerShell-only, because the admin center doesn’t offer it. Remove-SPODeletedSite or Remove-PnPTenantDeletedSite deletes just the site, not the group, so delete the group first.
Delete a hub site
A hub site can’t be deleted while it’s registered as a hub. Unregister it first, and the sites associated with it simply lose the shared navigation. If you’re unsure whether a site is a hub, my hub site vs subsite comparison explains the difference.
$hubUrl = "https://spguides.sharepoint.com/sites/SPGuidesHub"
# PnP PowerShell
Unregister-PnPHubSite -Site $hubUrl
Remove-PnPTenantSite -Url $hubUrl -Force
# SharePoint Online Management Shell
Unregister-SPOHubSite -Identity $hubUrl
Remove-SPOSite -Identity $hubUrl -Confirm:$false
Delete multiple SharePoint sites from a CSV file
For a cleanup project I list the URLs in a CSV file and run the loop with a dry-run switch first. The script skips hubs, sites on hold and group sites, so they get handled one at a time, and a single bad URL doesn’t stop the batch:
# sites.csv has one column: Url
$sites = Import-Csv -Path "C:\Scripts\sites-to-delete.csv"
$dryRun = $true # set to $false when the report looks right
foreach ($row in $sites) {
$site = try { Get-PnPTenantSite -Identity $row.Url -ErrorAction Stop } catch { $null }
if (-not $site) { Write-Warning "Not found: $($row.Url)"; continue }
if ($site.IsHubSite -or $site.HasHolds -or $site.GroupId -ne [guid]::Empty) {
Write-Warning "Skipped (hub, hold or group site): $($row.Url)"; continue
}
if ($dryRun) { "Would delete: $($row.Url)"; continue }
try {
Remove-PnPTenantSite -Url $row.Url -Force -ErrorAction Stop
"Deleted: $($row.Url)"
}
catch { Write-Warning "Failed: $($row.Url) - $($_.Exception.Message)" }
}
Check the “Would delete” lines with the site owners, then set $dryRun to $false. To confirm afterward that each URL is gone, use checking if a site exists in SharePoint Online.
Common errors and how to fix them
- The site can’t be deleted because of a retention policy or hold: Microsoft Purview blocks deleting a site that’s subject to retention. Remove the site from the policy or release the hold in Purview first, then wait for it to sync. See site retention policies in SharePoint for where these are set.
- Hub site error: unregister it with Unregister-PnPHubSite or Unregister-SPOHubSite, then delete.
- Access denied: your account needs the SharePoint Administrator role. For Remove-SPOSite, add yourself as a site collection admin, too.
- The URL is still in use after a delete: the site is only in Deleted sites. Permanently delete it and allow up to 24 hours.
- Deleting the root site: don’t. Every site becomes unreachable until it’s restored. Replace the root site in the admin center, then delete the old one from its new archive URL.
Cleaning up more than whole sites? These scripts handle the smaller pieces:
Frequently Asked Questions
How do I delete a SharePoint Online site using PowerShell?
Connect to the admin center with Connect-PnPOnline and run Remove-PnPTenantSite -Url -Force, or use Remove-SPOSite -Identity in the SharePoint Online Management Shell. Both move the site to Deleted sites, where you can restore it for 93 days.
What does Remove-SPODeletedSite do?
It permanently removes a site that’s already in Deleted sites, so it can’t be restored. Run Remove-SPOSite first. For a group-connected site it deletes only the site, not the group, as the Remove-SPODeletedSite documentation notes.
What is the difference between Remove-SPOSite and Remove-PnPTenantSite?
Both move a site to Deleted sites. Remove-SPOSite is in the SharePoint Online Management Shell and uses -Identity; Remove-PnPTenantSite is in PnP PowerShell, uses -Url and can skip the recycle bin with -SkipRecycleBin.
How long can I restore a deleted SharePoint site?
For 93 days, using Restore-PnPTenantSite or Restore-SPODeletedSite. For a group-connected site, the group and its mailbox are kept only 30 days. Microsoft’s Delete a site guide lists the options per site type.
How do I delete a SharePoint team site connected to a Microsoft 365 group?
Delete the Microsoft 365 group with Remove-PnPMicrosoft365Group, the Microsoft 365 admin center or the SharePoint admin center. That removes the site, mailbox, calendar and connected team together.

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.