Expo Image Picker provides a unified API for accessing the device camera and photo library on React Native apps. It enables users to select images, videos, and live photos from their device's media library or capture new content using the camera, with comprehensive support for permissions, editing, and multi-selection across iOS, Android, and web platforms.
npm install expo-image-pickerexpo-image-loaderexpoimport * as ImagePicker from 'expo-image-picker';
// Named imports
import {
launchCameraAsync,
launchImageLibraryAsync,
getCameraPermissionsAsync,
requestCameraPermissionsAsync,
getMediaLibraryPermissionsAsync,
requestMediaLibraryPermissionsAsync,
useCameraPermissions,
useMediaLibraryPermissions,
type ImagePickerResult,
type ImagePickerOptions
} from 'expo-image-picker';import * as ImagePicker from 'expo-image-picker';
// Request permissions first
const { status } = await ImagePicker.requestMediaLibraryPermissionsAsync();
if (status !== 'granted') {
alert('Permission denied!');
return;
}
// Pick an image from library
const result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: 'images',
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
if (!result.canceled) {
console.log('Selected image:', result.assets[0].uri);
}
// Take a photo with camera
const cameraResult = await ImagePicker.launchCameraAsync({
allowsEditing: true,
aspect: [1, 1],
quality: 1,
});Expo Image Picker is built around several key components:
launchCameraAsync and launchImageLibraryAsync for media selectionPrimary functions for capturing and selecting images and videos from camera or library.
function launchCameraAsync(options?: ImagePickerOptions): Promise<ImagePickerResult>;
function launchImageLibraryAsync(options?: ImagePickerOptions): Promise<ImagePickerResult>;Functions and hooks for managing camera and media library permissions across platforms.
function getCameraPermissionsAsync(): Promise<CameraPermissionResponse>;
function requestCameraPermissionsAsync(): Promise<CameraPermissionResponse>;
function getMediaLibraryPermissionsAsync(writeOnly?: boolean): Promise<MediaLibraryPermissionResponse>;
function requestMediaLibraryPermissionsAsync(writeOnly?: boolean): Promise<MediaLibraryPermissionResponse>;
const useCameraPermissions: (options?: PermissionHookOptions) => [PermissionResponse | null, () => Promise<PermissionResponse>, () => Promise<PermissionResponse>];
const useMediaLibraryPermissions: (options?: PermissionHookOptions<{ writeOnly?: boolean }>) => [MediaLibraryPermissionResponse | null, () => Promise<MediaLibraryPermissionResponse>, () => Promise<MediaLibraryPermissionResponse>];Comprehensive type definitions, configuration options, and utility functions for customizing picker behavior.
interface ImagePickerOptions {
allowsEditing?: boolean;
aspect?: [number, number];
quality?: number;
mediaTypes?: MediaType | MediaType[] | MediaTypeOptions;
allowsMultipleSelection?: boolean;
selectionLimit?: number;
base64?: boolean;
exif?: boolean;
}
type ImagePickerResult = ImagePickerSuccessResult | ImagePickerCanceledResult;
interface ImagePickerAsset {
uri: string;
width: number;
height: number;
type?: 'image' | 'video' | 'livePhoto' | 'pairedVideo';
assetId?: string | null;
fileName?: string | null;
fileSize?: number;
base64?: string | null;
exif?: Record<string, any> | null;
duration?: number | null;
mimeType?: string;
}// Result types
type ImagePickerResult = ImagePickerSuccessResult | ImagePickerCanceledResult;
interface ImagePickerSuccessResult {
canceled: false;
assets: ImagePickerAsset[];
}
interface ImagePickerCanceledResult {
canceled: true;
assets: null;
}
// Permission types
type CameraPermissionResponse = PermissionResponse;
interface MediaLibraryPermissionResponse extends PermissionResponse {
accessPrivileges?: 'all' | 'limited' | 'none';
}
// Media types
type MediaType = 'images' | 'videos' | 'livePhotos';
// Re-exported from expo-modules-core
enum PermissionStatus {
DENIED = 'denied',
GRANTED = 'granted',
UNDETERMINED = 'undetermined'
}
interface PermissionResponse {
status: PermissionStatus;
expires: PermissionExpiration;
granted: boolean;
canAskAgain: boolean;
}