{"id":31,"date":"2026-01-28T21:56:41","date_gmt":"2026-01-28T21:56:41","guid":{"rendered":"https:\/\/tomaszwojtasik.com\/?p=31"},"modified":"2026-01-28T21:56:41","modified_gmt":"2026-01-28T21:56:41","slug":"is-this-sharepoint-site-url-available","status":"publish","type":"post","link":"https:\/\/tomaszwojtasik.com\/index.php\/2026\/01\/28\/is-this-sharepoint-site-url-available\/","title":{"rendered":"Is This SharePoint Site URL Available?"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">The problem<\/h2>\n\n\n\n<p>When working on intranet solutions in SharePoint, a very common scenario is allowing users to create new sites \u2014 or at least request them through a form or custom application.<\/p>\n\n\n\n<p>In such cases, users are often asked to provide the site URL suffix \u2014 the part that comes after: <a href=\"https:\/\/tenant.sharepoint.com\/sites\/\u2026\">https:\/\/tenant.sharepoint.com\/sites\/\u2026<\/a><\/p>\n\n\n\n<p>Before creating a new site, we need to answer a simple question: <strong>Is the provided SharePoint site URL available, or is it already taken?<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Approach 1: Checking the Site via SharePoint REST API<\/h2>\n\n\n\n<p>The most obvious approach is to simply check whether a site exists under the given URL.<\/p>\n\n\n\n<p>One way to do this is by sending a request to the SharePoint REST API and trying to read basic site information, such as the site title:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:\/\/&lt;tenant>.sharepoint.com\/sites\/&lt;siteUrl>\/_api\/web?$select=Title<\/code><\/pre>\n\n\n\n<p>Based on the HTTP response, we might interpret the result as follows:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>200 OK<br><\/strong>The site exists and is accessible so the address is not available.<\/li>\n\n\n\n<li><strong>403 Forbidden<br><\/strong>We don\u2019t have permissions to access the site \u2014 which still means the site exists.<\/li>\n\n\n\n<li><strong>404 Not Found<br><\/strong>The site does not exist, so the URL must be available.<br>Right?<\/li>\n<\/ul>\n\n\n\n<p>At first glance, this logic seems correct. If SharePoint says the site is not found, we should be able to create a new site with that URL.<\/p>\n\n\n\n<p>Unfortunately, this assumption is wrong.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Approach 2: Handling Deleted (Soft-Deleted) Sites<\/h2>\n\n\n\n<p>The first approach works only as long as no one has deleted a site with the same URL.<\/p>\n\n\n\n<p>When a SharePoint site is deleted, it is not removed permanently right away. Instead, it goes into a <strong>soft-deleted state<\/strong> and remains there for <strong>93 days<\/strong>, during which it can still be restored.<\/p>\n\n\n\n<p>During this period:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The site <strong>cannot be accessed<\/strong><\/li>\n\n\n\n<li>The REST API call returns <strong>404 Not Found<\/strong><\/li>\n\n\n\n<li><strong>A new site cannot be created using the same URL<\/strong><\/li>\n<\/ul>\n\n\n\n<p>This creates a dangerous situation:<\/p>\n\n\n\n<p>The REST API indicates that the site does not exist, but SharePoint still blocks the URL. So while <strong>Approach 1 returns 404<\/strong>, the URL is <strong>not actually available<\/strong>. Clearly, we need a better solution \u2014 one that also accounts for deleted sites<\/p>\n\n\n\n<p>To properly validate whether a SharePoint site URL can be used, we can leverage the following internal SharePoint API endpoint:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:\/\/&lt;tenant>.sharepoint.com\/_api\/GroupSiteManager\/GetValidSiteUrlFromAlias?alias='mySite'<\/code><\/pre>\n\n\n\n<p>This endpoint returns a <strong>validated site URL<\/strong> based on the provided alias.<\/p>\n\n\n\n<p>The behavior is simple but effective:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If the requested URL <strong>is available<\/strong>, the response contains <strong>exactly the same URL<\/strong><\/li>\n\n\n\n<li>If the URL <strong>is not available<\/strong> (because it already exists or is soft-deleted), SharePoint returns a <strong>modified URL<\/strong>, usually with a number appended (for example, mySite2)<\/li>\n<\/ul>\n\n\n\n<p>While this is not the most elegant solution, it gives us a reliable signal:<\/p>\n\n\n\n<p><strong>If the returned URL differs from the requested one, the original URL is not available.<\/strong><\/p>\n\n\n\n<p>Most importantly, this mechanism <strong>takes soft-deleted sites into account<\/strong>, making it far more reliable than checking site existence via REST.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>Checking whether a SharePoint site URL is available is trickier than it looks:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Simply calling the site REST API and checking for 404 is <strong>not sufficient<\/strong><\/li>\n\n\n\n<li>Soft-deleted sites block URLs for up to <strong>93 days<\/strong><\/li>\n\n\n\n<li>The GroupSiteManager.GetValidSiteUrlFromAlias endpoint provides a <strong>practical and reliable way<\/strong> to validate URL availability before site creation<\/li>\n<\/ul>\n\n\n\n<p>If you are building custom provisioning solutions, request forms, or automated intranet tooling, this extra validation step can save you from unexpected provisioning failures \u2014 and confused users.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The problem When working on intranet solutions in SharePoint, a very common scenario is allowing users to create new sites \u2014 or at least request them through a form or custom application. In such cases, users are often asked to provide the site URL suffix \u2014 the part that comes after: https:\/\/tenant.sharepoint.com\/sites\/\u2026 Before creating a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-31","post","type-post","status-publish","format-standard","hentry","category-sharepoint"],"_links":{"self":[{"href":"https:\/\/tomaszwojtasik.com\/index.php\/wp-json\/wp\/v2\/posts\/31","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tomaszwojtasik.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tomaszwojtasik.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tomaszwojtasik.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tomaszwojtasik.com\/index.php\/wp-json\/wp\/v2\/comments?post=31"}],"version-history":[{"count":3,"href":"https:\/\/tomaszwojtasik.com\/index.php\/wp-json\/wp\/v2\/posts\/31\/revisions"}],"predecessor-version":[{"id":36,"href":"https:\/\/tomaszwojtasik.com\/index.php\/wp-json\/wp\/v2\/posts\/31\/revisions\/36"}],"wp:attachment":[{"href":"https:\/\/tomaszwojtasik.com\/index.php\/wp-json\/wp\/v2\/media?parent=31"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tomaszwojtasik.com\/index.php\/wp-json\/wp\/v2\/categories?post=31"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tomaszwojtasik.com\/index.php\/wp-json\/wp\/v2\/tags?post=31"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}