Is there a way to get the URL of a salesforce site from apex

I need this to send the url in an email message, so the apex is run outside of the site context. I basically want to expose a link to my salesforce site in an email message. But so far I haven't found a way to do that

I would prefer not hard coding the url in apex

  • Are Sites available in some table you can query? Like select NamespacePrefix, Name from ApexPage limit 10? – eyescream Jan 24 '13 at 17:29
  • 1
    yes, you can query them: [SELECT Name, Status, Subdomain FROM Site] this only gives me the subdomain in subdomain.force.com, this should work well when installed on a production org, but when using the app on a dev org / sandbox you get a different URL for example: http://subdomain.na14.force.com/sitename – pjcarly Jan 24 '13 at 17:35
  • 1
    I just posted an idea on the IdeaExchange to make this easier to do. Please vote! – Benj Oct 3 '13 at 0:57
  • Great idea, voted Benj. – greenstork Oct 3 '13 at 3:22

11 Answers 11



But with some cunning, you can extract this from the site debug mode endpoint:

String name = 'mysite';

Site site = [
    SELECT GuestUserId
    FROM Site
    WHERE Name = :name

String path = '/sites/servlet.SiteDebugMode';
PageReference pr = new PageReference(path);
pr.getParameters().put('guid', site.GuestUserId);
pr.getParameters().put('sitedebugmode', 'x');
String url = pr.getContent().toString().substringAfter('URL=').substringBefore(path);

System.debug(url); //eg "http://dev-bigass.cs81.force.com/mysite"

Seems to behave across environments regardless of Production / Sandbox / My Domain etc.

| improve this answer | |
  • 1
    What a beautiful hack-y solution, upvote, but I'm not going to use it any time soon in our AppExchange apps, I find it just a little too tricky. – pjcarly Oct 15 '15 at 15:08
  • glad you like it @pieterjancarly :-) lemme put that disclaimer up front – bigassforce Oct 15 '15 at 17:41
  • 1
    @bigassforce this seems to fail when running as a non-admin user – Phil B Dec 8 '16 at 19:16

Since Winter '17 (v38.0)

You can get the secureURL using the SiteDetail object

Site mySite = [select Id from Site where Name = 'MySite'];
SiteDetail mySiteDetail = [select SecureURL from SiteDetail where DurableId = :mySite.Id];
| improve this answer | |
  • 2
    I previously went with the solution of querying the description field, but this is definitely an improvement over that IMO. Nice one! – Matt Lacey Mar 29 '19 at 2:37
  • 2
    I think this answer should be marked as best answer – Ariel Jan 18 at 9:34
  • As of 2020-02-13, it's too bad one can't do a join query to get the SecureUrl, e.g. SELECT Id, SecureUrl FROM SiteDetail WHERE DurableId IN (SELECT Id FROM Site WHERE UrlPathPrefix = 'myPrefix') – Scott Pelak Feb 13 at 15:40

This doesn't seem to be possible from apex, I ended up trying the different ways described above, and decided to go with a Custom Setting. I added the Custom Setting Site URL which needs to be filled in every time when the app gets configured.

| improve this answer | |
  • 1
    that's simply wrong - at least today. URL.getSalesforceBaseUrl().toExternalForm() returns the complete org-url. – Jörn Berkefeld Sep 28 '16 at 16:07

Here is the solution:

    Site site = [SELECT GuestUserId, Name, Subdomain, UrlPathPrefix FROM Site WHERE Name = :'My Site'];

    Organization org = [SELECT InstanceName, IsSandbox, OrganizationType FROM Organization];

    String siteFullUrl = 'https://' + site.Subdomain + '.';
    siteFullUrl += (org.IsSandbox || org.OrganizationType == 'Developer Edition' ? (org.InstanceName.toLowerCase() + '.') : '') + 'force.com';
    siteFullUrl += '/' + site.UrlPathPrefix;
