File: push-notifications-setup.md | Updated: 11/15/2025
Hide navigation
Search
Ctrl K
Home Guides EAS Reference Learn
Archive Expo Snack Discord and Forums Newsletter
Copy page
Learn how to set up push notifications, get credentials for development and production, and send a testing push notification.
Copy page
To utilize Expo push notification service, you must configure your app by installing a set of libraries, implement functions to handle notifications, and set up credentials for Android and iOS.
Complete the steps outlined in this guide or follow the more detailed video below. At the end, you'll be able to send a push notification and receive it on a device.
To get the client-side ready for push notifications, the following things are required:
ExpoPushToken
.Do you want to use FCM / APNs directly, instead of the Expo push notification service?
If you need finer-grained control over your notifications, communicating directly with FCM and APNs may be necessary. Expo does not lock you into using Expo Application Services, and the expo-notifications API is push-service agnostic. Learn how to "Send notifications with FCM and APNs"
.
Important: Push notifications are not supported on Android Emulators and iOS Simulators. A real device is required.
The following steps described in this guide use EAS Build
. This is the easiest way to set up notifications since your EAS project will also contain the notification credentials
. However, you can use the expo-notifications library without EAS Build by building your project locally
.
1
Run the following command to install the expo-notifications, expo-device and expo-constants libraries:
Terminal
Copy
- npx expo install expo-notifications expo-device expo-constants
expo-notifications
library is used to request a user's permission and to obtain the ExpoPushToken for sending push notifications.expo-device
is used to check whether the app is running on a physical device.expo-constants
is used to get the projectId value from the app config.2
Add the expo-notifications plugin in the plugins array of your app config
:
app.json
Copy
{ "expo": { %%placeholder-start%%... %%placeholder-end%% "plugins": [ %%placeholder-start%%... %%placeholder-end%% "expo-notifications" ] } }
3
The code below shows a working example of how to register for, send, and receive push notifications in a React Native app. Copy and paste it into your project:
App.tsx
Copy
import { useState, useEffect, useRef } from 'react'; import { Text, View, Button, Platform } from 'react-native'; import * as Device from 'expo-device'; import * as Notifications from 'expo-notifications'; import Constants from 'expo-constants'; Notifications.setNotificationHandler({ handleNotification: async () => ({ shouldPlaySound: true, shouldSetBadge: true, shouldShowBanner: true, shouldShowList: true, }), }); async function sendPushNotification(expoPushToken: string) { const message = { to: expoPushToken, sound: 'default', title: 'Original Title', body: 'And here is the body!', data: { someData: 'goes here' }, }; await fetch('https://exp.host/--/api/v2/push/send', { method: 'POST', headers: { Accept: 'application/json', 'Accept-encoding': 'gzip, deflate', 'Content-Type': 'application/json', }, body: JSON.stringify(message), }); } function handleRegistrationError(errorMessage: string) { alert(errorMessage); throw new Error(errorMessage); } async function registerForPushNotificationsAsync() { if (Platform.OS === 'android') { await Notifications.setNotificationChannelAsync('default', { name: 'default', importance: Notifications.AndroidImportance.MAX, vibrationPattern: [0, 250, 250, 250], lightColor: '#FF231F7C', }); } if (Device.isDevice) { const { status: existingStatus } = await Notifications.getPermissionsAsync(); let finalStatus = existingStatus; if (existingStatus !== 'granted') { const { status } = await Notifications.requestPermissionsAsync(); finalStatus = status; } if (finalStatus !== 'granted') { handleRegistrationError('Permission not granted to get push token for push notification!'); return; } const projectId = Constants?.expoConfig?.extra?.eas?.projectId ?? Constants?.easConfig?.projectId; if (!projectId) { handleRegistrationError('Project ID not found'); } try { const pushTokenString = ( await Notifications.getExpoPushTokenAsync({ projectId, }) ).data; console.log(pushTokenString); return pushTokenString; } catch (e: unknown) { handleRegistrationError(`${e}`); } } else { handleRegistrationError('Must use physical device for push notifications'); } } export default function App() { const [expoPushToken, setExpoPushToken] = useState(''); const [notification, setNotification] = useState<Notifications.Notification | undefined>( undefined ); useEffect(() => { registerForPushNotificationsAsync() .then(token => setExpoPushToken(token ?? '')) .catch((error: any) => setExpoPushToken(`${error}`)); const notificationListener = Notifications.addNotificationReceivedListener(notification => { setNotification(notification); }); const responseListener = Notifications.addNotificationResponseReceivedListener(response => { console.log(response); }); return () => { notificationListener.remove(); responseListener.remove(); }; }, []); return ( <View style={{ flex: 1, alignItems: 'center', justifyContent: 'space-around' }}> <Text>Your Expo push token: {expoPushToken}</Text> <View style={{ alignItems: 'center', justifyContent: 'center' }}> <Text>Title: {notification && notification.request.content.title} </Text> <Text>Body: {notification && notification.request.content.body}</Text> <Text>Data: {notification && JSON.stringify(notification.request.content.data)}</Text> </View> <Button title="Press to Send Notification" onPress={async () => { await sendPushNotification(expoPushToken); }} /> </View> ); }
Show More
projectIdUsing the previous example, when you are registering for push notifications, you need to use projectId
. This property is used to attribute Expo push token to the specific project. For projects using EAS, the projectId property represents the Universally Unique Identifier (UUID) of that project.
projectId is set automatically when you create a development build. However, we recommend setting it manually in your project's code. To do so, you can use expo-constants
to get the projectId value from the app config.
const projectId = Constants?.expoConfig?.extra?.eas?.projectId ?? Constants?.easConfig?.projectId; const pushTokenString = (await Notifications.getExpoPushTokenAsync({ projectId })).data;
One advantage of attributing the Expo push token to your project's ID is that it doesn't change when a project is transferred between different accounts or the existing account gets renamed.
4
Get credentials for development builds
For Android and iOS, there are different requirements to set up your credentials.
Android
iOS
For Android, you need to configure Firebase Cloud Messaging (FCM) to get credentials and set up your Expo project.
Follow the steps in Add Android FCM V1 credentials to set up your credentials.
A paid Apple Developer Account is required to generate credentials.
For iOS, make sure you have registered your iOS device
on which you want to test before running the eas build command for the first time.
If you create a development build for the first time, you'll be asked to enable push notifications. Answer yes to the following questions when prompted by the EAS CLI:
If you are not using EAS Build, run
eas credentialsmanually.
5
Terminal
Copy
- eas build
6
Test using the push notifications tool
After creating and installing the development build, you can use Expo push notifications tool to quickly send a test notification to your device.
Start the development server for your project:
Terminal
Copy
- npx expo start
Open the development build on your device.
After the ExpoPushToken is generated, enter the value in the Expo push notifications tool with other details (for example, a message title and body).
Click on the Send a Notification button.

After sending the notification from the tool, you should see the notification on your device. Below is an example of an Android device receiving a push notification.
