The Complete Tutorial on iOS/iPhone Custom URL Schemes

Tue, Feb 25

Note: Since the introduction of custom URL schemes, this post has consistently been the top read content on the blog. Although much is the same, there are a few nuances that have changed. This is a re-write of the original post, updated for the latest iOS and Xcode versions.

One of the coolest features of the iPhone/iOS SDK is an application’s ability to “bind” itself to a custom URL scheme and for that scheme to be used to launch the application from either a browser or from another application.

Registering a Custom URL Scheme

The first step is to create a custom URL scheme – start by locating and clicking on the project info.plist in the Xcode Project Navigator. With the plist displayed in the right pane, right click on the list and select Add Row:

From the list presented scroll down and select URL types.

iOS Custom URL Scheme

Open the directional arrow and you’ll see Item 0, a dictionary entry. Expand Item 0 and you will see URL Identifier, a string object. This string is the name for the custom URL scheme you are defining. It’s recommended to ensure uniqueness of the name that you reverse domain name such as com.yourCompany.yourApp.

urlScheme2a

Tap on Item 0 and add a new row, select URL Schemes from the drop-down and tap Enter to complete the row insert.

iOS Custom URL Scheme

Notice URL Schemes is an array, allowing multiple URL schemes to be defined for an application.

iOS Custom URL Scheme

Expand the array and tap on Item 0. This is where you will define the name for the custom URL scheme. Enter just the name, do not append :// – for instance, if you enter iOSDevApp, your custom url will be iOSDevApp://

iOS Custom URL Scheme

Here is how the complete definition looks at this point:

iOS Custom URL Scheme

Although I appreciate Xcode’s intention when using descriptive names, I find it helpful to see the actual keys created. Here’s a handy trick, right-click on the plist and select Show Raw Keys/Values, the output will look as follows:

iOS Custom URL Scheme

There’s another output format that also has merit, XML, as it’s much easier to see the structure of the dictionary and the nested array and its entries. Tap the plist and this time choose Open As – Source Code:

iPhone Custom URL Scheme

Calling Custom URL Scheme from Safari

With the URL scheme defined, we can run a quick test to verify the app can be called as expected using the URL. Before we do that, I’ll create a barebones UI so we can identify the app with the custom URL. The app contains nothing more than a UILabel with the text “App With Custom URL.” Download source for creating iOS App with Custom URL Scheme.

iOS App with Custom URL

Using the simulator, here’s how to call the app:

- Run the application from within Xcode
- Once installed, the custom URL scheme will now be registered
- Close the app via the Hardware menu in simulator and choose Home
- Start Safari
- Enter the URL scheme defined previously in the browser address bar (see below)

Call Custom URL Scheme from Safari

At this point Safari will close and the app will be brought to the foreground. Congratulations, you’ve just called an iPhone application using a custom URL scheme!

Calling Custom URL Scheme from Another iPhone App

Let’s take a look at how to call the custom URL scheme from another iPhone application. Again, I’ve created a very simple iPhone application with nothing more than a UILabel and a UIButton – the former shows a message that this is the app that will call another app via a custom URL scheme, the button starts that process. Download source for creating iOS App to call Custom URL Scheme.

iPhone app that call Custom URL Scheme

The code inside the buttonPressed manages the URL processing:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- (void)buttonPressed:(UIButton *)button
{
  NSString *customURL = @"iOSDevTips://";
 
  if ([[UIApplication sharedApplication] 
    canOpenURL:[NSURL URLWithString:customURL]])
  {
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:customURL]];
  }
  else
  {
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"URL error"
                          message:[NSString stringWithFormat:
                            @"No custom URL defined for %@", customURL]
                          delegate:self cancelButtonTitle:@"Ok" 
                          otherButtonTitles:nil];
    [alert show];
  }    
}

Line 5 we check to see if the custom URL is defined, and if so, use the shared application instance to open the URL (line 8). The openURL: method starts the application and passes the URL into the app. The current application is exited during this process.

Passing Parameters To App Via Custom URL Scheme

Chances are you’ll need to pass parameters into the application with the custom URL definition. Let’s look at how we can do this with.

The NSURL class which is the basis for calling from one app to another conforms to the RFC 1808 (Relative Uniform Resource Locators). Therefore the same URL formatting you may be familiar with for web-based content will apply here as well.

In the application with the custom URL scheme, the app delegate must implement the method with the signature below:

- (BOOL)application:(UIApplication *)application 
  openURL:(NSURL *)url 
  sourceApplication:(NSString *)sourceApplication 
  annotation:(id)annotation

