Using the SharePoint Online REST API, I'm trying to retrieve a list of all sites and subsites.

This API gives me all top level sites, but no subsites:


Either of these APIs gives me all sub-sites of the root top level site:



I'd like a single query which retrieves all sites and all of their subsites -- not just subsites of the root site.


Now I've had time to come back to this, as suggested by @Gautam Sheth I've tried this:

   ?querytext='contentclass:STS_Site contentclass:STS_Web'

It's not quite working though. In a site structured like so, only the checked (✅) sites and subsites are being returned in the response:

  • ✅ Example Inc - Team Site (the default root site)
    • ✅ Subsite of Example Inc - Team Site
      • Nested subsite of Subsite of Example Inc - Team Site
      • Nested subsite #2 of Subsite of Example Inc - Team Site
    • Subsite #2 of Example Inc - Team Site
    • Subsite #3 of Example Inc - Team Site
  • ✅ David's Test Site (another top level site)
    • Subsite of David's Test Site
  • 3
    To be clear, this will not retrieve all sites, only the ones the current user has access to see. Event tenant admins will not have access to all sites by default, unless you put them there. Commented Nov 16, 2017 at 14:47
  • 1
    Agreed. Also, I only want the sites that the current user has access to. 👍
    – dvdsmpsn
    Commented Nov 16, 2017 at 14:48

3 Answers 3


You need to use STS_Site and STS_Web both in your queryText.

Your REST API endpoint should be as below:

querytext='contentclass:STS_Site contentclass:STS_Web'

Am able to get deep subsites as well using the above endpoint . Check the below screenshot which shows the deep subsite.

enter image description here

  • hey @dvdsmpsn, did you try this REST api endpoint ? if it worked for you, could you please mark it as answer ? Commented Nov 18, 2017 at 13:22
  • Unfortunately, this still didn't give me a list of all sites & subsites 😟 - I've updated the question with my new findings though
    – dvdsmpsn
    Commented Jul 24, 2018 at 13:38
  • Run this code with Site Collection admin rights and then run it with normal user rights. It could be that the user doesnt have the rights on the deeper subsite because permissions or inheritance were broken. Are you able to view these sites via UI using that user ? Commented Jul 24, 2018 at 14:23
  • Besides that ensure that the site is indeed allowed to indexed. Go to Site Settings > Search and offline availability and ensure that Allow this site to appear in search results value is set to Yes. Commented Jul 24, 2018 at 14:26
  • Thanks for the updates. I am actually running these searches as the site admin, right now. All the sites and subsites have been created by this user, and have "Allow this site to appear in search results?" set to Yes
    – dvdsmpsn
    Commented Jul 24, 2018 at 15:39

✅ If you just want to get a list of site & subsite URLs, you can cheat slightly.

Instead of looking for the sites or subsites, look for a /path/to/newsfeed.aspx entry instead. This appears to be present for all sites and subsites.

Here's the URL:


The ParentLink property contains the base URL for the site/sub-site.

While this is correct, it just feels like the wrong way of doing things.

This method also does not return the actual name of the site/sub-site, so is only a partial answer, but the best I can find right now.

If you can use the Microsoft Graph, it's much easier...


...will give all sites and subsites with their names 🙌

  • Hey this sort of answers my question over here: stackoverflow.com/questions/58029947/… Thanks!
    – fei0x
    Commented Sep 24, 2019 at 16:43
  • How would you write the Microsoft Graph line above using msGraphClientFactory? At the moment I'm using .api("sites") but that doesn't return anything. Commented Oct 6, 2023 at 10:12

You can use below code to achieve above functionality : Below code fetches Subsites of root site and their subsite mentioning their parents as well. Hope this solves your issue

//common Ajax call function which sends back the response call
function GETMethodAjaxCall(url, success) {
    type: "GET",
    contentType: "application/json",
    url: url,
    headers: {
        "Accept": "application/json; odata=verbose"
    dataType: "json",
    success: function(response) {
    error: function(err) {
$(document).ready(function() {

var url = _spPageContextInfo.webAbsoluteUrl + "/_api/Web/webs";

GETMethodAjaxCall(url, function(data) {
    $.each(data.d.results, function(index, value) {
        console.log("Site: " + value.Title + " " + "is Parent Site");

        GETMethodAjaxCall(value.Url + "/_api/Web/webs", function(data) {
            $.each(data.d.results, function(ind, val) {
                console.log("SubSite: " + val.Title + " " + "is child of " + value.Title);

  • Thanks for this. Unfortunately, I need a single API call to get these.
    – dvdsmpsn
    Commented Nov 15, 2017 at 17:00
  • your inner call shows only the last subsite. It does not show the rest? How can I show them in a master, child fashion? Commented Nov 15, 2018 at 12:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.