A React component that renders a preview for the device's front or back camera.
expo-camera
provides a React component that renders a preview of the device's front or back camera. The camera's parameters such as zoom, torch, and flash mode are adjustable. Using CameraView
, you can take photos and record videos that are saved to the app's cache. The component is also capable of detecting bar codes appearing in the preview. Run the example on your device to see all these features working together.
Installation
-Â
npx expo install expo-camera
If you are installing this in an existing React Native app, make sure to install expo
in your project.
Configuration in app config
You can configure expo-camera
using its built-in config plugin if you use config plugins in your project (EAS Build or npx expo run:[android|ios]
). The plugin allows you to configure various properties that cannot be set at runtime and require building a new app binary to take effect.
Example app.json with config plugin
{
"expo": {
"plugins": [
[
"expo-camera",
{
"cameraPermission": "Allow $(PRODUCT_NAME) to access your camera",
"microphonePermission": "Allow $(PRODUCT_NAME) to access your microphone",
"recordAudioAndroid": true
}
]
]
}
}
Configurable properties
Name | Default | Description |
---|---|---|
cameraPermission | "Allow $(PRODUCT_NAME) to access your camera" | Only for:  iOS A string to set the |
microphonePermission | "Allow $(PRODUCT_NAME) to access your microphone" | Only for:  iOS A string to set the |
recordAudioAndroid | true | Only for:  Android A boolean that determines whether to enable the |
Are you using this library in an existing React Native app?
If you're not using Continuous Native Generation (CNG) (you're using native android and ios projects manually), then you need to configure following permissions in your native projects:
Android
-
expo-camera
automatically addsandroid.permission.CAMERA
permission to your project's android/app/src/main/AndroidManifest.xml. If you want to record videos with audio, includeRECORD_AUDIO
permission:<!-- Added permission --> <uses-permission android:name="android.permission.CAMERA" /> <!-- Only add when recording videos with audio --> <uses-permission android:name="android.permission.RECORD_AUDIO" />
-
Then, adjust the android/build.gradle file to add new maven block after all other repositories as show below:
allprojects { repositories { // * Your other repositories here * // * Add a new maven block after other repositories / blocks * maven { // expo-camera bundles a custom com.google.android:cameraview url "$rootDir/../node_modules/expo-camera/android/maven" } } }
iOS
-
Add
NSCameraUsageDescription
andNSMicrophoneUsageDescription
keys to your project's ios/[app]/Info.plist:<key>NSCameraUsageDescription</key> <string>Allow $(PRODUCT_NAME) to access your camera</string> <key>NSMicrophoneUsageDescription</key> <string>Allow $(PRODUCT_NAME) to access your microphone</string>
Usage
Only one Camera preview can be active at any given time. If you have multiple screens in your app, you should unmountCamera
components whenever a screen is unfocused.
import { CameraView, CameraType, useCameraPermissions } from 'expo-camera';
import { useState } from 'react';
import { Button, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
export default function App() {
const [facing, setFacing] = useState<CameraType>('back');
const [permission, requestPermission] = useCameraPermissions();
if (!permission) {
// Camera permissions are still loading.
return <View />;
}
if (!permission.granted) {
// Camera permissions are not granted yet.
return (
<View style={styles.container}>
<Text style={styles.message}>We need your permission to show the camera</Text>
<Button onPress={requestPermission} title="grant permission" />
</View>
);
}
function toggleCameraFacing() {
setFacing(current => (current === 'back' ? 'front' : 'back'));
}
return (
<View style={styles.container}>
<CameraView style={styles.camera} facing={facing}>
<View style={styles.buttonContainer}>
<TouchableOpacity style={styles.button} onPress={toggleCameraFacing}>
<Text style={styles.text}>Flip Camera</Text>
</TouchableOpacity>
</View>
</CameraView>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
},
message: {
textAlign: 'center',
paddingBottom: 10,
},
camera: {
flex: 1,
},
buttonContainer: {
flex: 1,
flexDirection: 'row',
backgroundColor: 'transparent',
margin: 64,
},
button: {
flex: 1,
alignSelf: 'flex-end',
alignItems: 'center',
},
text: {
fontSize: 24,
fontWeight: 'bold',
color: 'white',
},
});
Advanced usage
A complete example that shows how to take a picture and display it. Written in TypeScript.
Web support
Most browsers support a version of web camera functionality, you can check out the web camera browser support here. Image URIs are always returned as base64 strings because local file system paths are unavailable in the browser.
Chrome iframe
usage
When using Chrome versions 64+, if you try to use a web camera in a cross-origin iframe nothing will render. To add support for cameras in your iframe simply add the attribute allow="microphone; camera;"
to the iframe element:
<iframe src="..." allow="microphone; camera;">
<!-- <CameraView /> -->
</iframe>
API
import { CameraView } from 'expo-camera';
Component
Type: React.Component<CameraViewProps>
boolean
 • Default: true
A boolean that determines whether the camera should be active. Useful in situations where the camera may not have unmounted but you still want to stop the camera session.
boolean
 • Default: true
A boolean that determines whether the camera shutter animation should be enabled.
BarcodeSettings
Example
<CameraView
barcodeScannerSettings={{
barcodeTypes: ["qr"],
}}
/>
boolean
 • Default: false
A boolean to enable or disable the torch.
CameraType
 • Default: 'back'
Camera facing. Use one of CameraType
. When front
, use the front-facing camera.
When back
, use the back-facing camera.
FlashMode
 • Default: 'off'
Camera flash mode. Use one of FlashMode
values. When on
, the flash on your device will
turn on when taking a picture. When off
, it won't. Setting it to auto
will fire flash if required.
boolean
 • Default: false
A boolean that determines whether the camera should mirror the image when using the front camera.
CameraMode
 • Default: 'picture'
Used to select image or video output.
boolean
 • Default: false
If present, video will be recorded with no sound.
(event: AvailableLenses) => void
Callback invoked when the cameras available lenses change.
event: AvailableLenses
result object that contains a lenses
property containing an array of available lenses.
(scanningResult: BarcodeScanningResult) => void
Callback that is invoked when a barcode has been successfully scanned. The callback is provided with
an object of the BarcodeScanningResult
shape, where the type
refers to the barcode type that was scanned, and the data
is the information encoded in the barcode
(in this case of QR codes, this is often a URL). See BarcodeType
for supported values.
() => void
Callback invoked when camera preview has been set.
(event: CameraMountError) => void
Callback invoked when camera preview could not start.
event: CameraMountError
Error object that contains a message
.
(event: ResponsiveOrientationChanged) => void
Callback invoked when responsive orientation changes. Only applicable if responsiveOrientationWhenOrientationLocked
is true
.
event: ResponsiveOrientationChanged
result object that contains updated orientation of camera
string
A string representing the size of pictures takePictureAsync
will take.
Available sizes can be fetched with getAvailablePictureSizesAsync
.
Setting this prop will cause the ratio
prop to be ignored as the aspect ratio is determined by the selected size.
CameraRatio
A string representing the aspect ratio of the preview. For example, 4:3
and 16:9
.
Note: Setting the aspect ratio here will change the scaleType of the camera preview from FILL
to FIT
.
Also, when using 1:1, devices only support certain sizes. If you specify an unsupported size, the closest supported ratio will be used.
boolean
Whether to allow responsive orientation of the camera when the screen orientation is locked (that is, when set to true
,
landscape photos will be taken if the device is turned that way, even if the app or device orientation is locked to portrait).
string
 • Default: 'builtInWideAngleCamera'
Available lenses are emitted to the onAvailableLensesChanged
callback whenever the currently selected camera changes or by calling getAvailableLensesAsync
.
You can read more about the available lenses in the Apple documentation.
number
The bitrate of the video recording in bits per second.
Note: On iOS, you must specify the video codec when calling recordAsync
to use this option.
Example
10_000_000
VideoQuality
Specify the quality of the recorded video. Use one of VideoQuality
possible values:
for 16:9 resolution 2160p
, 1080p
, 720p
, 480p
: Android only
and for 4:3 4:3
(the size is 640x480).
If the chosen quality is not available for a device, the highest available is chosen.
VideoStabilization
The video stabilization mode used for a video recording. Use one of VideoStabilization.<value>
.
You can read more about each stabilization type in Apple Documentation.
number
 • Default: 0
A value between 0
and 1
being a percentage of device's max zoom, where 0
means not zoomed and 1
means maximum zoom.
Static Methods
Dismiss the scanner presented by launchScanner
.
On Android, the scanner is dismissed automatically when a barcode is scanned.
Promise<void>
Queries the device for the available video codecs that can be used in video recording.
Promise<VideoCodec[]>
A promise that resolves to a list of strings that represents available codecs.
Check whether the current device has a camera. This is useful for web and simulators cases. This isn't influenced by the Permissions API (all platforms), or HTTP usage (in the browser). You will still need to check if the native permission has been accepted.
Promise<boolean>
Parameter | Type |
---|---|
options(optional) | ScanningOptions |
On Android, we will use the Google code scanner.
On iOS, presents a modal view controller that uses the DataScannerViewController
available on iOS 16+.
Promise<void>
Parameter | Type | Description |
---|---|---|
listener | (event: ScanningResult) => void | Invoked with the ScanningResult when a bar code has been successfully scanned. |
Invokes the listener
function when a bar code has been successfully scanned. The callback is provided with
an object of the ScanningResult
shape, where the type
refers to the bar code type that was scanned and the data
is the information encoded in the bar code
(in this case of QR codes, this is often a URL). See BarcodeType
for supported values.
EventSubscription
Component Methods
Returns the available lenses for the currently selected camera.
Promise<string[]>
Returns a Promise that resolves to an array of strings representing the lens type that can be passed to selectedLens
prop.
Get picture sizes that are supported by the device.
Promise<string[]>
Returns a Promise that resolves to an array of strings representing picture sizes that can be passed to pictureSize
prop.
The list varies across Android devices but is the same for every iOS.
Returns an object with the supported features of the camera on the current device.
{
isModernBarcodeScannerAvailable: boolean,
toggleRecordingAsyncAvailable: boolean
}
Pauses the camera preview. It is not recommended to use takePictureAsync
when preview is paused.
Promise<void>
Parameter | Type | Description |
---|---|---|
options(optional) | CameraRecordingOptions | A map of |
Starts recording a video that will be saved to cache directory. Videos are rotated to match device's orientation. Flipping camera during a recording results in stopping it.
Promise<undefined | {
uri: string
}>
Returns a Promise that resolves to an object containing video file uri
property and a codec
property on iOS.
The Promise is returned if stopRecording
was invoked, one of maxDuration
and maxFileSize
is reached or camera preview is stopped.
Resumes the camera preview.
Promise<void>
Parameter | Type | Description |
---|---|---|
options | CameraPictureOptions & {
pictureRef: true
} | An object in form of |
Takes a picture and saves it to app's cache directory. Photos are rotated to match device's orientation
(if options.skipProcessing
flag is not enabled) and scaled to match the preview.
Note: Make sure to wait for the
onCameraReady
callback before calling this method.
Promise<PictureRef>
Returns a Promise that resolves to CameraCapturedPicture
object, where uri
is a URI to the local image file on Android,
iOS, and a base64 string on web (usable as the source for an Image
element). The width
and height
properties specify
the dimensions of the image.
base64
is included if the base64
option was truthy, and is a string containing the JPEG data
of the image in Base64. Prepend it with 'data:image/jpg;base64,'
to get a data URI, which you can use as the source
for an Image
element for example.
exif
is included if the exif
option was truthy, and is an object containing EXIF
data for the image. The names of its properties are EXIF tags and their values are the values for those tags.
On native platforms, the local image URI is temporary. Use
FileSystem.copyAsync
to make a permanent copy of the image.
Note: Avoid calling this method while the preview is paused. On Android, this will throw an error. On iOS, this will take a picture of the last frame that is currently on screen.
Parameter | Type | Description |
---|---|---|
options(optional) | CameraPictureOptions | An object in form of |
Takes a picture and saves it to app's cache directory. Photos are rotated to match device's orientation
(if options.skipProcessing
flag is not enabled) and scaled to match the preview.
Note: Make sure to wait for the
onCameraReady
callback before calling this method.
Promise<CameraCapturedPicture>
Returns a Promise that resolves to CameraCapturedPicture
object, where uri
is a URI to the local image file on Android,
iOS, and a base64 string on web (usable as the source for an Image
element). The width
and height
properties specify
the dimensions of the image.
base64
is included if the base64
option was truthy, and is a string containing the JPEG data
of the image in Base64. Prepend it with 'data:image/jpg;base64,'
to get a data URI, which you can use as the source
for an Image
element for example.
exif
is included if the exif
option was truthy, and is an object containing EXIF
data for the image. The names of its properties are EXIF tags and their values are the values for those tags.
On native platforms, the local image URI is temporary. Use
FileSystem.copyAsync
to make a permanent copy of the image.
Note: Avoid calling this method while the preview is paused. On Android, this will throw an error. On iOS, this will take a picture of the last frame that is currently on screen.
Pauses or resumes the video recording. Only has an effect if there is an active recording. On iOS
, this method only supported on iOS
18.
Promise<undefined | void>
Example
const { toggleRecordingAsyncAvailable } = getSupportedFeatures()
return (
{toggleRecordingAsyncAvailable && (
<Button title="Toggle Recording" onPress={toggleRecordingAsync} />
)}
)
Hooks
Parameter | Type |
---|---|
options(optional) | PermissionHookOptions<object> |
Check or request permissions to access the camera.
This uses both requestCameraPermissionsAsync
and getCameraPermissionsAsync
to interact with the permissions.
[null | PermissionResponse, RequestPermissionMethod<PermissionResponse>, GetPermissionMethod<PermissionResponse>]
Example
const [status, requestPermission] = useCameraPermissions();
Parameter | Type |
---|---|
options(optional) | PermissionHookOptions<object> |
Check or request permissions to access the microphone.
This uses both requestMicrophonePermissionsAsync
and getMicrophonePermissionsAsync
to interact with the permissions.
[null | PermissionResponse, RequestPermissionMethod<PermissionResponse>, GetPermissionMethod<PermissionResponse>]
Example
const [status, requestPermission] = Camera.useMicrophonePermissions();