The trick to passing in parameters from one app to another is via the URL. For example, assume we are using the following custom URL scheme and want to pass in a value for a ‘token’ and a flag indicating registration state, we could create URL as follows:

NSString *customURL = @"iOSDevTips://?token=123abct&registered=1";

As in web development, the string ?token=123abct&registered=1 is known as the query string.

Inside the app delegate of the app being called (the app with the custom URL), the code to retrieve the parameters would be as follows:

1
2
3
4
5
6
7
8
9
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
        sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
  NSLog(@"Calling Application Bundle ID: %@", sourceApplication);
  NSLog(@"URL scheme:%@", [url scheme]);
  NSLog(@"URL query: %@", [url query]);
 
  return YES;
}

The output from the app with the custom URL (using my Bundle ID), when called from another app, is as follows:

Calling Application Bundle ID: com.3Sixty.CallCustomURL
URL scheme:iOSDevTips
URL query: token=123abct&registered=1

Take note of the ‘Calling Application Bundle ID’ as you could use this to ensure that only an application that you define can interact directly with your app.

Let’s change up the delegate method to verify the calling application Bundle ID is known:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
        sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
  // Check the calling application Bundle ID
  if ([sourceApplication isEqualToString:@"com.3Sixty.CallCustomURL"])
  {
    NSLog(@"Calling Application Bundle ID: %@", sourceApplication);
    NSLog(@"URL scheme:%@", [url scheme]);
    NSLog(@"URL query: %@", [url query]);
 
    return YES;
  }
  else
    return NO;
}

It’s important to note that you cannot prevent another application from calling your app via custom URL scheme, however you can skip any further processing and return NO as shown above. With that said, if you desire to keep other apps from calling your app, create a unique (non-obvious) URL scheme. Although this will guarantee you app won’t be called, it will make it more unlikely.

Custom URL Scheme Example Projects

I realize it can be a little tricky to follow all the steps above. I’ve included two (very basic) iOS apps, one that has the custom URL scheme defined and one that calls the app, passing in a short parameter list (query string). These are good starting points to experiment with custom URL’s.

Additional Resources

42 comments

How can we make the URL of application such that User can click on the email or in the sms and Our app can start??

Thanks in advance

by Sanniv on Apr 30, 2009. #

I my be barking up the wrong tree.

I am wanting to add a url to my iPhone app that would launch safari, then load my website, when you tap on the url text in my app.

Thanks for any help you can offer.

Mark

by Mark Collins on May 6, 2009. #

Q: Will this work from within the app? For instance, in a tab bar-based app with multiple Web Views, it would be nice to be able to pick a link within one web view, and immediately end up at application:handleOpenURL: since the app is already running. (If not, how is this sort of thing accomplished within an app that uses web views?)

by Joe on Aug 24, 2009. #

We’re working on a centralized place to register all public URL schemes: http://www.handleOpenURL.com

Please add your URL schemes to the index: http://www.handleOpenURL.com/developers

The aim is to work towards a more elegant and advanced manner of sharing your apps functionality with other apps.

Thanks,

by Maarten Wolzak on Sep 10, 2009. #

Anyone figure out the answer to @Joe’s question above? Can you use these from within an app to message that same app without relaunching it?

by Aaron Hill on Sep 29, 2009. #

@Aaron: Greetings! If application:handleOpenURL: is _not_ invoked, the next best thing might be to check the delegate method webView:shouldStartLoadWithRequest:navigationType: … though I’m hopeful it’s still possible the other way. :)

by Joe on Sep 29, 2009. #

Regarding Joe’s question…

Create a class that implements the IWebViewDelegate protocol and implement the shouldStartLoadWithRequest method. When your webview needs to load a page (via a clicked link, an ajax request, some sort of javascript event, whatever…) it will call this method on your delegate and pass in an NSUrlRequest object.

if [[request url] scheme] is your app’s custom scheme, go ahead and do whatever it is the url indicates you should do, and return NO to prevent the webview from continuing to process the request. If the scheme isn’t something you want to catch, return YES to let the webview handle the request in the usual manner.

PhoneGap does this (see /iphone/PhoneGapLib/Classes/PhoneGapDelegate.m) in a very elegant way, providing a way for their javascript framework to call methods written in obj-c. They use the stringByEvaluatingJavaScriptFromString method of the webview to pass information back into the browser from obj-c, which is also pretty slick.

by brandon on Dec 2, 2009. #

