Skip to main content

expo-linking

Version: 55.0.4 Create and open deep links universally. Handle incoming links, create links to your app, and open external URLs.

Installation

npx expo install expo-linking

Usage

import * as Linking from 'expo-linking';

// Open URL
await Linking.openURL('https://expo.dev');

// Parse URL
const url = Linking.parse('myapp://path/into/app?hello=world');
console.log(url.hostname, url.path, url.queryParams);

// Create URL
const url = Linking.createURL('path/into/app', {
  queryParams: { hello: 'world' },
});

// Listen for incoming URLs
Linking.addEventListener('url', ({ url }) => {
  console.log('Received URL:', url);
});

API Reference

Methods

openURL(url)
(url: string) => Promise<void>
Opens URL
await Linking.openURL('https://expo.dev');
await Linking.openURL('tel:+1234567890');
await Linking.openURL('mailto:support@expo.dev');
canOpenURL(url)
(url: string) => Promise<boolean>
Checks if URL can be opened
const can = await Linking.canOpenURL('myapp://');
openSettings()
() => Promise<void>
Opens app settings
await Linking.openSettings();
createURL(path, options)
(path: string, options?: CreateURLOptions) => string
Creates deep link URL
const url = Linking.createURL('profile/123', {
  queryParams: { ref: 'notification' },
  scheme: 'myapp',
});
// Result: myapp://profile/123?ref=notification
parse(url)
(url: string) => URLObject
Parses URL into components
const parsed = Linking.parse('myapp://user/42?name=John');
console.log(parsed.hostname); // 'user'
console.log(parsed.path); // '42'
console.log(parsed.queryParams); // { name: 'John' }
getInitialURL()
() => Promise<string | null>
Gets URL that opened the app
const url = await Linking.getInitialURL();
if (url) {
  console.log('App opened with:', url);
}
addEventListener(type, handler)
(type: 'url', handler: URLListener) => void
Listens for URL events
Linking.addEventListener('url', ({ url }) => {
  const parsed = Linking.parse(url);
  // Handle deep link
});

Examples

import * as Linking from 'expo-linking';
import { useEffect } from 'react';
import { useNavigation } from '@react-navigation/native';

export default function App() {
  const navigation = useNavigation();

  useEffect(() => {
    // Handle initial URL
    Linking.getInitialURL().then((url) => {
      if (url) handleDeepLink(url);
    });

    // Handle subsequent URLs
    const subscription = Linking.addEventListener('url', ({ url }) => {
      handleDeepLink(url);
    });

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

  function handleDeepLink(url: string) {
    const { hostname, path, queryParams } = Linking.parse(url);
    
    if (hostname === 'user' && path) {
      navigation.navigate('Profile', { id: path });
    }
  }

  return <NavigationContainer linking={linkingConfig}>...</NavigationContainer>;
}

URL Schemes

import * as Linking from 'expo-linking';

// Open phone dialer
await Linking.openURL('tel:+1234567890');

// Send email
await Linking.openURL('mailto:support@example.com?subject=Help&body=I need help');

// Open maps
await Linking.openURL('https://maps.apple.com/?q=coffee');

// Open another app
await Linking.openURL('instagram://user?username=expo');

Platform Support

PlatformSupported
iOS
Android
Web

Configuration

app.json

{
  "expo": {
    "scheme": "myapp",
    "android": {
      "intentFilters": [
        {
          "action": "VIEW",
          "data": [
            {
              "scheme": "myapp",
              "host": "*.myapp.io"
            }
          ],
          "category": ["BROWSABLE", "DEFAULT"]
        }
      ]
    }
  }
}

Resources