Enumerate all SharePoint Online site collections via the Graph API

In another article of the “this is now finally possible in Office 365”, here’s how to get a list of all SharePoint Online site collections (or “sites”, as Microsoft is confusingly calling them  lately) via a simple Graph API query:

GET https://graph.microsoft.com/v1.0/sites

OK, not so fast! There are some important details we need to discuss here, starting with authentication. You need to have an app with at least Sites.Read.All application permissions granted. I repeat, application permissions! Delegate permissions are not currently supported, as apparently it’s too challenging to trim the output to just the sites a given user can access!?

Graph SPO list sitesThe good news is that the method is available in /v1.0. As in, officially supported, GA, etc. Another good news is that it returns not only all the sites (collections) you will find listed under the SPO Admin Center, but also all personal ODFB sites. Which will come in handy for my “list all shared files” proof of concept script, which until now had to rely on workarounds in order to generate a list of all ODFB sites within the tenant. It does not however return “hidden” sites, such as those used by the redirect functionality, deleted ones, etc.

And of course, as with most things Graph, it’s not all good news. The set of properties returned for each site (collection) is minimal, and you cannot for example get useful information, such as which template is used. And while the lastModifiedDateTime property sounds like a useful one to report on, the value returned seems to always reflect the exact time you obtained the data. But hey, it’s a start.

Without further ado, here’s how a complete example looks like. Well, complete sans the authentication part, but here’s another reminder that you should be using the client credentials flow/application permissions model! Sample code below:

#List all sites, app-only context needed!
$uri = "https://graph.microsoft.com/v1.0/sites"
$Gr = Invoke-WebRequest -Headers $AuthHeader1 -Uri $uri -Verbose -Debug
$result = ($gr.Content | ConvertFrom-Json).Value
$result.count

61

So, a total of 61 site collections were returned for my tenant. We can group those by their type (not the same thing as template!), as follows:

$result | select @{n="Type";e={$_.siteCollection.hostname}} | group type -NoElement

Count Name
----- ----
12 michev-my.sharepoint.com
48 michev.sharepoint.com
1 michev-public.sharepoint.com

So, 12 out of these 61 site collections correspond to personal ODFB sites. We can filter out those directly via something like:

$result | ? {$_.siteCollection.Hostname -eq "michev-my.sharepoint.com"} | select name,webUrl,id

Unfortunately, we cannot filter out Group/Team sites, private channels and so on, as the output doesn’t feature any information on the template used.

Before finishing up, here’s another reminder that you must use application permissions to obtain the above! Here’s what the same call will result in when used with Graph explorer for example, even when running in the context of a Global admin user and having all delegate permissions granted:

Site collections cannot currently be enumerated via delegate permissionsNo Graph explorer for you!

/// UPDATE May 2023: To better support multi-geo scenarios, Microsoft added the /sites/getAllSites endpoint. As above, only usable via application permissions. More details here: https://learn.microsoft.com/en-us/graph/api/site-getallsites?view=graph-rest-1.0&tabs=http

1 thought on “Enumerate all SharePoint Online site collections via the Graph API

  1. Hardik Dobariya says:

    First of all a great article and this has helped us to resolve our fetching sites in an organization using application permission. However, we have a large number of sites available in an organization so calling the/sites API would not help as we have to page and get all the sites to search for a specific site. We came across/Sites?Search={query} API which resolved our concerns about searching the sites. To make sure we used /Site?Search=* to fetch all the sites and to our surprise, we are not getting ODFB sites in the searching API. We even tried using the keywords /Site?Search=test for ODFB site however we are still not able to get the ODFB sites. Please help us further on this as we want to only use /Sites?Search={query} API using application permission.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.