@brandon – right on! Thanks for walking through that. Very much appreciated.

by Joe on Dec 2, 2009. #

I’ve written an app that hides the status bar at the top of the phone (the one with the carrier, etc.) When I open it using this method, the bar shows up. How can I keep it hidden?

by Lawson Culver on Dec 24, 2009. #

@Lawson Culver – this one had me bugged too. Instead of doing it through code ( [[UIApplication sharedApplication] setStatusBarHidden: YES]; ) you will need to add the “Status bar is initially hidden” line to your Info.plist and check the box. Once I did that, it worked for me!

by Jeffrey Berthiaume on Jan 17, 2010. #

As a rookie I have question you probably all be able to answer. I am building a mobile website and would like to include a line of code that automatically launches an iPhone app. It should be through some kind of URL link. Do you know how I could make this work? What is the ‘launch code’ or URL code for an iPhone application that you would have on your phone?

any tips are mostly appreciated!

by Robbert on Mar 15, 2010. #

@Robbert:

Simply use the apps custom URL scheme in a link like so:

<a href="//start" rel="nofollow">Start iThrown, a fun game!</a>

You can extend that with a small timeout to redirect the visitor to the Apps homepage or the iTunes page when the app is not installed like so:

<a href="//start" rel="nofollow">Play iThrown</a>

If the app is not installed, Safari will alert the user that it cannot open the link. Once the user clicks the OK button the setTimeout will kick in and send the user on to the apps page. You will want to work on this to inform/query the user on the next action.

You can check a lot of URL scheme’s of different apps at: http://handleOpenURL.com/

Good luck with your mobile site!

by Maarten on Mar 15, 2010. #

Hello Marrten, How to avoid the alert of 404 from safari when the app is not install? Search by Google. Unluckly, I can’t find the solution about this issue. Thanks! @Maarten

by sandyjing on Sep 26, 2012. #

Hm, I didn’t expect the links to translate… the first was supposed to state:

http://ithrown/start

The second was supposed to have an onclicked attribute with a setTimeout function in it redirecting the user in 500 mSeconds giving Safari enough time to pass control to the app if it is installed but short enough to keep the show going.

by Maarten on Mar 15, 2010. #

Thx for the post!
Any idea on what to do if the mail app (on the iPhone) does not recognize the link as such (instead it is displaying plain text that can not be interacted with).

by Boris on Jun 21, 2010. #

Did you ever figure this out Boris? I’m having the same problem

by James on Jun 2, 2011. #

I’ve been able to use @”mailto://foo@foobar.com” in the body of an sms, which will create a link that launches the mail app on the iPhone. Is this close to what you are looking to do?

by John Muchow on Jun 2, 2011. #

Im Using a webservice that send an email to the client which notifies them of an update to the app. Then Once they click the link inside the email, they should go to my custom app. For some reason mail won’t interpret the link as a link, but if i put the scheme in the url it works. I’m stumped

by James on Jun 2, 2011. #

@Boris
You might want to try to make an HTML (rich) email with a link in it.
(To avoid spam-filters you should use the same link in the href as the visible one.)

Another, albeit less elegant, option is to create a page at your server which will transfer visitors over to the app. So the link in your emails point at http://www.your-server.com/transfer-to-app?open-code and the script redirects Safari to the correct location. Safari WILL recognize the URL scheme and will open the app accordingly.
You can also display a link to the itunes store here for those who do not have the app installed.
In PHP this would look something like:

<?
header('Location:'.$_GET['scheme']);
 
// add the following which will only be shown if the browser can't follow the 'header' directive:
echo "You do not have so-and-so installed yet. <a href="itunes-store/app/so-and-so" rel="nofollow">Click here</a> if you would like to do so now";
 
?>

Hope that helps.

by Maarten on Jun 21, 2010. #

DUDE! Thanks! That PHP is exactly the answer for me!! I’m going to build a PHP script which will take into account the client viewing a QR code and server up either a web URL or activate a Forusquare app check-in

by Jason Rundell on Aug 24, 2011. #

@Maarten is there a way to automatically determine if an app is installed using a variation of your script? Perhaps in the UIWebView we could detect that it will try to navigate to a custom protocol and then ask UIWebView to stop the navigation (in ObjectiveC we can listen to this event). Thoughts?

by Laurent on Jul 23, 2010. #

Thanx Maarten.

What I need is .. I have to launch my application through another application when we click on a button. I tried this requirement using URL Scheme. Its working and I just want to know is there any other way to do the same task ??

