Skip to main content
The Linking API provides a general interface to interact with both incoming and outgoing app links. You can open URLs in the browser, launch other apps, and handle deep links into your app.

Import

import { Linking } from 'react-native';

Methods

openURL()

Attempts to open a URL with any of the installed apps.
Linking.openURL(url);
url
string
required
The URL to open. Can be:
  • Web URLs: https://example.com
  • Phone numbers: tel:+1234567890
  • SMS: sms:+1234567890
  • Email: mailto:[email protected]
  • App-specific schemes: myapp://path
Returns: Promise<void> - Resolves when the URL is opened, rejects if no app can handle the URL.

canOpenURL()

Checks if an app is installed that can handle a given URL.
Linking.canOpenURL(url);
url
string
required
The URL to check.
Returns: Promise<boolean> - Resolves to true if the URL can be opened, false otherwise.
iOS: You must add URL schemes to LSApplicationQueriesSchemes in Info.plist or canOpenURL() will always return false for third-party schemes.

getInitialURL()

Returns the URL that launched the app, if any.
Linking.getInitialURL();
Returns: Promise<string | null> - The initial URL, or null if the app wasn’t launched via a link.

addEventListener()

Listens for incoming app links while the app is running.
const subscription = Linking.addEventListener('url', handler);
type
string
required
Must be 'url'.
handler
function
required
Callback function that receives an object with a url property.
Returns: EventSubscription - Object with a remove() method to unsubscribe.

openSettings()

Opens the operating system settings for your app.
Linking.openSettings();
Returns: Promise<void>

sendIntent() (Android only)

Launches an Android intent with optional extras.
Linking.sendIntent(action, extras);
action
string
required
The Android intent action (e.g., 'android.intent.action.VIEW').
extras
array
Array of extra data objects with key, value properties.
Returns: Promise<void>

Examples

Opening a Web URL

import React from 'react';
import { Button, Linking, Alert } from 'react-native';

const OpenURLButton = ({ url, children }) => {
  const handlePress = async () => {
    // Check if the URL can be opened
    const supported = await Linking.canOpenURL(url);

    if (supported) {
      await Linking.openURL(url);
    } else {
      Alert.alert(`Don't know how to open this URL: ${url}`);
    }
  };

  return <Button title={children} onPress={handlePress} />;
};

// Usage
<OpenURLButton url="https://react.dev">
  Open React Website
</OpenURLButton>

Making a Phone Call

import { Button, Linking, Platform } from 'react-native';

const CallButton = ({ phoneNumber }) => {
  const handlePress = async () => {
    const url = `tel:${phoneNumber}`;
    
    const canOpen = await Linking.canOpenURL(url);
    if (canOpen) {
      await Linking.openURL(url);
    }
  };

  return <Button title="Call" onPress={handlePress} />;
};

// Usage
<CallButton phoneNumber="+1234567890" />

Sending an Email

import { Button, Linking } from 'react-native';

