For SharePoint on-prem
If the search API is enabled for you, use this answer above: https://sharepoint.stackexchange.com/a/113625/60157
Otherwise...
Soap call - sites.asmx - GetContent
One sure-fire way to get the site collections on your system with REST calls is to make call Soap with your REST client.
You have to make 2+ soap calls to get the result.
C# Code Example:
public XmlDocument getContent(string siteUrl, String contentType, string contentId) {
List<string> allSites = new List<string>();
var _url = string.Format("{0}/_vti_bin/SiteData.asmx", siteUrl);
var _action = "http://schemas.microsoft.com/sharepoint/soap/GetContent";
XmlDocument soapEnvelopeXml = CreateSoapEnvelope(contentType, contentId);
HttpWebRequest webRequest = CreateWebRequest(_url, _action);
InsertSoapEnvelopeIntoWebRequest(soapEnvelopeXml, webRequest);
// begin async call to web request.
IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);
// suspend this thread until call is complete. You might want to
// do something usefull here like update your UI.
asyncResult.AsyncWaitHandle.WaitOne();
// get the response from the completed web request.
XmlDocument contentDatabaseResult = new XmlDocument();
using (WebResponse webResponse = webRequest.EndGetResponse(asyncResult)) {
using (StreamReader rd = new StreamReader(webResponse.GetResponseStream())) {
contentDatabaseResult.Load(rd);
}
}
return contentDatabaseResult;
}
public List<string> GetAllSiteCollections() {
List<String> allSites = new List<string>();
XmlDocument virtualServerGetContentResult = getContent(rootSite, "VirtualServer", null);
XmlNode contentResultNode = virtualServerGetContentResult.SelectSingleNode("//*[local-name() = 'GetContentResult']");
if (contentResultNode == null || contentResultNode.InnerText == null) {
throw new Exception(string.Format("Cannot list top level sites from {0}", rootSite));
}
XmlDocument innerXmlDoc = new XmlDocument();
innerXmlDoc.LoadXml(contentResultNode.InnerText);
string contentDatabaseId = innerXmlDoc.SelectSingleNode("//*[local-name() = 'ContentDatabase']").Attributes["ID"].Value;
if (contentDatabaseId == null) {
throw new Exception(string.Format("Cannot list top level sites from {0}", rootSite));
}
XmlDocument contentDatabaseGetContentResult = getContent(rootSite, "ContentDatabase", contentDatabaseId);
XmlNode contentDatabaseResultNode = contentDatabaseGetContentResult.SelectSingleNode("//*[local-name() = 'GetContentResult']");
if (contentDatabaseResultNode == null || contentDatabaseResultNode.InnerText == null) {
throw new Exception(string.Format("Cannot list top level sites from {0}", rootSite));
}
innerXmlDoc = new XmlDocument();
innerXmlDoc.LoadXml(contentDatabaseResultNode.InnerText);
XmlNodeList sites = innerXmlDoc.SelectNodes("//*[local-name() = 'Site']");
foreach (XmlNode siteNode in sites) {
allSites.Add(siteNode.Attributes["URL"].Value);
}
return allSites;
}
HttpWebRequest CreateWebRequest(string url, string action) {
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
webRequest.Headers.Add("SOAPAction", action);
webRequest.ContentType = "text/xml;charset=\"utf-8\"";
webRequest.Accept = "text/xml";
webRequest.Method = "POST";
webRequest.Credentials = credentialCache;
return webRequest;
}
XmlDocument CreateSoapEnvelope(string objectType, string objectId) {
XmlDocument soapEnvelopeDocument = new XmlDocument();
string soapEnv = @"<soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:soap=""http://schemas.microsoft.com/sharepoint/soap/"">
<soapenv:Header/>
<soapenv:Body>
<soap:GetContent>
<soap:objectType>{0}</soap:objectType>
{1}
<soap:retrieveChildItems>true</soap:retrieveChildItems>
<soap:securityOnly>false</soap:securityOnly>
</soap:GetContent>
</soapenv:Body>
</soapenv:Envelope>";
soapEnvelopeDocument.LoadXml(string.Format(soapEnv, objectType,
objectId == null ? "" : "<soap:objectId>" + objectId + "</soap:objectId>"));
return soapEnvelopeDocument;
}
void InsertSoapEnvelopeIntoWebRequest(XmlDocument soapEnvelopeXml, HttpWebRequest webRequest) {
using (Stream stream = webRequest.GetRequestStream()) {
soapEnvelopeXml.Save(stream);
}
}
}
For SharePoint Online
Rest call - WCF ProcessQuery
First see https://pholpar.wordpress.com/2011/05/25/interpreting-network-traffic-generated-by-the-sharepoint-client-object-model/ for how to make rest calls to the WCF client.svc endpoint. I will not include the process of creating SPOIDCRL cookie and getting the X-Digest value. But you will need these.
curl -X POST \
https://xxxxxxxxx-admin.sharepoint.com/_vti_bin/client.svc/ProcessQuery \
-H 'Content-Type: text/xml' \
-H 'Cookie: SPOIDCRL=77u/PD94b.....TwvU1A+' \
-H 'X-ClientService-ClientTag: TAPS (16.0.7813.0)' \
-H 'X-FORMS_BASED_AUTH_ACCEPTED: f' \
-H 'X-RequestDigest: 0x089E7....905ED2601,03 Aug 2018 05:12:10 -0000' \
-H 'X-RequestForceAuthentication: true' \
-d '<?xml version="1.0" encoding="UTF-8"?>
<Request xmlns="http://schemas.microsoft.com/sharepoint/clientquery/2009" AddExpandoFieldTypeSuffix="true" SchemaVersion="15.0.0.0" LibraryVersion="16.0.7918.1217" ApplicationName="Lucidworks Fusion">
<Actions>
<ObjectPath Id="4" ObjectPathId="3" />
<ObjectPath Id="6" ObjectPathId="5" />
<Query Id="7" ObjectPathId="5">
<Query SelectAllProperties="true">
<Properties>
<Property Name="NextStartIndexFromSharePoint" ScalarProperty="true" />
</Properties>
</Query>
<ChildItemQuery SelectAllProperties="true">
<Properties />
</ChildItemQuery>
</Query>
</Actions>
<ObjectPaths>
<Constructor Id="3" TypeId="{268004ae-ef6b-4e9b-8425-127220d84719}" />
<Method Id="5" ParentId="3" Name="GetSitePropertiesFromSharePoint">
<Parameters>
<Parameter Type="Null" />
<Parameter Type="Boolean">false</Parameter>
</Parameters>
</Method>
</ObjectPaths>
</Request>'
The result will contain your site collections.
If you happen to have 1000's site collections in your SharePoint online, you may need to figure out how to change this query to support paging.