These 2 are the assumed conditions:
The app which I am trying to launch is already there in iPhone and I know the name of the application.

by Dee on Jul 26, 2010. #

I’m figuring that the best way to handle uniqueness of the URL scheme is to also have it be com.company.appname. I researched valid url scheme names and there are certainly standard url schemes (z39.50r for example) that have periods in them. So when you activate your app via webpage the url would look like “com.company.appname://whatever_parameters_you_want”. Any flaw with this approach? Not sure why we need a fancy registration process since this is pretty much guaranteed to be unique.

by Paul on Oct 8, 2010. #

@FadiN: No, wont work. It is not possible to pre-fill the body part in the official text-app. There’s 2 more SMS apps in our index (http://handleopenurl.com/search?scheme=sms) of which the BeSMS allows setting the body. You can check if that app is available on the users’ phone (or iPod Touch, BeSMS works there too!). If it is, you can use that and otherwise fall back to the ‘normal’ SMS app.

@Dinesh: There is no way to return to your app from the telephone app.

@Paul: completely right you are. A fancy registration would only be useful if you would want to publish the possibilities of your app.

by Maarten Wolzak on Oct 8, 2010. #

@Maarten : First of all thanks for insight on URL scheme. But my problem in little different.

I wast to open iBook, PDF reader etc. applications through URL’s similar to what DropBox is doing. But the issue is how will I find the URL for these applications. I tried searching “http://www.handleopenurl.com/” but the URLs are not listed there.

Thanks in advance.
Manish

by manish on Feb 14, 2011. #

hi,
I am doing the exact thing .But i am getting this error “my app cannot be opened because of a problem : check with developer to make sure myapp works with this version of Mac os X.”

Please can anyone explain little more on this topic.

by rakesh on Jan 27, 2011. #

Awesome tutorial! Thanks a billion!

by Sebbern on Feb 20, 2011. #

Nice tutorial, I have recommended it on my blog

by Jayson on Feb 21, 2011. #

Fantastic tutorial….

Thanks a lot!!!

by Vinay jain on Mar 16, 2011. #

Thanks! Exactly what I’ve been looking for.

by Luke on Mar 16, 2011. #

We have an SDK that is embedded in 100s of games and would like to enable each of them to at least start from another app. It sounds like the scheme has to be in the info.plist which is read only in the app? Thats such a terrible design. I would really like my SDK to be able to set up a standard scheme in each game so that we could call each app … there are so few games with scheme’s in them

by powerpop on Mar 19, 2011. #

Hello,

This is a great post. I have an extremely simple webView application, and I would like to pass the URL in via a get operation.

[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://punchedin.com/cgi-bin/start/appentry.html" + urlscheme ]]];

I added ‘urlscheme’ just to demponstrate what I am wanting to do. How can I append the url to the end of the initial URL the app goes to in its web view?

Thanks,

Terry Riegel

by Terry Riegel on Jun 16, 2011. #

This is very nice!, but how can i load the app?

with
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url;

you are making the app being able to get called.

but how can we call it?

by Emre on Jun 21, 2011. #

Check out this post that shows a few examples: Launching Other Apps within an iPhone Application

by John Muchow on Jun 21, 2011. #

I want to launching to other app and after 5 min I want to return to my own app, is it possible?
Someone can help me or give me some idea ? Thanks~

by henry on Dec 25, 2011. #

If your application also has a custom URL, the first app you launched could set a timer and call your app after 5 minutes.

by John Muchow on Dec 26, 2011. #

What happens if your App is not installed? Is there a technique that can be used to go to the AppStore to install your App?

by Cris on Mar 11, 2012. #

hi guys/gals this is a really cool tutorial / blog

i would like to thank the poster, for the great explanation, but i cant get my app to launch from the html link.
could you please anyone please post an example ?
this is how i am calling my app from a web page : go to urlapp

is this syntax correct ? does my app have to be on the app store ? (because i can call facebook app in the same manner)

thank you, for answering me (i hope) … sorry for the incohesive post :S

by nicholas jakubowicz on Aug 2, 2012. #

ok, so it converted my href tag into an actual tag …
>a href= “urlapp://” /a< (inverted brackets to see the code)

sorry

by nicholas jakubowicz on Aug 2, 2012. #

I want lo launch my “Evernote” app.. How can I do that?

by Mario on Feb 14, 2014. #

I don’t think Evernote supports a URL scheme: Evernote discussion

by John Muchow on Feb 14, 2014. #