const EmailButton = () => {
  const handlePress = async () => {
    const email = '[email protected]';
    const subject = 'App Feedback';
    const body = 'Hello, I have some feedback...';
    
    const url = `mailto:${email}?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
    
    await Linking.openURL(url);
  };

  return <Button title="Send Email" onPress={handlePress} />;
};

Sending an SMS

import { Button, Linking, Platform } from 'react-native';

const SMSButton = ({ phoneNumber, message }) => {
  const handlePress = async () => {
    const separator = Platform.OS === 'ios' ? '&' : '?';
    const url = `sms:${phoneNumber}${separator}body=${encodeURIComponent(message)}`;
    
    await Linking.openURL(url);
  };

  return <Button title="Send SMS" onPress={handlePress} />;
};

// Usage
<SMSButton phoneNumber="+1234567890" message="Hello from React Native!" />
import React, { useEffect } from 'react';
import { Linking, Alert } from 'react-native';

const DeepLinkHandler = () => {
  useEffect(() => {
    // Handle deep link when app is already open
    const subscription = Linking.addEventListener('url', ({ url }) => {
      console.log('Received URL:', url);
      handleDeepLink(url);
    });

    // Handle deep link when app is opened from closed state
    Linking.getInitialURL().then((url) => {
      if (url) {
        console.log('Initial URL:', url);
        handleDeepLink(url);
      }
    });

    return () => {
      subscription.remove();
    };
  }, []);

  const handleDeepLink = (url) => {
    // Parse the URL and navigate accordingly
    // Example: myapp://profile/123
    const route = url.replace(/.*?:\/\//g, '');
    const [screen, id] = route.split('/');
    
    Alert.alert('Deep Link', `Navigate to ${screen} with ID: ${id}`);
    // Navigate to the appropriate screen
  };

  return null;
};

Opening App Settings

import React from 'react';
import { Button, Linking } from 'react-native';

const SettingsButton = () => {
  const openSettings = async () => {
    await Linking.openSettings();
  };

  return (
    <Button
      title="Open App Settings"
      onPress={openSettings}
    />
  );
};

Opening Maps

import { Linking, Platform } from 'react-native';

const openMaps = async (latitude, longitude, label) => {
  const scheme = Platform.select({
    ios: 'maps:',
    android: 'geo:',
  });
  
  const url = Platform.select({
    ios: `${scheme}${latitude},${longitude}?q=${label}`,
    android: `${scheme}${latitude},${longitude}?q=${label}`,
  });

  await Linking.openURL(url);
};

// Usage
openMaps(37.7749, -122.4194, 'San Francisco');

Opening Social Media Apps

import { Linking, Alert } from 'react-native';

const openSocialMedia = async (platform, handle) => {
  const urls = {
    twitter: `twitter://user?screen_name=${handle}`,
    twitterWeb: `https://twitter.com/${handle}`,
    instagram: `instagram://user?username=${handle}`,
    instagramWeb: `https://instagram.com/${handle}`,
    facebook: `fb://profile/${handle}`,
    facebookWeb: `https://facebook.com/${handle}`,
  };

  const appUrl = urls[platform];
  const webUrl = urls[`${platform}Web`];

  try {
    const supported = await Linking.canOpenURL(appUrl);
    if (supported) {
      await Linking.openURL(appUrl);
    } else {
      await Linking.openURL(webUrl);
    }
  } catch (error) {
    Alert.alert('Error', 'Failed to open link');
  }
};

// Usage
openSocialMedia('twitter', 'reactnative');

Android Intent Example

import { Linking, Platform } from 'react-native';

const shareViaIntent = async () => {
  if (Platform.OS === 'android') {
    await Linking.sendIntent('android.intent.action.SEND', [
      { key: 'android.intent.extra.TEXT', value: 'Check out this app!' },
      { key: 'android.intent.extra.SUBJECT', value: 'App Recommendation' },
    ]);
  }
};

iOS Setup

Add URL schemes to your Info.plist:
<key>CFBundleURLTypes</key>
<array>
  <dict>
    <key>CFBundleURLSchemes</key>
    <array>
      <string>myapp</string>
    </array>
  </dict>
</array>

<key>LSApplicationQueriesSchemes</key>
<array>
  <string>tel</string>
  <string>mailto</string>
  <string>maps</string>
</array>

Android Setup

Add intent filters to your AndroidManifest.xml:
<activity
  android:name=".MainActivity"
  android:launchMode="singleTask">
  
  <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="myapp" />
  </intent-filter>
  
</activity>

Common URL Schemes

TypeURL FormatExample
HTTP/HTTPShttps://https://example.com
Phonetel:tel:+1234567890
SMSsms:sms:+1234567890?body=Hello
Emailmailto:mailto:[email protected]
Maps (iOS)maps:maps:37.7749,-122.4194?q=SF
Maps (Android)geo:geo:37.7749,-122.4194?q=SF
WhatsAppwhatsapp://whatsapp://send?phone=1234567890
Twittertwitter://twitter://user?screen_name=handle
Instagraminstagram://instagram://user?username=handle
Facebookfb://fb://profile/userid

Best Practices

Always check if a URL can be opened with canOpenURL() before calling openURL() to handle cases where required apps aren’t installed.
Wrap Linking.openURL() calls in try-catch blocks to handle errors gracefully.
On iOS, you must declare URL schemes you want to query in LSApplicationQueriesSchemes in Info.plist, or canOpenURL() will always return false.

Error Handling

const safeOpenURL = async (url) => {
  try {
    const supported = await Linking.canOpenURL(url);
    
    if (!supported) {
      Alert.alert('Error', `Cannot open URL: ${url}`);
      return false;
    }
    
    await Linking.openURL(url);
    return true;
  } catch (error) {
    Alert.alert('Error', `Failed to open URL: ${error.message}`);
    return false;
  }
};

Build docs developers (and LLMs) love