| improve this answer | |
  • 1
    For sandboxes, the sandbox name gets prefixed onto the URL, like: https://(sandboxname)-(site.Dubdomain).(instancename).force.com/(urlPathPrefix) ... getting the sandboxname is not easy though. Seems best to take it from end of username. – codeulike Jan 16 '16 at 14:19
  • The solution from @bigassforce had worked beautifully for a while, but when we added new non-admin licensing types the process began to fail. This solution works well, thank you. – Mike Topalovich Jul 17 '18 at 16:29

This used to work. I didn't tested it recently, try it out.

Site s = [SELECT s.Subdomain FROM Site s LIMIT 1 ];
String urlCode = String.valueof(URL.getSalesforceBaseUrl().toExternalForm());
String [] cuts = urlCode.split('[.]');
urlCode = '';
for(Integer i = 1; i < cuts.size(); i++){
        urlCode += cuts[i] + '.';
urlCode = urlCode.substring(0, urlCode.length()-1);  
urlCode = 'https://'+s.Subdomain+'.'+urlCode+'/yourpage;
| improve this answer | |
  • I'll give it a try, and keep you posted, thanks for the code! – pjcarly Jan 24 '13 at 22:12
  • unfortunately this doesn't seem to give me the correct site address on a developer org, but will probably work on a production org though – pjcarly Jan 25 '13 at 13:26
  • Is that because DE orgs have the "-developer" portion enforced on the URL? – joshbirk Feb 20 '13 at 15:45
String sfdcBaseURL = URL.getSalesforceBaseUrl().toExternalForm();

This should work for your requirement.

| improve this answer | |

A quick hack if you don't want to create a custom setting just to store the url is to use the description field on the site to store the URL address. Then just query the site based on the Name or MasterLabel.

string siteUrl = [SELECT Description FROM Site WHERE MasterLabel = 'Site Name'].Description;

You can still store a general description in the field, you'll just want to wrap your URL in a distinct tag character and then use String.substringBetween(tag).

For example if your description was "This is my super cool site for promoting super cool stuff ~myCustomSiteURLAddress~". You could then get just the url by querying...

string siteUrl = [SELECT Description FROM Site WHERE MasterLabel = 'Site Name'].Description.substringBetween('~');

| improve this answer | |

If you are looking to associate to a single record, you will need to use the PageReference class. Specifically:




To piece that together you would use the following:

String url = 'https://' + ApexPages.currentPage().getHeaders().get('Host') + ApexPages.currentPage().getHeaders().getUrl();

If you are looking to link to a specific object, you just need the host and the ID of that object. Say you want to link to an account for instance and the account you have is referenced by the acc variable:

String url = 'https://' + ApexPages.currentPage().getHeaders().get('Host') + '/' + acc.Id;
| improve this answer | |
  • I don't have a Page i'm executing from, so there is no Apexpages available, it is run directly from apex. – pjcarly Jan 24 '13 at 16:53
  • Ah ok. I don't know if there is a way to get the host outside of the Page context. In this scenario, to avoid hard coding a value, I would just create a custom setting and reference that. You can then update that custom setting whenever needed. It is a similar concept to a property file used in other programming languages. – Jesse Altman Jan 24 '13 at 16:56
  • I know custom settings, but the thing is, i'm trying to write an app, and having to set a custom setting per deployment is quite a hasstle – pjcarly Jan 24 '13 at 17:01

For using some of the above mentioned answers, I believe it is required to enable the site object in your org. For me it was not available and this was the best possible solution I could have.

String sfdcBaseURL = URL.getSalesforceBaseUrl().toExternalForm();

| improve this answer | |

Please refer the below link:


seems you might need to make use of

apexpages.currentpage().getURL() and apexpages.currentpages().getHeaders().get('HOST')
| improve this answer | |
  • 1
    that's not answering my question, I need the site url like so: 'https://mysaleforceorg.force.com/', Site.getCustomWebAddress() keeps returning NULL because it is run from outside the site context – pjcarly Jan 24 '13 at 16:50

As others have noticed, this isn't currently possible in Apex. I've posted an idea on the IdeaExchange to request that this feature be added. Please consider voting for it!


| improve this answer | |
  • sorry for downvote, but this is not an answer. This is a very good idea, but it is still not an answer – Novarg Mar 31 '15 at 14:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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